AgentCore CLI で自作したAIエージェントを GenU に統合してみた

AgentCore CLI で自作したAIエージェントを GenU に統合してみた

2026.03.28

はじめに

こんにちは!AI 事業本部のこーすけです。

前回・前々回の記事では、GenU の AgentCore 機能の有効化と AgentBuilder を紹介しました。

https://dev.classmethod.jp/articles/genu-agentcore/
https://dev.classmethod.jp/articles/genu-agentcore-builder/

今回は、GenU の外部で独自のエージェントを作成し、GenU の UI に統合するところまでを紹介します。エージェントのデプロイには、新しくリリースされた AgentCore CLI を使います。

今回やること

  1. AgentCore CLI でエージェントプロジェクトを作成
  2. 天気予報ツールを実装
  3. ローカルで動作確認
  4. AWS にデプロイ
  5. GenU の agentCoreExternalRuntimes に ARN を追加して統合

完成すると、GenU のチャット UI から自作の天気予報エージェントを選択して使えるようになります。

AgentCore CLI とは

https://github.com/aws/agentcore-cli

AgentCore CLI は、Amazon Bedrock AgentCore 向けのターミナルツールです。まだ Public Preview ですが、エージェントの作成からデプロイまでを 4 つのコマンドで完結できます。

agentcore create   # プロジェクト作成
agentcore dev      # ローカル開発サーバー起動
agentcore deploy   # AWS へデプロイ
agentcore invoke   # デプロイ済みエージェントの実行

対応しているエージェントフレームワークは以下の通りです。

フレームワーク 対応モデル
Strands Agents Bedrock(Claude 等)
LangChain / LangGraph 各種
Google ADK Gemini
OpenAI Agents OpenAI

今回は個人的に使い慣れている Strands Agents + Bedrock を使います。

インストール

npm install -g @aws/agentcore

以下、今回使用した環境になります。

ツール バージョン
AgentCore CLI 0.3.0-preview.6.1
Node.js v22.12.0
Python 3.11.1
uv 0.7.19
AWS CLI 2.26.4

エージェントの作成

まずは、AgentCore CLI を使ってエージェントを作成します。

ステップ 1: プロジェクト作成

agentcore create を実行すると、対話形式でプロジェクトの設定を選択できます。

agentcore create

設定値は次のようにしました。

Name:       WeatherAgent
Language:   Python
Build:      Container
Protocol:   HTTP
Framework:  Strands
Model:      Bedrock (us.anthropic.claude-sonnet-4-5-20250514-v1:0)
Memory:     None
Network:    PUBLIC
  1. プロジェクト名:WeatherAgent
    スクリーンショット 2026-03-28 174406

  2. エージェントを追加するか:Yes
    スクリーンショット 2026-03-28 174419

  3. エージェント名:MyAgent
    スクリーンショット 2026-03-28 174451

  4. 新規エージェントを作成するか:作成する
    スクリーンショット 2026-03-28 174509

  5. Language:Python
    スクリーンショット 2026-03-28 174531

  6. Build:Container
    スクリーンショット 2026-03-28 174602

  7. Protocol:HTTP
    スクリーンショット 2026-03-28 174617

  8. Framework:Strands Agents SDK
    スクリーンショット 2026-03-28 174629

  9. Model:Bedrock   API Key が不要なため Bedrock が手軽です。
    スクリーンショット 2026-03-28 174646

  10. Memory:None
    スクリーンショット 2026-03-28 174707

  11. Network:PUBLIC
    スクリーンショット 2026-03-28 174718

最後に確認画面が出ます。
スクリーンショット 2026-03-28 174810

作成が完了したらプロジェクトディレクトリに移動します。

cd WeatherAgent

生成されるプロジェクト構造は以下の通りです。

WeatherAgent/
├── agentcore/
│   ├── agentcore.json      # リソース設定
│   ├── aws-targets.json    # デプロイ先設定
│   └── cdk/                # CDK インフラ(自動生成)
└── app/
    └── MyAgent/
        └── main.py         # エージェントのコード

デフォルトで生成されるエージェントのコードはこちらになります。

app/MyAgent/main.py
from strands import Agent, tool
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from model.load import load_model
from mcp_client.client import get_streamable_http_mcp_client
from memory.session import get_memory_session_manager

