Claude Agent の Python SDK です。詳細はClaude Agent SDK ドキュメントを参照してください。
pip install claude-agent-sdk前提条件:
- Python 3.10 以上
注記:Claude Code CLI はパッケージに自動的にバンドルされており、別途インストールは不要です!SDK はデフォルトでバンドルされた CLI を使用します。システム全体へのインストールまたは特定のバージョンを使用したい場合は、以下のようにできます:
- Claude Code を別途インストール:
curl -fsSL https://claude.ai/install.sh | bash - カスタムパスを指定:
ClaudeAgentOptions(cli_path="/path/to/claude")
import anyio
from claude_agent_sdk import query
async def main():
async for message in query(prompt="What is 2 + 2?"):
print(message)
anyio.run(main)query() は Claude Code をクエリするための非同期関数です。レスポンスメッセージの AsyncIterator を返します。src/claude_agent_sdk/query.py を参照してください。
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
# Simple query
async for message in query(prompt="Hello Claude"):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
# With options
options = ClaudeAgentOptions(
system_prompt="You are a helpful assistant",
max_turns=1
)
async for message in query(prompt="Tell me a joke", options=options):
print(message)デフォルトでは、Claude は完全な Claude Code ツールセット(Read、Write、Edit、Bash など)にアクセスできます。allowed_tools は許可アクセスリストです:リストされたツールは自動承認され、リストされていないツールは permission_mode と can_use_tool で判断されます。これは Claude のツールセットからツールを削除しません。特定のツールをブロックするには、disallowed_tools を使用してください。完全な評価順序については、許可ガイド を参照してください。
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"], # auto-approve these tools
permission_mode='acceptEdits' # auto-accept file edits
)
async for message in query(
prompt="Create a hello.py file",
options=options
):
# Process tool use and results
passfrom pathlib import Path
options = ClaudeAgentOptions(
cwd="/path/to/project" # or Path("/path/to/project")
)ClaudeSDKClient は Claude Code との双方向対話会話をサポートします。src/claude_agent_sdk/client.py を参照してください。
query() とは異なり、ClaudeSDKClient はさらにカスタムツールとフックを有効にし、両方とも Python 関数として定義できます。
カスタムツール は、Claude が必要に応じて呼び出すために Claude に提供できる Python 関数です。
カスタムツールはインプロセス MCP サーバーとして実装されており、Python アプリケーション内で直接実行され、通常の MCP サーバーが必要とする別プロセスの必要性が排除されます。
エンドツーエンドの例については、MCP Calculator を参照してください。
from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions, ClaudeSDKClient
# Define a tool using the @tool decorator
@tool("greet", "Greet a user", {"name": str})
async def greet_user(args):
return {
"content": [
{"type": "text", "text": f"Hello, {args['name']}!"}
]
}
# Create an SDK MCP server
server = create_sdk_mcp_server(
name="my-tools",
version="1.0.0",
tools=[greet_user]
)
# Use it with Claude. allowed_tools pre-approves the tool so it runs
# without a permission prompt; it does not control tool availability.
options = ClaudeAgentOptions(
mcp_servers={"tools": server},
allowed_tools=["mcp__tools__greet"]
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Greet Alice")
# Extract and print response
async for msg in client.receive_response():
print(msg)- サブプロセス管理が不要 - アプリケーションと同じプロセスで実行されます
- パフォーマンス向上 - ツール呼び出しのIPC オーバーヘッドがありません
- デプロイが簡単 - 複数のプロセスではなく、単一の Python プロセスです
- デバッグが容易 - すべてのコードが同じプロセスで実行されます
- 型安全性 - 型ヒント付きの直接的な Python 関数呼び出し
# BEFORE: External MCP server (separate process)
options = ClaudeAgentOptions(
mcp_servers={
"calculator": {
"type": "stdio",
"command": "python",
"args": ["-m", "calculator_server"]
}
}
)
# AFTER: SDK MCP server (in-process)
from my_tools import add, subtract # Your tool functions
calculator = create_sdk_mcp_server(
name="calculator",
tools=[add, subtract]
)
options = ClaudeAgentOptions(
mcp_servers={"calculator": calculator}
)SDK と外部 MCP サーバーを一緒に使用することができます:
options = ClaudeAgentOptions(
mcp_servers={
"internal": sdk_server, # In-process SDK server
"external": { # External subprocess server
"type": "stdio",
"command": "external-server"
}
}
)フックは、Claude Code アプリケーション(Claude ではなく)が Claude エージェントループの特定の時点で呼び出す Python 関数です。フックは決定論的な処理と Claude への自動フィードバックを提供できます。詳細は エージェント動作をインターセプトおよび制御するフック を参照してください。
その他の例は examples/hooks.py を参照してください。
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient, HookMatcher
async def check_bash_command(input_data, tool_use_id, context):
tool_name = input_data["tool_name"]
tool_input = input_data["tool_input"]
if tool_name != "Bash":
return {}
command = tool_input.get("command", "")
block_patterns = ["foo.sh"]
for pattern in block_patterns:
if pattern in command:
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": f"Command contains invalid pattern: {pattern}",
}
}
return {}
options = ClaudeAgentOptions(
allowed_tools=["Bash"],
hooks={
"PreToolUse": [
HookMatcher(matcher="Bash", hooks=[check_bash_command]),
],
}
)
async with ClaudeSDKClient(options=options) as client:
# Test 1: Command with forbidden pattern (will be blocked)
await client.query("Run the bash command: ./foo.sh --help")
async for msg in client.receive_response():
print(msg)
print("\n" + "=" * 50 + "\n")
# Test 2: Safe command that should work
await client.query("Run the bash command: echo 'Hello from hooks example!'")
async for msg in client.receive_response():
print(msg)完全な型定義は src/claude_agent_sdk/types.py を参照してください:
ClaudeAgentOptions- 設定オプションAssistantMessage,UserMessage,SystemMessage,ResultMessage- メッセージタイプTextBlock,ToolUseBlock,ToolResultBlock- コンテンツブロック
from claude_agent_sdk import (
ClaudeSDKError, # Base error
CLINotFoundError, # Claude Code not installed
CLIConnectionError, # Connection issues
ProcessError, # Process failed
CLIJSONDecodeError, # JSON parsing issues
)
try:
async for message in query(prompt="Hello"):
pass
except CLINotFoundError:
print("Please install Claude Code")
except ProcessError as e:
print(f"Process failed with exit code: {e.exit_code}")
except CLIJSONDecodeError as e:
print(f"Failed to parse response: {e}")