Claude Platform Docs
  • Messaggi
  • Agenti gestiti
  • Amministrazione

Search...
⌘K
Primi passi
Introduzione a ClaudeGuida rapida
Sviluppare con Claude
Panoramica delle funzionalitàUtilizzo dell'API MessagesMotivi di interruzione e fallbackRifiuti e fallbackCredito di fallback
Capacità del modello
Pensiero estesoPensiero adattivoEffortBudget delle attività (beta)Modalità veloce (anteprima di ricerca)Output strutturatiCitazioniStreaming dei messaggiElaborazione batchRisultati di ricercaStreaming dei rifiutiSupporto multilingueEmbedding
Strumenti
PanoramicaCome funziona l'uso degli strumentiTutorial: Creare un agente che usa strumentiDefinire gli strumentiGestire le chiamate agli strumentiUso degli strumenti in paralleloTool Runner (SDK)Uso degli strumenti rigorosoStrumenti serverStrumento di ricerca webStrumento di recupero webStrumento di esecuzione codiceStrumento advisorStrumento di ricerca strumentiStrumento di memoriaStrumento BashStrumento editor di testoStrumento di uso del computerRisoluzione dei problemi
Infrastruttura degli strumenti
Riferimento strumentiGestire il contesto degli strumentiCombinazioni di strumentiUso degli strumenti con cache dei promptChiamata programmatica degli strumentiStreaming granulare degli strumenti
Gestione del contesto
Finestre di contestoCompattazioneModifica del contestoCache dei promptMessaggi di sistema a metà conversazioneCreare una modalità di orchestrazioneDiagnostica della cache (beta)Conteggio dei token
Lavorare con i file
API FilesSupporto PDF
Skill
PanoramicaGuida rapidaBest practiceSkill per le aziendeSkill nell'API
MCP
Server MCP remotiConnettore MCP
Claude su piattaforme cloud
Amazon BedrockAmazon Bedrock (legacy)Claude Platform su AWSGoogle CloudMicrosoft Foundry

Log in
Tutorial: Creare un agente che usa strumenti
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Claude Platform Docs

Solutions

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

Partners

  • Claude on AWS
  • Claude on Google Cloud

Learn

  • Blog
  • 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
  • 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
Messaggi/Strumenti

Tutorial: Costruire un agente che usa strumenti

Una guida passo passo da una singola chiamata a uno strumento fino a un ciclo agentico pronto per la produzione.

Questo tutorial costruisce un agente per la gestione del calendario in cinque anelli concentrici. Ogni anello è un programma completo ed eseguibile che aggiunge esattamente un concetto all'anello precedente. Alla fine avrai scritto il ciclo agentico a mano e poi lo avrai sostituito con l'astrazione Tool Runner dell'SDK.

Lo strumento di esempio è create_calendar_event. Il suo schema utilizza oggetti annidati, array e campi opzionali, così potrai vedere come Claude gestisce forme di input realistiche anziché una singola stringa piatta.



Ogni anello funziona in modo autonomo. Copia qualsiasi anello in un nuovo file e verrà eseguito senza il codice degli anelli precedenti.

Anello 1: Singolo strumento, singolo turno

Il programma più piccolo possibile che usa strumenti: uno strumento, un messaggio utente, una chiamata allo strumento, un risultato. Il codice è ampiamente commentato così puoi mappare ogni riga al ciclo di vita dell'uso degli strumenti.

La richiesta invia un array tools insieme al messaggio utente. Quando Claude decide di chiamare uno strumento, la risposta ritorna con stop_reason: "tool_use" e un blocco di contenuto tool_use che contiene il nome dello strumento, un id univoco e l'input strutturato. Il tuo codice esegue lo strumento, poi invia il risultato in un blocco tool_result il cui tool_use_id corrisponde all'id della chiamata.

Cosa aspettarsi

Output
stop_reason: tool_use
Tool: create_calendar_event
Input: {'title': 'Sync', 'start': '2026-03-30T10:00:00', 'end': '2026-03-30T10:30:00', 'attendees': ['[email protected]', '[email protected]']}
stop_reason: end_turn
I've scheduled your 30-minute sync with Alice and Bob for next Monday at 10am.