app = BedrockAgentCoreApp()
log = app.logger

# MCP クライアントの定義
mcp_clients = [get_streamable_http_mcp_client()]

# ツールの定義
tools = []

@tool
def add_numbers(a: int, b: int) -> int:
    """Return the sum of two numbers"""
    return a+b
tools.append(add_numbers)

for mcp_client in mcp_clients:
    if mcp_client:
        tools.append(mcp_client)

def agent_factory():
    cache = {}
    def get_or_create_agent(session_id, user_id):
        key = f"{session_id}/{user_id}"
        if key not in cache:
            cache[key] = Agent(
                model=load_model(),
                session_manager=get_memory_session_manager(session_id, user_id),
                system_prompt="You are a helpful assistant. Use tools when appropriate.",
                tools=tools
            )
        return cache[key]
    return get_or_create_agent
get_or_create_agent = agent_factory()

@app.entrypoint
async def invoke(payload, context):
    log.info("Invoking Agent.....")
    session_id = getattr(context, 'session_id', 'default-session')
    user_id = getattr(context, 'user_id', 'default-user')
    agent = get_or_create_agent(session_id, user_id)

    stream = agent.stream_async(payload.get("prompt"))
    async for event in stream:
        if "data" in event and isinstance(event["data"], str):
            yield event["data"]

if __name__ == "__main__":
    app.run()

ステップ 2: 天気予報ツールの実装

app/MyAgent/main.py を編集して、天気予報ツールを追加します。

天気予報を取得するための API には Open-Meteo API を使用しました。Open-Meteo API はオープンソースの API であり、無料で API キーも不要なのでデモに最適でした。

https://open-meteo.com/

変更のポイントは以下の 3 点です。

  1. 天気予報ツールの追加: @tool デコレータで get_weather を定義し、Open-Meteo API から天気情報を取得する。
  2. 会話履歴の引き継ぎ: GenU のフロントエンドは毎回の会話履歴を messages として送信してくるため、Agent(messages=messages) で渡して会話を継続できるようにする。(ただし今回はテキストデータのみ抽出しているので画像や添付ファイルには対応していません。)
  3. 出力形式を GenU に合わせる: ストリーミングの部分は GenU 側が期待する出力形式になるように合わせる。(GenU 側の Agent のコードは generative-ai-use-cases-jp/packages/cdk/lambda-python/generic-agent-core-runtime/src/agent.py に記述されているのでここの実装に合わせました。)
app/MyAgent/main.py
import json
import urllib.request

from strands import Agent, tool
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from model.load import load_model

app = BedrockAgentCoreApp()
log = app.logger

@tool
def get_weather(city: str) -> str:
    """指定された都市の現在の天気を取得します。

    Args:
        city: 天気を取得したい都市名(例: Tokyo, New York, London)
    """
    # 都市名から緯度経度を取得(Open-Meteo Geocoding API)
    geo_url = f"https://geocoding-api.open-meteo.com/v1/search?name={city}&count=1&language=ja"
    with urllib.request.urlopen(geo_url) as response:
        geo_data = json.loads(response.read())

    if "results" not in geo_data:
        return f"都市 '{city}' が見つかりませんでした。"

    location = geo_data["results"][0]
    lat = location["latitude"]
    lon = location["longitude"]
    name = location.get("name", city)

    # 天気情報を取得(Open-Meteo Weather API)
    weather_url = (
        f"https://api.open-meteo.com/v1/forecast?"
        f"latitude={lat}&longitude={lon}"
        f"&current=temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m"
        f"&timezone=Asia/Tokyo"
    )
    with urllib.request.urlopen(weather_url) as response:
        weather_data = json.loads(response.read())

    current = weather_data["current"]
    return (
        f"{name} の現在の天気\n"
        f"気温: {current['temperature_2m']}°C\n"
        f"湿度: {current['relative_humidity_2m']}%\n"
        f"風速: {current['wind_speed_10m']} km/h"
    )

def process_prompt(prompt):
    """GenU が送る prompt(ContentBlock 配列)からテキストを抽出する。"""
    if isinstance(prompt, str):
        return prompt
    if isinstance(prompt, list):
        texts = [block["text"] for block in prompt if isinstance(block, dict) and "text" in block]
        return "\n".join(texts) if texts else ""
    return str(prompt)

