Prérequis

  • Python 3.10+
  • claude-code-sdk depuis PyPI
  • Node.js 18+
  • @anthropic-ai/claude-code depuis NPM

Pour voir le code source du SDK Python, consultez le dépôt claude-code-sdk.

Pour le développement interactif, utilisez IPython : pip install ipython

Installation

Installez claude-code-sdk depuis PyPI et @anthropic-ai/claude-code depuis NPM :

pip install claude-code-sdk
npm install -g @anthropic-ai/claude-code  # Dépendance requise

(Optionnel) Installez IPython pour le développement interactif :

pip install ipython

Démarrage rapide

Créez votre premier agent :

# legal-agent.py
import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def main():
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Vous êtes un assistant juridique. Identifiez les risques et suggérez des améliorations.",
            max_turns=2
        )
    ) as client:
        # Envoyez la requête
        await client.query(
            "Examinez cette clause contractuelle pour d'éventuels problèmes : 'La partie accepte une responsabilité illimitée...'"
        )

        # Diffusez la réponse en streaming
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                # Imprimez le contenu en streaming au fur et à mesure qu'il arrive
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

if __name__ == "__main__":
    asyncio.run(main())

Sauvegardez le code ci-dessus sous legal-agent.py, puis exécutez :

python legal-agent.py

Pour les notebooks IPython/Jupyter, vous pouvez exécuter le code directement dans une cellule :

await main()

Les exemples Python de cette page utilisent asyncio, mais vous pouvez également utiliser anyio.

Utilisation de base

Le SDK Python fournit deux interfaces principales :

1. La classe ClaudeSDKClient (recommandée)

Idéale pour les réponses en streaming, les conversations multi-tours et les applications interactives :

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def main():
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Vous êtes un ingénieur de performance",
            allowed_tools=["Bash", "Read", "WebSearch"],
            max_turns=5
        )
    ) as client:
        await client.query("Analysez les performances du système")

        # Diffusez les réponses en streaming
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

# Exécutez comme script
asyncio.run(main())

# Ou dans IPython/Jupyter : await main()

2. La fonction query

Pour des requêtes simples et ponctuelles :

from claude_code_sdk import query, ClaudeCodeOptions

async for message in query(
    prompt="Analysez les performances du système",
    options=ClaudeCodeOptions(system_prompt="Vous êtes un ingénieur de performance")
):
    if type(message).__name__ == "ResultMessage":
        print(message.result)

Options de configuration

Le SDK Python accepte tous les arguments pris en charge par la ligne de commande via la classe ClaudeCodeOptions.

Paramètres ClaudeCodeOptions

from claude_code_sdk import ClaudeCodeOptions

options = ClaudeCodeOptions(
    # Configuration principale
    system_prompt="Vous êtes un assistant utile",
    append_system_prompt="Instructions système supplémentaires",
    max_turns=5,
    model="claude-3-5-sonnet-20241022",
    max_thinking_tokens=8000,
    
    # Gestion des outils
    allowed_tools=["Bash", "Read", "Write"],
    disallowed_tools=["WebSearch"],
    
    # Gestion des sessions
    continue_conversation=False,
    resume="session-uuid",
    
    # Environnement
    cwd="/chemin/vers/repertoire/travail",
    add_dirs=["/repertoire/contexte/supplementaire"],
    settings="/chemin/vers/settings.json",
    
    # Permissions
    permission_mode="acceptEdits",  # "default", "acceptEdits", "plan", "bypassPermissions"
    permission_prompt_tool_name="mcp__approval_tool",
    
    # Intégration MCP
    mcp_servers={
        "my_server": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-example"],
            "env": {"API_KEY": "votre-cle"}
        }
    },
    
    # Avancé
    extra_args={"--verbose": None, "--custom-flag": "value"}
)

