Skip to content

Story エージェントの実装と設定

タスク1: ストーリーエージェントの実装

Section titled “タスク1: ストーリーエージェントの実装”

ストーリーエージェントはStrandsのエージェントで、GameActionのリストをコンテキストとして物語を進行します。インベントリMCPサーバーと連携してプレイヤーの所持アイテムを管理するよう設定します。

エージェントを実装するには、packages/story/dungeon_adventure_story/agent配下のファイルを更新します:

import uuid
import uvicorn
from bedrock_agentcore.runtime.models import PingStatus
from fastapi.responses import PlainTextResponse, StreamingResponse
from pydantic import BaseModel
from .agent import get_agent
from .init import app
class Action(BaseModel):
role: str
content: str
class InvokeInput(BaseModel):
playerName: str
genre: str
actions: list[Action]
async def handle_invoke(input: InvokeInput):
"""Streaming handler for agent invocation"""
messages = [{"role": "user", "content": [{"text": "Continue or create a new story..."}]}]
for action in input.actions:
messages.append({"role": action.role, "content": [{"text": action.content}]})
with get_agent(input.playerName, input.genre, session_id=str(uuid.uuid4())) as agent:
stream = agent.stream_async(messages)
async for event in stream:
print(event)
content = event.get("event", {}).get("contentBlockDelta", {}).get("delta", {}).get("text")
if content is not None:
yield content
elif event.get("event", {}).get("messageStop") is not None:
yield "\n"
@app.post("/invocations", openapi_extra={"x-streaming": True}, response_class=PlainTextResponse)
async def invoke(input: InvokeInput) -> str:
"""Entry point for agent invocation"""
return StreamingResponse(handle_invoke(input), media_type="text/event-stream")
@app.get("/ping")
def ping() -> str:
# TODO: if running an async task, return PingStatus.HEALTHY_BUSY
return PingStatus.HEALTHY
if __name__ == "__main__":
uvicorn.run("dungeon_adventure_story.agent.main:app", port=8080)

この実装では以下を構成します:

  • エージェントペイロードからプレイヤー情報、ジャンル、アクションを抽出、
  • SigV4認証でMCPサーバーを呼び出すためのクライアントの構築、および
  • システムプロンプトとMCPサーバーツールを備えたエージェントの作成。

コードをビルドするには:

Terminal window
pnpm nx run-many --target build --all

アプリケーションをデプロイするには、以下のコマンドを実行します:

Terminal window
pnpm nx deploy infra dungeon-adventure-infra-sandbox/*

デプロイは約2分で完了します。

デプロイが完了すると、以下のような出力が表示されます(一部の値は編集済み):

Terminal window
dungeon-adventure-infra-sandbox-Application
dungeon-adventure-infra-sandbox-Application: deploying... [2/2]
dungeon-adventure-infra-sandbox-Application
Deployment time: 354s
Outputs:
dungeon-adventure-infra-sandbox-Application.ElectroDbTableTableNameXXX = dungeon-adventure-infra-sandbox-Application-ElectroDbTableXXX-YYY
dungeon-adventure-infra-sandbox-Application.GameApiEndpointXXX = https://xxx.execute-api.region.amazonaws.com/prod/
dungeon-adventure-infra-sandbox-Application.GameUIDistributionDomainNameXXX = xxx.cloudfront.net
dungeon-adventure-infra-sandbox-Application.InventoryMcpArn = arn:aws:bedrock-agentcore:region:xxxxxxx:runtime/dungeonadventureventoryMcpServerXXXX-YYYY
dungeon-adventure-infra-sandbox-Application.StoryAgentArn = arn:aws:bedrock-agentcore:region:xxxxxxx:runtime/dungeonadventurecationStoryAgentXXXX-YYYY
dungeon-adventure-infra-sandbox-Application.UserIdentityUserIdentityIdentityPoolIdXXX = region:xxx
dungeon-adventure-infra-sandbox-Application.UserIdentityUserIdentityUserPoolIdXXX = region_xxx

APIのテスト方法は2通りあります:

  • エージェントサーバーをローカルで起動しcurlで呼び出す、または
  • デプロイ済みAPIをJWTトークン付きのcurlで呼び出す。

以下のコマンドでローカルエージェントサーバーを起動します:

Terminal window
INVENTORY_MCP_ARN=arn:aws:bedrock-agentcore:region:xxxxxxx:runtime/dungeonadventureventoryMcpServerXXXX-YYYY AWS_REGION=<region> pnpm nx run dungeon_adventure.story:agent-serve

エージェントサーバー起動後(出力は表示されません)、以下のコマンドで呼び出します:

Terminal window
curl -N -X POST http://127.0.0.1:8081/invocations \
-d '{"genre":"superhero", "actions":[], "playerName":"UnnamedHero"}' \
-H "Content-Type: application/json"

コマンドが正常に実行されると、以下のようなストリーミングイベントが表示されます:

data: {"init_event_loop": true}
data: {"start": true}
data: {"start_event_loop": true}
data: {"event": {"messageStart": {"role": "assistant"}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "Welcome"}, "contentBlockIndex": 0}}}
...

おめでとうございます。Bedrock AgentCore Runtime上に初めてのStrandsエージェントを構築・デプロイできました! 🎉🎉🎉