Il primo stop_reason è tool_use perché Claude sta aspettando il risultato del calendario. Dopo aver inviato il risultato, il secondo stop_reason è end_turn e il contenuto è linguaggio naturale per l'utente.

Anello 2: Il ciclo agentico

L'Anello 1 presupponeva che Claude chiamasse lo strumento esattamente una volta. I compiti reali spesso richiedono diverse chiamate: Claude potrebbe creare un evento, leggere la conferma, poi crearne un altro. La soluzione è un ciclo while che continua a eseguire strumenti e a restituire i risultati finché stop_reason non è più "tool_use".

L'altra modifica riguarda la cronologia della conversazione. Invece di ricostruire l'array messages da zero a ogni richiesta, mantieni una lista in esecuzione e aggiungi elementi ad essa. Ogni turno vede il contesto precedente completo.

Cosa aspettarsi

Output
I've set up your weekly team standup for the next 4 Mondays at 9am with Alice, Bob, and Carol invited.

Il ciclo potrebbe essere eseguito una o più volte a seconda di come Claude scompone il compito. Il tuo codice non ha più bisogno di saperlo in anticipo.

Anello 3: Strumenti multipli, chiamate parallele

Gli agenti raramente hanno una sola capacità. Aggiungi un secondo strumento, list_calendar_events, così Claude può controllare il calendario esistente prima di creare qualcosa di nuovo.

Quando Claude ha più chiamate a strumenti indipendenti da effettuare, potrebbe restituire diversi blocchi tool_use in una singola risposta. Il tuo ciclo deve elaborarli tutti e inviare tutti i risultati insieme in un unico messaggio utente. Itera su ogni blocco tool_use in response.content, non solo sul primo.

Cosa aspettarsi

Output
I checked your calendar for next Monday and found an existing meeting from 2pm to 3pm. I've scheduled the planning session for 10am to 11am to avoid the conflict.

Per maggiori informazioni sull'esecuzione concorrente e sulle garanzie di ordinamento, consulta Uso parallelo degli strumenti.

Anello 4: Gestione degli errori

Gli strumenti falliscono. Un'API di calendario potrebbe rifiutare un evento con troppi partecipanti, oppure una data potrebbe essere malformata. Quando uno strumento genera un errore, invia il messaggio di errore con is_error: true invece di andare in crash. Claude legge l'errore e può riprovare con input corretto, chiedere chiarimenti all'utente o spiegare la limitazione.

Cosa aspettarsi

Output
I tried to schedule the all-hands but the calendar only allows 10 attendees per event. I can split this into two sessions, or you can let me know which 10 people to prioritize.

Il flag is_error è l'unica differenza rispetto a un risultato riuscito. Claude vede il flag e il testo dell'errore, e risponde di conseguenza. Consulta Gestire le chiamate agli strumenti per il riferimento completo sulla gestione degli errori.

Anello 5: L'astrazione Tool Runner dell'SDK

Gli Anelli da 2 a 4 hanno scritto lo stesso ciclo a mano: chiama l'API, controlla stop_reason, esegui gli strumenti, aggiungi i risultati, ripeti. Il Tool Runner fa questo per te. Definisci ogni strumento come una funzione, passa la lista a tool_runner e recupera il messaggio finale una volta completato il ciclo. Il wrapping degli errori, la formattazione dei risultati e la gestione della conversazione sono gestiti internamente.

L'SDK Python usa il decoratore @beta_tool per inferire lo schema dai type hint e dalla docstring. L'SDK TypeScript usa betaZodTool con uno schema Zod. Gli altri SDK seguono lo stesso pattern con i propri helper: BetaRunnableTool in C# e PHP, classi di strumenti tipizzate in Java e Ruby, e toolrunner.NewBetaToolFromJSONSchema in Go.



