Bedrock AgentのDraft, Version, Aliasの構造とTerraform管理の難しさ


※この記事は自分が所属する組織で書いた以下の記事のコピーです。投稿した記事は個人の著作物として自ブログにコピーして良いルールとしています。

https://tech-blog.mitsucari.com/entry/2025/04/17/100532


こんにちは、ミツカリCTOの塚本こと、つかびー(@tsukaby0) です。

先日弊社は生成AIをプロダクトに組み込んだとある機能をリリースしました。

https://x.com/takanori52/status/1904356576913457285

こちらの機能の生成AI基盤にはAWS Bedrockを利用しています。今回の記事ではAWS Bedrock Agentの構造やTerraformを使う場合のバージョン管理の課題について説明します。

AWS BedrockとAgent

AWS Bedrockは生成AIの製品です。

AWS BedrockではAnthropic Claudeなどのモデルを直で利用することもできれば、Bedrock Agentという仕組みで間接的に使うこともできます。

例えばAWS Ruby SDKでは以下のように呼び出すことができます。

直利用

https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/BedrockRuntime/Client.html

client = Aws::BedrockRuntime::Client.new(
  region: region_name,
  credentials: credentials,
  # ...
)

client.invoke_model(params)

Agent経由での利用

https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/BedrockAgentRuntime/Client.html

client = Aws::BedrockAgentRuntime::Client.new(
  region: region_name,
  credentials: credentials,
  # ...
)

client.invoke_agent(params)

Agentの方が高機能であり、どちらを使うべきかは用途や要件によって異なります。今回はAgentの話がメインです。

Agentについては以下の資料が役に立つと思います。

https://aws.amazon.com/jp/bedrock/agents/

上記は公式ですが、ざっくりとした内容を掴むことができます。

とはいえ、これだけだとよくわからないので、以下の資料もおすすめです。

https://dev.classmethod.jp/articles/introduction-2024-agents-for-amazon-bedrock/

さすがのクラスメソッドさんですね。

上記の記事でも触れられていますが、フローや内部構造の概要について把握したい場合は以下のBlack beltの資料や公式資料も参考になります。

https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2024_Amazon-Bedrock-Agents-b_1029_v1.pdf

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/advanced-prompts.html

前処理やオーケストレーションというのは取っつきにくいと思いますが、AWSのマネジメントコンソール(Web GUI)上で色々と設定しては動かしてみるということができるので、ハンズオン形式でキャッチアップしていくのが良いと思います。AWS SDKでAPIを呼び出すみたいなことはせずにWeb GUI上で検証できるので便利ですね。もちろんBedrockは他の製品から呼び出せるのでDifyなんかを経由して使うのもありだとは思います。

好みの生成AIエージェントを作るうえでプロンプトエンジニアリングは欠かせません。生成AIはコンテキストを把握することは苦手ですから、察してもらうのではなくある程度細かな指示を与える必要があります。生成AIのエンドユーザーはそこまで考慮してくれないので、ある程度の枠組みであるシステムプロンプトを我々エンジニアやプロダクトマネージャ(PdM)が設計することが大事です。

これについては以下の資料が役に立つと思います。例えばClaudeの生成AIを使う場合はリンクされているClaudeのdocを読みましょう。

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/prompt-engineering-guidelines.html

Bedrock Agentについて一言で説明すると**「単なるチャットではなく、特定のタスクが実行できる高機能な生成AIエージェントを作れる製品」**です。

AWS Bedrock Agentのバージョンおよびエイリアス

Bedrock Agentをもし利用する場合はどのような構造になっているか把握し、どう運用するかを考える必要があります。今回、ここで言う把握や運用とは、あくまでインフラエンジニア目線での話であり、PdMやアプリケーションエンジニアのレイヤの話ではありません。そのため、プロンプトエンジニアリングやオーケストレーションの話は省きます。

Bedrock Agentには

  • Version
  • Draft version
  • Alias

という概念があります。AWS Lambdaの経験者であればとっつきやすいかもしれません。

まず、Agentを作成した後で編集できる状態になりますが、ここで編集を加える先は常にDraft Versionになります。つまりどのような変更を加えようとも即時STGやPRDなどの環境に影響は出ません。編集を重ねてDraftを編集したらその最新版を指す特殊なAliasであるテストエイリアスがあるので、それを使ってGUI上で動作確認が行えます(スクショの右側のテスト、という部分です)。

これで動作検証し、OKとなったら、Aliasを作成します。このとき自動でVersionも作成されます。

既存のAliasを編集することもできます。

このとき、昔に作られたVersionを紐づけなおすこともできますし、新しく現在のDraftからVersionを作って、それを紐づけることもできます。

GUIで操作する分には特に難しいことはありません。

先ほどAWS Bedrock SDKを利用するコードを示しましたが、より具体的には以下のようなコードとなります。

