AgentCore Gateway にツールを束ねて Managed Harness から使ってみた

AgentCore Gateway にツールを束ねて Managed Harness から使ってみた

AgentCore の Managed Harness でサクッとエージェントを作れるのは便利ですが、RAG などのツール準備が手間ですよね。今回は、ナレッジベース検索・Web ページ取得・AWS ドキュメント検索の3つのツールを Gateway に束ねて、CDK でデプロイするだけで誰でも使えるキットを作ってみました。
2026.05.18

はじめに

こんにちは、恋愛リアリティーショーも大好きなコンサル部の神野です。

AgentCore の Managed Harness、コードを書かずにサクッとエージェントが作れるのはめちゃくちゃ便利ですよね。 みなさん使っていますか?

https://dev.classmethod.jp/articles/bedrock-agentcore-managed-harness-preview/

私も使ってみたのですが、ツール側の準備は自分でやる必要があります。特にRAGとか作りたいのに自前で毎度作るのは手間だな・・・と感じました。Bedrock Agentsみたくお手軽にできたらなと思う今日この頃です。

そこで今回は簡単にHarness 利用者が RAGなどを使えるように、AgentCore Gateway にナレッジベース検索・Web ページ取得・AWS ドキュメント検索の3つのツールを束ねて、CDK でデプロイしておけば誰でも Managed Harness から繋いで使える、というコンセプトのツールキットを作ってみました。

Gateway 1つ繋ぐだけで3つのツールが全部使えるようになるので、利用者側の手間がかなり少なくて済みますね。

今回のコードは下記リポジトリで公開しています。記事中ではポイントを抜粋して解説していますが、全体像はこちらを参照ください。

https://github.com/yuu551/agentcore-gateway-kit

AgentCore Gateway

本題に入る前に、Gateway の役割を軽く整理しておきます。

Gateway は既存の API や Lambda 関数、MCP Server などを束ねて、エージェントから統一的に呼び出せるようにするハブです。

Gatewayの概要

Gateway を使わなくても Runtime から Lambda や MCP Server を直接呼び出すことはできます。ただ、組織内に Lambda や MCP Server がたくさんある場合、個別にエージェントへ紐づけるのは管理が大変ですよね。

Gatewayを使う場合と使わない場合の比較

Gateway に集約しておけば、エージェント側は Gateway 1つを接続するだけで裏にある全ツールにアクセスできます。ツールの追加や変更があってもエージェント側のコードを変える必要がないのもメリットです。

今回のようにインフラ提供者が Gateway を CDK でデプロイしておけば、利用者は Managed Harness のコンソールから Gateway を追加するだけ。ツールの中身を意識する必要がないのがポイントです。

Gateway の詳細やプロダクション運用のTipsについては、下記記事で解説しています!

https://dev.classmethod.jp/articles/amazon-bedrock-agentcore-production-tips-ai-builders-day-2025/

アーキテクチャ

全体像はこんな感じです。

architecture

複数のユーザーがそれぞれ Managed Harness で AI エージェントを作成し、Gateway 経由で RAG などのツールにアクセスする構成です。ツール開発者は CDK で一度デプロイしておくだけで、利用者側は Gateway を繋ぐだけでツールが使えるようになります。

Gateway に3つの Target を登録しています。

Target ツール名 説明 実装方式
kb-retrieve retrieve_documents ナレッジベースからドキュメント検索 Lambda
web-tools fetch_webpage Web ページのテキスト取得 FastMCP on AgentCore Runtime
aws-knowledge search_documentation 他 AWS 公式ドキュメント検索 AWS ホスト済み MCP Server

Target の実装方式をあえて3種類にしています。Lambda ターゲット / MCP Server on Runtime / 外部 MCP Server、それぞれ CDK でどう書くのかを一通り試したかったのが理由です。

前提

  • AWS CDK v2.254.0
  • @aws-cdk/aws-bedrock-agentcore-alpha v2.254.0-alpha.0
  • Node.js 22+(検証は v25.9.0)
  • Docker(Runtime のコンテナビルドに必要)
  • デプロイリージョン: us-east-1

プロジェクト構成

agentcore-gateway-kit/
├── bin/
│   └── app.ts                     # CDK エントリーポイント
├── lib/
│   ├── knowledge-base-stack.ts    # Stack 1: KB + S3 Vectors
│   └── rag-gateway-stack.ts       # Stack 2: Gateway + Lambda + Runtime
├── lambda/
│   └── kb-retrieve/
│       └── index.py               # KB Retrieve Lambda
├── mcp-server/
│   ├── server.py                  # FastMCP Web Tools
│   ├── requirements.txt
│   └── Dockerfile
├── sample-data/
│   └── sample.txt
├── cdk.json
├── package.json
└── tsconfig.json