Détails des paramètres

  • system_prompt: str | None - Prompt système personnalisé définissant le rôle de l’agent
  • append_system_prompt: str | None - Texte supplémentaire ajouté au prompt système
  • max_turns: int | None - Nombre maximum de tours de conversation (illimité si None)
  • model: str | None - Modèle Claude spécifique à utiliser
  • max_thinking_tokens: int - Nombre maximum de tokens pour le processus de réflexion de Claude (par défaut : 8000)
  • allowed_tools: list[str] - Outils spécifiquement autorisés à l’utilisation
  • disallowed_tools: list[str] - Outils qui ne doivent pas être utilisés
  • continue_conversation: bool - Continuer la conversation la plus récente (par défaut : False)
  • resume: str | None - UUID de session pour reprendre une conversation spécifique
  • cwd: str | Path | None - Répertoire de travail pour la session
  • add_dirs: list[str | Path] - Répertoires supplémentaires à inclure dans le contexte
  • settings: str | None - Chemin vers le fichier de paramètres ou chaîne JSON des paramètres
  • permission_mode: str | None - Mode de gestion des permissions
  • permission_prompt_tool_name: str | None - Nom de l’outil de prompt de permission personnalisé
  • mcp_servers: dict | str | Path - Configurations des serveurs MCP
  • extra_args: dict[str, str | None] - Passer des drapeaux CLI arbitraires au CLI Claude Code sous-jacent

Modes de permission

  • "default": CLI demande confirmation pour les outils dangereux (comportement par défaut)
  • "acceptEdits": Accepter automatiquement les modifications de fichiers sans demander confirmation
  • "plan": Mode Plan - analyser sans apporter de modifications
  • "bypassPermissions": Autoriser tous les outils sans demander confirmation (à utiliser avec précaution)

Exemple de configuration avancée

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def advanced_agent():
    """Exemple présentant les options de configuration avancées"""
    
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            # Répertoire de travail personnalisé et contexte supplémentaire
            cwd="/racine/projet",
            add_dirs=["/libs/partagees", "/utilitaires/communs"],
            
            # Configuration du modèle et de la réflexion
            model="claude-3-5-sonnet-20241022",
            max_thinking_tokens=12000,
            
            # Contrôle avancé des outils
            allowed_tools=["Read", "Write", "Bash", "Grep"],
            disallowed_tools=["WebSearch", "Bash(rm*)"],
            
            # Paramètres personnalisés et arguments CLI
            settings='{"editor": "vim", "theme": "dark"}',
            extra_args={
                "--verbose": None,
                "--timeout": "300"
            }
        )
    ) as client:
        await client.query("Analysez la structure de la base de code")
        
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

asyncio.run(advanced_agent())

Messages structurés et entrées d’images

Le SDK prend en charge le passage de messages structurés et d’entrées d’images :

from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async with ClaudeSDKClient() as client:
    # Message texte
    await client.query("Analysez ce code pour les problèmes de sécurité")

    # Message avec référence d'image (l'image sera lue par l'outil Read de Claude)
    await client.query("Expliquez ce qui est montré dans screenshot.png")

    # Plusieurs messages en séquence
    messages = [
        "D'abord, analysez le diagramme d'architecture dans diagram.png",
        "Maintenant suggérez des améliorations basées sur le diagramme",
        "Enfin, générez le code d'implémentation"
    ]

    for msg in messages:
        await client.query(msg)
        async for response in client.receive_response():
            # Traitez chaque réponse
            pass

# Le SDK gère les fichiers d'images via l'outil Read intégré de Claude
# Formats pris en charge : PNG, JPG, PDF et autres formats courants

Conversations multi-tours

Méthode 1 : Utilisation de ClaudeSDKClient pour des conversations persistantes

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions, query

# Méthode 1 : Utilisation de ClaudeSDKClient pour des conversations persistantes
async def multi_turn_conversation():
    async with ClaudeSDKClient() as client:
        # Première requête
        await client.query("Refactorisons le module de paiement")
        async for msg in client.receive_response():
            # Traitez la première réponse
            pass

        # Continuez dans la même session
        await client.query("Maintenant ajoutez une gestion d'erreur complète")
        async for msg in client.receive_response():
            # Traitez la continuation
            pass

        # Le contexte de conversation est maintenu tout au long

# Méthode 2 : Utilisation de la fonction query avec gestion de session
async def resume_session():
    # Continuez la conversation la plus récente
    async for message in query(
        prompt="Maintenant refactorisez ceci pour de meilleures performances",
        options=ClaudeCodeOptions(continue_conversation=True)
    ):
        if type(message).__name__ == "ResultMessage":
            print(message.result)

    # Reprenez une session spécifique
    async for message in query(
        prompt="Mettez à jour les tests",
        options=ClaudeCodeOptions(
            resume="550e8400-e29b-41d4-a716-446655440000",
            max_turns=3
        )
    ):
        if type(message).__name__ == "ResultMessage":
            print(message.result)

