8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2025年のAIエージェント開発の到達点はClaude Code on Bedrock AgentCoreかもしれない

Posted at

今年は「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エージェントが構築できた気がするので、紹介します。

■簡単な構成

image.png

Claude Agent SDKはこんな感じ

Claude Agent SDKは、Python版とTypeScript版が提供されています。(本日時点で、TypeScript版はV2が開発中のようです)

前提としてClaude Codeをインストールしておく必要があります。

今回はPython版を使用します。ライブラリーをインストールします。

Shell
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にデプロイしちゃいましょう

Shell
uv add bedrock-agentcore aws-opentelemetry-distro

Bedrock AgentCore SDKと組み合わせます。messageをJSONにしてストリームします。

main.py
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で動作確認ができます。

Shell(AgentCore Runtimeにデプロイするエージェントをローカルで起動)
uv run main.py
Shell(エージェント呼び出し)
curl http://localhost:8080/invocations -XPOST -d '{"prompt": "hello"}'

AgentCore Runtimeにデプロイしましょう。簡単にやりたいのでstarter toolkitを使いましょう。

Shell
uv add --dev bedrock-agentcore-starter-toolkit

agentcore configureします。

Shell
uv run agentcore configure -e ./main.py

出来上がったDockerfileを大胆に置き換えます。Node.jsとnpm、Claude Codeをインストールします。

.bedrock_agentcore/claude_agent_on_agentcore/Dockerfile
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にデプロイします。

Shell
uv run agentcore launch

デプロイできたら、サンドボックスで動作確認できます。

続きはGitHubで

この先は細々してきますので、以下のGitHubリポジトリを参照してください。(そして★をください!)

このあたりを実装しています。

  • StreamlitのUI
  • MCP対応
  • Agent Skills対応
  • ファイル入出力対応
  • マルチターンの会話とセッション分離
  • CDKによるバックエンドデプロイ
  • ガードレールプロンプト

StreamlitのUI

みなれた(みあきた?)見た目です。処理中のメッセージはStatusにまとめてます。また、ファイルの入出力にも対応してます。

image.png

image.png

MCP対応

.mcp.jsonをおきます。

setting_sourcesprojectにすることで.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が最強なのか?

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?