2スタック構成にしています。Knowledge Base と Gateway を分けることで、Knowledge Base は残しつつ Gateway 側だけ差し替える、といった運用ができます。

実装のポイント

コード全体はリポジトリを参照いただくとして、ここでは CDK で Gateway + 各 Target を組む際のポイントに絞って解説していきます。

Knowledge Base スタック

ベクトルストアに S3 Vectors を使っています。OpenSearch Serverless と違って追加のインフラが不要で、検証用途ならお安くて扱いやすいです。

S3 Vectors は CDK の L1 構成(CfnVectorBucket / CfnIndex)で定義します。

lib/knowledge-base-stack.ts
const vectorBucket = new s3vectors.CfnVectorBucket(this, 'VectorBucket', {
  vectorBucketName,
});

const vectorIndex = new s3vectors.CfnIndex(this, 'VectorIndex', {
  vectorBucketName,
  indexName: 'rag-gateway-index',
  dimension: VECTOR_DIMENSION,
  distanceMetric: 'cosine',
  dataType: 'float32',
});
vectorIndex.addDependency(vectorBucket);

Knowledge Base の storageConfiguration で S3_VECTORS を指定して紐づけます。

lib/knowledge-base-stack.ts
const knowledgeBase = new bedrock.CfnKnowledgeBase(this, 'KnowledgeBase', {
  name: 'RagGatewayKnowledgeBase',
  roleArn: kbRole.roleArn,
  knowledgeBaseConfiguration: {
    type: 'VECTOR',
    vectorKnowledgeBaseConfiguration: {
      embeddingModelArn: `arn:aws:bedrock:${cdk.Aws.REGION}::foundation-model/${EMBEDDING_MODEL_ID}`,
    },
  },
  storageConfiguration: {
    type: 'S3_VECTORS',
    s3VectorsConfiguration: {
      vectorBucketArn: vectorBucket.attrVectorBucketArn,
      indexName: vectorIndex.indexName!,
    },
  },
});

Embedding モデルは Amazon Titan Embed Text V2(1024次元)を使用しています。

Gateway の作成

lib/rag-gateway-stack.ts
const gateway = new agentcore.Gateway(this, 'RagGateway', {
  gatewayName: 'rag-gateway-kit',
  description: 'RAG Gateway Kit: KB Retrieve + Web Fetch + AWS Knowledge',
  authorizerConfiguration: agentcore.GatewayAuthorizer.usingAwsIam(),
});

@aws-cdk/aws-bedrock-agentcore-alpha の L2 構成を使っています。L2 のデフォルトは Cognito 認証ですが、Managed Harness は IAM で接続するため Cognito だとエラーになります。GatewayAuthorizer.usingAwsIam() で明示的に IAM を指定しています。

Lambda ターゲット(Knowledge Base Retrieve)

Lambda ターゲットは L2 の addLambdaTarget で追加できます。

lib/rag-gateway-stack.ts
gateway.addLambdaTarget('KBRetrieveTarget', {
  gatewayTargetName: 'kb-retrieve',
  lambdaFunction: kbRetrieveFn,
  toolSchema: agentcore.ToolSchema.fromInline([
    {
      name: 'retrieve_documents',
      description: 'ナレッジベースからドキュメントを検索します。',
      inputSchema: {
        type: agentcore.SchemaDefinitionType.OBJECT,
        properties: {
          query: { type: agentcore.SchemaDefinitionType.STRING, description: '検索クエリ' },
          maxResults: { type: agentcore.SchemaDefinitionType.INTEGER, description: '最大取得件数' },
        },
        required: ['query'],
      },
    },
  ]),
});

ToolSchema.fromInline でツールの入力スキーマを定義しています。型の指定には SchemaDefinitionType の enum を使う必要があり、文字列リテラル("object" など)だとコンパイルエラーになる点に注意です。

Lambda 側の処理はこんな感じです。

lambda/kb-retrieve/index.py
def handler(event, context):
    query = event.get('query', '')
    kb_id = event.get('knowledgeBaseId', KNOWLEDGE_BASE_ID)
    max_results = min(event.get('maxResults', 5), 100)

    response = client.retrieve(
        knowledgeBaseId=kb_id,
        retrievalQuery={'text': query},
        retrievalConfiguration={
            'vectorSearchConfiguration': { 'numberOfResults': max_results }
        },
    )

    results = []
    for r in response.get('retrievalResults', []):
        results.append({
            'content': r['content'].get('text', ''),
            'score': r.get('score'),
            'location': r.get('location', {}),
        })

    return { 'results': results, 'count': len(results) }

Bedrock の Retrieve API を呼んで検索結果を返すだけのシンプルな実装です。RetrieveAndGenerate ではなく Retrieve を使っているのは、Managed Harness 側のモデルに回答を生成させるためです。

MCP Server on Runtime(Web ページ取得)