# Exécutez les exemples
asyncio.run(multi_turn_conversation())

Prompts système personnalisés

Les prompts système définissent le rôle, l’expertise et le comportement de votre agent :

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def specialized_agents():
    # Agent de réponse aux incidents SRE avec streaming
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Vous êtes un expert SRE. Diagnostiquez les problèmes de manière systématique et fournissez des solutions exploitables.",
            max_turns=3
        )
    ) as sre_agent:
        await sre_agent.query("L'API est en panne, enquêtez")

        # Diffusez le processus de diagnostic en streaming
        async for message in sre_agent.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

    # Agent de révision juridique avec prompt personnalisé
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            append_system_prompt="Incluez toujours une gestion d'erreur complète et des tests unitaires.",
            max_turns=2
        )
    ) as dev_agent:
        await dev_agent.query("Refactorisez cette fonction")

        # Collectez la réponse complète
        full_response = []
        async for message in dev_agent.receive_response():
            if type(message).__name__ == "ResultMessage":
                print(message.result)

asyncio.run(specialized_agents())

Outils personnalisés via MCP

Le Protocole de Contexte de Modèle (MCP) vous permet de donner à vos agents des outils et capacités personnalisés :

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def mcp_enabled_agent():
    # Agent juridique avec accès aux documents et streaming
    # Note : Configurez vos serveurs MCP selon vos besoins
    mcp_servers = {
        # Exemple de configuration - décommentez et configurez selon vos besoins :
        # "docusign": {
        #     "command": "npx",
        #     "args": ["-y", "@modelcontextprotocol/server-docusign"],
        #     "env": {"API_KEY": "votre-cle"}
        # }
    }

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            mcp_servers=mcp_servers,
            allowed_tools=["mcp__docusign", "mcp__compliance_db"],
            system_prompt="Vous êtes un avocat d'entreprise spécialisé dans la révision de contrats.",
            max_turns=4
        )
    ) as client:
        await client.query("Examinez ce contrat pour les risques de conformité")

        # Surveillez l'utilisation des outils et les réponses
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'type'):
                        if block.type == 'tool_use':
                            print(f"\n[Utilisation de l'outil : {block.name}]\n")
                        elif hasattr(block, 'text'):
                            print(block.text, end='', flush=True)
                    elif hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

            if type(message).__name__ == "ResultMessage":
                print(f"\n\nRévision terminée. Coût total : ${message.total_cost_usd:.4f}")

asyncio.run(mcp_enabled_agent())

Outil de prompt de permission personnalisé

Implémentez une gestion de permissions personnalisée pour les appels d’outils :

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def use_permission_prompt():
    """Exemple utilisant un outil de prompt de permission personnalisé"""

    # Configuration du serveur MCP
    mcp_servers = {
        # Exemple de configuration - décommentez et configurez selon vos besoins :
        # "security": {
        #     "command": "npx",
        #     "args": ["-y", "@modelcontextprotocol/server-security"],
        #     "env": {"API_KEY": "votre-cle"}
        # }
    }

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            permission_prompt_tool_name="mcp__security__approval_prompt",  # Changé de permission_prompt_tool
            mcp_servers=mcp_servers,
            allowed_tools=["Read", "Grep"],
            disallowed_tools=["Bash(rm*)", "Write"],
            system_prompt="Vous êtes un auditeur de sécurité"
        )
    ) as client:
        await client.query("Analysez et corrigez les problèmes de sécurité")

        # Surveillez l'utilisation des outils et les permissions
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'type'):  # Ajout de la vérification de l'attribut 'type'
                        if block.type == 'tool_use':
                            print(f"[Outil : {block.name}] ", end='')
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

            # Vérifiez les refus de permission dans les messages d'erreur
            if type(message).__name__ == "ErrorMessage":
                if hasattr(message, 'error') and "Permission denied" in str(message.error):
                    print(f"\n⚠️ Permission refusée : {message.error}")

# Exemple d'implémentation de serveur MCP (Python)
# Ceci serait dans votre code de serveur MCP
async def approval_prompt(tool_name: str, input: dict, tool_use_id: str = None):
    """Gestionnaire de prompt de permission personnalisé"""
    # Votre logique personnalisée ici
    if "allow" in str(input):
        return json.dumps({
            "behavior": "allow",
            "updatedInput": input
        })
    else:
        return json.dumps({
            "behavior": "deny",
            "message": f"Permission refusée pour {tool_name}"
        })