@app.entrypoint
async def invoke(payload):
    log.info("Invoking Agent.....")

    # GenUのフロントエンドが送るペイロードから会話履歴と現在の入力を取得
    messages = payload.get("messages", [])
    prompt = process_prompt(payload.get("prompt", ""))

    agent = Agent(
        model=load_model(),
        system_prompt="あなたは天気予報アシスタントです。ユーザーが都市名を伝えると、現在の天気を取得して日本語で回答します。",
        tools=[get_weather],
        messages=messages,
    )
    # GenUのフロントエンドにレスポンス形式を合わせる
    async for event in agent.stream_async(prompt):
        if "event" in event:
            yield event

if __name__ == "__main__":
    app.run()

ステップ 3: ローカルテスト

続いて、ローカルサーバを立ち上げテストをしてみます。事前にデプロイ予定の環境にスイッチロールしてからコマンドを実行してください。

agentcore dev

対話できるウィンドが立ち上がるので、試しに今日の東京の天気を聞いてみましょう。
スクリーンショット 2026-03-28 185619

追加したget_weatherを使いバッチリ回答してくれています!
スクリーンショット 2026-03-28 212146

AWS へデプロイ

ローカルでの動作確認ができたのでAWSにデプロイします。

ステップ 4: デプロイ

agentcore deploy

およそ5分くらいでデプロイが完了しました。
スクリーンショット 2026-03-28 201916

続いて、ステータスを確認します。

agentcore status

スクリーンショット 2026-03-28 202313

作成された Runtime ARNが表示されます。こちらは GenU に統合する際に必要になるので控えておきましょう。

arn:aws:bedrock-agentcore:ap-northeast-1:123456789012:runtime/xxxxxxxx

ここで一つ注意点があります。レスポンス形式を変更したため、agentcore invoke のレスポンス結果は空になります。実際のエージェントは正常に動作しており、GenU のフロントエンドから呼び出せば正しくレスポンスが表示されます。

そのため、以下のコマンドでの動作検証はうまくいきません。

agentcore invoke "今日の大阪の天気を教えてください" --agent MyAgent

GenU に統合する

続いて、GenU の修正に移ります。

ステップ 5: parameter.ts の編集

GenU の packages/cdk/parameter.ts に、デプロイした Runtime の ARN を agentCoreExternalRuntimes として追加します。

const envs: Record<string, Partial<StackInput>> = {
  myenv: {
    modelRegion: "us-east-1",
    createGenericAgentCoreRuntime: true,
    agentBuilderEnabled: true,
    agentCoreExternalRuntimes: [
      {
        name: 'WeatherAgent',
        arn: 'arn:aws:bedrock-agentcore:ap-northeast-1:123456789012:runtime/xxxxxxxx',
        description: 'This is WeatherAgent.',
      },
    ],
  },
};

ステップ 6: GenU を再デプロイ

npm run cdk:deploy

ステップ 7: 動作確認

GenU の AgentCore ページを開くと、ランタイム選択のドロップダウンに WeatherAgent が追加されています。

スクリーンショット 2026-03-28 210719

「東京の天気を教えてください」と送信すると、天気予報エージェントが Open-Meteo API を呼び出して回答してくれます。
トレースを開くと、get_weather ツールが呼び出されていることが確認できます。さらに会話の履歴も加味した回答をしてくれていることが確認できますね。

スクリーンショット 2026-03-28 214751

おわりに

AgentCore CLI を使うと、CDK やインフラのコードを一切書かずに、わずか数コマンドでエージェントを AWS にデプロイできました。GenU との統合も agentCoreExternalRuntimes に ARN を追加するだけなので非常に手軽ですね。

3回にわたって GenU の AgentCore 周りを紹介しましたが、まとめると以下のような使い分けになるかと思います。

やりたいこと 方法
エージェントをすぐ使いたい createGenericAgentCoreRuntime: true
UI からノーコードでエージェントを作りたい agentBuilderEnabled: true
独自ロジックのエージェントを統合したい agentCoreExternalRuntimes

GenUでも独自エージェントの実装に集中できる環境が整ってきていると感じます。

この記事をシェアする

FacebookHatena blogX

関連記事