コンテンツにスキップ

第14章 RAGで社内データをエージェントに活かす — 学習メモ

書籍「Amazon Bedrock AgentCore実践入門」第14章のサンプルコード(このフォルダ)を読み解いた個人学習メモ。 AgentCore 全体像は ../../lectures/agentcore_basics/STUDY_NOTES.md 参照。 実行検証は伴わない。コードに現れた API 名だけ断定し、読めない挙動は「〜と推測」で明示する。

一言で

「同じBedrockナレッジベースに、①生のboto3 API・②Strandsのretrieveツール・③外部MCPサーバー経由、の3通りで辿り着く」章。この章もAgentCoreを使わないbedrock_agentcorechapter14/*.py で grep して確認、ヒット0件)。

全体像

  • 3つの独立したスクリプトがあるだけで、互いに依存関係は無い。各スクリプトが単独で「質問→検索→回答」を完結させる。
  • 重要な食い違い: リポジトリの .claude/CLAUDE.md(章タイプ一覧)では第14章は「Streamlitベースの RAG」と分類されているが、実際のサンプルコードにStreamlit UIは存在しないstreamlit を含む行をgrepしてヒット0件)。3つの独立したPythonスクリプトのみで、対話UIは無い。原稿(authoring側)の記述とコードの実態がずれている可能性がある点は正直に書いておく。
  • README.mdにも明記されている通り、本章はBedrockナレッジベースをこの章では新規構築しない。書籍の別章(Gateway章)で作成済みのナレッジベースを流用する前提で、コード内の"ナレッジベースID""モデルARN"をプレースホルダーとして置き換える必要がある。
flowchart TD
    Q["ユーザーの質問"] --> P1["①retrieve_and_generate<br>01-retrieve_and_generate.py"]
    Q --> P2["②Strandsのretrieveツール<br>02-retrieve-tool.py"]
    Q --> P3["③MCPサーバー経由<br>03-mcp-tool.py"]
    P1 -->|"検索と生成を1回のAPI呼び出しで完結"| KB[("Bedrockナレッジベース<br>本章では構築しない・流用のみ")]
    P2 -->|"retrieveツール呼び出し・生成は呼び出し元のLLM"| KB
    P3 -->|"uvx起動のMCPサーバー経由で検索"| KB

使用ライブラリ・原理

  • pyproject.toml(project名はhandsonのまま。テンプレート名残りと推測)固定バージョン: boto3[crt]==1.42.96, strands-agents==1.38.0, strands-agents-tools==0.5.1, mcp==1.27.0requires-python = ">=3.14")。
  • retrieve_and_generate APIboto3bedrock-agent-runtime クライアント): 検索(ベクトル検索)と生成(LLM回答生成)を1回のAPI呼び出しでAWS側に丸ごと任せるマネージドな方式。retrievalConfiguration にチャンク数・検索タイプ・フィルタ・リランキングを、generationConfiguration にガードレールを、orchestrationConfiguration にクエリ分解を設定できる(サンプルではいずれも空dict {} のプレースホルダーのままで、機能自体は有効化されていない)。
  • ②Strands retrieve ツールstrands_tools.retrieve): strands_tools/retrieve.py の実装を確認すると、内部では bedrock_agent_runtime_client.retrieve()retrieve_and_generateではなくretrieve単体API)を呼び、ベクトル検索結果のみを取得する(.venv/lib/python3.14/site-packages/strands_tools/retrieve.py:350-352)。回答生成はretrieveツールの外側、つまりAgent本体が使っているBedrockモデル(サンプルコードではBedrockModel未指定なのでStrandsのデフォルトモデル)が担う。①と②は「検索と生成を誰がやるか」が根本的に違う: ①はAWS側が両方やる、②はAWSが検索だけ・生成はStrands側のLLM呼び出し。
  • ナレッジベースIDは環境変数 KNOWLEDGE_BASE_ID から、リージョンは AWS_REGION から読む(retrieve.py:307-308)。AWS_REGION未指定時のデフォルトはus-west-2だが、サンプルコードはos.environ["AWS_REGION"] = "us-east-1"で明示上書きしている(02-retrieve-tool.py:7、書籍全体の統一リージョンに合わせる形)。
  • ③MCP経由strands.tools.mcp.MCPClient + mcp.stdio_client): awslabs.bedrock-kb-retrieval-mcp-server@latest という外部パッケージをuvxでその場ダウンロード・起動し、標準入出力(stdio)経由でMCPサーバーと通信する。このMCPサーバー自体のコードは本リポジトリに含まれない外部パッケージであり、内部実装は未確認(②のretrieve相当のAPIを叩いていると推測されるが断定はできない)。

ファイル別の役割

ファイル 役割
01-retrieve_and_generate.py 生のboto3 bedrock-agent-runtimeクライアントでretrieve_and_generateを1回呼ぶ。検索と生成をAWS側に一任するパターン
02-retrieve-tool.py Strands Agent + ビルトインツール strands_tools.retrieve。環境変数KNOWLEDGE_BASE_ID/AWS_REGIONでナレッジベースを指定し、Agent自身のLLMが検索結果をもとに回答生成
03-mcp-tool.py Strands Agent + MCPClient(stdio_client(StdioServerParameters(...)))uvxで外部MCPサーバーawslabs.bedrock-kb-retrieval-mcp-serverを都度起動し、MCP経由でナレッジベース検索
pyproject.toml 依存バージョン固定(本文「使用ライブラリ・原理」節参照)
README.md 本章が解説章であること、KBは書籍の別章(Gateway章)で構築済みのものを流用する前提であることを明記

中心コードの読み解き

3パターンの核心部分を並べて比較する。

①retrieve_and_generate(01-retrieve_and_generate.py:1-27)

client = boto3.client("bedrock-agent-runtime")
response = client.retrieve_and_generate(       # ①
    retrieveAndGenerateConfiguration={
        "knowledgeBaseConfiguration": {
            "knowledgeBaseId": "ナレッジベースID",
            "modelArn": "モデルARN",
            "retrievalConfiguration": {...},    # ②
            "generationConfiguration": {},      # ③
            "orchestrationConfiguration": {...},
        },
        "type": "KNOWLEDGE_BASE",
    },
    input={"text": prompt},
)

②Strands retrieveツール(02-retrieve-tool.py:1-14)

os.environ["KNOWLEDGE_BASE_ID"] = "ナレッジベースID"  # ④
os.environ["AWS_REGION"] = "us-east-1"

agent = Agent(
    tools=[retrieve],                          # ⑤
    system_prompt="社内規定を参照して正確に回答してください。"
)
agent("出張時の宿泊費の上限を教えて")

③MCP経由(03-mcp-tool.py:1-22)

mcp_client = MCPClient(
    lambda: stdio_client(
        StdioServerParameters(
            command="uvx",                     # ⑥
            args=["--with", "boto3[crt]==1.42.96",
                  "awslabs.bedrock-kb-retrieval-mcp-server@latest"],
            env={"AWS_REGION": "us-east-1", "FASTMCP_LOG_LEVEL": "ERROR"},
        )
    )
)
agent = Agent(tools=[mcp_client], system_prompt="...")
番号 やってること なぜ
01-retrieve_and_generate.py:6 検索+生成を1回のAPIで完結 AWS側にオーケストレーションを一任し、アプリ側のコードを最小化できる。反面、生成モデルの細かい制御(システムプロンプト等)はAPIの設定項目に縛られる
01-retrieve_and_generate.py:11-18 numberOfResults・検索タイプ・フィルタ・リランキングを一つの設定ブロックにまとめる ベクトル検索の挙動をリクエスト単位で細かく制御するための構成
01-retrieve_and_generate.py:19 generationConfiguration(ガードレール等)が空dict サンプルはあくまで最小構成の提示で、実運用ではガードレールIDなどを設定する箇所と読める(プレースホルダーのまま実行しても機能は有効化されない)
02-retrieve-tool.py:6-7 KNOWLEDGE_BASE_ID/AWS_REGIONを環境変数にセット strands_tools.retrieveがこれらの環境変数を読みに行く実装のため(retrieve.py:307-308で確認)。AWS_REGION未設定時のデフォルトはus-west-2だが明示上書きしている
02-retrieve-tool.py:9-11 tools=[retrieve]だけでAgentに検索能力を付与 Strandsのツール抽象化により、複雑なboto3呼び出しが1つのビルトインツールに隠蔽されている
03-mcp-tool.py:8-9 command="uvx"で外部MCPサーバーをその場取得・起動 ローカルにインストール済みでなくてもuvxが都度ダウンロード・実行してくれるため、依存関係の事前セットアップが不要になる(半面、毎回ネットワークアクセスが発生する)

学んだこと(要点)

  • 「検索」と「生成」の主体が誰かで3パターンが分かれる。①はAWSが両方、②・③はAWS(またはMCPサーバー)が検索だけを担当し生成はStrands側のAgentが担う。この違いは「回答の口調やロジックをどこまで自分のプロンプトで制御したいか」の設計判断に直結する。
  • 同じ検索能力でも「ツールとして直接呼ぶ(②)」と「MCP経由で呼ぶ(③)」の2通りがある。MCPを挟むと、検索ロジックが別プロセス・別パッケージ(awslabs.bedrock-kb-retrieval-mcp-server)としてAWS公式から配布される形になり、Strandsアプリ側のコード変更なしにMCPサーバー側だけをアップデートできる利点がある(と推測)。
  • retrieveツールの環境変数依存KNOWLEDGE_BASE_ID/AWS_REGION)は、コード上に明示的な引数として渡すのではなくグローバルな環境変数で暗黙的に設定される点に注意(ツール呼び出し時にknowledgeBaseId引数で上書きも可能、retrieve.pyのTOOL_SPEC参照)。

落とし穴・現代版に移植するなら

  • "ナレッジベースID" "モデルARN" の置換必須。プレースホルダーのまま実行するとAWS API側でバリデーションエラーになる(README.mdでも明記)。
  • 本章単独ではナレッジベースが作れない。第8章(Gateway)のハンズオンで構築したKBを流用する前提のため、第8章未実施だと実行できない。
  • ③はuvxで毎回外部MCPサーバーパッケージを取得・起動する。オフライン環境や厳格なサプライチェーン管理下では、@latest指定(バージョン固定なし)とネットワーク依存がリスクになる。本番移植時はバージョンピン留め(awslabs.bedrock-kb-retrieval-mcp-server==x.y.z)とプライベートミラー経由の配布を検討すべき。
  • README表と実装コードの不一致(Streamlit)は、読者・学習者が本文を鵜呑みにせずコードで裏取りする必要がある一例として記録しておく。
  • pyproject.tomlproject.name"handson"のままchapter14ではない)。uv init直後のテンプレート名が変更されずに残っていると推測され、実行には影響しないが命名の一貫性は崩れている。

記事参照

  • 書籍「Amazon Bedrock AgentCore実践入門」第14章。
  • 関連: ../../lectures/agentcore_basics/STUDY_NOTES.md(AgentCore全体像・第14章の位置づけ、Gateway章とのKB流用関係)
  • 関連: ~/ai-engineering-study/lectures/rag_vector_basics/(LangChain+Chromaでのベクトル RAG。マネージドKB版との対比)

作成: 2026-07-17 / 最終更新: 2026-07-17