今年は「AIエージェントをどう作るか」をたくさん考えてきました。
2026年は「どんなAIエージェントを作るか」を頑張っていきます
みなさんが大好きなClaude CodeをAIエージェントとして利用できるライブラリーが「Claude Agent SDK」です。
2025/9/30のClaude 4.5 Sonnetの発表時に一般提供開始のアナウンスがありました。その後もガンガンアップデートがあり、MCPやAgent Skills、セッション管理など、機能もかなり充実してきました。
Claude Agent SDKとClaude Codeで作ったAIエージェントを、Amazon Bedrock AgentCoreのRuntimeにホスティングすることで、拡張性の高いAIエージェントが構築できた気がするので、紹介します。
■簡単な構成
Claude Agent SDKはこんな感じ
Claude Agent SDKは、Python版とTypeScript版が提供されています。(本日時点で、TypeScript版はV2が開発中のようです)
前提としてClaude Codeをインストールしておく必要があります。
今回はPython版を使用します。ライブラリーをインストールします。
uv add claude-agent-sdk
シンプルなコードはこんな感じです。
import asyncio
from claude_agent_sdk import query
async def main():
prompt = "こんにちは"
async for message in query(prompt=prompt):
print(message)
if __name__ == "__main__":
asyncio.run(main())
SystemMessage(subtype='init', data={'type': 'system', 'subtype': 'init', 'cwd': '/workspaces/workspace/1224_claude-agent_agentcore/qiita/claude-agent', 'session_id': '2f147c74-0488-471c-a0f7-c9a913b649ee', 'tools': ['Task', 'TaskOutput', 'Bash', 'Glob', 'Grep', 'ExitPlanMode', 'Read', 'Edit', 'Write', 'NotebookEdit', 'WebFetch', 'TodoWrite', 'KillShell', 'AskUserQuestion', 'Skill', 'SlashCommand', 'EnterPlanMode'], 'mcp_servers': [], 'model': 'us.anthropic.claude-sonnet-4-5-20250929-v1:0', 'permissionMode': 'default', 'slash_commands': ['compact', 'context', 'cost', 'init', 'pr-comments', 'release-notes', 'review', 'security-review'], 'apiKeySource': 'none', 'claude_code_version': '2.0.72', 'output_style': 'default', 'agents': ['general-purpose', 'statusline-setup', 'Explore', 'Plan'], 'skills': [], 'plugins': [], 'uuid': 'e53ebe8e-2a02-48d7-8316-613e51a3fb2a'})
AssistantMessage(content=[ThinkingBlock(thinking='The user has greeted me in Japanese with "こんにちは" which means "Hello" or "Good afternoon/day". This is a simple greeting, so I should respond in a friendly and welcoming manner. \n\nLooking at the available tools, I don\'t see a "greeting-responder" agent or any specific tool for handling greetings. This is just a conversational greeting that doesn\'t require any tools - I should simply respond naturally in a friendly way.\n\nI can respond in Japanese to match their language choice, and also let them know I\'m here to help with any coding or technical tasks they might have.', signature='EvEFCkgICxABGAIqQA2Xr9ZRAdiEGEj5jjZqEUoT0v3XAEiGQ2KryjNdS72uch/AMvJU+KZjWRHSyLlF22YuXg4flPqDt9pTk1fXVMISDG29n/vDNTkZuAdt4RoM5ScgC8sNDBnCMs/TIjClz9w50dq+k6v66gSvdFRX+c4osiPuZwetxHIpJX/KJf6BZXO7++eEF1SafJ3AqA8q1gRYa02qVSex7turJKSt+ft0JZPV9V28/icz/FGZK+gRGB5s+TagOCkHgIuv6OgeMrcmEMYBzZz9kXeO1u4hPFBhLjpWI5n5whAVaeXouTxXO9J4XiuPgJf17aO0eQF/JRC6iTrocwD3Kblh0x15+im01CSmN1pIl/vkwYQQ/CVSpETTRcnfFZZJJG/eq77B3AP272psLtiNkEJR4sbPdJBwluYVbBfyKN3yACd6LclVsH51mkyqyAcZzpjxsoqFSMPuUlC1UI5cFkOUIATFZXKpT6N/2ZGcDPHogxKQtYs1JE+ecu4Pqw2kx3X/j6rAA1wLOPBTR+vkwNbKehRkcWi9lVUhNqmPhaDbuXpc0xB6XAlzeq1DhH7FPIuXWfdUaBbK8CPlvMNksHj41ZghK0y1oT7XK1UFD8g3ALTbsfxbhrsSmZRS3HwW376Qg0KvgOEfMDPP/7DSYEbSdgeJOKHiemyz2ykCqm9JzbDkk5N1L1eBrppbwvaFbtnRV0uIWROq4QJ7NUEseivyrCcU9SFk/huPyC529lOXPscaxukzWNhU1NU43EIEMx6ctfdc2S9AJXh0ZdXErb1RMnO4YPsg+d2T8HR+ytIQroGCLQ1kUWilzD5qiQffmgEHiyPH1xsxHqAiEdI0esDpOeBDKOhd4fySrsnWWdLKGHdJSmjzFg4fi3mflKlPX1pjvR5XOZAnDgr5GAk+e8BZ5Ox51YrZEZvqtm4wIBBRknkhMwIVfVkVol00b/U0IR7dfze0hWqGUJLAMOcNnhTQyyLeewH3zSY8JPpgGAE=')], model='claude-sonnet-4-5-20250929', parent_tool_use_id=None, error=None)
AssistantMessage(content=[TextBlock(text="こんにちは!Claude Codeです。お手伝いできることがあれば教えてください。\n\nコーディング、ファイルの編集、コードベースの探索、デバッグなど、様々なタスクをサポートできます。何かご質問やご依頼はありますか?\n\n(Hello! I'm Claude Code. Please let me know if there's anything I can help you with. I can support various tasks such as coding, file editing, codebase exploration, debugging, and more. Do you have any questions or requests?)")], model='claude-sonnet-4-5-20250929', parent_tool_use_id=None, error=None)
ResultMessage(subtype='success', duration_ms=12189, duration_api_ms=30841, is_error=False, num_turns=1, session_id='2f147c74-0488-471c-a0f7-c9a913b649ee', total_cost_usd=0, usage={'input_tokens': 0, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'output_tokens': 0, 'server_tool_use': {'web_search_requests': 0, 'web_fetch_requests': 0}, 'service_tier': 'standard', 'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0}}, result="こんにちは!Claude Codeです。お手伝いできることがあれば教えてください。\n\nコーディング、ファイルの編集、コードベースの探索、デバッグなど、様々なタスクをサポートできます。何かご質問やご依頼はありますか?\n\n(Hello! I'm Claude Code. Please let me know if there's anything I can help you with. I can support various tasks such as coding, file editing, codebase exploration, debugging, and more. Do you have any questions or requests?)", structured_output=None)
Bedrockを使う場合は、こんな感じで環境変数をセットします。
export ANTHROPIC_DEFAULT_SONNET_MODEL=us.anthropic.claude-sonnet-4-5-20250929-v1:0
export ANTHROPIC_DEFAULT_HAIKU_MODEL=us.anthropic.claude-haiku-4-5-20251001-v1:0
export CLAUDE_CODE_SUBAGENT_MODEL=us.anthropic.claude-haiku-4-5-20251001-v1:0
export CLAUDE_CODE_USE_BEDROCK=1
export AWS_REGION=us-west-2
export CLAUDE_CODE_MAX_OUTPUT_TOKENS=4096
export MAX_THINKING_TOKENS=1024
AgentCore Runtimeにデプロイ!
このままAgentCore Runtimeにデプロイしちゃいましょう
uv add bedrock-agentcore aws-opentelemetry-distro
Bedrock AgentCore SDKと組み合わせます。messageをJSONにしてストリームします。
import json
from dataclasses import asdict
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from claude_agent_sdk import query
app = BedrockAgentCoreApp()
@app.entrypoint
async def invocations(payload, context):
prompt = payload.get("prompt", "")
async for message in query(prompt=prompt):
data = {"type": message.__class__.__name__, **asdict(message)}
yield {"message": json.dumps(data, ensure_ascii=False)}
if __name__ == "__main__":
app.run()
ローカルで起動すると、cURLで動作確認ができます。
uv run main.py
curl http://localhost:8080/invocations -XPOST -d '{"prompt": "hello"}'
AgentCore Runtimeにデプロイしましょう。簡単にやりたいのでstarter toolkitを使いましょう。
uv add --dev bedrock-agentcore-starter-toolkit
agentcore configureします。
uv run agentcore configure -e ./main.py
出来上がったDockerfileを大胆に置き換えます。Node.jsとnpm、Claude Codeをインストールします。
FROM --platform=linux/arm64 ghcr.io/astral-sh/uv:python3.13-trixie
RUN apt-get update && apt-get install -y \
nodejs \
npm \
&& rm -rf /var/lib/apt/lists/*
RUN groupadd -g 1000 appuser && useradd -u 1000 -g 1000 -m appuser
USER appuser
RUN mkdir ~/.npm-global
RUN npm config set prefix '~/.npm-global'
ENV PATH=~/.npm-global/bin:$PATH\
NODE_PATH=/home/appuser/.npm-global/lib/node_modules
RUN npm install -g @anthropic-ai/claude-code
ENV CLAUDE_CODE_USE_BEDROCK=1\
ANTHROPIC_MODEL=haiku \
ANTHROPIC_DEFAULT_SONNET_MODEL=global.anthropic.claude-sonnet-4-5-20250929-v1:0\
ANTHROPIC_DEFAULT_HAIKU_MODEL=global.anthropic.claude-haiku-4-5-20251001-v1:0 \
CLAUDE_CODE_SUBAGENT_MODEL=haiku \
MAX_THINKING_TOKENS=1024
WORKDIR /app
COPY --chown=1000:1000 pyproject.toml uv.lock ./
RUN uv sync --frozen
COPY --chown=1000:1000 main.py ./
CMD ["uv", "run", "opentelemetry-instrument", "python", "main.py"]
AgentCore Runtimeにデプロイします。
uv run agentcore launch
デプロイできたら、サンドボックスで動作確認できます。
続きはGitHubで
この先は細々してきますので、以下のGitHubリポジトリを参照してください。(そして★をください!)
このあたりを実装しています。
- StreamlitのUI
- MCP対応
- Agent Skills対応
- ファイル入出力対応
- マルチターンの会話とセッション分離
- CDKによるバックエンドデプロイ
- ガードレールプロンプト
StreamlitのUI
みなれた(みあきた?)見た目です。処理中のメッセージはStatusにまとめてます。また、ファイルの入出力にも対応してます。
MCP対応
.mcp.jsonをおきます。
setting_sourcesをprojectにすることで.mcp.jsonが読み込まれます。あと、呼び出し時に承認を求められないようにallowed_toolsに追加します。
Agent Skills対応
.claude/skillsディレクトリ内に必要なSkillを格納します。
とりあえず私はAnthropic製のSkillから、「docx」「pdf」「pptx」「xlsx」を入れてます。これらのSkillの動作に必要なライブラリーはDockerfileやpyproject.tomlで事前にインストールしておきます。
ファイル入出力対応
フロントエンド(Streamlit)からPrompt以外にBase64変換したファイルを渡せるようにしました。
受け取ったAgentCoreでは所定の場所(/work/input)に格納します。
そして、System promptで「inputディレクトリにファイルがあるよ。そして出力はoutputディレクトリにしてね」と伝えます。
Claude Code呼び出し後、/work/outputにあるファイルをBase64に変換してフロントエンドに返却します。
これで安定してファイルのやり取りができるようになりました。
マルチターンの会話とセッション分離
AgentCore Runtimeは同一セッションIDを渡すと同じインスタンスへ、違うセッションIDを渡すと別のインスタンスへリクエストがルーティングされる特徴があります。Streamlitの画面表示時にランダムなセッションIDを生成することで、セッションを分離します。
Claude Agent SDKはClaudeAgentOptionsのresumeに前回のセッションIDを渡すと前回のセッションの続きとして処理できます。
前回のセッションIDはmessageに含まれます。
CDKによるバックエンドデプロイ
CDKのL2 ConstructとしてAgentCoreのものがあるので、それを使いました。
説明するより見てもらったほうが早そうなコード量で構築完了です。
ガードレールプロンプト
ローカルの開発環境だと「OSのバージョン調べて」とか、「ls -laして」みたいな指示を出すと思います。ただ、AgentCore Runtime内で不用意なコマンドは実行してほしくないので、システムプロンプトでガードレールとして動作させるプロンプトを入れています。
ただ、これで完璧かはわからないので、ご利用は計画的に!
どうして到達点?
作った感想ですが、「AIエージェントをどう構築するか」ではなく「どんなMCPとSkillsを用意するか」で、「どんなAIエージェントでも構築できるのでは?」という感触を得ました。(私が試していないだけで、HooksやスラッシュコマンドもClaude Codeと同様に利用できるようです。)
AIエージェントの型は、もうこれでいいんじゃね感。
今後もどんどんClaude Codeはアップデートしていくでしょうし、モデルも賢くなっていくことでしょう。Claude Codeの内部実装は公開されていませんが、Claudeモデルとの組み合わせは、現状、地球上でもっとも協力なAIエージェントであることは間違いありません。Claude Code on AgentCoreの構成を組んでおけば、Claude CodeとClaudeモデルの更新を直ぐに自分のものにできます。すごい!
もう一つ思ったのは、「あれ、これってClaude Desktopの再発明?」というものです。一周回ってClaude Desktopが最強なのか?



