Claude Platform Docs
  • Mensagens
  • Agentes Gerenciados
  • Administração

Search...
⌘K
Primeiros passos
Introdução ao ClaudeInício rápido
Desenvolvendo com o Claude
Visão geral dos recursosUsando a API de MensagensMotivos de parada e fallbackRecusas e fallbackCrédito de fallback
Capacidades do modelo
Pensamento estendidoPensamento adaptativoEsforçoOrçamentos de tarefas (beta)Modo rápido (prévia de pesquisa)Saídas estruturadasCitaçõesStreaming de MensagensProcessamento em loteResultados de pesquisaStreaming de recusasSuporte multilíngueEmbeddings
Ferramentas
Visão geralComo funciona o uso de ferramentasTutorial: Crie um agente que usa ferramentasDefinir ferramentasLidar com chamadas de ferramentasUso de ferramentas em paraleloTool Runner (SDK)Uso de ferramentas estritoFerramentas de servidorFerramenta de pesquisa na webFerramenta de busca na webFerramenta de execução de códigoFerramenta de consultoriaFerramenta de busca de ferramentasFerramenta de memóriaFerramenta BashFerramenta de editor de textoFerramenta de uso de computadorSolução de problemas
Infraestrutura de ferramentas
Referência de ferramentasGerenciar contexto de ferramentasCombinações de ferramentasUso de ferramentas com cache de promptChamada programática de ferramentasStreaming granular de ferramentas
Gerenciamento de contexto
Janelas de contextoCompactaçãoEdição de contextoCache de promptMensagens de sistema no meio da conversaCriar um modo de orquestraçãoDiagnóstico de cache (beta)Contagem de tokens
Trabalhando com arquivos
API de ArquivosSuporte a PDF
Habilidades
Visão geralInício rápidoPráticas recomendadasHabilidades para empresasHabilidades na API
MCP
Servidores MCP remotosConector MCP
Claude em plataformas de nuvem
Amazon BedrockAmazon Bedrock (legado)Claude Platform na AWSGoogle CloudMicrosoft Foundry

Log in
Tutorial: Crie um agente que usa ferramentas
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
Mensagens/Ferramentas

Tutorial: Construa um agente que usa ferramentas

Um passo a passo guiado, desde uma única chamada de ferramenta até um loop agêntico pronto para produção.

Este tutorial constrói um agente de gerenciamento de calendário em cinco anéis concêntricos. Cada anel é um programa completo e executável que adiciona exatamente um conceito ao anel anterior. Ao final, você terá escrito o loop agêntico manualmente e depois o substituído pela abstração do SDK Tool Runner.

A ferramenta de exemplo é create_calendar_event. Seu schema usa objetos aninhados, arrays e campos opcionais, para que você veja como o Claude lida com formatos de entrada realistas em vez de uma única string plana.



Cada anel é executado de forma independente. Copie qualquer anel para um arquivo novo e ele será executado sem o código dos anéis anteriores.

Anel 1: Uma ferramenta, um turno

O menor programa possível que usa ferramentas: uma ferramenta, uma mensagem do usuário, uma chamada de ferramenta, um resultado. O código é amplamente comentado para que você possa mapear cada linha ao ciclo de vida do uso de ferramentas.

A requisição envia um array tools junto com a mensagem do usuário. Quando o Claude decide chamar uma ferramenta, a resposta retorna com stop_reason: "tool_use" e um bloco de conteúdo tool_use contendo o nome da ferramenta, um id único e o input estruturado. Seu código executa a ferramenta e então envia o resultado de volta em um bloco tool_result cujo tool_use_id corresponde ao id da chamada.

# Anel 1: Ferramenta única, turno único.

import json

import anthropic

# Crie um cliente. Ele lê ANTHROPIC_API_KEY do ambiente.
client = anthropic.Anthropic()

# Defina uma ferramenta. O input_schema é um objeto JSON Schema que descreve
# os argumentos que o Claude deve passar ao chamar esta ferramenta. Este schema
# inclui objetos aninhados (recurrence), arrays (attendees) e campos
# opcionais, mais próximo de ferramentas reais do que um argumento string simples.
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"],
        },
    }
]

# Envie a solicitação do usuário junto com a definição da ferramenta. O Claude
# decide se chama a ferramenta com base na solicitação e na descrição dela.
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 o Claude chama uma ferramenta, a resposta tem stop_reason "tool_use"
# e o array content contém um bloco tool_use junto com qualquer texto.
print(f"stop_reason: {response.stop_reason}")

# Encontre o bloco tool_use. Uma resposta pode conter blocos de texto antes do
# bloco tool_use, então percorra o array content em vez de assumir a posição.
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}")

# Execute a ferramenta. Em um sistema real, isso chamaria sua API de calendário.
# Aqui o resultado é fixo no código para manter o exemplo autocontido.
result = {"event_id": "evt_123", "status": "created"}

# Envie o resultado de volta. O bloco tool_result vai em uma mensagem do usuário
# e seu tool_use_id deve corresponder ao id do bloco tool_use acima. A resposta
# anterior do assistente é incluída para que o Claude tenha o histórico completo.
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),
                }
            ],
        },
    ],
)

# Com o resultado da ferramenta em mãos, o Claude produz uma resposta final em
# linguagem natural e stop_reason se torna "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)

O que esperar

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.

