blog
AIブログ
Claude Agent SDK とは?エージェント開発の始め方【2026年版】
Claude Agent SDKとは:開発者が知るべき全体像
Claude Agent SDKは、Anthropic公式のPython・TypeScript向けSDKを基盤として、エージェントパターン(ツール呼び出し・状態管理・ループ制御)を実装するためのエコシステムです。「プロンプトを送り、レスポンスを受け取る」という一問一答型ではなく、目標を与えたらツール選択・実行・評価を自律的に繰り返して最終成果物を返す連続的な推論・実行サイクルを構築するためのものです。
利用可能なモデルはClaude Opus 4.8(最上位)・Sonnet 4.6・Haiku 4.5などで、エージェントの用途や予算に応じて使い分けます。各モデルのスペック・ベンチ比較の詳細はClaudeのモデル比較をご参照ください。
本記事では「SDKをどう設計・実装するか」という開発者目線の実務に集中します。
end_turn になるまで反復するこのループをゼロから作ると、状態管理・エラーハンドリング・コンテキスト制御の定型コードが膨大になります。SDKが提供する抽象化により、開発者はビジネスロジックとツール定義に集中できます。
インストールと初期セットアップ
まず公式SDKをインストールします。Python・TypeScriptどちらも利用可能です。
pip install anthropic
# TypeScript / Node.js
npm install @anthropic-ai/sdk
クライアントの初期化はシンプルです。APIキーは環境変数 ANTHROPIC_API_KEY から自動で読まれます。
client = anthropic.Anthropic()
# ANTHROPIC_API_KEY 環境変数を自動読み込み
# または client = anthropic.Anthropic(api_key=”sk-ant-…”)
.envファイルや環境変数で管理し、.gitignoreに必ず追加してください。
コアAPI:messages.createの使い方と設計思想
エージェント実装の中心は client.messages.create() です。このAPIを繰り返し呼び出すことでエージェントループが成立します。主要パラメータと役割を整理します。
| パラメータ | 型・例 | 役割と設計上の注意点 |
|---|---|---|
| model | “claude-sonnet-4-5” | 使用モデルを文字列で指定。タスク要件に応じて切り替える |
| max_tokens | 1024〜8192 | 出力の上限トークン数。ツール呼び出しを含む応答が途中で切れないよう十分に確保する |
| system | str | エージェントの役割・制約・目標を定義。ループ全体を通じて一定。後述の「目標再注入」の場所 |
| messages | list[dict] | 会話履歴全体を配列で渡す。ループごとにtool_resultを追記して会話を継続させる |
| tools | list[dict] | JSON Schemaで定義したツール一覧。Claudeはここから自律的に呼ぶツールを選択する |
| temperature | 0〜1(デフォルト1) | ツール呼び出しが主なエージェントでは0〜0.3に下げて安定性を上げるのが実務的な定石 |
stop_reasonによる制御フロー
エージェントループの根幹は stop_reason の判定です。レスポンスのこのフィールドを見て次の行動を決定します。
messages = [{“role”: “user”, “content”: user_message}]
iteration = 0
while iteration < max_iterations:
response = client.messages.create(
model=“claude-sonnet-4-5”,
max_tokens=4096,
tools=TOOLS,
messages=messages
)
# ① ループ終了:最終応答を返す
if response.stop_reason == “end_turn”:
return response.content[0].text
# ② ツール呼び出し:実行してフィードバック
if response.stop_reason == “tool_use”:
tool_results = execute_tools(response.content)
messages.append({“role”: “assistant”, “content”: response.content})
messages.append({“role”: “user”, “content”: tool_results})
iteration += 1
# max_iterations到達:安全に終了
raise RuntimeError(f”エージェントが{max_iterations}ターンで完了しませんでした”)
無限ループはコスト爆発に直結します。本番では必ずイテレーション上限を設け、超過時は例外を上げてアラートを発火させてください。20〜50が一般的な目安ですが、タスクの性質によって調整します。
ツール定義:エージェント能力設計の核心
エージェントの実力はツール定義で決まります。Claudeはツールの description を読んで「いつ・なぜそのツールを使うか」を判断するため、descriptionの品質がエージェント全体の動作精度を左右します。
ツール定義の構造
{
“name”: “search_web”,
“description”: “””ウェブ検索を実行して最新情報を取得する。
使用タイミング: ユーザーの質問に対してリアルタイム情報が必要な場合、
または学習データに存在しない可能性がある最新の事実を確認する場合。
使用しない場合: 一般的な知識・概念の説明は検索せずに直接回答すること。”””,
“input_schema”: {
“type”: “object”,
“properties”: {
“query”: {
“type”: “string”,
“description”: “検索クエリ。できる限り具体的な日本語で記述すること”
},
“num_results”: {
“type”: “integer”,
“description”: “取得件数(1〜10、デフォルト5)”,
“default”: 5
}
},
“required”: [“query”]
}
}
]
descriptionを書く5つの原則
当社の実運用での試行錯誤から導いた、description品質を高める原則です。
「〜の場合に使用」「〜のときは使わない」を両方書く。Claudeは使わない条件も判断に使う。
「このツールはDBに書き込みを行う」「外部APIに課金が発生する」など、不可逆な操作は必ず明記する。
「JSON形式で{title, url, snippet}を返す」と書くことで、Claudeが結果の解釈を誤りにくくなる。
「1回のクエリで最大10件」「文字数は5000字まで」など、ツールの限界をClaudeに伝えることで無駄な呼び出しを防ぐ。
日本語で運用するエージェントでは、descriptionも日本語にすることでツール選択精度が体感できるほど改善する。
ツールの実装パターン
ツール定義(スキーマ)とツール実行(実際の処理)は分離して実装します。Claudeが返す tool_use ブロックの name と input を見て、対応する関数にディスパッチします。
“””レスポンス内のtool_useブロックを全て実行し、tool_resultを返す”””
tool_results = []
for block in content_blocks:
if block.type != “tool_use”:
continue
try:
# ツール名でディスパッチ
result = TOOL_REGISTRY[block.name](**block.input)
tool_results.append({
“type”: “tool_result”,
“tool_use_id”: block.id,
“content”: str(result)
})
except Exception as e:
# エラーもClaudeにフィードバックする(重要)
tool_results.append({
“type”: “tool_result”,
“tool_use_id”: block.id,
“content”: f”エラー: {str(e)}”,
“is_error”: True
})
return tool_results
ツール呼び出しが失敗した場合、例外をそのまま投げるのではなく
is_error: true の tool_result としてClaudeに返します。Claudeはエラーメッセージをもとにリトライ方法を変えたり、別の手段にフォールバックしたりする判断を自律的に行えます。
MCPとの連携:ツールを外部サーバーに切り出す
Model Context Protocol(MCP)は、エージェントとツールを標準プロトコルで接続する仕組みです。ツール実装をMCPサーバーとして外部化することで、複数のエージェントやアプリケーションからツールを共有・再利用できます。
・PostgreSQL / MySQL
・GitHub API
・社内カスタムAPI
・Slack / Notion 等
MCPサーバーへの接続実装
from anthropic import Anthropic
client = Anthropic()
# MCPサーバーをtool providerとして接続
# stdio経由でローカルMCPサーバーを起動・接続する例
server_params = {
“command”: “python”,
“args”: [“my_mcp_server.py”],
“env”: {“DB_URL”: “postgresql://…”}
}
# MCPツールはAgents SDK経由で自動的にtool定義に変換される
# anthropic.BetaContentBlockParam等のMCP対応APIを利用
MCPを使う最大のメリットはツール実装とエージェントロジックの分離です。データベースアクセスツールをMCPサーバーとして実装しておけば、リサーチエージェント・コードエージェント・レポートエージェントが同一ツールを共有でき、ツール側のバグ修正も一箇所で済みます。
MCPの使いどころと注意点
| 観点 | MCPが有効なケース | 直接実装が有効なケース |
|---|---|---|
| 再利用性 | 複数エージェント・複数アプリで共有 | 1つのエージェント専用ツール |
| レイテンシ | 許容できる(数十〜数百ms増) | レイテンシ最小化が最優先 |
| チーム分業 | ツール開発者とエージェント開発者が別チーム | 小規模・1人開発 |
| プロトタイピング | 設計が固まった後 | PoC・検証フェーズ |
コンテキスト管理:長期ループで崩れないエージェント設計
エージェントループが長くなるほど、会話履歴(messages配列)が膨らみ、コンテキストウィンドウを圧迫します。何も対策しなければ、数十ターンのループでトークン超過エラーが発生します。
コンテキスト管理の3つの戦略
summary = summarize_history(messages[:-4])
messages = [summary_message(summary)] + messages[-4:]
save_memo(key, value) / load_memo(key) を定義→ エージェントが自律的に中間結果を保存・参照
各フェーズで独立したエージェントループを起動
トークン使用量の監視実装
response = client.messages.create(…)
input_tokens = response.usage.input_tokens
output_tokens = response.usage.output_tokens
total = input_tokens + output_tokens
print(f”入力: {input_tokens} / 出力: {output_tokens} / 合計: {total}”)
# コンテキスト上限の80%を超えたら圧縮をトリガー
CONTEXT_LIMIT = 200000 # モデルのコンテキストウィンドウ
if input_tokens > CONTEXT_LIMIT * 0.8:
messages = compress_context(messages)
エラーハンドリング:実運用で頻出する5パターン
エージェントが自律ループするほど、エラーの種類と累積確率が増えます。パターンごとに対策を実装してください。
| エラーパターン | 発生原因 | 実装すべき対策 |
|---|---|---|
| 無限ループ | 完了条件の曖昧さ・目標逸脱 | max_iterations を必ず設定。超過時は例外+アラート |
| ツール失敗 | 外部API障害・タイムアウト・バリデーションエラー | 指数バックオフで最大3回リトライ。失敗内容をClaudeにフィードバック |
| コンテキスト超過 | 長期ループでトークン枯渇 | ループ毎にトークン監視。閾値80%で要約圧縮を自動実行 |
| 目標逸脱 | 多ステップで当初の指示が希釈 | system promptに最終目標を繰り返し明記。中間タスクの完了ごとに目標を再確認させる |
| Rate Limit | API呼び出し頻度超過(特に並列エージェント) | Tier別制限を把握した上でリクエスト間隔制御。retry-afterヘッダーを尊重 |
リトライ実装の実例
def call_tool_with_retry(tool_fn, kwargs, max_retries=3):
for attempt in range(max_retries):
try:
return tool_fn(**kwargs)
except RateLimitError:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
except TimeoutError as e:
if attempt == max_retries – 1:
return f”ツール実行タイムアウト: {str(e)}”
time.sleep(2 ** attempt)
マルチエージェント構成:設計パターンと実装の勘所
複雑なタスクは単一エージェントよりも役割分担した複数エージェントの協調が有効です。ここでは実装レベルの設計判断を整理します。
モデル: Haiku 4.5
モデル: Sonnet 4.6
モデル: Sonnet 4.6
エージェント間の通信フォーマット設計
サブエージェントへの指示とサブエージェントからの返値は必ず構造化JSON形式で定義してください。自由テキストでの通信はオーケストレーターの解釈ミスを招きます。
task_spec = {
“task_id”: “research_001”,
“goal”: “2024年の日本のEV市場シェアを調査する”,
“constraints”: {
“max_searches”: 5,
“output_format”: “json”,
“required_fields”: [“market_share”, “sources”, “confidence”]
}
}
# サブエージェントの返値フォーマット(例)
result_spec = {
“task_id”: “research_001”,
“status”: “success”, # or “partial” / “failed”
“data”: {…},
“confidence”: 0.85, # 信頼度スコア(オーケストレーターが活用)
“iterations_used”: 3 # コスト把握のため
}
モデル選択のコスト最適化戦略
マルチエージェント構成では、各エージェントに必要な処理能力に応じてモデルを使い分けるハイブリッド戦略が実践的です。
| 役割 | 推奨モデル | 選択理由 |
|---|