resp = client.invoke_agent({
  agent_alias_id: "AgentAliasId", # required
  agent_id: "AgentId", # required

agent_idはAgent作成時に払い出されるもので、初期作成後は固定です。

agent_alias_idは作成したAliasのIDで、これをどのタイミングで変えるかは運用次第です。インフラ側では毎回異なるAliasを払い出して、アプリケーション側で適用するタイミングをコントロールする(コードを変更してリリースする)、というやり方もありですし、Aliasは常に固定の1つだけとして、それをインフラ側で都度更新することでIDは変えずに変更をリリースするというやり方も良いと思います。

ミツカリにおいては後者のやり方が良いという判断をしました。

Terraformでの難しさ

ここからが本題です。ミツカリではIaCツールにTerraformを使っており、今回のBedrock AgentもIaC化しています。

しかし、Terraformを使う場合、上記のAlias周りの最適なフローを組みづらいため、この記事ではその問題について説明します。

まず、Terraformの公式docを確認すると以下のよう定義されてます。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/bedrockagent_agent

resource "aws_bedrockagent_agent" "example" {
  agent_name                  = "my-agent-name"
  agent_resource_role_arn     = aws_iam_role.example.arn
  idle_session_ttl_in_seconds = 500
  foundation_model            = "anthropic.claude-v2"
}

Agentを定義できますが、これだけだと先ほど説明したDraft versionを作成、更新するだけの処理になってしまいます。

そこで、 aws_bedrockagent_agent_alias を使います。

resource "aws_bedrockagent_agent_alias" "example" {
  agent_alias_name = "my-agent-alias"
  agent_id         = aws_bedrockagent_agent.example.agent_id
  description      = "Test Alias"
}

これを使うとAliasを作成すると同時にVersionを作成できます。ただし、これにはとある問題があります。Aliasが更新されないという問題です。

今回考えていた運用としては、Agentの設定を変えたら自動で新しいVersionが作成されてAliasが更新される、というものですが、これは普通に書いても実現しません。というのもAgent resourceを変えてもAlias resourceとしては何も変わらないため、更新する必要がないとみなされてしまうためです。

ちなみにこの問題については他の方も困っているようで、以下の記事でも解説されています。

https://tosi-tech.net/2024/12/bedrock-agents-versioning-by-terraform/

resource "aws_bedrockagent_agent_alias" "this" {
  agent_alias_name = "latest"
  agent_id         = module.agent.agent_id

  lifecycle {
    replace_triggered_by = [
      null_resource.trigger.id
    ]
  }
}

resource "null_resource" "trigger" {
  triggers = {
    always_run = timestamp()
  }
}

null_resourceを使ったこのやり方も悪くはないです。このやり方ではnull_resourceのtriggersの中の評価結果としてはterraform apply実行ごとに異なるタイムスタンプになるので、毎回Aliasを再作成するという処理になります。

ただし、このやり方にも問題があります。Terraform applyのたびにVersionが作成されてしまい、変更がないのに不要にVersion番号が増加してしまうという問題があります。Agentの設定のMD5か何かを取って差分があったときだけ変更するというやり方に改良することもできますが、そもそも別の根本的な問題があり、Aliasがreplace(Delete, Create)されてしまうという問題があります。つまりAlias IDが変わってしまうので、それを利用するアプリケーション側としては困ってしまいます。

これに対する理想的な解決方法としては、Terraform側がversionリソースというものを用意することで、versionリソースを新しく作ったらそれに応じてAliasの紐づけも更新できる、というものだと思います。しかし残念ながら現時点でversionリソースはありません。

aws_bedrockagent_agent_versions というData resourceはありますが、これを使ってもversionは作れなさそうです。このData resourceは現在のバージョン一覧取得のためのもののようですね。この問題は現時点でTerraform側のIssueなどに存在しないので、特に困っている人が多くないのかもしれません。

あるいはそもそもTerraform側で技術的に実現できない可能性もありそうです。

https://docs.aws.amazon.com/ja_jp/bedrock/latest/APIReference/API_Operations_Agents_for_Amazon_Bedrock.html

こちらを見るとAWSのAPIにどのようなものがあるか把握できますが、現時点で CreateAgentVersion というようなものはありません。また、CreateAgentAliasはありますが、Versionだけ作成し、Aliasは再作成しないというような挙動ができるのかが不明瞭です。

結局どうしたか

残念ながら良い解決方法が見つからなかったので、ミツカリでは以下のような手動操作を交えた運用方法を取ることにしました。

  1. TerraformでAgentとAliasのリソースは作る。ただし、Aliasのリソースは更新対象としない
  2. Agentに変更があった場合は、 terraform apply でDraft versionのみ更新する
  3. Bedrock agentリソースに更新がある場合、PR上で警告コメントを投稿するCIを追加する。開発者はコメントを読んで以下の手動の作業を行う
  4. 開発者はAWSのGUI上で手動でlatest aliasを更新し、新しいVersionを作成するとともに紐づけを更新する

手動作業が入ってしまうので、そこは残念ですね。IaC化の恩恵を最大限享受できない状況となってしまいました。ただし、一番肝心なAgentの設定部分はコード化できているので全くだめというわけではないかなと思います。

もしかするとAliasをその都度新規作成し、アプリケーション側の任意のタイミングで新しいエイリアスに切り替える運用の方が良いかもしれません。とはいえそれも手動作業が入ってしまうのでちょっと微妙ですし、Terraformのtfファイル上にAlias resourceの定義が増えていくのは微妙です。

このあたりは今後良い方法が出てきたら改良していきたいところです。


現在、ミツカリではITエンジニアを募集しています。興味のある方はぜひお気軽にご連絡ください!

https://herp.careers/v1/mitsucari