asyncio.run(use_permission_prompt())

Formats de sortie

Sortie texte avec streaming

# Sortie texte par défaut avec streaming
async with ClaudeSDKClient() as client:
    await client.query("Expliquez le fichier src/components/Header.tsx")

    # Diffusez le texte en streaming au fur et à mesure qu'il arrive
    async for message in client.receive_response():
        if hasattr(message, 'content'):
            for block in message.content:
                if hasattr(block, 'text'):
                    print(block.text, end='', flush=True)
                    # La sortie se diffuse en temps réel : Ceci est un composant React montrant...

Sortie JSON avec métadonnées

# Collectez tous les messages avec métadonnées
async with ClaudeSDKClient() as client:
    await client.query("Comment fonctionne la couche de données ?")

    messages = []
    result_data = None

    async for message in client.receive_messages():
        messages.append(message)

        # Capturez le message de résultat avec métadonnées
        if type(message).__name__ == "ResultMessage":
            result_data = {
                "result": message.result,
                "cost": message.total_cost_usd,
                "duration": message.duration_ms,
                "num_turns": message.num_turns,
                "session_id": message.session_id
            }
            break

    print(result_data)

Formats d’entrée

import asyncio
from claude_code_sdk import ClaudeSDKClient

async def process_inputs():
    async with ClaudeSDKClient() as client:
        # Entrée texte
        await client.query("Expliquez ce code")
        async for message in client.receive_response():
            # Traitez la réponse en streaming
            pass

        # Entrée image (Claude utilisera automatiquement l'outil Read)
        await client.query("Qu'y a-t-il dans ce diagramme ? screenshot.png")
        async for message in client.receive_response():
            # Traitez l'analyse d'image
            pass

        # Entrées multiples avec contenu mixte
        inputs = [
            "Analysez l'architecture dans diagram.png",
            "Comparez-la avec les meilleures pratiques",
            "Générez une version améliorée"
        ]

        for prompt in inputs:
            await client.query(prompt)
            async for message in client.receive_response():
                # Traitez chaque réponse
                pass

asyncio.run(process_inputs())

Exemples d’intégration d’agents

Agent de réponse aux incidents SRE

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def investigate_incident(incident_description: str, severity: str = "medium"):
    """Agent de réponse automatisée aux incidents avec streaming en temps réel"""

    # Configuration du serveur MCP pour les outils de surveillance
    mcp_servers = {
        # Exemple de configuration - décommentez et configurez selon vos besoins :
        # "datadog": {
        #     "command": "npx",
        #     "args": ["-y", "@modelcontextprotocol/server-datadog"],
        #     "env": {"API_KEY": "votre-cle-datadog", "APP_KEY": "votre-cle-app"}
        # }
    }

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Vous êtes un expert SRE. Diagnostiquez les problèmes de manière systématique et f ournissez des solutions exploitables.",
            max_turns=6,
            allowed_tools=["Bash", "Read", "WebSearch", "mcp__datadog"],
            mcp_servers=mcp_servers
        )
    ) as client:
        # Envoyez les détails de l'incident
        prompt = f"Incident : {incident_description} (Gravité : {severity})"
        print(f"🚨 Enquête : {prompt}\n")
        await client.query(prompt)

        # Diffusez le processus d'enquête en streaming
        investigation_log = []
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'type'):
                        if block.type == 'tool_use':
                            print(f"[{block.name}] ", end='')
                    if hasattr(block, 'text'):
                        text = block.text
                        print(text, end='', flush=True)
                        investigation_log.append(text)

            # Capturez le résultat final
            if type(message).__name__ == "ResultMessage":
                return {
                    'analysis': ''.join(investigation_log),
                    'cost': message.total_cost_usd,
                    'duration_ms': message.duration_ms
                }

# Utilisation
result = await investigate_incident("L'API de paiement renvoie des erreurs 500", "high")
print(f"\n\nEnquête terminée. Coût : ${result['cost']:.4f}")

Révision de sécurité automatisée

