Loading...
    • Entwicklerleitfaden
    • API-Referenz
    • MCP
    • Ressourcen
    • Versionshinweise
    Search...
    ⌘K
    Erste Schritte
    Einführung in ClaudeSchnelleinstieg
    Modelle & Preise
    ModellübersichtModellauswahlNeuerungen in Claude 4.5Migration zu Claude 4.5ModellabschreibungenPreise
    Mit Claude entwickeln
    FunktionsübersichtMessages API verwendenKontextfensterBest Practices für Prompts
    Fähigkeiten
    Prompt-CachingKontext-BearbeitungErweitertes DenkenAufwandStreaming MessagesBatch-VerarbeitungZitationenMehrsprachige UnterstützungToken-ZählungEmbeddingsVisionPDF-UnterstützungFiles APISuchergebnisseStrukturierte Ausgaben
    Tools
    ÜbersichtTool-Nutzung implementierenFeingranulares Tool-StreamingBash-ToolCode-Ausführungs-ToolProgrammatischer Tool-AufrufComputer-Use-ToolText-Editor-ToolWeb-Fetch-ToolWeb-Such-ToolMemory-ToolTool-Such-Tool
    Agent Skills
    ÜbersichtSchnelleinstiegBest PracticesSkills mit der API verwenden
    Agent SDK
    ÜbersichtSchnelleinstiegTypeScript SDKTypeScript V2 (Vorschau)Python SDKMigrationsleitfaden
    Streaming-EingabeBerechtigungen verwaltenAusführung mit Hooks steuernSitzungsverwaltungStrukturierte Ausgaben im SDKAgent SDK hostenKI-Agenten sicher bereitstellenSystem-Prompts ändernMCP im SDKBenutzerdefinierte ToolsSubagents im SDKSlash-Befehle im SDKAgent Skills im SDKKosten und Nutzung verfolgenTodo-ListenPlugins im SDK
    MCP in der API
    MCP-ConnectorRemote MCP-Server
    Claude auf Plattformen von Drittanbietern
    Amazon BedrockMicrosoft FoundryVertex AI
    Prompt Engineering
    ÜbersichtPrompt-GeneratorPrompt-Vorlagen verwendenPrompt-VerbessererKlar und direkt seinBeispiele verwenden (Multishot-Prompting)Claude denken lassen (CoT)XML-Tags verwendenClaude eine Rolle geben (System-Prompts)Claudes Antwort vorausfüllenKomplexe Prompts verkettenTipps für langen KontextTipps für erweitertes Denken
    Testen & Evaluieren
    Erfolgskriterien definierenTestfälle entwickelnEvaluierungs-Tool verwendenLatenz reduzieren
    Schutzmaßnahmen verstärken
    Halluzinationen reduzierenAusgabekonsistenz erhöhenJailbreaks abschwächenStreaming-AblehnungenPrompt-Lecks reduzierenClaude im Charakter halten
    Verwaltung und Überwachung
    Admin API ÜbersichtNutzungs- und Kosten-APIClaude Code Analytics API
    Console
    Log in
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Partners

    • Amazon Bedrock
    • Google Cloud's Vertex AI

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Help and security

    • Availability
    • Status
    • Support
    • Discord

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy
    Leitfäden

    Agent-Verhalten mit Hooks abfangen und steuern

    Agent-Verhalten an wichtigen Ausführungspunkten mit Hooks abfangen und anpassen

    Hooks ermöglichen es Ihnen, die Agent-Ausführung an wichtigen Punkten abzufangen, um Validierung, Protokollierung, Sicherheitskontrollen oder benutzerdefinierte Logik hinzuzufügen. Mit Hooks können Sie:

    • Gefährliche Operationen blockieren, bevor sie ausgeführt werden, wie destruktive Shell-Befehle oder nicht autorisierter Dateizugriff
    • Protokollieren und überprüfen jeden Tool-Aufruf für Compliance, Debugging oder Analytik
    • Eingaben und Ausgaben transformieren, um Daten zu bereinigen, Anmeldedaten einzufügen oder Dateipfade umzuleiten
    • Menschliche Genehmigung erfordern für sensible Aktionen wie Datenbankschreibvorgänge oder API-Aufrufe
    • Sitzungslebenszyklus verfolgen, um den Status zu verwalten, Ressourcen freizugeben oder Benachrichtigungen zu senden

    Ein Hook hat zwei Teile:

    1. Die Callback-Funktion: die Logik, die ausgeführt wird, wenn der Hook ausgelöst wird
    2. Die Hook-Konfiguration: teilt dem SDK mit, welches Ereignis abgefangen werden soll (wie PreToolUse) und welche Tools abgeglichen werden sollen

    Das folgende Beispiel blockiert den Agent daran, -Dateien zu ändern. Definieren Sie zunächst einen Callback, der den Dateipfad überprüft, und übergeben Sie ihn dann an , um ihn vor jedem Write- oder Edit-Tool-Aufruf auszuführen:

    • Verfügbare Hooks
    • Häufige Anwendungsfälle
    • Hooks konfigurieren
    • Matcher
    • Callback-Funktionseingaben
    • Eingabedaten
    • Callback-Ausgaben
    • Erweiterte Szenarien handhaben
    • Mehrere Hooks verketten
    • Tool-spezifische Matcher mit Regex
    • Subagent-Aktivität verfolgen
    • Asynchrone Operationen in Hooks
    • Benachrichtigungen senden (nur TypeScript)
    • Häufige Probleme beheben
    • Hook wird nicht ausgelöst
    • Matcher filtert nicht wie erwartet
    • Hook-Timeout
    • Tool unerwartet blockiert
    • Geänderte Eingabe nicht angewendet
    • Sitzungs-Hooks nicht verfügbar
    • Subagent-Berechtigungsaufforderungen vervielfachen sich
    • Rekursive Hook-Schleifen mit Subagents
    • systemMessage erscheint nicht in der Ausgabe
    • Weitere Informationen
    .env
    query()
    import asyncio
    from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher
    
    # Define a hook callback that receives tool call details
    async def protect_env_files(input_data, tool_use_id, context):
        # Extract the file path from the tool's input arguments
        file_path = input_data['tool_input'].get('file_path', '')
        file_name = file_path.split('/')[-1]
    
        # Block the operation if targeting a .env file
        if file_name == '.env':
            return {
                'hookSpecificOutput': {
                    'hookEventName': input_data['hook_event_name'],
                    'permissionDecision': 'deny',
                    'permissionDecisionReason': 'Cannot modify .env files'
                }
            }
    
        # Return empty object to allow the operation
        return {}
    
    async def main():
        async for message in query(
            prompt="Update the database configuration",
            options=ClaudeAgentOptions(
                hooks={
                    # Register the hook for PreToolUse events
                    # The matcher filters to only Write and Edit tool calls
                    'PreToolUse': [HookMatcher(matcher='Write|Edit', hooks=[protect_env_files])]
                }
            )
        ):
            print(message)
    
    asyncio.run(main())

    Dies ist ein PreToolUse-Hook. Er wird vor der Ausführung des Tools ausgeführt und kann Operationen basierend auf Ihrer Logik blockieren oder zulassen. Der Rest dieses Leitfadens behandelt alle verfügbaren Hooks, ihre Konfigurationsoptionen und Muster für häufige Anwendungsfälle.

    Verfügbare Hooks

    Das SDK bietet Hooks für verschiedene Phasen der Agent-Ausführung. Einige Hooks sind in beiden SDKs verfügbar, während andere nur für TypeScript verfügbar sind, da das Python SDK sie nicht unterstützt.

    Hook-EreignisPython SDKTypeScript SDKWas löst es ausBeispiel-Anwendungsfall
    PreToolUseJaJaTool-Aufrufanforderung (kann blockiert oder geändert werden)Gefährliche Shell-Befehle blockieren
    PostToolUseJaJaTool-AusführungsergebnisAlle Dateiänderungen im Audit-Trail protokollieren
    PostToolUseFailureNeinJaTool-AusführungsfehlerTool-Fehler behandeln oder protokollieren
    UserPromptSubmitJaJaBenutzer-Prompt-EinreichungZusätzlichen Kontext in Prompts einfügen
    StopJaJaAgent-Ausführung stoppenSitzungsstatus vor dem Beenden speichern
    SubagentStartNeinJaSubagent-InitialisierungParallele Task-Erzeugung verfolgen
    SubagentStopJaJaSubagent-FertigstellungErgebnisse aus parallelen Tasks aggregieren
    PreCompactJaJaAnforderung zur GesprächskomprimierungVollständiges Transkript vor der Zusammenfassung archivieren
    PermissionRequestNeinJaBerechtigungsdialog würde angezeigtBenutzerdefinierte Berechtigungsbehandlung
    SessionStartNeinJaSitzungsinitialisierungProtokollierung und Telemetrie initialisieren
    SessionEndNeinJaSitzungsbeendigungTemporäre Ressourcen bereinigen
    NotificationNeinJaAgent-StatusmeldungenAgent-Status-Updates an Slack oder PagerDuty senden

    Häufige Anwendungsfälle

    Hooks sind flexibel genug, um viele verschiedene Szenarien zu handhaben. Hier sind einige der häufigsten Muster, organisiert nach Kategorie.

    Hooks konfigurieren

    Um einen Hook für Ihren Agent zu konfigurieren, übergeben Sie den Hook im Parameter options.hooks beim Aufrufen von query():

    async for message in query(
        prompt="Your prompt",
        options=ClaudeAgentOptions(
            hooks={
                'PreToolUse': [HookMatcher(matcher='Bash', hooks=[my_callback])]
            }
        )
    ):
        print(message)

    Die hooks-Option ist ein Wörterbuch (Python) oder Objekt (TypeScript), wobei:

    • Schlüssel Hook-Ereignisnamen sind (z. B. 'PreToolUse', 'PostToolUse', 'Stop')
    • Werte Arrays von Matchern sind, die jeweils ein optionales Filtermuster und Ihre Callback-Funktionen enthalten

    Ihre Hook-Callback-Funktionen erhalten Eingabedaten über das Ereignis und geben eine Antwort zurück, damit der Agent weiß, ob die Operation zulässig, blockiert oder geändert werden soll.

    Matcher

    Verwenden Sie Matcher, um zu filtern, welche Tools Ihre Callbacks auslösen:

    OptionTypStandardBeschreibung
    matcherstringundefinedRegex-Muster zum Abgleich von Tool-Namen. Integrierte Tools umfassen Bash, Read, Write, Edit, Glob, Grep, WebFetch, Task und andere. MCP-Tools verwenden das Muster mcp__<server>__<action>.
    hooksHookCallback[]-Erforderlich. Array von Callback-Funktionen, die ausgeführt werden, wenn das Muster übereinstimmt
    timeoutnumber60Timeout in Sekunden; erhöhen Sie es für Hooks, die externe API-Aufrufe tätigen

    Verwenden Sie das matcher-Muster, um wenn möglich spezifische Tools anzusteuern. Ein Matcher mit 'Bash' wird nur für Bash-Befehle ausgeführt, während das Weglassen des Musters Ihre Callbacks für jeden Tool-Aufruf ausführt. Beachten Sie, dass Matcher nur nach Tool-Namen filtern, nicht nach Dateipfaden oder anderen Argumenten – um nach Dateipfad zu filtern, überprüfen Sie tool_input.file_path in Ihrem Callback.

    Matcher gelten nur für Tool-basierte Hooks (PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest). Für Lifecycle-Hooks wie Stop, SessionStart und Notification werden Matcher ignoriert und der Hook wird für alle Ereignisse dieses Typs ausgelöst.

    Tool-Namen entdecken: Überprüfen Sie das tools-Array in der anfänglichen Systemnachricht, wenn Ihre Sitzung startet, oder fügen Sie einen Hook ohne Matcher hinzu, um alle Tool-Aufrufe zu protokollieren.

    MCP-Tool-Benennung: MCP-Tools beginnen immer mit mcp__ gefolgt vom Servernamen und der Aktion: mcp__<server>__<action>. Wenn Sie beispielsweise einen Server namens playwright konfigurieren, werden seine Tools mcp__playwright__browser_screenshot, mcp__playwright__browser_click usw. benannt. Der Servername stammt aus dem Schlüssel, den Sie in der mcpServers-Konfiguration verwenden.

    Dieses Beispiel verwendet einen Matcher, um einen Hook nur für dateiändernde Tools auszuführen, wenn das PreToolUse-Ereignis ausgelöst wird:

    options = ClaudeAgentOptions(
        hooks={
            'PreToolUse': [
                HookMatcher(matcher='Write|Edit', hooks=[validate_file_path])
            ]
        }
    )

    Callback-Funktionseingaben

    Jeder Hook-Callback erhält drei Argumente:

    1. Eingabedaten (dict / HookInput): Ereignisdetails. Siehe Eingabedaten für Felder
    2. Tool-Verwendungs-ID (str | None / string | null): Korrelieren Sie PreToolUse- und PostToolUse-Ereignisse
    3. Kontext (HookContext): In TypeScript enthält eine signal-Eigenschaft (AbortSignal) zur Stornierung. Übergeben Sie dies an asynchrone Operationen wie fetch(), damit sie automatisch storniert werden, wenn der Hook ein Timeout hat. In Python ist dieses Argument für zukünftige Verwendung reserviert.

    Eingabedaten

    Das erste Argument für Ihren Hook-Callback enthält Informationen über das Ereignis. Feldnamen sind über SDKs identisch (beide verwenden snake_case).

    Gemeinsame Felder in allen Hook-Typen:

    FeldTypBeschreibung
    hook_event_namestringDer Hook-Typ (PreToolUse, PostToolUse usw.)
    session_idstringAktuelle Sitzungskennung
    transcript_pathstringPfad zum Gesprächstranskript
    cwdstringAktuelles Arbeitsverzeichnis

    Hook-spezifische Felder variieren je nach Hook-Typ. Elemente, die mit TS gekennzeichnet sind, sind nur im TypeScript SDK verfügbar:

    FeldTypBeschreibungHooks
    tool_namestringName des aufgerufenen ToolsPreToolUse, PostToolUse, PostToolUseFailureTS, PermissionRequestTS
    tool_inputobjectAn das Tool übergebene ArgumentePreToolUse, PostToolUse, PostToolUseFailureTS, PermissionRequestTS
    tool_responseanyVon der Tool-Ausführung zurückgegebenes ErgebnisPostToolUse
    errorstringFehlermeldung aus Tool-AusführungsfehlerPostToolUseFailureTS
    is_interruptbooleanOb der Fehler durch eine Unterbrechung verursacht wurdePostToolUseFailureTS
    promptstringDer Text des Benutzer-PromptsUserPromptSubmit
    stop_hook_activebooleanOb ein Stop-Hook gerade verarbeitet wirdStop, SubagentStop
    agent_idstringEindeutige Kennung für den SubagentSubagentStartTS, SubagentStopTS
    agent_typestringTyp/Rolle des SubagentsSubagentStartTS
    agent_transcript_pathstringPfad zum Gesprächstranskript des SubagentsSubagentStopTS
    triggerstringWas die Komprimierung ausgelöst hat: manual oder autoPreCompact
    custom_instructionsstringBenutzerdefinierte Anweisungen für die KomprimierungPreCompact
    permission_suggestionsarrayVorgeschlagene Berechtigungsaktualisierungen für das ToolPermissionRequestTS
    sourcestringWie die Sitzung gestartet wurde: startup, resume, clear oder compactSessionStartTS
    reasonstringWarum die Sitzung endete: clear, logout, prompt_input_exit, bypass_permissions_disabled oder otherSessionEndTS
    messagestringStatusmeldung vom AgentNotificationTS
    notification_typestringArt der Benachrichtigung: permission_prompt, idle_prompt, auth_success oder elicitation_dialogNotificationTS
    titlestringOptionaler Titel, der vom Agent gesetzt wirdNotificationTS

    Der folgende Code definiert einen Hook-Callback, der tool_name und tool_input verwendet, um Details zu jedem Tool-Aufruf zu protokollieren:

    async def log_tool_calls(input_data, tool_use_id, context):
        if input_data['hook_event_name'] == 'PreToolUse':
            print(f"Tool: {input_data['tool_name']}")
            print(f"Input: {input_data['tool_input']}")
        return {}

    Callback-Ausgaben

    Ihre Callback-Funktion gibt ein Objekt zurück, das dem SDK mitteilt, wie es fortfahren soll. Geben Sie ein leeres Objekt {} zurück, um die Operation ohne Änderungen zuzulassen. Um die Operation zu blockieren, zu ändern oder Kontext hinzuzufügen, geben Sie ein Objekt mit einem hookSpecificOutput-Feld zurück, das Ihre Entscheidung enthält.

    Top-Level-Felder (außerhalb von hookSpecificOutput):

    FeldTypBeschreibung
    continuebooleanOb der Agent nach diesem Hook fortfahren soll (Standard: true)
    stopReasonstringMeldung, die angezeigt wird, wenn continue false ist
    suppressOutputbooleanStdout aus dem Transkript ausblenden (Standard: false)
    systemMessagestringMeldung, die in das Gespräch für Claude eingefügt wird

    Felder in hookSpecificOutput:

    FeldTypHooksBeschreibung
    hookEventNamestringAlleErforderlich. Verwenden Sie input.hook_event_name, um das aktuelle Ereignis abzugleichen
    permissionDecision'allow' | 'deny' | 'ask'PreToolUseSteuert, ob das Tool ausgeführt wird
    permissionDecisionReasonstringPreToolUseErklärung, die Claude für die Entscheidung angezeigt wird
    updatedInputobjectPreToolUseGeänderte Tool-Eingabe (erfordert permissionDecision: 'allow')
    additionalContextstringPostToolUse, UserPromptSubmit, SessionStartTS, SubagentStartTSKontext, der zum Gespräch hinzugefügt wird

    Dieses Beispiel blockiert Schreibvorgänge in das /etc-Verzeichnis und fügt gleichzeitig eine Systemnachricht ein, um Claude an sichere Dateipraktiken zu erinnern:

    async def block_etc_writes(input_data, tool_use_id, context):
        file_path = input_data['tool_input'].get('file_path', '')
    
        if file_path.startswith('/etc'):
            return {
                # Top-level field: inject guidance into the conversation
                'systemMessage': 'Remember: system directories like /etc are protected.',
                # hookSpecificOutput: block the operation
                'hookSpecificOutput': {
                    'hookEventName': input_data['hook_event_name'],
                    'permissionDecision': 'deny',
                    'permissionDecisionReason': 'Writing to /etc is not allowed'
                }
            }
        return {}

    Berechtigungsentscheidungsfluss

    Wenn mehrere Hooks oder Berechtigungsregeln gelten, wertet das SDK sie in dieser Reihenfolge aus:

    1. Deny-Regeln werden zuerst überprüft (jede Übereinstimmung = sofortige Ablehnung).
    2. Ask-Regeln werden als zweite überprüft.
    3. Allow-Regeln werden als dritte überprüft.
    4. Standard auf Ask, wenn nichts übereinstimmt.

    Wenn ein Hook deny zurückgibt, wird die Operation blockiert – andere Hooks, die allow zurückgeben, können dies nicht überschreiben.

    Ein Tool blockieren

    Geben Sie eine Deny-Entscheidung zurück, um die Tool-Ausführung zu verhindern:

    async def block_dangerous_commands(input_data, tool_use_id, context):
        if input_data['hook_event_name'] != 'PreToolUse':
            return {}
    
        command = input_data['tool_input'].get('command', '')
    
        if 'rm -rf /' in command:
            return {
                'hookSpecificOutput': {
                    'hookEventName': input_data['hook_event_name'],
                    'permissionDecision': 'deny',
                    'permissionDecisionReason': 'Dangerous command blocked: rm -rf /'
                }
            }
        return {}

    Tool-Eingabe ändern

    Geben Sie aktualisierte Eingabe zurück, um zu ändern, was das Tool erhält:

    async def redirect_to_sandbox(input_data, tool_use_id, context):
        if input_data['hook_event_name'] != 'PreToolUse':
            return {}
    
        if input_data['tool_name'] == 'Write':
            original_path = input_data['tool_input'].get('file_path', '')
            return {
                'hookSpecificOutput': {
                    'hookEventName': input_data['hook_event_name'],
                    'permissionDecision': 'allow',
                    'updatedInput': {
                        **input_data['tool_input'],
                        'file_path': f'/sandbox{original_path}'
                    }
                }
            }
        return {}

    Wenn Sie updatedInput verwenden, müssen Sie auch permissionDecision einschließen. Geben Sie immer ein neues Objekt zurück, anstatt das ursprüngliche tool_input zu mutieren.

    Eine Systemnachricht hinzufügen

    Fügen Sie Kontext in das Gespräch ein:

    async def add_security_reminder(input_data, tool_use_id, context):
        return {
            'systemMessage': 'Remember to follow security best practices.'
        }

    Spezifische Tools automatisch genehmigen

    Umgehen Sie Berechtigungsaufforderungen für vertrauenswürdige Tools. Dies ist nützlich, wenn Sie möchten, dass bestimmte Operationen ohne Benutzerbestätigung ausgeführt werden:

    async def auto_approve_read_only(input_data, tool_use_id, context):
        if input_data['hook_event_name'] != 'PreToolUse':
            return {}
    
        read_only_tools = ['Read', 'Glob', 'Grep', 'LS']
        if input_data['tool_name'] in read_only_tools:
            return {
                'hookSpecificOutput': {
                    'hookEventName': input_data['hook_event_name'],
                    'permissionDecision': 'allow',
                    'permissionDecisionReason': 'Read-only tool auto-approved'
                }
            }
        return {}

    Das Feld permissionDecision akzeptiert drei Werte: 'allow' (automatisch genehmigen), 'deny' (blockieren) oder 'ask' (zur Bestätigung auffordern).

    Erweiterte Szenarien handhaben

    Diese Muster helfen Ihnen, anspruchsvollere Hook-Systeme für komplexe Anwendungsfälle zu erstellen.

    Mehrere Hooks verketten

    Hooks werden in der Reihenfolge ausgeführt, in der sie im Array erscheinen. Halten Sie jeden Hook auf eine einzelne Verantwortung konzentriert und verketten Sie mehrere Hooks für komplexe Logik. Dieses Beispiel führt alle vier Hooks für jeden Tool-Aufruf aus (kein Matcher angegeben):

    options = ClaudeAgentOptions(
        hooks={
            'PreToolUse': [
                HookMatcher(hooks=[rate_limiter]),        # First: check rate limits
                HookMatcher(hooks=[authorization_check]), # Second: verify permissions
                HookMatcher(hooks=[input_sanitizer]),     # Third: sanitize inputs
                HookMatcher(hooks=[audit_logger])         # Last: log the action
            ]
        }
    )

    Tool-spezifische Matcher mit Regex

    Verwenden Sie Regex-Muster, um mehrere Tools abzugleichen:

    options = ClaudeAgentOptions(
        hooks={
            'PreToolUse': [
                # Match file modification tools
                HookMatcher(matcher='Write|Edit|Delete', hooks=[file_security_hook]),
    
                # Match all MCP tools
                HookMatcher(matcher='^mcp__', hooks=[mcp_audit_hook]),
    
                # Match everything (no matcher)
                HookMatcher(hooks=[global_logger])
            ]
        }
    )

    Matcher gleichen nur Tool-Namen ab, nicht Dateipfade oder andere Argumente. Um nach Dateipfad zu filtern, überprüfen Sie tool_input.file_path in Ihrem Hook-Callback.

    Subagent-Aktivität verfolgen

    Verwenden Sie SubagentStop-Hooks, um die Subagent-Fertigstellung zu überwachen. Die tool_use_id hilft, Parent-Agent-Aufrufe mit ihren Subagents zu korrelieren:

    async def subagent_tracker(input_data, tool_use_id, context):
        if input_data['hook_event_name'] == 'SubagentStop':
            print(f"[SUBAGENT] Completed")
            print(f"  Tool use ID: {tool_use_id}")
            print(f"  Stop hook active: {input_data.get('stop_hook_active')}")
        return {}
    
    options = ClaudeAgentOptions(
        hooks={
            'SubagentStop': [HookMatcher(hooks=[subagent_tracker])]
        }
    )

    Asynchrone Operationen in Hooks

    Hooks können asynchrone Operationen wie HTTP-Anfragen ausführen. Behandeln Sie Fehler elegant, indem Sie Ausnahmen abfangen, anstatt sie zu werfen. In TypeScript übergeben Sie signal an fetch(), damit die Anfrage storniert wird, wenn der Hook ein Timeout hat:

    import aiohttp
    from datetime import datetime
    
    async def webhook_notifier(input_data, tool_use_id, context):
        if input_data['hook_event_name'] != 'PostToolUse':
            return {}
    
        try:
            async with aiohttp.ClientSession() as session:
                await session.post(
                    'https://api.example.com/webhook',
                    json={
                        'tool': input_data['tool_name'],
                        'timestamp': datetime.now().isoformat()
                    }
                )
        except Exception as e:
            print(f'Webhook request failed: {e}')
    
        return {}

    Benachrichtigungen senden (nur TypeScript)

    Verwenden Sie Notification-Hooks, um Status-Updates vom Agent zu erhalten und diese an externe Dienste wie Slack oder Monitoring-Dashboards weiterzuleiten:

    TypeScript
    import { query, HookCallback, NotificationHookInput } from "@anthropic-ai/claude-agent-sdk";
    
    const notificationHandler: HookCallback = async (input, toolUseID, { signal }) => {
      const notification = input as NotificationHookInput;
    
      await fetch('https://hooks.slack.com/services/YOUR/WEBHOOK/URL', {
        method: 'POST',
        body: JSON.stringify({
          text: `Agent status: ${notification.message}`
        }),
        signal
      });
    
      return {};
    };
    
    for await (const message of query({
      prompt: "Analyze this codebase",
      options: {
        hooks: {
          Notification: [{ hooks: [notificationHandler] }]
        }
      }
    })) {
      console.log(message);
    }

    Häufige Probleme beheben

    Dieser Abschnitt behandelt häufige Probleme und deren Lösungen.

    Hook wird nicht ausgelöst

    • Überprüfen Sie, ob der Hook-Ereignisname korrekt und case-sensitiv ist (PreToolUse, nicht preToolUse)
    • Überprüfen Sie, ob Ihr Matcher-Muster genau mit dem Tool-Namen übereinstimmt
    • Stellen Sie sicher, dass der Hook unter dem richtigen Ereignistyp in options.hooks ist
    • Für SubagentStop, Stop, SessionStart, SessionEnd und Notification-Hooks werden Matcher ignoriert. Diese Hooks werden für alle Ereignisse dieses Typs ausgelöst.
    • Hooks werden möglicherweise nicht ausgelöst, wenn der Agent das max_turns-Limit erreicht, da die Sitzung endet, bevor Hooks ausgeführt werden können

    Matcher filtert nicht wie erwartet

    Matcher gleichen nur Tool-Namen ab, nicht Dateipfade oder andere Argumente. Um nach Dateipfad zu filtern, überprüfen Sie tool_input.file_path in Ihrem Hook:

    const myHook: HookCallback = async (input, toolUseID, { signal }) => {
      const preInput = input as PreToolUseHookInput;
      const filePath = preInput.tool_input?.file_path as string;
      if (!filePath?.endsWith('.md')) return {};  // Skip non-markdown files
      // Process markdown files...
    };

    Hook-Timeout

    • Erhöhen Sie den timeout-Wert in der HookMatcher-Konfiguration
    • Verwenden Sie das AbortSignal aus dem dritten Callback-Argument, um die Stornierung elegant in TypeScript zu handhaben

    Tool unerwartet blockiert

    • Überprüfen Sie alle PreToolUse-Hooks auf permissionDecision: 'deny'-Rückgaben
    • Fügen Sie Protokollierung zu Ihren Hooks hinzu, um zu sehen, welche permissionDecisionReason sie zurückgeben
    • Überprüfen Sie, ob Matcher-Muster nicht zu breit sind (ein leerer Matcher passt zu allen Tools)

    Geänderte Eingabe nicht angewendet

    • Stellen Sie sicher, dass updatedInput in hookSpecificOutput ist, nicht auf der obersten Ebene:

      return {
        hookSpecificOutput: {
          hookEventName: input.hook_event_name,
          permissionDecision: 'allow',
          updatedInput: { command: 'new command' }
        }
      };
    • Sie müssen auch permissionDecision: 'allow' zurückgeben, damit die Eingabeänderung wirksam wird

    • Schließen Sie hookEventName in hookSpecificOutput ein, um zu identifizieren, welcher Hook-Typ die Ausgabe ist

    Sitzungs-Hooks nicht verfügbar

    SessionStart, SessionEnd und Notification-Hooks sind nur im TypeScript SDK verfügbar. Das Python SDK unterstützt diese Ereignisse aufgrund von Setup-Einschränkungen nicht.

    Subagent-Berechtigungsaufforderungen vervielfachen sich

    Beim Erzeugen mehrerer Subagents kann jeder einzelne Berechtigungen separat anfordern. Subagents erben nicht automatisch Parent-Agent-Berechtigungen. Um wiederholte Aufforderungen zu vermeiden, verwenden Sie PreToolUse-Hooks, um spezifische Tools automatisch zu genehmigen, oder konfigurieren Sie Berechtigungsregeln, die für Subagent-Sitzungen gelten.

    Rekursive Hook-Schleifen mit Subagents

    Ein UserPromptSubmit-Hook, der Subagents erzeugt, kann unendliche Schleifen erstellen, wenn diese Subagents denselben Hook auslösen. Um dies zu verhindern:

    • Überprüfen Sie auf einen Subagent-Indikator in der Hook-Eingabe, bevor Sie Subagents erzeugen
    • Verwenden Sie das Feld parent_tool_use_id, um zu erkennen, ob Sie sich bereits in einem Subagent-Kontext befinden
    • Beschränken Sie Hooks so, dass sie nur für die Top-Level-Agent-Sitzung ausgeführt werden

    systemMessage erscheint nicht in der Ausgabe

    Das Feld systemMessage fügt Kontext zum Gespräch hinzu, das das Modell sieht, aber es wird möglicherweise nicht in allen SDK-Ausgabemodi angezeigt. Wenn Sie Hook-Entscheidungen für Ihre Anwendung anzeigen müssen, protokollieren Sie sie separat oder verwenden Sie einen dedizierten Ausgabekanal.

    Weitere Informationen

    • Berechtigungen: Steuern Sie, was Ihr Agent tun kann
    • Benutzerdefinierte Tools: Erstellen Sie Tools, um die Agent-Funktionen zu erweitern
    • TypeScript SDK-Referenz
    • Python SDK-Referenz