Tool Runner è disponibile in tutti e sette gli SDK: Python, TypeScript, C#, Go, Java, PHP e Ruby. Consulta Tool Runner per il riferimento completo. Le schede cURL e CLI mostrano una nota invece del codice; mantieni il ciclo dell'Anello 4 per gli script basati su curl o CLI.

Cosa aspettarsi

Output
I checked your calendar for next Monday and found an existing meeting from 2pm to 3pm. I've scheduled the planning session for 10am to 11am to avoid the conflict.

L'output è identico all'Anello 3. La differenza è nel codice: circa la metà delle righe, nessun ciclo manuale, e lo schema risiede accanto all'implementazione.

Cosa hai costruito

Hai iniziato con una singola chiamata a uno strumento hardcoded e sei arrivato a un agente strutturato per la produzione che gestisce strumenti multipli, chiamate parallele ed errori, poi hai compresso tutto questo nel Tool Runner. Lungo il percorso hai visto ogni parte del protocollo di uso degli strumenti: blocchi tool_use, blocchi tool_result, corrispondenza di tool_use_id, controllo di stop_reason e segnalazione con is_error.

Passaggi successivi

Definire gli strumenti

Specifica dello schema e best practice.

Approfondimento su Tool Runner

Il riferimento completo dell'astrazione SDK.

Risoluzione dei problemi

Risolvi gli errori comuni nell'uso degli strumenti.

Was this page helpful?

  • Anello 1: Singolo strumento, singolo turno
  • Anello 2: Il ciclo agentico
  • Anello 3: Strumenti multipli, chiamate parallele
  • Anello 4: Gestione degli errori
  • Anello 5: L'astrazione Tool Runner dell'SDK
  • Cosa hai costruito
  • Passaggi successivi
# Anello 1: Singolo strumento, singolo turno.

import json

import anthropic

# Crea un client. Legge ANTHROPIC_API_KEY dall'ambiente.
client = anthropic.Anthropic()

# Definisci uno strumento. L'input_schema è un oggetto JSON Schema che descrive
# gli argomenti che Claude deve passare quando chiama questo strumento. Questo schema
# include oggetti annidati (recurrence), array (attendees) e campi
# opzionali, più vicino agli strumenti reali rispetto a un semplice argomento stringa.
tools = [
    {
        "name": "create_calendar_event",
        "description": "Create a calendar event with attendees and optional recurrence.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"},
                "attendees": {
                    "type": "array",
                    "items": {"type": "string", "format": "email"},
                },
                "recurrence": {
                    "type": "object",
                    "properties": {
                        "frequency": {"enum": ["daily", "weekly", "monthly"]},
                        "count": {"type": "integer", "minimum": 1},
                    },
                },
            },
            "required": ["title", "start", "end"],
        },
    }
]

# Invia la richiesta dell'utente insieme alla definizione dello strumento. Claude decide
# se chiamare lo strumento in base alla richiesta e alla descrizione dello strumento.
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto", "disable_parallel_tool_use": True},
    messages=[
        {
            "role": "user",
            "content": "Schedule a 30-minute sync with [email protected] and [email protected] next Monday at 10am.",
        }
    ],
)

# Quando Claude chiama uno strumento, la risposta ha stop_reason "tool_use"
# e l'array content contiene un blocco tool_use insieme a eventuale testo.
print(f"stop_reason: {response.stop_reason}")

# Trova il blocco tool_use. Una risposta può contenere blocchi di testo prima del
# blocco tool_use, quindi scansiona l'array content invece di presumere la posizione.
tool_use = next(block for block in response.content if block.type == "tool_use")
print(f"Tool: {tool_use.name}")
print(f"Input: {tool_use.input}")

# Esegui lo strumento. In un sistema reale questo chiamerebbe la tua API calendario.
# Qui il risultato è hardcoded per mantenere l'esempio autonomo.
result = {"event_id": "evt_123", "status": "created"}

