Loading...
    • Guida per sviluppatori
    • Riferimento API
    • MCP
    • Risorse
    • Note sulla versione
    Search...
    ⌘K
    Primi passi
    Introduzione a ClaudeAvvio rapido
    Modelli e prezzi
    Panoramica dei modelliScelta di un modelloNovità in Claude 4.6Guida alla migrazioneDeprecazioni dei modelliPrezzi
    Crea con Claude
    Panoramica delle funzioniUtilizzo dell'API MessagesGestione dei motivi di arrestoBest practice per i prompt
    Capacità del modello
    Extended thinkingAdaptive thinkingEffortFast mode (anteprima di ricerca)Output strutturatiCitazioniStreaming dei messaggiElaborazione batchSupporto PDFRisultati di ricercaSupporto multilingueEmbeddingsVision
    Strumenti
    PanoramicaCome implementare l'uso degli strumentiStrumento di ricerca webStrumento di recupero webStrumento di esecuzione del codiceStrumento di memoriaStrumento BashStrumento Computer useStrumento editor di testo
    Infrastruttura degli strumenti
    Ricerca strumentiChiamata programmatica degli strumentiStreaming granulare degli strumenti
    Gestione del contesto
    Finestre di contestoCompattazioneModifica del contestoPrompt cachingConteggio dei token
    File e risorse
    API Files
    Agent Skills
    PanoramicaAvvio rapidoBest practiceSkills per l'aziendaUtilizzo di Skills con l'API
    Agent SDK
    PanoramicaAvvio rapidoTypeScript SDKTypeScript V2 (anteprima)Python SDKGuida alla migrazione
    Streaming InputStreaming delle risposte in tempo realeGestione dei motivi di arrestoGestione dei permessiApprovazioni utente e inputControllare l'esecuzione con hookGestione della sessioneCheckpoint dei fileOutput strutturati nell'SDKHosting dell'Agent SDKDistribuzione sicura degli agenti AIModifica dei prompt di sistemaMCP nell'SDKStrumenti personalizzatiSubagenti nell'SDKSlash Commands nell'SDKAgent Skills nell'SDKTracciamento dei costi e dell'utilizzoElenchi di attivitàPlugin nell'SDK
    MCP nell'API
    Connettore MCPServer MCP remoti
    Claude su piattaforme di terze parti
    Amazon BedrockMicrosoft FoundryVertex AI
    Prompt engineering
    PanoramicaGeneratore di promptUsa modelli di promptMiglioratore di promptSii chiaro e direttoUsa esempi (multishot prompting)Lascia che Claude pensi (CoT)Usa tag XMLDai a Claude un ruolo (prompt di sistema)Concatena prompt complessiSuggerimenti per il contesto lungoSuggerimenti per extended thinking
    Test e valutazione
    Definisci criteri di successoSviluppa casi di testUtilizzo dello strumento di valutazioneRiduzione della latenza
    Rafforza i guardrail
    Riduci le allucinazioniAumenta la coerenza dell'outputMitiga i jailbreakStreaming dei rifiutiRiduci la perdita di promptMantieni Claude nel personaggio
    Amministrazione e monitoraggio
    Panoramica dell'API AdminResidenza dei datiWorkspaceAPI di utilizzo e costiAPI Claude Code AnalyticsZero Data Retention
    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
    Guide

    Gestire approvazioni e input dell'utente

    Presenta le richieste di approvazione di Claude e le domande di chiarimento agli utenti, quindi restituisci le loro decisioni all'SDK.

    Mentre lavora su un'attività, Claude a volte ha bisogno di verificare con gli utenti. Potrebbe aver bisogno di autorizzazione prima di eliminare file, oppure potrebbe aver bisogno di chiedere quale database utilizzare per un nuovo progetto. La tua applicazione deve presentare queste richieste agli utenti in modo che Claude possa continuare con il loro input.

    Claude richiede input dell'utente in due situazioni: quando ha bisogno di autorizzazione per utilizzare uno strumento (come eliminare file o eseguire comandi), e quando ha domande di chiarimento (tramite lo strumento AskUserQuestion). Entrambi attivano il tuo callback canUseTool, che mette in pausa l'esecuzione fino a quando non restituisci una risposta. Questo è diverso dai normali turni di conversazione in cui Claude finisce e attende il tuo prossimo messaggio.

    Per le domande di chiarimento, Claude genera le domande e le opzioni. Il tuo ruolo è presentarle agli utenti e restituire le loro selezioni. Non puoi aggiungere le tue domande a questo flusso; se hai bisogno di chiedere qualcosa agli utenti tu stesso, fallo separatamente nella logica della tua applicazione.

    Questa guida ti mostra come rilevare ogni tipo di richiesta e rispondere in modo appropriato.

    Rilevare quando Claude ha bisogno di input

    Passa un callback canUseTool nelle opzioni della tua query. Il callback si attiva ogni volta che Claude ha bisogno di input dell'utente, ricevendo il nome dello strumento e l'input come argomenti:

    async def handle_tool_request(tool_name, input_data, context):
        # Chiedi all'utente e restituisci allow o deny
        ...
    
    options = ClaudeAgentOptions(can_use_tool=handle_tool_request)

    Il callback si attiva in due casi:

    1. Lo strumento ha bisogno di approvazione: Claude vuole utilizzare uno strumento che non è approvato automaticamente dalle regole di autorizzazione o dalle modalità. Controlla tool_name per lo strumento (ad es. "Bash", "Write").
    2. Claude pone una domanda: Claude chiama lo strumento AskUserQuestion. Controlla se tool_name == "AskUserQuestion" per gestirlo diversamente. Se specifichi un array tools, includi AskUserQuestion affinché funzioni. Vedi Gestire domande di chiarimento per i dettagli.

    Per consentire o negare automaticamente gli strumenti senza chiedere agli utenti, utilizza invece gli hook. Gli hook vengono eseguiti prima di canUseTool e possono consentire, negare o modificare le richieste in base alla tua logica. Puoi anche utilizzare l'hook PermissionRequest per inviare notifiche esterne (Slack, email, push) quando Claude è in attesa di approvazione.

    Gestire richieste di approvazione dello strumento

    Una volta passato un callback canUseTool nelle opzioni della tua query, si attiva quando Claude vuole utilizzare uno strumento che non è approvato automaticamente. Il tuo callback riceve due argomenti:

    ArgomentoDescrizione
    toolNameIl nome dello strumento che Claude vuole utilizzare (ad es. "Bash", "Write", "Edit")
    inputI parametri che Claude sta passando allo strumento. Il contenuto varia a seconda dello strumento.

    L'oggetto input contiene parametri specifici dello strumento. Esempi comuni:

    StrumentoCampi di input
    Bashcommand, description, timeout
    Writefile_path, content
    Editfile_path, old_string, new_string
    Readfile_path, offset, limit

    Vedi il riferimento dell'SDK per gli schemi di input completi: Python | TypeScript.

    Puoi visualizzare queste informazioni all'utente in modo che possa decidere se consentire o rifiutare l'azione, quindi restituire la risposta appropriata.

    L'esempio seguente chiede a Claude di creare ed eliminare un file di test. Quando Claude tenta ogni operazione, il callback stampa la richiesta dello strumento nel terminale e chiede l'approvazione s/n.

    import asyncio
    
    from claude_agent_sdk import ClaudeAgentOptions, query
    from claude_agent_sdk.types import (
        HookMatcher,
        PermissionResultAllow,
        PermissionResultDeny,
        ToolPermissionContext,
    )
    
    
    async def can_use_tool(
        tool_name: str, input_data: dict, context: ToolPermissionContext
    ) -> PermissionResultAllow | PermissionResultDeny:
        # Visualizza la richiesta dello strumento
        print(f"\nTool: {tool_name}")
        if tool_name == "Bash":
            print(f"Command: {input_data.get('command')}")
            if input_data.get("description"):
                print(f"Description: {input_data.get('description')}")
        else:
            print(f"Input: {input_data}")
    
        # Ottieni l'approvazione dell'utente
        response = input("Allow this action? (y/n): ")
    
        # Restituisci allow o deny in base alla risposta dell'utente
        if response.lower() == "y":
            # Allow: lo strumento viene eseguito con l'input originale (o modificato)
            return PermissionResultAllow(updated_input=input_data)
        else:
            # Deny: lo strumento non viene eseguito, Claude vede il messaggio
            return PermissionResultDeny(message="User denied this action")
    
    
    # Workaround richiesto: hook dummy mantiene il flusso aperto per can_use_tool
    async def dummy_hook(input_data, tool_use_id, context):
        return {"continue_": True}
    
    
    async def prompt_stream():
        yield {
            "type": "user",
            "message": {
                "role": "user",
                "content": "Create a test file in /tmp and then delete it",
            },
        }
    
    
    async def main():
        async for message in query(
            prompt=prompt_stream(),
            options=ClaudeAgentOptions(
                can_use_tool=can_use_tool,
                hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    
    
    asyncio.run(main())

    In Python, can_use_tool richiede la modalità streaming e un hook PreToolUse che restituisce {"continue_": True} per mantenere il flusso aperto. Senza questo hook, il flusso si chiude prima che il callback di autorizzazione possa essere invocato.

    Questo esempio utilizza un flusso s/n in cui qualsiasi input diverso da s è trattato come un rifiuto. In pratica, potresti creare un'interfaccia utente più ricca che consenta agli utenti di modificare la richiesta, fornire feedback o reindirizzare completamente Claude. Vedi Rispondere alle richieste dello strumento per tutti i modi in cui puoi rispondere.

    Rispondere alle richieste dello strumento

    Il tuo callback restituisce uno di due tipi di risposta:

    RispostaPythonTypeScript
    AllowPermissionResultAllow(updated_input=...){ behavior: "allow", updatedInput }
    DenyPermissionResultDeny(message=...){ behavior: "deny", message }

    Quando consenti, passa l'input dello strumento (originale o modificato). Quando neghi, fornisci un messaggio che spiega il motivo. Claude vede questo messaggio e potrebbe adattare il suo approccio.

    from claude_agent_sdk.types import PermissionResultAllow, PermissionResultDeny
    
    # Consenti l'esecuzione dello strumento
    return PermissionResultAllow(updated_input=input_data)
    
    # Blocca lo strumento
    return PermissionResultDeny(message="User rejected this action")

    Oltre a consentire o negare, puoi modificare l'input dello strumento o fornire un contesto che aiuti Claude ad adattare il suo approccio:

    • Approva: consenti l'esecuzione dello strumento come richiesto da Claude
    • Approva con modifiche: modifica l'input prima dell'esecuzione (ad es. sanitizza i percorsi, aggiungi vincoli)
    • Rifiuta: blocca lo strumento e spiega a Claude il motivo
    • Suggerisci un'alternativa: blocca ma guida Claude verso ciò che l'utente vuole invece
    • Reindirizza completamente: utilizza input streaming per inviare a Claude un'istruzione completamente nuova

    Gestire domande di chiarimento

    Quando Claude ha bisogno di più indicazioni su un'attività con più approcci validi, chiama lo strumento AskUserQuestion. Questo attiva il tuo callback canUseTool con toolName impostato su AskUserQuestion. L'input contiene le domande di Claude come opzioni a scelta multipla, che visualizzi all'utente e restituisci le loro selezioni.

    Le domande di chiarimento sono particolarmente comuni nella modalità plan, dove Claude esplora la base di codice e pone domande prima di proporre un piano. Questo rende la modalità plan ideale per i flussi di lavoro interattivi in cui vuoi che Claude raccolga i requisiti prima di apportare modifiche.

    I seguenti passaggi mostrano come gestire le domande di chiarimento:

    1. 1

      Passa un callback canUseTool

      Passa un callback canUseTool nelle opzioni della tua query. Per impostazione predefinita, AskUserQuestion è disponibile. Se specifichi un array tools per limitare le capacità di Claude (ad esempio, un agente di sola lettura con solo Read, Glob e Grep), includi AskUserQuestion in quell'array. Altrimenti, Claude non sarà in grado di porre domande di chiarimento:

      async for message in query(
          prompt="Analyze this codebase",
          options=ClaudeAgentOptions(
              # Includi AskUserQuestion nella tua lista di strumenti
              tools=["Read", "Glob", "Grep", "AskUserQuestion"],
              can_use_tool=can_use_tool,
          ),
      ):
          # ...
    2. 2

      Rileva AskUserQuestion

      Nel tuo callback, controlla se toolName è uguale a AskUserQuestion per gestirlo diversamente da altri strumenti:

      async def can_use_tool(tool_name: str, input_data: dict, context):
          if tool_name == "AskUserQuestion":
              # La tua implementazione per raccogliere risposte dall'utente
              return await handle_clarifying_questions(input_data)
          # Gestisci altri strumenti normalmente
          return await prompt_for_approval(tool_name, input_data)
    3. 3

      Analizza l'input della domanda

      L'input contiene le domande di Claude in un array questions. Ogni domanda ha una question (il testo da visualizzare), options (le scelte) e multiSelect (se sono consentite più selezioni):

      {
        "questions": [
          {
            "question": "How should I format the output?",
            "header": "Format",
            "options": [
              { "label": "Summary", "description": "Brief overview" },
              { "label": "Detailed", "description": "Full explanation" }
            ],
            "multiSelect": false
          },
          {
            "question": "Which sections should I include?",
            "header": "Sections",
            "options": [
              { "label": "Introduction", "description": "Opening context" },
              { "label": "Conclusion", "description": "Final summary" }
            ],
            "multiSelect": true
          }
        ]
      }

      Vedi Formato della domanda per le descrizioni complete dei campi.

    4. 4

      Raccogli risposte dall'utente

      Presenta le domande all'utente e raccogli le loro selezioni. Come lo fai dipende dalla tua applicazione: un prompt del terminale, un modulo web, una finestra di dialogo mobile, ecc.

    5. 5

      Restituisci le risposte a Claude

      Costruisci l'oggetto answers come un record in cui ogni chiave è il testo della question e ogni valore è l'label dell'opzione selezionata:

      Dall'oggetto domandaUsa come
      Campo question (ad es. "How should I format the output?")Chiave
      Campo label dell'opzione selezionata (ad es. "Summary")Valore

      Per le domande a selezione multipla, unisci più label con ", ". Se supporti input di testo libero, utilizza il testo personalizzato dell'utente come valore.

      return PermissionResultAllow(
          updated_input={
              "questions": input_data.get("questions", []),
              "answers": {
                  "How should I format the output?": "Summary",
                  "Which sections should I include?": "Introduction, Conclusion"
              }
          }
      )

    Formato della domanda

    L'input contiene le domande generate da Claude in un array questions. Ogni domanda ha questi campi:

    CampoDescrizione
    questionIl testo completo della domanda da visualizzare
    headerEtichetta breve per la domanda (max 12 caratteri)
    optionsArray di 2-4 scelte, ognuna con label e description
    multiSelectSe true, gli utenti possono selezionare più opzioni

    Ecco un esempio della struttura che riceverai:

    {
      "questions": [
        {
          "question": "How should I format the output?",
          "header": "Format",
          "options": [
            { "label": "Summary", "description": "Brief overview of key points" },
            { "label": "Detailed", "description": "Full explanation with examples" }
          ],
          "multiSelect": false
        }
      ]
    }

    Formato della risposta

    Restituisci un oggetto answers che mappa il campo question di ogni domanda all'label dell'opzione selezionata:

    CampoDescrizione
    questionsPassa attraverso l'array di domande originale (richiesto per l'elaborazione dello strumento)
    answersOggetto in cui le chiavi sono il testo della domanda e i valori sono le label selezionate

    Per le domande a selezione multipla, unisci più label con ", ". Per l'input di testo libero, utilizza il testo personalizzato dell'utente direttamente.

    {
      "questions": [...],
      "answers": {
        "How should I format the output?": "Summary",
        "Which sections should I include?": "Introduction, Conclusion"
      }
    }

    Supporta input di testo libero

    Le opzioni predefinite di Claude non copriranno sempre ciò che gli utenti vogliono. Per consentire agli utenti di digitare la propria risposta:

    • Visualizza una scelta "Other" aggiuntiva dopo le opzioni di Claude che accetta input di testo
    • Utilizza il testo personalizzato dell'utente come valore della risposta (non la parola "Other")

    Vedi l'esempio completo di seguito per un'implementazione completa.

    Esempio completo

    Claude pone domande di chiarimento quando ha bisogno di input dell'utente per procedere. Ad esempio, quando gli viene chiesto di aiutare a decidere uno stack tecnologico per un'app mobile, Claude potrebbe chiedere informazioni su cross-platform vs nativo, preferenze di backend o piattaforme target. Queste domande aiutano Claude a prendere decisioni che corrispondono alle preferenze dell'utente piuttosto che indovinare.

    Questo esempio gestisce quelle domande in un'applicazione terminale. Ecco cosa accade ad ogni passaggio:

    1. Instrada la richiesta: Il callback canUseTool controlla se il nome dello strumento è "AskUserQuestion" e instrada a un gestore dedicato
    2. Visualizza le domande: Il gestore scorre l'array questions e stampa ogni domanda con opzioni numerate
    3. Raccogli input: L'utente può inserire un numero per selezionare un'opzione, o digitare testo libero direttamente (ad es. "jquery", "i don't know")
    4. Mappa le risposte: Il codice controlla se l'input è numerico (utilizza l'etichetta dell'opzione) o testo libero (utilizza il testo direttamente)
    5. Restituisci a Claude: La risposta include sia l'array questions originale che la mappatura answers
    import asyncio
    
    from claude_agent_sdk import ClaudeAgentOptions, query
    from claude_agent_sdk.types import HookMatcher, PermissionResultAllow
    
    
    def parse_response(response: str, options: list) -> str:
        """Analizza l'input dell'utente come numero(i) di opzione o testo libero."""
        try:
            indices = [int(s.strip()) - 1 for s in response.split(",")]
            labels = [options[i]["label"] for i in indices if 0 <= i < len(options)]
            return ", ".join(labels) if labels else response
        except ValueError:
            return response
    
    
    async def handle_ask_user_question(input_data: dict) -> PermissionResultAllow:
        """Visualizza le domande di Claude e raccogli le risposte dell'utente."""
        answers = {}
    
        for q in input_data.get("questions", []):
            print(f"\n{q['header']}: {q['question']}")
    
            options = q["options"]
            for i, opt in enumerate(options):
                print(f"  {i + 1}. {opt['label']} - {opt['description']}")
            if q.get("multiSelect"):
                print("  (Enter numbers separated by commas, or type your own answer)")
            else:
                print("  (Enter a number, or type your own answer)")
    
            response = input("Your choice: ").strip()
            answers[q["question"]] = parse_response(response, options)
    
        return PermissionResultAllow(
            updated_input={
                "questions": input_data.get("questions", []),
                "answers": answers,
            }
        )
    
    
    async def can_use_tool(tool_name: str, input_data: dict, context) -> PermissionResultAllow:
        # Instrada AskUserQuestion al nostro gestore di domande
        if tool_name == "AskUserQuestion":
            return await handle_ask_user_question(input_data)
        # Auto-approva altri strumenti per questo esempio
        return PermissionResultAllow(updated_input=input_data)
    
    
    async def prompt_stream():
        yield {
            "type": "user",
            "message": {"role": "user", "content": "Help me decide on the tech stack for a new mobile app"},
        }
    
    
    # Workaround richiesto: hook dummy mantiene il flusso aperto per can_use_tool
    async def dummy_hook(input_data, tool_use_id, context):
        return {"continue_": True}
    
    
    async def main():
        async for message in query(
            prompt=prompt_stream(),
            options=ClaudeAgentOptions(
                can_use_tool=can_use_tool,
                hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    
    
    asyncio.run(main())

    Limitazioni

    • Subagenti: AskUserQuestion non è attualmente disponibile nei subagenti generati tramite lo strumento Task
    • Limiti delle domande: ogni chiamata AskUserQuestion supporta 1-4 domande con 2-4 opzioni ciascuna

    Altri modi per ottenere input dell'utente

    Il callback canUseTool e lo strumento AskUserQuestion coprono la maggior parte degli scenari di approvazione e chiarimento, ma l'SDK offre altri modi per ottenere input dagli utenti:

    Input streaming

    Utilizza input streaming quando hai bisogno di:

    • Interrompere l'agente a metà attività: invia un segnale di annullamento o cambia direzione mentre Claude sta lavorando
    • Fornire contesto aggiuntivo: aggiungi informazioni di cui Claude ha bisogno senza aspettare che le chieda
    • Costruire interfacce di chat: consenti agli utenti di inviare messaggi di follow-up durante operazioni di lunga durata

    L'input streaming è ideale per le interfacce conversazionali in cui gli utenti interagiscono con l'agente durante l'esecuzione, non solo nei punti di approvazione.

    Strumenti personalizzati

    Utilizza strumenti personalizzati quando hai bisogno di:

    • Raccogliere input strutturato: costruisci moduli, procedure guidate o flussi di lavoro multi-step che vanno oltre il formato a scelta multipla di AskUserQuestion
    • Integrare sistemi di approvazione esterni: connettiti a piattaforme di ticketing, flussi di lavoro o approvazione esistenti
    • Implementare interazioni specifiche del dominio: crea strumenti personalizzati per le esigenze della tua applicazione, come interfacce di revisione del codice o liste di controllo di distribuzione

    Gli strumenti personalizzati ti danno il controllo completo sull'interazione, ma richiedono più lavoro di implementazione rispetto all'utilizzo del callback canUseTool integrato.

    Risorse correlate

    • Configura autorizzazioni: imposta modalità e regole di autorizzazione
    • Controlla l'esecuzione con hook: esegui codice personalizzato nei punti chiave del ciclo di vita dell'agente
    • Riferimento SDK TypeScript: documentazione completa dell'API canUseTool

    Was this page helpful?

    • Rilevare quando Claude ha bisogno di input
    • Gestire richieste di approvazione dello strumento
    • Rispondere alle richieste dello strumento
    • Gestire domande di chiarimento
    • Formato della domanda
    • Formato della risposta
    • Esempio completo
    • Limitazioni
    • Altri modi per ottenere input dell'utente
    • Input streaming
    • Strumenti personalizzati
    • Risorse correlate