
Strands Agents から LiteLLM Proxy 経由で Amazon Bedrock を呼び出してみた
はじめに
こんにちは、スーパーマーケットのラ・ムーが好きなコンサル部の神野(じんの)です。
最近、AI エージェントフレームワークの Strands Agents を触っているのですが、LLM の呼び出し先を一元管理したいケースがありました。例えばチームごとにアクセスできるモデルを制限したい、使用量を把握したい、といった要件です。
こういったマルチプロバイダー対応の LLM ゲートウェイとしては、AWS 公式のソリューションが公開されています。
この公式ソリューションは CloudFront + WAF + Route53 + Middleware コンテナなどフル装備の本番向け構成で、すぐに展開するのに便利ですが、軽い検証目的にはちょっと重たく感じます。
そこで今回は、勉強がてら Terraform で必要最小限の LiteLLM Proxy 環境を自前で構築し、Strands Agents から Proxy 経由で Amazon Bedrock の Claude モデルを呼び出す構成を試してみました。
LiteLLM には OSS 版(MIT ライセンス)と Enterprise 版がありますが、今回使用するのは OSS 版です。Team 管理、仮想 API Key、使用量トラッキングといった機能は OSS 版で利用できるので、無料で試せます。
LiteLLM の管理画面で Team を作成し、仮想 API Key を発行して、アクセス制御付きで通信するところまでやっていきます。
なお、LiteLLM Proxy の管理画面(Admin UI)でどんなことができるかについては、弊社の記事で網羅的に紹介されています。管理画面の機能を把握したい方はこちらもあわせてご覧ください。
前提
環境
- Python 3.12
- strands-agents 1.29.0(litellm extras 込み)
- strands-agents-tools 0.2.22
- LiteLLM Proxy main-v1.81.14-stable(AWS ECS Fargate 上にデプロイ済み)
- Amazon Bedrock(us-east-1)
通信の流れ
Strands Agents から見ると、LiteLLM Proxy は OpenAI 互換の API エンドポイントとして振る舞います。Bedrock の認証情報はプロキシ側(ECS Task Role)が持っているため、クライアント側では AWS の認証情報を意識する必要がありません。
LiteLLM Proxy の構築(Terraform)
今回は Terraform でシンプルな LiteLLM Proxy 環境を構築しました。コード全体は GitHub リポジトリに公開しています。
アーキテクチャ
VPC + ALB + ECS Fargate + RDS のシンプルな構成です。

RDS にログやモデル情報を永続化し、S3 には LiteLLM の設定ファイル(config.yaml)を格納します。
Terraform のモジュール構成
terraform/
├── main.tf # プロバイダー + モジュール構成
├── variables.tf # 入力変数
├── outputs.tf # ALB DNS 名の出力
├── terraform.tfvars.example # 変数サンプル
├── config/
│ └── config.yaml.tpl # LiteLLM 設定テンプレート
└── modules/
├── network/ # VPC + public/private subnets + NAT Gateway
├── ecs/ # ECS Fargate + ALB + IAM + S3(config) + SG
├── rds/ # (optional) PostgreSQL 15
└── redis/ # (optional) ElastiCache Redis 7.1
RDS や Redis は enable_rds / enable_redis 変数でオプショナルに切り替えられるようにしています。今回は Team 機能を使うために RDS を有効にしています。
デプロイ手順
cd terraform
cp terraform.tfvars.example terraform.tfvars
# terraform.tfvars を編集して litellm_master_key を設定
terraform init
terraform apply
terraform.tfvars は下記のような内容です。
aws_region = "us-east-1"
name_prefix = "litellm"
litellm_version = "main-v1.81.14-stable"
litellm_master_key = "sk-your-secret-key-here"
ecs_cpu = 512
ecs_memory = 1024
desired_count = 1
enable_rds = true
enable_redis = false
litellm_version で LiteLLM のイメージタグを固定しています。ghcr.io/berriai/litellm の公開イメージを直接利用するため、ECR へのビルド・プッシュは不要です。litellm_master_key が管理者用の API Key で、enable_rds = true にすると Team / 仮想 API Key / 使用量トラッキングが使えるようになります。
apply が完了すると ALB の DNS 名が output に表示されます。
Apply complete! Resources: 44 added, 0 changed, 0 destroyed.
Outputs:
alb_dns_name = "litellm-alb-xxxxxxxxx.us-east-1.elb.amazonaws.com"
service_url = "http://litellm-alb-xxxxxxxxx.us-east-1.elb.amazonaws.com"
LiteLLM の config.yaml
Terraform の templatefile() で生成される LiteLLM の設定は下記のようになっています。
model_list:
- model_name: claude-sonnet
litellm_params:
model: bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0
aws_region_name: us-east-1
- model_name: claude-haiku
litellm_params:
model: bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0
aws_region_name: us-east-1
general_settings:
store_model_in_db: true
store_prompts_in_spend_logs: true
litellm_settings:
drop_params: true
num_retries: 3
router_settings:
routing_strategy: usage-based-routing-v2
model_name がプロキシ上のモデルエイリアスで、クライアントからはこのエイリアス名で呼び出します。store_model_in_db: true を設定すると管理画面からモデルの追加・変更ができるようになり、store_prompts_in_spend_logs: true でリクエスト / レスポンスの内容も管理画面から確認できます。
Bedrock の認証は ECS Task Role に bedrock:* の IAM ポリシーを付与しているため、API Key の設定は不要です。
LiteLLM 管理画面での Team 作成と仮想 API Key 発行
LiteLLM Proxy には管理画面が組み込まれています。http://<ALB_DNS>/ui にアクセスし、Username に admin、Password に litellm_master_key で設定した Master Key を入力してログインします。