# Invia il risultato. Il blocco tool_result va in un messaggio user e
# il suo tool_use_id deve corrispondere all'id del blocco tool_use sopra. La
# risposta precedente dell'assistente è inclusa così Claude ha la cronologia completa.
followup = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto", "disable_parallel_tool_use": True},
    messages=[
        {
            "role": "user",
            "content": "Schedule a 30-minute sync with [email protected] and [email protected] next Monday at 10am.",
        },
        {"role": "assistant", "content": response.content},
        {
            "role": "user",
            "content": [
                {
                    "type": "tool_result",
                    "tool_use_id": tool_use.id,
                    "content": json.dumps(result),
                }
            ],
        },
    ],
)

# Con il risultato dello strumento a disposizione, Claude produce una risposta finale
# in linguaggio naturale e stop_reason diventa "end_turn".
print(f"stop_reason: {followup.stop_reason}")
final_text = next(block for block in followup.content if block.type == "text")
print(final_text.text)
# Anello 2: Il ciclo agentico.

import json

import anthropic

client = anthropic.Anthropic()

tools = [
    {
        "name": "create_calendar_event",
        "description": "Create a calendar event with attendees and optional recurrence.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"},
                "attendees": {
                    "type": "array",
                    "items": {"type": "string", "format": "email"},
                },
                "recurrence": {
                    "type": "object",
                    "properties": {
                        "frequency": {"enum": ["daily", "weekly", "monthly"]},
                        "count": {"type": "integer", "minimum": 1},
                    },
                },
            },
            "required": ["title", "start", "end"],
        },
    }
]


def run_tool(name, tool_input):
    if name == "create_calendar_event":
        return {"event_id": "evt_123", "status": "created", "title": tool_input["title"]}
    return {"error": f"Unknown tool: {name}"}


# Conserva l'intera cronologia della conversazione in una lista così ogni turno vede il contesto precedente.
messages = [
    {
        "role": "user",
        "content": "Schedule a weekly team standup every Monday at 9am for the next 4 weeks. Invite the whole team: [email protected], [email protected], [email protected].",
    }
]

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto", "disable_parallel_tool_use": True},
    messages=messages,
)

# Itera finché Claude non smette di richiedere strumenti. Ogni iterazione esegue lo
# strumento richiesto, aggiunge il risultato alla cronologia e chiede a Claude di continuare.
while response.stop_reason == "tool_use":
    tool_use = next(block for block in response.content if block.type == "tool_use")
    result = run_tool(tool_use.name, tool_use.input)

    messages.append({"role": "assistant", "content": response.content})
    messages.append(
        {
            "role": "user",
            "content": [
                {
                    "type": "tool_result",
                    "tool_use_id": tool_use.id,
                    "content": json.dumps(result),
                }
            ],
        }
    )

    response = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        tools=tools,
        tool_choice={"type": "auto", "disable_parallel_tool_use": True},
        messages=messages,
    )

final_text = next(block for block in response.content if block.type == "text")
print(final_text.text)
# Anello 3: Strumenti multipli, chiamate parallele.

import json

import anthropic

client = anthropic.Anthropic()

tools = [
    {
        "name": "create_calendar_event",
        "description": "Create a calendar event with attendees and optional recurrence.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"},
                "attendees": {
                    "type": "array",
                    "items": {"type": "string", "format": "email"},
                },
                "recurrence": {
                    "type": "object",
                    "properties": {
                        "frequency": {"enum": ["daily", "weekly", "monthly"]},
                        "count": {"type": "integer", "minimum": 1},
                    },
                },
            },
            "required": ["title", "start", "end"],
        },
    },
    {
        "name": "list_calendar_events",
        "description": "List all calendar events on a given date.",
        "input_schema": {
            "type": "object",
            "properties": {
                "date": {"type": "string", "format": "date"},
            },
            "required": ["date"],
        },
    },
]


def run_tool(name, tool_input):
    if name == "create_calendar_event":
        return {"event_id": "evt_123", "status": "created", "title": tool_input["title"]}
    if name == "list_calendar_events":
        return {"events": [{"title": "Existing meeting", "start": "14:00", "end": "15:00"}]}
    return {"error": f"Unknown tool: {name}"}