AgentCore Runtime 上で動く FastMCP サーバーを Gateway Target として登録します。

MCP Server のコードです。

mcp-server/server.py
mcp = FastMCP("web-tools", host="0.0.0.0", stateless_http=True)

@mcp.tool()
def fetch_webpage(url: str, max_length: int = 5000) -> str:
    """Fetch a web page and return its text content."""
    response = httpx.get(url, follow_redirects=True, timeout=30, headers={
        'User-Agent': 'AgentCore-WebTools/1.0',
    })
    response.raise_for_status()

    html = response.text
    text = re.sub(r'<script[^>]*>.*?</script>', '', html, flags=re.DOTALL)
    text = re.sub(r'<style[^>]*>.*?</style>', '', text, flags=re.DOTALL)
    text = re.sub(r'<[^>]+>', ' ', text)
    text = re.sub(r'\s+', ' ', text).strip()

    return text[:max_length]

FastMCP のデコレータでツールを定義しています。HTML タグを除去してテキストだけ返すシンプルな処理です。

CDK 側では、L2 の AgentRuntimeArtifact.fromAsset で Dockerfile のビルドから ECR プッシュまで自動でやってくれます。

lib/rag-gateway-stack.ts
const runtimeEndpointUrl = cdk.Fn.sub(
  'https://bedrock-agentcore.${AWS::Region}.amazonaws.com/runtimes/arn%3Aaws%3Abedrock-agentcore%3A${AWS::Region}%3A${AWS::AccountId}%3Aruntime%2F${RuntimeId}/invocations',
  { RuntimeId: webToolsRuntime.agentRuntimeId },
);

const webToolsTarget = new bedrockagentcore.CfnGatewayTarget(this, 'WebToolsTarget', {
  gatewayIdentifier: gateway.gatewayId,
  name: 'web-tools',
  targetConfiguration: {
    mcp: {
      mcpServer: { endpoint: runtimeEndpointUrl },
    },
  },
  credentialProviderConfigurations: [{
    credentialProviderType: 'GATEWAY_IAM_ROLE',
    credentialProvider: {
      iamCredentialProvider: { service: 'bedrock-agentcore' },
    },
  }],
});

エンドポイント URL は Runtime ARN を URL エンコードして埋め込む形式です。

MCP Server ターゲットの credentialProviderConfigurations で iamCredentialProvider のサブプロパティ(service)を指定する必要があります。L2 の GatewayCredentialProvider.fromIamRole() はこのサブプロパティを出力しないため、MCP Server ターゲットでは L1(CfnGatewayTarget)を使用します。Lambda ターゲットの場合は L2 で問題ありません。

もう1つ重要なのが依存関係です。

lib/rag-gateway-stack.ts
webToolsTarget.addDependency(
  webToolsRuntime.node.defaultChild as cdk.CfnResource,
);
const gatewayDefaultPolicy = gateway.role.node.findChild('DefaultPolicy').node.defaultChild as cdk.CfnResource;
webToolsTarget.addDependency(gatewayDefaultPolicy);

Gateway Target の作成時に、Gateway はエンドポイントに接続してツール一覧を取得しようとします。このとき Runtime が READY 状態でないと失敗しますし、Gateway ロールに InvokeAgentRuntime 権限がないと接続自体ができません。両方の依存を明示的に追加しています。

AWS Knowledge MCP Server

AWS が公式でホストしている MCP Server です。エンドポイント URL を指定するだけで使えます。

https://awslabs.github.io/mcp/servers/aws-knowledge-mcp-server

lib/rag-gateway-stack.ts
new bedrockagentcore.CfnGatewayTarget(this, 'AWSKnowledgeTarget', {
  gatewayIdentifier: gateway.gatewayId,
  name: 'aws-knowledge',
  targetConfiguration: {
    mcp: {
      mcpServer: { endpoint: 'https://knowledge-mcp.global.api.aws' },
    },
  },
});

認証不要のパブリックエンドポイントなので、credentialProviderConfigurations は省略しています。search_documentation / read_documentation / recommend / list_regions / get_regional_availability / retrieve_skill の6つのツールが自動で Gateway に登録されます。

Gateway にツールを追加するには

Gateway の良いところは、ターゲットを追加するだけで新しいツールを足せることです。ここでは Lambda ターゲットと MCP Server ターゲットの追加例を紹介します。

Lambda ツールの追加

L2 の addLambdaTarget で追加できます。

lib/rag-gateway-stack.ts
gateway.addLambdaTarget('MyNewTarget', {
  gatewayTargetName: 'my-tool',
  lambdaFunction: myFunction,
  toolSchema: agentcore.ToolSchema.fromInline([{
    name: 'my_tool',
    description: 'ツールの説明',
    inputSchema: {
      type: agentcore.SchemaDefinitionType.OBJECT,
      properties: { /* ... */ },
    },
  }]),
});