import subprocess
import asyncio
import json
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def audit_pr(pr_number: int):
    """Agent d'audit de sécurité pour les pull requests avec retour en streaming"""
    # Obtenez le diff de la PR
    pr_diff = subprocess.check_output(
        ["gh", "pr", "diff", str(pr_number)],
        text=True
    )

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Vous êtes un ingénieur de sécurité. Examinez cette PR pour les vulnérabilités, les modèles non sécurisés et les problèmes de conformité.",
            max_turns=3,
            allowed_tools=["Read", "Grep", "WebSearch"]
        )
    ) as client:
        print(f"🔍 Audit de la PR #{pr_number}\n")
        await client.query(pr_diff)

        findings = []
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        # Diffusez les découvertes en streaming au fur et à mesure qu'elles sont découvertes
                        print(block.text, end='', flush=True)
                        findings.append(block.text)

            if type(message).__name__ == "ResultMessage":
                return {
                    'pr_number': pr_number,
                    'findings': ''.join(findings),
                    'metadata': {
                        'cost': message.total_cost_usd,
                        'duration': message.duration_ms,
                        'severity': 'high' if 'vulnerability' in ''.join(findings).lower() else 'medium'
                    }
                }

# Utilisation
report = await audit_pr(123)
print(f"\n\nAudit terminé. Gravité : {report['metadata']['severity']}")
print(json.dumps(report, indent=2))

Assistant juridique multi-tours

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def legal_review():
    """Révision de documents juridiques avec session persistante et streaming"""

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Vous êtes un avocat d'entreprise. Fournissez une analyse juridique détaillée.",
            max_turns=2
        )
    ) as client:
        # Révision en plusieurs étapes dans la même session
        steps = [
            "Examinez contract.pdf pour les clauses de responsabilité",
            "Vérifiez la conformité aux exigences RGPD",
            "Générez un résumé exécutif des risques"
        ]

        review_results = []

        for step in steps:
            print(f"\n📋 {step}\n")
            await client.query(step)

            step_result = []
            async for message in client.receive_response():
                if hasattr(message, 'content'):
                    for block in message.content:
                        if hasattr(block, 'text'):
                            text = block.text
                            print(text, end='', flush=True)
                            step_result.append(text)

                if type(message).__name__ == "ResultMessage":
                    review_results.append({
                        'step': step,
                        'analysis': ''.join(step_result),
                        'cost': message.total_cost_usd
                    })

        # Résumé
        total_cost = sum(r['cost'] for r in review_results)
        print(f"\n\n✅ Révision juridique terminée. Coût total : ${total_cost:.4f}")
        return review_results

# Utilisation
results = await legal_review()

Meilleures pratiques spécifiques à Python

Modèles clés

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

# Utilisez toujours des gestionnaires de contexte
async with ClaudeSDKClient() as client:
    await client.query("Analysez ce code")
    async for msg in client.receive_response():
        # Traitez les messages en streaming
        pass

# Exécutez plusieurs agents simultanément
async with ClaudeSDKClient() as reviewer, ClaudeSDKClient() as tester:
    await asyncio.gather(
        reviewer.query("Examinez main.py"),
        tester.query("Écrivez des tests pour main.py")
    )

# Gestion d'erreur
from claude_code_sdk import CLINotFoundError, ProcessError

try:
    async with ClaudeSDKClient() as client:
        # Votre code ici
        pass
except CLINotFoundError:
    print("Installez CLI : npm install -g @anthropic-ai/claude-code")
except ProcessError as e:
    print(f"Erreur de processus : {e}")

# Collectez la réponse complète avec métadonnées
async def get_response(client, prompt):
    await client.query(prompt)
    text = []
    async for msg in client.receive_response():
        if hasattr(msg, 'content'):
            for block in msg.content:
                if hasattr(block, 'text'):
                    text.append(block.text)
        if type(msg).__name__ == "ResultMessage":
            return {'text': ''.join(text), 'cost': msg.total_cost_usd}

Conseils IPython/Jupyter

# Dans Jupyter, utilisez await directement dans les cellules
client = ClaudeSDKClient()
await client.connect()
await client.query("Analysez data.csv")
async for msg in client.receive_response():
    print(msg)
await client.disconnect()

# Créez des fonctions d'aide réutilisables
async def stream_print(client, prompt):
    await client.query(prompt)
    async for msg in client.receive_response():
        if hasattr(msg, 'content'):
            for block in msg.content:
                if hasattr(block, 'text'):
                    print(block.text, end='', flush=True)

Ressources connexes