Team の作成
- サイドバーから「Teams」を選択
- 「+ Create New Team」ボタンを押下

- 下記情報を入力
- Team Name: 任意のチーム名(例:
dev-team) - Models: チームがアクセスできるモデルを選択(例:
claude-haikuのみ)

- Team Name: 任意のチーム名(例:
- 「Create Team」ボタンを押下
これでチームが作成されました。ここで設定したモデルだけが、このチームに所属する API Key からアクセスできるようになります。
なお、今回は検証していませんが、Team には Max Budget(予算上限)や Budget のリセット期間(日次・月次など)、TPM / RPM のレートリミットも設定できます。予算を超過するとリクエストがブロックされるため、チームごとのコスト管理にも活用できそうですね。詳しくは公式ドキュメントを参照してください。
仮想 API Key の発行
- サイドバーから「Virtual Keys」を選択
- 「+ Create New Key」ボタンを押下

- 下記情報を入力
- Key Name: 任意のキー名(例:
dev-team-key) - Team: 先ほど作成したチームを選択(例:
dev-team) - Models: Team から継承するため、
All Team Modelsを選択

- Key Name: 任意のキー名(例:
- 「Create Key」ボタンを押下
- 生成された API Key(
sk-xxxxxxxx形式)をコピー

これで Team に紐づいた仮想 API Key が発行されました。この Key を使って Strands Agents からアクセスしていきます。
実装
依存関係のインストール
まずは必要なパッケージをインストールします。
uv add 'strands-agents[litellm]' strands-agents-tools
Agent の実装
LiteLLM Proxy 経由で Bedrock Claude を呼び出す Agent を実装します。
litellm用の処理も用意されているので、基本はそれを使うだけです。便利ですね。
"""Strands Agents + LiteLLM Proxy sample."""
from strands import Agent
from strands.models.litellm import LiteLLMModel
from strands_tools import calculator
# LiteLLM Proxy の接続情報
LITELLM_PROXY_URL = "http://<ALB_DNS>"
LITELLM_PROXY_KEY = "sk-xxxxxxxx" # 発行した仮想 API Key
model = LiteLLMModel(
client_args={
"api_key": LITELLM_PROXY_KEY,
"api_base": LITELLM_PROXY_URL,
"use_litellm_proxy": True,
},
model_id="claude-haiku",
params={
"max_tokens": 4096,
"temperature": 0.7,
},
)
agent = Agent(
model=model,
tools=[calculator],
system_prompt="あなたは親切な日本語アシスタントです。計算が必要な場合はcalculatorツールを使ってください。",
)
def main():
print("=== Strands Agent + LiteLLM Proxy サンプル ===\n")
# 単純な会話
print("--- 会話テスト ---")
response = agent("日本の首都はどこですか?")
print(f"回答: {response}\n")
# ツール使用(calculator)
print("--- ツール使用テスト ---")
response = agent("123 * 456 + 789 を計算してください")
print(f"回答: {response}\n")
if __name__ == "__main__":
main()
client_args の use_litellm_proxy: True を設定することで、 Strands の LiteLLM プロバイダーがプロキシモードで動作します。
api_base にプロキシの URL、api_key に発行した仮想 API Key を指定します。model_id には config.yaml で定義したモデルエイリアス名を指定する点に注意してください。Bedrock のモデル ID ではなく、プロキシ側で定義した claude-haiku や claude-sonnet を使います。
今回は strands_tools の calculator をツールとして渡して、LiteLLM Proxy 経由でも Function Calling が動くか確認してみます。
補足
use_litellm_proxy: True の代わりに、model_id に litellm_proxy/ プレフィックスを付ける方法もあります。
model = LiteLLMModel(
client_args={
"api_key": LITELLM_PROXY_KEY,
"api_base": LITELLM_PROXY_URL,
},
model_id="litellm_proxy/claude-haiku",
)
どちらでも動作しますが、use_litellm_proxy を使う方が明示的でわかりやすいかなと思います。
動作確認
正常系:会話テスト
python main.py
--- 会話テスト ---
日本の首都は**東京**です。
東京は日本の政治、経済、文化の中心地であり、内閣総理大臣官邸や国会議事堂などの重要な政府機関が置かれています。また、人口も日本最大の都市で、世界的にも有数の大都市として知られています。回答: 日本の首都は**東京**です。
東京は日本の政治、経済、文化の中心地であり、内閣総理大臣官邸や国会議事堂などの重要な政府機関が置かれています。また、人口も日本最大の都市で、世界的にも有数の大都市として知られています。
--- ツール使用テスト ---
計算させていただきます。
Tool #1: calculator
**123 × 456 + 789 = 56,877** です
計算過程:
- 123 × 456 = 56,088
- 56,088 + 789 = 56,877回答: **123 × 456 + 789 = 56,877** です
計算過程:
- 123 × 456 = 56,088
- 56,088 + 789 = 56,877
会話もツール呼び出しも問題なく動いていますね!(2重で表示されているのはprint文を仕込んだからです・・・)
LiteLLM Proxy を経由していますが、Strands Agents のツール呼び出しがそのまま使えています。Proxy はリクエストを透過的に Bedrock へ中継してくれるので、Agent の実装側は直接 Bedrock を呼ぶ場合と変わらない書き方ができます。
モデルアクセス制御の確認
先ほど claude-haiku のみ許可した Team の API Key を使っている状態で、claude-sonnet を呼び出してみます。
model = LiteLLMModel(
client_args={
"api_key": LITELLM_PROXY_KEY,
"api_base": LITELLM_PROXY_URL,
"use_litellm_proxy": True,
},
- model_id="claude-haiku",
+ model_id="claude-sonnet",
)
litellm.exceptions.AuthenticationError: litellm.AuthenticationError: AuthenticationError: Litellm_proxyException - team not allowed to access model. This team can only access models=['claude-haiku']. Tried to access claude-sonnet
Team で許可されていないモデルへのアクセスがブロックされていますね!
このように、LiteLLM Proxy の Team 機能を使うことで、API Key 単位でアクセスできるモデルを制御できます。開発チームには Haiku のみ、本番環境には Sonnet も許可する、といった運用が可能になります。
管理画面での使用量確認
管理画面(/ui)から、使用量やログを確認できます。サイドバーの OBSERVABILITY セクションに Usage と Logs があります。
Team 別の使用量
Usage タブで Team Usage を選択すると、チーム単位での利用状況が確認できます。

Total Spend(合計コスト)、Total Requests(リクエスト数)、Successful Requests(成功数)、Failed Requests(失敗数)、Total Tokens(トークン数)がひと目でわかります。Daily Spend のグラフで日ごとの推移も確認できますね。
Key 別の使用量
Key Activity タブに切り替えると、API Key 単位でさらに詳細な内訳が確認できます。

Model Usage のテーブルでは、モデルごとの Spend(コスト)、Successful / Failed リクエスト数、Tokens が表示されます。先ほどの動作確認で claude-sonnet にアクセスしてブロックされた分が Failed Requests: 1 としてカウントされていますね。アクセス制御がログにもしっかり反映されています。
リクエストログ
Logs 画面では、個々のリクエストの詳細を確認できます。

store_prompts_in_spend_logs: true を設定しているため、各リクエストのプロンプトとレスポンスの内容まで確認できます。右側のパネルでは、System Prompt、ユーザーの入力、モデルの応答、ツール呼び出し(calculator)の結果、トークン数やコストの内訳が表示されています。デバッグや監査に便利ですね。
おわりに
Strands Agents 側の実装はほとんど変わらず、client_args でプロキシの接続情報を渡すだけでした。シンプルに利用できて良いですね!
LiteLLM Proxy をゲートウェイとして挟むことで、Team / 仮想 API Key によるモデルアクセス制御や使用量トラッキング、リクエスト / レスポンスの監査ログが使えるようになります。もし要件として必要であれば検討したいですね。
ちなみに、今回の Terraform モジュールには Bedrock Guardrails を LiteLLM のガードレール機能と連携させる仕組みも組み込んでいます。こちらについては別の記事で詳しく紹介したいと思います。
本記事が少しでも参考になりましたら幸いです。最後までご覧いただきありがとうございました!