Lambda ターゲットは L2 だけで完結するのでシンプルですね。

MCP Server ターゲットの追加

前述の通り、MCP Server ターゲットは L1(CfnGatewayTarget)を使います。

lib/rag-gateway-stack.ts
new bedrockagentcore.CfnGatewayTarget(this, 'MyMcpTarget', {
  gatewayIdentifier: gateway.gatewayId,
  name: 'my-mcp-server',
  targetConfiguration: {
    mcp: {
      mcpServer: {
        endpoint: 'https://your-mcp-server.example.com',
      },
    },
  },
  credentialProviderConfigurations: [{
    credentialProviderType: 'GATEWAY_IAM_ROLE',
    credentialProvider: {
      iamCredentialProvider: {
        service: 'bedrock-agentcore',
      },
    },
  }],
});

service の値は接続先によって変わります。AgentCore Runtime 上の MCP Server なら bedrock-agentcoreを指定します。

Target を追加して cdk deploy するだけで、既存の Managed Harness から新しいツールがすぐ使えるようになります。エージェント側を触る必要がないのは運用として嬉しいですね。

今回はシンプルにスタック内で直接書いていますが、Target の種類ごとにヘルパー関数や Construct を作っておくと、ツールが増えたときにもっと楽に管理できそうです。

デプロイ

実行コマンド
npm install
npx cdk deploy --all

デプロイすると、sample-data 配下の AgentCore に関するサンプルドキュメントが S3 バケットに自動アップロードされます。ただし、S3 にファイルが置かれただけでは Knowledge Base には反映されません。コンソールまたは CLI から同期を実行する必要があります。

コンソールの場合は、Knowledge Base の画面から DataSource を選択して「Sync」ボタンを押します。

kb-sync

CLI の場合は下記コマンドです。KnowledgeBaseId と DataSourceId は CDK の Output から取得できます。

実行コマンド
aws bedrock-agent start-ingestion-job \
  --knowledge-base-id <KnowledgeBaseId> \
  --data-source-id <DataSourceId>

自分のドキュメントを検索対象にしたい場合は、sample-data 配下にドキュメントを追加してcdk deployを実施するか、S3 バケットにアップロードしてから同期を実行してください。

実行コマンド
aws s3 cp my-document.txt s3://<DataSourceBucketName>/

aws bedrock-agent start-ingestion-job \
  --knowledge-base-id <KnowledgeBaseId> \
  --data-source-id <DataSourceId>

動作確認

デプロイが完了したら、コンソールから Managed Harness を作成して動作確認してみます!

Managed Harness の作成

AWS コンソール → Bedrock → AgentCore → Managed Harness を開きます。
Advanced create harness から新規作成します。

harness-list

Tools セクションで Gateway を有効にし、デプロイした rag-gateway-kit を選択します。Gateway を1つ追加するだけで、3つの Target に含まれる全ツールが利用可能になります。

harness-create

簡単に作れましたね。

作成が完了すると Status が Ready になります。「Test harness」から動作確認していきましょう。

harness-detail

Knowledge Base 検索(retrieve_documents)の確認

まずはナレッジベースの検索から試してみます。「AgentCore について RAG で検索して」と投げてみました。

test-kb-search

ナレッジベースから情報を取得して回答が生成されていますね!Gateway Kit の活用シナリオまで表にまとめてくれています。

Web ページ取得(fetch_webpage)の確認

次に Web ページの取得です。DevelopersIO の記事 URL を渡して内容を聞いてみます。

test-web-fetch

URL の内容を取得して、記事の概要・使用環境・検証結果まで構造化して返してくれていますね!

AWS ドキュメント検索(search_documentation 他)の確認

最後に AWS の公式ドキュメント検索です。「S3 について教えて」と投げてみます。

test-aws-knowledge

AWS Knowledge MCP Server 経由で公式ドキュメントの情報を取得して、S3 の基本概念からストレージクラス、最新アップデートまでまとめてくれました。ツール呼び出しの詳細を開くと、search_documentation が実行されているのが確認できます。

test-aws-knowledge-tool

3つのツールすべてが Gateway 経由で問題なく動作していることが確認できました!

おわりに

Gateway に複数のツールを束ねて Managed Harness から使えるようにする、という構成を CDK で作成してみました。Lambda ターゲット / MCP Server on Runtime / 外部 MCP Server の3パターンを1つの Gateway に集約して多数のHarnessから手軽に利用できるのは良いですね。

Gateway に Target を追加するだけで新しいツールを足せるのも嬉しいポイントです。Harness利用者から多くニーズがあった機能はGatewayに追加するなども考えられそうです!(例えば、Braveを使ったWeb検索機能とか)

本記事が少しでも参考になりましたら幸いです。最後までご覧いただきありがとうございました!

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事