messages = [
    {
        "role": "user",
        "content": "Check what I have next Monday, then schedule a planning session that avoids any conflicts.",
    }
]

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=tools,
    messages=messages,
)

while response.stop_reason == "tool_use":
    # Una singola risposta può contenere più blocchi tool_use. Elaborali tutti
    # e restituisci tutti i risultati insieme in un unico messaggio utente.
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            result = run_tool(block.name, block.input)
            tool_results.append(
                {
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": json.dumps(result),
                }
            )

    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})

    response = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )

final_text = next(block for block in response.content if block.type == "text")
print(final_text.text)
# Anello 4: Gestione degli errori.

import json

import anthropic

client = anthropic.Anthropic()

tools = [
    {
        "name": "create_calendar_event",
        "description": "Create a calendar event with attendees and optional recurrence.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"},
                "attendees": {
                    "type": "array",
                    "items": {"type": "string", "format": "email"},
                },
                "recurrence": {
                    "type": "object",
                    "properties": {
                        "frequency": {"enum": ["daily", "weekly", "monthly"]},
                        "count": {"type": "integer", "minimum": 1},
                    },
                },
            },
            "required": ["title", "start", "end"],
        },
    },
    {
        "name": "list_calendar_events",
        "description": "List all calendar events on a given date.",
        "input_schema": {
            "type": "object",
            "properties": {
                "date": {"type": "string", "format": "date"},
            },
            "required": ["date"],
        },
    },
]


def run_tool(name, tool_input):
    if name == "create_calendar_event":
        if "attendees" in tool_input and len(tool_input["attendees"]) > 10:
            raise ValueError("Too many attendees (max 10)")
        return {"event_id": "evt_123", "status": "created", "title": tool_input["title"]}
    if name == "list_calendar_events":
        return {"events": [{"title": "Existing meeting", "start": "14:00", "end": "15:00"}]}
    raise ValueError(f"Unknown tool: {name}")


messages = [
    {
        "role": "user",
        "content": "Schedule an all-hands with everyone: " + ", ".join(f"user{i}@example.com" for i in range(15)),
    }
]

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=tools,
    messages=messages,
)

while response.stop_reason == "tool_use":
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            try:
                result = run_tool(block.name, block.input)
                tool_results.append(
                    {"type": "tool_result", "tool_use_id": block.id, "content": json.dumps(result)}
                )
            except Exception as exc:
                # Segnala il fallimento così Claude può riprovare o chiedere chiarimenti.
                tool_results.append(
                    {
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": str(exc),
                        "is_error": True,
                    }
                )

    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})

    response = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )

final_text = next(block for block in response.content if block.type == "text")
print(final_text.text)
# Anello 5: l'astrazione Tool Runner SDK.

import json

import anthropic
from anthropic import beta_tool

client = anthropic.Anthropic()


@beta_tool
def create_calendar_event(
    title: str,
    start: str,
    end: str,
    attendees: list[str] | None = None,
    recurrence: dict | None = None,
) -> str:
    """Create a calendar event with attendees and optional recurrence.

    Args:
        title: Event title.
        start: Start time in ISO 8601 format.
        end: End time in ISO 8601 format.
        attendees: Email addresses to invite.
        recurrence: Dict with 'frequency' (daily, weekly, monthly) and 'count'.
    """
    if attendees and len(attendees) > 10:
        raise ValueError("Too many attendees (max 10)")
    return json.dumps({"event_id": "evt_123", "status": "created", "title": title})


@beta_tool
def list_calendar_events(date: str) -> str:
    """List all calendar events on a given date.

    Args:
        date: Date in YYYY-MM-DD format.
    """
    return json.dumps({"events": [{"title": "Existing meeting", "start": "14:00", "end": "15:00"}]})


final_message = client.beta.messages.tool_runner(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=[create_calendar_event, list_calendar_events],
    messages=[
        {
            "role": "user",
            "content": "Check what I have next Monday, then schedule a planning session that avoids any conflicts.",
        }
    ],
).until_done()

for block in final_message.content:
    if block.type == "text":
        print(block.text)