O primeiro stop_reason é tool_use porque o Claude está aguardando o resultado do calendário. Depois que você envia o resultado, o segundo stop_reason é end_turn e o conteúdo é linguagem natural para o usuário.

Anel 2: O loop agêntico

O Anel 1 assumiu que o Claude chamaria a ferramenta exatamente uma vez. Tarefas reais frequentemente precisam de várias chamadas: o Claude pode criar um evento, ler a confirmação e então criar outro. A solução é um loop while que continua executando ferramentas e enviando resultados de volta até que stop_reason não seja mais "tool_use".

A outra mudança é o histórico da conversa. Em vez de reconstruir o array messages do zero a cada requisição, mantenha uma lista contínua e adicione a ela. Cada turno vê todo o contexto anterior completo.

# Anel 2: O loop agêntico.

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}"}


# Mantenha o histórico completo da conversa em uma lista para que cada turno veja o contexto anterior.
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,
)

# Itere até que o Claude pare de solicitar ferramentas. Cada iteração executa a ferramenta
# solicitada, anexa o resultado ao histórico e pede ao Claude que continue.
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)

O que esperar

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

O loop pode ser executado uma ou várias vezes, dependendo de como o Claude divide a tarefa. Seu código não precisa mais saber disso com antecedência.

Anel 3: Múltiplas ferramentas, chamadas paralelas

Agentes raramente têm apenas uma capacidade. Adicione uma segunda ferramenta, list_calendar_events, para que o Claude possa verificar a agenda existente antes de criar algo novo.

Quando o Claude tem múltiplas chamadas de ferramenta independentes a fazer, ele pode retornar vários blocos tool_use em uma única resposta. Seu loop precisa processar todos eles e enviar todos os resultados juntos em uma única mensagem do usuário. Itere sobre cada bloco tool_use em response.content, não apenas o primeiro.

# Anel 3: Múltiplas ferramentas, chamadas paralelas.

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":
    # Uma única resposta pode conter múltiplos blocos tool_use. Processe todos
    # eles e retorne todos os resultados juntos em uma única mensagem do usuário.
    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)

O que esperar

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.

Para mais informações sobre execução concorrente e garantias de ordenação, consulte Uso paralelo de ferramentas.

Anel 4: Tratamento de erros

Ferramentas falham. Uma API de calendário pode rejeitar um evento com participantes demais, ou uma data pode estar malformada. Quando uma ferramenta gera um erro, envie a mensagem de erro de volta com is_error: true em vez de travar. O Claude lê o erro e pode tentar novamente com entrada corrigida, pedir esclarecimentos ao usuário ou explicar a limitação.

# Anel 4: Tratamento de erros.

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:
                # Sinaliza falha para que o Claude possa tentar novamente ou pedir esclarecimentos.
                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)

O que esperar

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.

A flag is_error é a única diferença em relação a um resultado bem-sucedido. O Claude vê a flag e o texto do erro, e responde de acordo. Consulte Lidar com chamadas de ferramentas para a referência completa de tratamento de erros.

Anel 5: A abstração do SDK Tool Runner

Os Anéis 2 a 4 escreveram o mesmo loop manualmente: chamar a API, verificar stop_reason, executar ferramentas, anexar resultados, repetir. O Tool Runner faz isso por você. Defina cada ferramenta como uma função, passe a lista para tool_runner e recupere a mensagem final quando o loop for concluído. O encapsulamento de erros, a formatação de resultados e o gerenciamento da conversa são tratados internamente.

O SDK Python usa o decorador @beta_tool para inferir o schema a partir de type hints e da docstring. O SDK TypeScript usa betaZodTool com um schema Zod. Os outros SDKs seguem o mesmo padrão com seus próprios helpers: BetaRunnableTool em C# e PHP, classes de ferramentas tipadas em Java e Ruby, e toolrunner.NewBetaToolFromJSONSchema em Go.



O Tool Runner está disponível em todos os sete SDKs: Python, TypeScript, C#, Go, Java, PHP e Ruby. Consulte Tool Runner para a referência completa. As abas cURL e CLI mostram uma nota em vez de código; mantenha o loop do Anel 4 para scripts baseados em curl ou CLI.

# Anel 5: A abstração do 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)

O que esperar

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.

A saída é idêntica à do Anel 3. A diferença está no código: aproximadamente metade das linhas, nenhum loop manual, e o schema fica junto da implementação.

O que você construiu

Você começou com uma única chamada de ferramenta hardcoded e terminou com um agente em formato de produção que lida com múltiplas ferramentas, chamadas paralelas e erros, e então condensou tudo isso no Tool Runner. Ao longo do caminho, você viu cada parte do protocolo de uso de ferramentas: blocos tool_use, blocos tool_result, correspondência de tool_use_id, verificação de stop_reason e sinalização de is_error.

Próximos passos

Definir ferramentas

Especificação de schema e melhores práticas.

Aprofundamento no Tool Runner

A referência completa da abstração do SDK.

Solução de problemas

Corrija erros comuns de uso de ferramentas.

Was this page helpful?

  • Anel 1: Uma ferramenta, um turno
  • Anel 2: O loop agêntico
  • Anel 3: Múltiplas ferramentas, chamadas paralelas
  • Anel 4: Tratamento de erros
  • Anel 5: A abstração do SDK Tool Runner
  • O que você construiu
  • Próximos passos