pip install claude-agent-sdkquery() et ClaudeSDKClientLe SDK Python fournit deux façons d'interagir avec Claude Code :
| Fonctionnalité | query() | ClaudeSDKClient |
|---|---|---|
| Session | Crée une nouvelle session à chaque fois | Réutilise la même session |
| Conversation | Échange unique | Plusieurs échanges dans le même contexte |
| Connexion | Gérée automatiquement | Contrôle manuel |
| Entrée en streaming | ✅ Supportée | ✅ Supportée |
| Interruptions | ❌ Non supportée | ✅ Supportée |
| Hooks | ❌ Non supportés | ✅ Supportés |
| Outils personnalisés | ❌ Non supportés | ✅ Supportés |
| Continuer la conversation | ❌ Nouvelle session à chaque fois | ✅ Maintient la conversation |
| Cas d'usage | Tâches ponctuelles | Conversations continues |
query() (Nouvelle session à chaque fois)Idéal pour :
ClaudeSDKClient (Conversation continue)Idéal pour :
query()Crée une nouvelle session pour chaque interaction avec Claude Code. Retourne un itérateur asynchrone qui produit des messages au fur et à mesure qu'ils arrivent. Chaque appel à query() recommence à zéro sans mémoire des interactions précédentes.
async def query(
*,
prompt: str | AsyncIterable[dict[str, Any]],
options: ClaudeAgentOptions | None = None
) -> AsyncIterator[Message]| Paramètre | Type | Description |
|---|---|---|
prompt | str | AsyncIterable[dict] | L'invite d'entrée sous forme de chaîne ou d'itérable asynchrone pour le mode streaming |
options | ClaudeAgentOptions | None | Objet de configuration optionnel (par défaut ClaudeAgentOptions() si None) |
Retourne un AsyncIterator[Message] qui produit des messages de la conversation.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
system_prompt="You are an expert Python developer",
permission_mode='acceptEdits',
cwd="/home/user/project"
)
async for message in query(
prompt="Create a Python web server",
options=options
):
print(message)
asyncio.run(main())tool()Décorateur pour définir les outils MCP avec la sécurité des types.
def tool(
name: str,
description: str,
input_schema: type | dict[str, Any]
) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]| Paramètre | Type | Description |
|---|---|---|
name | str | Identifiant unique pour l'outil |
description | str | Description lisible de ce que fait l'outil |
input_schema | type | dict[str, Any] | Schéma définissant les paramètres d'entrée de l'outil (voir ci-dessous) |
Mappage de type simple (recommandé) :
{"text": str, "count": int, "enabled": bool}Format JSON Schema (pour la validation complexe) :
{
"type": "object",
"properties": {
"text": {"type": "string"},
"count": {"type": "integer", "minimum": 0}
},
"required": ["text"]
}Une fonction décorateur qui enveloppe l'implémentation de l'outil et retourne une instance SdkMcpTool.
from claude_agent_sdk import tool
from typing import Any
@tool("greet", "Greet a user", {"name": str})
async def greet(args: dict[str, Any]) -> dict[str, Any]:
return {
"content": [{
"type": "text",
"text": f"Hello, {args['name']}!"
}]
}create_sdk_mcp_server()Créer un serveur MCP en processus qui s'exécute dans votre application Python.
def create_sdk_mcp_server(
name: str,
version: str = "1.0.0",
tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
name | str | - | Identifiant unique pour le serveur |
version | str | "1.0.0" | Chaîne de version du serveur |
tools | list[SdkMcpTool[Any]] | None | None | Liste des fonctions d'outil créées avec le décorateur @tool |
Retourne un objet McpSdkServerConfig qui peut être passé à ClaudeAgentOptions.mcp_servers.
from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("add", "Add two numbers", {"a": float, "b": float})
async def add(args):
return {
"content": [{
"type": "text",
"text": f"Sum: {args['a'] + args['b']}"
}]
}
@tool("multiply", "Multiply two numbers", {"a": float, "b": float})
async def multiply(args):
return {
"content": [{
"type": "text",
"text": f"Product: {args['a'] * args['b']}"
}]
}
calculator = create_sdk_mcp_server(
name="calculator",
version="2.0.0",
tools=[add, multiply] # Pass decorated functions
)
# Use with Claude
options = ClaudeAgentOptions(
mcp_servers={"calc": calculator},
allowed_tools=["mcp__calc__add", "mcp__calc__multiply"]
)ClaudeSDKClientMaintient une session de conversation sur plusieurs échanges. C'est l'équivalent Python de la façon dont la fonction query() du SDK TypeScript fonctionne en interne - elle crée un objet client qui peut continuer les conversations.
query()@tool) et les hooksclass ClaudeSDKClient:
def __init__(self, options: ClaudeAgentOptions | None = None)
async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None
async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None
async def receive_messages(self) -> AsyncIterator[Message]
async def receive_response(self) -> AsyncIterator[Message]
async def interrupt(self) -> None
async def disconnect(self) -> None| Méthode | Description |
|---|---|
__init__(options) | Initialiser le client avec une configuration optionnelle |
connect(prompt) | Se connecter à Claude avec une invite initiale optionnelle ou un flux de messages |
query(prompt, session_id) | Envoyer une nouvelle demande en mode streaming |
receive_messages() | Recevoir tous les messages de Claude en tant qu'itérateur asynchrone |
receive_response() | Recevoir les messages jusqu'à et incluant un ResultMessage |
interrupt() | Envoyer un signal d'interruption (fonctionne uniquement en mode streaming) |
disconnect() | Se déconnecter de Claude |
Le client peut être utilisé comme gestionnaire de contexte asynchrone pour la gestion automatique de la connexion :
async with ClaudeSDKClient() as client:
await client.query("Hello Claude")
async for message in client.receive_response():
print(message)Important : Lors de l'itération sur les messages, évitez d'utiliser
breakpour quitter tôt car cela peut causer des problèmes de nettoyage asyncio. À la place, laissez l'itération se terminer naturellement ou utilisez des drapeaux pour suivre quand vous avez trouvé ce que vous cherchiez.
import asyncio
from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
async def main():
async with ClaudeSDKClient() as client:
# First question
await client.query("What's the capital of France?")
# Process response
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
# Follow-up question - Claude remembers the previous context
await client.query("What's the population of that city?")
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
# Another follow-up - still in the same conversation
await client.query("What are some famous landmarks there?")
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
asyncio.run(main())import asyncio
from claude_agent_sdk import ClaudeSDKClient
async def message_stream():
"""Generate messages dynamically."""
yield {"type": "text", "text": "Analyze the following data:"}
await asyncio.sleep(0.5)
yield {"type": "text", "text": "Temperature: 25°C"}
await asyncio.sleep(0.5)
yield {"type": "text", "text": "Humidity: 60%"}
await asyncio.sleep(0.5)
yield {"type": "text", "text": "What patterns do you see?"}
async def main():
async with ClaudeSDKClient() as client:
# Stream input to Claude
await client.query(message_stream())
# Process response
async for message in client.receive_response():
print(message)
# Follow-up in same session
await client.query("Should we be concerned about these readings?")
async for message in client.receive_response():
print(message)
asyncio.run(main())import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
async def interruptible_task():
options = ClaudeAgentOptions(
allowed_tools=["Bash"],
permission_mode="acceptEdits"
)
async with ClaudeSDKClient(options=options) as client:
# Start a long-running task
await client.query("Count from 1 to 100 slowly")
# Let it run for a bit
await asyncio.sleep(2)
# Interrupt the task
await client.interrupt()
print("Task interrupted!")
# Send a new command
await client.query("Just say hello instead")
async for message in client.receive_response():
# Process the new response
pass
asyncio.run(interruptible_task())from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions
)
async def custom_permission_handler(
tool_name: str,
input_data: dict,
context: dict
):
"""Custom logic for tool permissions."""
# Block writes to system directories
if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):
return {
"behavior": "deny",
"message": "System directory write not allowed",
"interrupt": True
}
# Redirect sensitive file operations
if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""):
safe_path = f"./sandbox/{input_data['file_path']}"
return {
"behavior": "allow",
"updatedInput": {**input_data, "file_path": safe_path}
}
# Allow everything else
return {
"behavior": "allow",
"updatedInput": input_data
}
async def main():
options = ClaudeAgentOptions(
can_use_tool=custom_permission_handler,
allowed_tools=["Read", "Write", "Edit"]
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Update the system config file")
async for message in client.receive_response():
# Will use sandbox path instead
print(message)
asyncio.run(main())SdkMcpToolDéfinition pour un outil MCP SDK créé avec le décorateur @tool.
@dataclass
class SdkMcpTool(Generic[T]):
name: str
description: str
input_schema: type[T] | dict[str, Any]
handler: Callable[[T], Awaitable[dict[str, Any]]]| Propriété | Type | Description |
|---|---|---|
name | str | Identifiant unique pour l'outil |
description | str | Description lisible |
input_schema | type[T] | dict[str, Any] | Schéma pour la validation d'entrée |
handler | Callable[[T], Awaitable[dict[str, Any]]] | Fonction asynchrone qui gère l'exécution de l'outil |
ClaudeAgentOptionsClasse de configuration pour les requêtes Claude Code.
@dataclass
class ClaudeAgentOptions:
allowed_tools: list[str] = field(default_factory=list)
system_prompt: str | SystemPromptPreset | None = None
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
permission_mode: PermissionMode | None = None
continue_conversation: bool = False
resume: str | None = None
max_turns: int | None = None
disallowed_tools: list[str] = field(default_factory=list)
model: str | None = None
output_format: OutputFormat | None = None
permission_prompt_tool_name: str | None = None
cwd: str | Path | None = None
settings: str | None = None
add_dirs: list[str | Path] = field(default_factory=list)
env: dict[str, str] = field(default_factory=dict)
extra_args: dict[str, str | None] = field(default_factory=dict)
max_buffer_size: int | None = None
debug_stderr: Any = sys.stderr # Deprecated
stderr: Callable[[str], None] | None = None
can_use_tool: CanUseTool | None = None
hooks: dict[HookEvent, list[HookMatcher]] | None = None
user: str | None = None
include_partial_messages: bool = False
fork_session: bool = False
agents: dict[str, AgentDefinition] | None = None
setting_sources: list[SettingSource] | None = None| Propriété | Type | Par défaut | Description |
|---|---|---|---|
allowed_tools | list[str] | [] | Liste des noms d'outils autorisés |
system_prompt | str | SystemPromptPreset | None | None | Configuration de l'invite système. Passez une chaîne pour une invite personnalisée, ou utilisez {"type": "preset", "preset": "claude_code"} pour l'invite système de Claude Code. Ajoutez "append" pour étendre le préréglage |
mcp_servers | dict[str, McpServerConfig] | str | Path |
OutputFormatConfiguration pour la validation de la sortie structurée.
class OutputFormat(TypedDict):
type: Literal["json_schema"]
schema: dict[str, Any]| Champ | Requis | Description |
|---|---|---|
type | Oui | Doit être "json_schema" pour la validation JSON Schema |
schema | Oui | Définition JSON Schema pour la validation de sortie |
SystemPromptPresetConfiguration pour utiliser l'invite système préréglée de Claude Code avec des ajouts optionnels.
class SystemPromptPreset(TypedDict):
type: Literal["preset"]
preset: Literal["claude_code"]
append: NotRequired[str]| Champ | Requis | Description |
|---|---|---|
type | Oui | Doit être "preset" pour utiliser une invite système préréglée |
preset | Oui | Doit être "claude_code" pour utiliser l'invite système de Claude Code |
append | Non | Instructions supplémentaires à ajouter à l'invite système préréglée |
SettingSourceContrôle les sources de configuration basées sur le système de fichiers que le SDK charge.
SettingSource = Literal["user", "project", "local"]| Valeur | Description | Emplacement |
|---|---|---|
"user" | Paramètres utilisateur globaux | ~/.claude/settings.json |
"project" | Paramètres de projet partagés (contrôle de version) | .claude/settings.json |
"local" | Paramètres de projet locaux (gitignorés) | .claude/settings.local.json |
Quand setting_sources est omis ou None, le SDK ne charge pas les paramètres du système de fichiers. Cela fournit l'isolation pour les applications SDK.
Charger tous les paramètres du système de fichiers (comportement hérité) :
# Load all settings like SDK v0.0.x did
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="Analyze this code",
options=ClaudeAgentOptions(
setting_sources=["user", "project", "local"] # Load all settings
)
):
print(message)Charger uniquement des sources de paramètres spécifiques :
# Load only project settings, ignore user and local
async for message in query(
prompt="Run CI checks",
options=ClaudeAgentOptions(
setting_sources=["project"] # Only .claude/settings.json
)
):
print(message)Environnements de test et CI :
# Ensure consistent behavior in CI by excluding local settings
async for message in query(
prompt="Run tests",
options=ClaudeAgentOptions(
setting_sources=["project"], # Only team-shared settings
permission_mode="bypassPermissions"
)
):
print(message)Applications SDK uniquement :
# Define everything programmatically (default behavior)
# No filesystem dependencies - setting_sources defaults to None
async for message in query(
prompt="Review this PR",
options=ClaudeAgentOptions(
# setting_sources=None is the default, no need to specify
agents={ /* ... */ },
mcp_servers={ /* ... */ },
allowed_tools=["Read", "Grep", "Glob"]
)
):
print(message)Chargement des instructions de projet CLAUDE.md :
# Load project settings to include CLAUDE.md files
async for message in query(
prompt="Add a new feature following project conventions",
options=ClaudeAgentOptions(
system_prompt={
"type": "preset",
"preset": "claude_code" # Use Claude Code's system prompt
},
setting_sources=["project"], # Required to load CLAUDE.md from project
allowed_tools=["Read", "Write", "Edit"]
)
):
print(message)Quand plusieurs sources sont chargées, les paramètres sont fusionnés avec cette précédence (la plus élevée à la plus basse) :
.claude/settings.local.json).claude/settings.json)~/.claude/settings.json)Les options programmatiques (comme agents, allowed_tools) remplacent toujours les paramètres du système de fichiers.
AgentDefinitionConfiguration pour un sous-agent défini par programmation.
@dataclass
class AgentDefinition:
description: str
prompt: str
tools: list[str] | None = None
model: Literal["sonnet", "opus", "haiku", "inherit"] | None = None| Champ | Requis | Description |
|---|---|---|
description | Oui | Description en langage naturel de quand utiliser cet agent |
tools | Non | Tableau des noms d'outils autorisés. S'il est omis, hérite de tous les outils |
prompt | Oui | L'invite système de l'agent |
model | Non | Remplacement du modèle pour cet agent. S'il est omis, utilise le modèle principal |
PermissionModeModes de permission pour contrôler l'exécution des outils.
PermissionMode = Literal[
"default", # Standard permission behavior
"acceptEdits", # Auto-accept file edits
"plan", # Planning mode - no execution
"bypassPermissions" # Bypass all permission checks (use with caution)
]McpSdkServerConfigConfiguration pour les serveurs MCP SDK créés avec create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict):
type: Literal["sdk"]
name: str
instance: Any # MCP Server instanceMcpServerConfigType union pour les configurations du serveur MCP.
McpServerConfig = McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfigMcpStdioServerConfigclass McpStdioServerConfig(TypedDict):
type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility
command: str
args: NotRequired[list[str]]
env: NotRequired[dict[str, str]]McpSSEServerConfigclass McpSSEServerConfig(TypedDict):
type: Literal["sse"]
url: str
headers: NotRequired[dict[str, str]]McpHttpServerConfigclass McpHttpServerConfig(TypedDict):
type: Literal["http"]
url: str
headers: NotRequired[dict[str, str]]SdkPluginConfigConfiguration pour charger les plugins dans le SDK.
class SdkPluginConfig(TypedDict):
type: Literal["local"]
path: str| Champ | Type | Description |
|---|---|---|
type | Literal["local"] | Doit être "local" (seuls les plugins locaux sont actuellement supportés) |
path | str | Chemin absolu ou relatif vers le répertoire du plugin |
Exemple :
plugins=[
{"type": "local", "path": "./my-plugin"},
{"type": "local", "path": "/absolute/path/to/plugin"}
]Pour des informations complètes sur la création et l'utilisation des plugins, voir Plugins.
MessageType union de tous les messages possibles.
Message = UserMessage | AssistantMessage | SystemMessage | ResultMessageUserMessageMessage d'entrée utilisateur.
@dataclass
class UserMessage:
content: str | list[ContentBlock]AssistantMessageMessage de réponse de l'assistant avec des blocs de contenu.
@dataclass
class AssistantMessage:
content: list[ContentBlock]
model: strSystemMessageMessage système avec métadonnées.
@dataclass
class SystemMessage:
subtype: str
data: dict[str, Any]ResultMessageMessage de résultat final avec informations de coût et d'utilisation.
@dataclass
class ResultMessage:
subtype: str
duration_ms: int
duration_api_ms: int
is_error: bool
num_turns: int
session_id: str
total_cost_usd: float | None = None
usage: dict[str, Any] | None = None
result: str | None = NoneContentBlockType union de tous les blocs de contenu.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlockTextBlockBloc de contenu texte.
@dataclass
class TextBlock:
text: strThinkingBlockBloc de contenu de réflexion (pour les modèles avec capacité de réflexion).
@dataclass
class ThinkingBlock:
thinking: str
signature: strToolUseBlockBloc de demande d'utilisation d'outil.
@dataclass
class ToolUseBlock:
id: str
name: str
input: dict[str, Any]ToolResultBlockBloc de résultat d'exécution d'outil.
@dataclass
class ToolResultBlock:
tool_use_id: str
content: str | list[dict[str, Any]] | None = None
is_error: bool | None = NoneClaudeSDKErrorClasse d'exception de base pour toutes les erreurs SDK.
class ClaudeSDKError(Exception):
"""Base error for Claude SDK."""CLINotFoundErrorLevée quand Claude Code CLI n'est pas installé ou introuvable.
class CLINotFoundError(CLIConnectionError):
def __init__(self, message: str = "Claude Code not found", cli_path: str | None = None):
"""
Args:
message: Error message (default: "Claude Code not found")
cli_path: Optional path to the CLI that was not found
"""CLIConnectionErrorLevée quand la connexion à Claude Code échoue.
class CLIConnectionError(ClaudeSDKError):
"""Failed to connect to Claude Code."""ProcessErrorLevée quand le processus Claude Code échoue.
class ProcessError(ClaudeSDKError):
def __init__(self, message: str, exit_code: int | None = None, stderr: str | None = None):
self.exit_code = exit_code
self.stderr = stderrCLIJSONDecodeErrorLevée quand l'analyse JSON échoue.
class CLIJSONDecodeError(ClaudeSDKError):
def __init__(self, line: str, original_error: Exception):
"""
Args:
line: The line that failed to parse
original_error: The original JSON decode exception
"""
self.line = line
self.original_error = original_errorHookEventTypes d'événements de hook supportés. Notez que en raison des limitations de configuration, le SDK Python ne supporte pas les hooks SessionStart, SessionEnd et Notification.
HookEvent = Literal[
"PreToolUse", # Called before tool execution
"PostToolUse", # Called after tool execution
"UserPromptSubmit", # Called when user submits a prompt
"Stop", # Called when stopping execution
"SubagentStop", # Called when a subagent stops
"PreCompact" # Called before message compaction
]HookCallbackDéfinition de type pour les fonctions de rappel de hook.
HookCallback = Callable[
[dict[str, Any], str | None, HookContext],
Awaitable[dict[str, Any]]
]Paramètres :
input_data : Données d'entrée spécifiques au hook (voir documentation des hooks)tool_use_id : Identifiant d'utilisation d'outil optionnel (pour les hooks liés aux outils)context : Contexte du hook avec des informations supplémentairesRetourne un dictionnaire qui peut contenir :
decision : "block" pour bloquer l'actionsystemMessage : Message système à ajouter à la transcriptionhookSpecificOutput : Données de sortie spécifiques au hookHookContextInformations de contexte passées aux rappels de hook.
@dataclass
class HookContext:
signal: Any | None = None # Future: abort signal supportHookMatcherConfiguration pour faire correspondre les hooks à des événements ou des outils spécifiques.
@dataclass
class HookMatcher:
matcher: str | None = None # Tool name or pattern to match (e.g., "Bash", "Write|Edit")
hooks: list[HookCallback] = field(default_factory=list) # List of callbacks to executefrom claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext
from typing import Any
async def validate_bash_command(
input_data: dict[str, Any],
tool_use_id: str | None,
context: HookContext
) -> dict[str, Any]:
"""Validate and potentially block dangerous bash commands."""
if input_data['tool_name'] == 'Bash':
command = input_data['tool_input'].get('command', '')
if 'rm -rf /' in command:
return {
'hookSpecificOutput': {
'hookEventName': 'PreToolUse',
'permissionDecision': 'deny',
'permissionDecisionReason': 'Dangerous command blocked'
}
}
return {}
async def log_tool_use(
input_data: dict[str, Any],
tool_use_id: str | None,
context: HookContext
) -> dict[str, Any]:
"""Log all tool usage for auditing."""
print(f"Tool used: {input_data.get('tool_name')}")
return {}
options = ClaudeAgentOptions(
hooks={
'PreToolUse': [
HookMatcher(matcher='Bash', hooks=[validate_bash_command]),
HookMatcher(hooks=[log_tool_use]) # Applies to all tools
],
'PostToolUse': [
HookMatcher(hooks=[log_tool_use])
]
}
)
async for message in query(
prompt="Analyze this codebase",
options=options
):
print(message)Documentation des schémas d'entrée/sortie pour tous les outils Claude Code intégrés. Bien que le SDK Python n'exporte pas ces types, ils représentent la structure des entrées et sorties d'outils dans les messages.
Nom de l'outil : Task
Entrée :
{
"description": str, # A short (3-5 word) description of the task
"prompt": str, # The task for the agent to perform
"subagent_type": str # The type of specialized agent to use
}Sortie :
{
"result": str, # Final result from the subagent
"usage": dict | None, # Token usage statistics
"total_cost_usd": float | None, # Total cost in USD
"duration_ms": int | None # Execution duration in milliseconds
}Nom de l'outil : Bash
Entrée :
{
"command": str, # The command to execute
"timeout": int | None, # Optional timeout in milliseconds (max 600000)
"description": str | None, # Clear, concise description (5-10 words)
"run_in_background": bool | None # Set to true to run in background
}Sortie :
{
"output": str, # Combined stdout and stderr output
"exitCode": int, # Exit code of the command
"killed": bool | None, # Whether command was killed due to timeout
"shellId": str | None # Shell ID for background processes
}Nom de l'outil : Edit
Entrée :
{
"file_path": str, # The absolute path to the file to modify
"old_string": str, # The text to replace
"new_string": str, # The text to replace it with
"replace_all": bool | None # Replace all occurrences (default False)
}Sortie :
{
"message": str, # Confirmation message
"replacements": int, # Number of replacements made
"file_path": str # File path that was edited
}Nom de l'outil : Read
Entrée :
{
"file_path": str, # The absolute path to the file to read
"offset": int | None, # The line number to start reading from
"limit": int | None # The number of lines to read
}Sortie (fichiers texte) :
{
"content": str, # File contents with line numbers
"total_lines": int, # Total number of lines in file
"lines_returned": int # Lines actually returned
}Sortie (images) :
{
"image": str, # Base64 encoded image data
"mime_type": str, # Image MIME type
"file_size": int # File size in bytes
}Nom de l'outil : Write
Entrée :
{
"file_path": str, # The absolute path to the file to write
"content": str # The content to write to the file
}Sortie :
{
"message": str, # Success message
"bytes_written": int, # Number of bytes written
"file_path": str # File path that was written
}Nom de l'outil : Glob
Entrée :
{
"pattern": str, # The glob pattern to match files against
"path": str | None # The directory to search in (defaults to cwd)
}Sortie :
{
"matches": list[str], # Array of matching file paths
"count": int, # Number of matches found
"search_path": str # Search directory used
}Nom de l'outil : Grep
Entrée :
{
"pattern": str, # The regular expression pattern
"path": str | None, # File or directory to search in
"glob": str | None, # Glob pattern to filter files
"type": str | None, # File type to search
"output_mode": str | None, # "content", "files_with_matches", or "count"
"-i": bool | None, # Case insensitive search
"-n": bool | None, # Show line numbers
"-B": int | None, # Lines to show before each match
"-A": int | None, # Lines to show after each match
"-C": int | None, # Lines to show before and after
"head_limit": int | None, # Limit output to first N lines/entries
"multiline": bool | None # Enable multiline mode
}Sortie (mode contenu) :
{
"matches": [
{
"file": str,
"line_number": int | None,
"line": str,
"before_context": list[str] | None,
"after_context": list[str] | None
}
],
"total_matches": int
}Sortie (mode fichiers_avec_correspondances) :
{
"files": list[str], # Files containing matches
"count": int # Number of files with matches
}Nom de l'outil : NotebookEdit
Entrée :
{
"notebook_path": str, # Absolute path to the Jupyter notebook
"cell_id": str | None, # The ID of the cell to edit
"new_source": str, # The new source for the cell
"cell_type": "code" | "markdown" | None, # The type of the cell
"edit_mode": "replace" | "insert" | "delete" | None # Edit operation type
}Sortie :
{
"message": str, # Success message
"edit_type": "replaced" | "inserted" | "deleted", # Type of edit performed
"cell_id": str | None, # Cell ID that was affected
"total_cells": int # Total cells in notebook after edit
}Nom de l'outil : WebFetch
Entrée :
{
"url": str, # The URL to fetch content from
"prompt": str # The prompt to run on the fetched content
}Sortie :
{
"response": str, # AI model's response to the prompt
"url": str, # URL that was fetched
"final_url": str | None, # Final URL after redirects
"status_code": int | None # HTTP status code
}Nom de l'outil : WebSearch
Entrée :
{
"query": str, # The search query to use
"allowed_domains": list[str] | None, # Only include results from these domains
"blocked_domains": list[str] | None # Never include results from these domains
}Sortie :
{
"results": [
{
"title": str,
"url": str,
"snippet": str,
"metadata": dict | None
}
],
"total_results": int,
"query": str
}Nom de l'outil : TodoWrite
Entrée :
{
"todos": [
{
"content": str, # The task description
"status": "pending" | "in_progress" | "completed", # Task status
"activeForm": str # Active form of the description
}
]
}Sortie :
{
"message": str, # Success message
"stats": {
"total": int,
"pending": int,
"in_progress": int,
"completed": int
}
}Nom de l'outil : BashOutput
Entrée :
{
"bash_id": str, # The ID of the background shell
"filter": str | None # Optional regex to filter output lines
}Sortie :
{
"output": str, # New output since last check
"status": "running" | "completed" | "failed", # Current shell status
"exitCode": int | None # Exit code when completed
}Nom de l'outil : KillBash
Entrée :
{
"shell_id": str # The ID of the background shell to kill
}Sortie :
{
"message": str, # Success message
"shell_id": str # ID of the killed shell
}Nom de l'outil : ExitPlanMode
Entrée :
{
"plan": str # The plan to run by the user for approval
}Sortie :
{
"message": str, # Confirmation message
"approved": bool | None # Whether user approved the plan
}Nom de l'outil : ListMcpResources
Entrée :
{
"server": str | None # Optional server name to filter resources by
}Sortie :
{
"resources": [
{
"uri": str,
"name": str,
"description": str | None,
"mimeType": str | None,
"server": str
}
],
"total": int
}Nom de l'outil : ReadMcpResource
Entrée :
{
"server": str, # The MCP server name
"uri": str # The resource URI to read
}Sortie :
{
"contents": [
{
"uri": str,
"mimeType": str | None,
"text": str | None,
"blob": str | None
}
],
"server": str
}from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, TextBlock
import asyncio
class ConversationSession:
"""Maintains a single conversation session with Claude."""
def __init__(self, options: ClaudeAgentOptions = None):
self.client = ClaudeSDKClient(options)
self.turn_count = 0
async def start(self):
await self.client.connect()
print("Starting conversation session. Claude will remember context.")
print("Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session")
while True:
user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")
if user_input.lower() == 'exit':
break
elif user_input.lower() == 'interrupt':
await self.client.interrupt()
print("Task interrupted!")
continue
elif user_input.lower() == 'new':
# Disconnect and reconnect for a fresh session
await self.client.disconnect()
await self.client.connect()
self.turn_count = 0
print("Started new conversation session (previous context cleared)")
continue
# Send message - Claude remembers all previous messages in this session
await self.client.query(user_input)
self.turn_count += 1
# Process response
print(f"[Turn {self.turn_count}] Claude: ", end="")
async for message in self.client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text, end="")
print() # New line after response
await self.client.disconnect()
print(f"Conversation ended after {self.turn_count} turns.")
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
permission_mode="acceptEdits"
)
session = ConversationSession(options)
await session.start()
# Example conversation:
# Turn 1 - You: "Create a file called hello.py"
# Turn 1 - Claude: "I'll create a hello.py file for you..."
# Turn 2 - You: "What's in that file?"
# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)
# Turn 3 - You: "Add a main function to it"
# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
asyncio.run(main())from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
HookMatcher,
HookContext
)
import asyncio
from typing import Any
async def pre_tool_logger(
input_data: dict[str, Any],
tool_use_id: str | None,
context: HookContext
) -> dict[str, Any]:
"""Log all tool usage before execution."""
tool_name = input_data.get('tool_name', 'unknown')
print(f"[PRE-TOOL] About to use: {tool_name}")
# You can modify or block the tool execution here
if tool_name == "Bash" and "rm -rf" in str(input_data.get('tool_input', {})):
return {
'hookSpecificOutput': {
'hookEventName': 'PreToolUse',
'permissionDecision': 'deny',
'permissionDecisionReason': 'Dangerous command blocked'
}
}
return {}
async def post_tool_logger(
input_data: dict[str, Any],
tool_use_id: str | None,
context: HookContext
) -> dict[str, Any]:
"""Log results after tool execution."""
tool_name = input_data.get('tool_name', 'unknown')
print(f"[POST-TOOL] Completed: {tool_name}")
return {}
async def user_prompt_modifier(
input_data: dict[str, Any],
tool_use_id: str | None,
context: HookContext
) -> dict[str, Any]:
"""Add context to user prompts."""
original_prompt = input_data.get('prompt', '')
# Add timestamp to all prompts
from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return {
'hookSpecificOutput': {
'hookEventName': 'UserPromptSubmit',
'updatedPrompt': f"[{timestamp}] {original_prompt}"
}
}
async def main():
options = ClaudeAgentOptions(
hooks={
'PreToolUse': [
HookMatcher(hooks=[pre_tool_logger]),
HookMatcher(matcher='Bash', hooks=[pre_tool_logger])
],
'PostToolUse': [
HookMatcher(hooks=[post_tool_logger])
],
'UserPromptSubmit': [
HookMatcher(hooks=[user_prompt_modifier])
]
},
allowed_tools=["Read", "Write", "Bash"]
)
async with ClaudeSDKClient(options=options) as client:
await client.query("List files in current directory")
async for message in client.receive_response():
# Hooks will automatically log tool usage
pass
asyncio.run(main())from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
ToolUseBlock,
ToolResultBlock,
TextBlock
)
import asyncio
async def monitor_progress():
options = ClaudeAgentOptions(
allowed_tools=["Write", "Bash"],
permission_mode="acceptEdits"
)
async with ClaudeSDKClient(options=options) as client:
await client.query(
"Create 5 Python files with different sorting algorithms"
)
# Monitor progress in real-time
files_created = []
async for message in client.receive_messages():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, ToolUseBlock):
if block.name == "Write":
file_path = block.input.get("file_path", "")
print(f"🔨 Creating: {file_path}")
elif isinstance(block, ToolResultBlock):
print(f"✅ Completed tool execution")
elif isinstance(block, TextBlock):
print(f"💭 Claude says: {block.text[:100]}...")
# Check if we've received the final result
if hasattr(message, 'subtype') and message.subtype in ['success', 'error']:
print(f"\n🎯 Task completed!")
break
asyncio.run(monitor_progress())from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
import asyncio
async def create_project():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
permission_mode='acceptEdits',
cwd="/home/user/project"
)
async for message in query(
prompt="Create a Python project structure with setup.py",
options=options
):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, ToolUseBlock):
print(f"Using tool: {block.name}")
asyncio.run(create_project())from claude_agent_sdk import (
query,
CLINotFoundError,
ProcessError,
CLIJSONDecodeError
)
try:
async for message in query(prompt="Hello"):
print(message)
except CLINotFoundError:
print("Please install Claude Code: npm install -g @anthropic-ai/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}")from claude_agent_sdk import ClaudeSDKClient
import asyncio
async def interactive_session():
async with ClaudeSDKClient() as client:
# Send initial message
await client.query("What's the weather like?")
# Process responses
async for msg in client.receive_response():
print(msg)
# Send follow-up
await client.query("Tell me more about that")
# Process follow-up response
async for msg in client.receive_response():
print(msg)
asyncio.run(interactive_session())from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
tool,
create_sdk_mcp_server,
AssistantMessage,
TextBlock
)
import asyncio
from typing import Any
# Define custom tools with @tool decorator
@tool("calculate", "Perform mathematical calculations", {"expression": str})
async def calculate(args: dict[str, Any]) -> dict[str, Any]:
try:
result = eval(args["expression"], {"__builtins__": {}})
return {
"content": [{
"type": "text",
"text": f"Result: {result}"
}]
}
except Exception as e:
return {
"content": [{
"type": "text",
"text": f"Error: {str(e)}"
}],
"is_error": True
}
@tool("get_time", "Get current time", {})
async def get_time(args: dict[str, Any]) -> dict[str, Any]:
from datetime import datetime
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return {
"content": [{
"type": "text",
"text": f"Current time: {current_time}"
}]
}
async def main():
# Create SDK MCP server with custom tools
my_server = create_sdk_mcp_server(
name="utilities",
version="1.0.0",
tools=[calculate, get_time]
)
# Configure options with the server
options = ClaudeAgentOptions(
mcp_servers={"utils": my_server},
allowed_tools=[
"mcp__utils__calculate",
"mcp__utils__get_time"
]
)
# Use ClaudeSDKClient for interactive tool usage
async with ClaudeSDKClient(options=options) as client:
await client.query("What's 123 * 456?")
# Process calculation response
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Calculation: {block.text}")
# Follow up with time query
await client.query("What time is it now?")
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Time: {block.text}")
asyncio.run(main()){}| Configurations du serveur MCP ou chemin vers le fichier de configuration |
permission_mode | PermissionMode | None | None | Mode de permission pour l'utilisation des outils |
continue_conversation | bool | False | Continuer la conversation la plus récente |
resume | str | None | None | ID de session à reprendre |
max_turns | int | None | None | Nombre maximum de tours de conversation |
disallowed_tools | list[str] | [] | Liste des noms d'outils non autorisés |
model | str | None | None | Modèle Claude à utiliser |
output_format | OutputFormat | None | None | Définir le format de sortie pour les résultats de l'agent. Voir Sorties structurées pour les détails |
permission_prompt_tool_name | str | None | None | Nom de l'outil MCP pour les invites de permission |
cwd | str | Path | None | None | Répertoire de travail actuel |
settings | str | None | None | Chemin vers le fichier de paramètres |
add_dirs | list[str | Path] | [] | Répertoires supplémentaires auxquels Claude peut accéder |
env | dict[str, str] | {} | Variables d'environnement |
extra_args | dict[str, str | None] | {} | Arguments CLI supplémentaires à passer directement à la CLI |
max_buffer_size | int | None | None | Nombre maximum d'octets lors de la mise en mémoire tampon de la sortie stdout de la CLI |
debug_stderr | Any | sys.stderr | Obsolète - Objet de type fichier pour la sortie de débogage. Utilisez plutôt le rappel stderr |
stderr | Callable[[str], None] | None | None | Fonction de rappel pour la sortie stderr de la CLI |
can_use_tool | CanUseTool | None | None | Fonction de rappel de permission d'outil |
hooks | dict[HookEvent, list[HookMatcher]] | None | None | Configurations de hook pour intercepter les événements |
user | str | None | None | Identifiant utilisateur |
include_partial_messages | bool | False | Inclure les événements de streaming de messages partiels |
fork_session | bool | False | Lors de la reprise avec resume, bifurquer vers un nouvel ID de session au lieu de continuer la session d'origine |
agents | dict[str, AgentDefinition] | None | None | Sous-agents définis par programmation |
plugins | list[SdkPluginConfig] | [] | Charger les plugins personnalisés à partir de chemins locaux. Voir Plugins pour les détails |
setting_sources | list[SettingSource] | None | None (pas de paramètres) | Contrôler les paramètres du système de fichiers à charger. Lorsqu'il est omis, aucun paramètre n'est chargé. Remarque : Doit inclure "project" pour charger les fichiers CLAUDE.md |