AI Agents Claude

Claude Tool Use: Como Dou Capacidades Reais aos Meus Agentes de IA

Alejandro Rioja
Alejandro Rioja
12 min de leitura
TL;DR

O tool use do Claude permite que seu agente tome ações — não apenas gerar texto. Você define ferramentas como esquemas JSON, o Claude decide quando chamá-las, e seu código executa a ação no mundo real. O loop tem três etapas: enviar mensagem → receber bloco tool_use → executar e retornar resultado. Implantei isso em mais de 15 agentes de produção no Cloudflare Workers. O ponto de falha quase nunca é a IA — são os resultados ambíguos que retornam das ferramentas.

Newsletter gratuita

Toda quarta-feira. 28.400+ operadores. Zero enrolação.

Índice

Atualizado julho 2026.

TL;DR: O tool use do Claude permite que seu agente tome ações — não apenas gerar texto. Você define ferramentas como esquemas JSON, o Claude decide quando chamá-las, e seu código executa a ação no mundo real. O loop tem três etapas: enviar mensagem → receber bloco tool_use → executar e retornar resultado. Implantei isso em mais de 15 agentes de produção no Cloudflare Workers. O ponto de falha quase nunca é a IA — são os resultados ambíguos que retornam das ferramentas.

[Perspectiva do operador] Gerencio mais de 30 agentes de IA em produção entre uma marca de consultoria e a Pickleland, uma instalação de pickleball em Pflugerville, TX. Cerca de metade usa tool use — o recurso da API do Claude que permite ao modelo chamar funções definidas pelo seu código. Aqui está o padrão ao qual cheguei após implantar e iterar em produção.

Por que o tool use muda o que um agente pode fazer

Sem ferramentas, um agente só pode gerar texto. Isso é útil para resumos, rascunhos e classificação — mas não é o que a maioria das automações empresariais realmente precisa. As automações empresariais precisam consultar informações, escrever em bancos de dados, chamar APIs, enviar mensagens.

O tool use é a forma como você dá esse acesso ao Claude. Você define um conjunto de ferramentas como esquemas JSON. O Claude lê os esquemas, decide qual ferramenta chamar e com quais argumentos, e retorna um bloco de conteúdo tool_use estruturado. Seu código executa a função real. O Claude obtém o resultado e decide o que fazer a seguir — incluindo chamar outra ferramenta ou produzir uma resposta de texto final.

A chave: o Claude decide quando e se chamar uma ferramenta. Você define as capacidades. O modelo raciocina sobre quando usá-las.

Como funciona o fluxo da API

O loop de tool use tem três etapas. Você executará este loop uma ou várias vezes dependendo de quantas chamadas de ferramenta o modelo fizer.

Etapa 1: Envie sua mensagem com as ferramentas definidas

typescript
const response = await anthropic.messages.create({
  model: "claude-haiku-4-5-20251001",
  max_tokens: 1024,
  tools: [
    {
      name: "check_court_availability",
      description:
        "Check if a court is available at a given date, time, and duration",
      input_schema: {
        type: "object",
        properties: {
          date: {
            type: "string",
            description: "Date in YYYY-MM-DD format",
          },
          time: {
            type: "string",
            description: "Start time in HH:MM format (24h)",
          },
          duration_minutes: {
            type: "number",
            description: "Duration of the booking in minutes",
          },
        },
        required: ["date", "time", "duration_minutes"],
      },
    },
  ],
  messages: [
    {
      role: "user",
      content: "Is a court available tomorrow at 2pm for 90 minutes?",
    },
  ],
});

Etapa 2: Verifique se o Claude quer chamar uma ferramenta

typescript
if (response.stop_reason === "tool_use") {
  const toolUseBlock = response.content.find(
    (block): block is Anthropic.ToolUseBlock => block.type === "tool_use"
  );

  if (!toolUseBlock) throw new Error("Expected tool_use block");

  // Run your actual function
  const toolResult = await checkCourtAvailability(
    toolUseBlock.input as CourtAvailabilityInput
  );

  // Step 3: Return the result to Claude
  const finalResponse = await anthropic.messages.create({
    model: "claude-haiku-4-5-20251001",
    max_tokens: 1024,
    tools: [
      /* same tools as before */
    ],
    messages: [
      {
        role: "user",
        content: "Is a court available tomorrow at 2pm for 90 minutes?",
      },
      { role: "assistant", content: response.content },
      {
        role: "user",
        content: [
          {
            type: "tool_result",
            tool_use_id: toolUseBlock.id,
            content: JSON.stringify(toolResult),
          },
        ],
      },
    ],
  });

  // finalResponse.content now has the text answer
}

Esse é o padrão completo. Três interações de API por chamada de ferramenta: definir ferramentas → receber bloco tool_use → retornar resultado.

Exemplo real: o verificador de disponibilidade da Pickleland

A Pickleland é uma instalação de pickleball. Recebemos perguntas de reserva no Facebook Messenger, nos comentários e através de um chatbot. A pergunta é quase sempre alguma variação de “vocês estão abertos no sábado às 15h?” ou “posso reservar uma quadra para meu grupo de 8 pessoas?”

O agente verificador de disponibilidade usa tool use para consultar o sistema de reservas real em tempo real, em vez de dar uma resposta genérica.

Aqui está o agente completo — simplificado, mas fiel à produção:

typescript
// workers/availability-checker.ts
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

const AVAILABILITY_TOOLS: Anthropic.Tool[] = [
  {
    name: "check_availability",
    description:
      "Check court availability for a date, time, and group size. Returns available courts and their prices.",
    input_schema: {
      type: "object",
      properties: {
        date: { type: "string", description: "YYYY-MM-DD" },
        start_time: { type: "string", description: "HH:MM (24h)" },
        duration_minutes: { type: "number" },
        players: { type: "number", description: "Number of players" },
      },
      required: ["date", "start_time", "duration_minutes"],
    },
  },
  {
    name: "get_pricing",
    description:
      "Get current pricing for court rentals and open play sessions",
    input_schema: {
      type: "object",
      properties: {
        session_type: {
          type: "string",
          enum: ["court_rental", "open_play", "clinics"],
        },
      },
      required: ["session_type"],
    },
  },
];

export async function handleInquiry(
  userMessage: string,
  env: Env
): Promise<string> {
  const messages: Anthropic.MessageParam[] = [
    { role: "user", content: userMessage },
  ];

  // Agentic loop — keep going until stop_reason is "end_turn"
  while (true) {
    const response = await anthropic.messages.create({
      model: "claude-haiku-4-5-20251001",
      max_tokens: 512,
      system:
        "You are the booking assistant for Pickleland, a pickleball facility in Pflugerville, TX. " +
        "Use the tools to look up real availability and pricing. Never make up availability or prices. " +
        "If the customer wants to book, direct them to pickleland.com/book.",
      tools: AVAILABILITY_TOOLS,
      messages,
    });

    // Push the assistant's response into message history
    messages.push({ role: "assistant", content: response.content });

    if (response.stop_reason === "end_turn") {
      const textBlock = response.content.find(
        (b): b is Anthropic.TextBlock => b.type === "text"
      );
      return (
        textBlock?.text ??
        "I wasn't able to answer that — please call us directly."
      );
    }

    if (response.stop_reason === "tool_use") {
      // Process ALL tool calls in this response (Claude can request multiple at once)
      const toolResults: Anthropic.ToolResultBlockParam[] = [];

      for (const block of response.content) {
        if (block.type !== "tool_use") continue;

        let result: unknown;

        switch (block.name) {
          case "check_availability":
            result = await checkAvailability(
              block.input as AvailabilityInput,
              env
            );
            break;
          case "get_pricing":
            result = await getPricing(block.input as PricingInput, env);
            break;
          default:
            result = { error: `Unknown tool: ${block.name}` };
        }

        toolResults.push({
          type: "tool_result",
          tool_use_id: block.id,
          content: JSON.stringify(result),
        });
      }

      // Return all tool results in a single user message
      messages.push({ role: "user", content: toolResults });
    }
  }
}

Dois pontos a destacar aqui.

O loop agêntico. Continuo até que stop_reason === "end_turn". O Claude pode chamar check_availability, decidir que também precisa de preços, chamar get_pricing, e então produzir a resposta final — isso são três chamadas de API para uma única mensagem do usuário. O loop lida com isso sem nenhuma lógica especial.

Múltiplas chamadas de ferramenta por turno. O Claude pode retornar múltiplos blocos tool_use em uma única resposta. Processo todos eles e retorno todos os resultados em uma única mensagem user. Se você os processar um a um e retorná-los individualmente, quebra o fluxo da conversa e desperdiça tokens.

Exemplo real: o agente de pesquisa de leads

Minha marca de consultoria usa um agente de pesquisa que enriquece leads de entrada antes de falar com eles. Quando alguém preenche o formulário de contato, o agente pesquisa a empresa e extrai o que preciso saber antes da ligação.

As definições de ferramentas para este incluem uma ferramenta de escrita — e é aqui que o padrão fica interessante:

typescript
const RESEARCH_TOOLS: Anthropic.Tool[] = [
  {
    name: "search_company",
    description: "Search for information about a company",
    input_schema: {
      type: "object",
      properties: {
        company_name: { type: "string" },
        website: { type: "string", description: "Company website if known" },
      },
      required: ["company_name"],
    },
  },
  {
    name: "save_research",
    description:
      "Save the completed research summary to Airtable. Call this when all research is complete.",
    input_schema: {
      type: "object",
      properties: {
        company_summary: { type: "string" },
        estimated_size: {
          type: "string",
          enum: ["1-10", "11-50", "51-200", "200+"],
        },
        likely_use_case: { type: "string" },
        priority: { type: "string", enum: ["high", "medium", "low"] },
        notes: { type: "string" },
      },
      required: [
        "company_summary",
        "estimated_size",
        "likely_use_case",
        "priority",
      ],
    },
  },
];

save_research é o que chamo de ferramenta de escrita — seu propósito não é obter informações, mas confirmar a saída do Claude em um banco de dados em forma estruturada. Uso esse padrão em vez de tentar fazer parse de JSON de uma resposta de texto. O Claude sabe quando a pesquisa está concluída e chama save_research com campos corretamente tipados. Nunca escrevo um parser.

Esta é a aplicação mais limpa do tool use: defina uma ferramenta de “ação final” com o esquema exato que você quer, e o Claude entrega saída estruturada através da chamada de ferramenta. Sem parse de texto, sem regex, sem validação JSONSchema de saída em texto livre.

Uma ferramenta vs. muitas

O instinto ao começar com tool use é construir uma ferramenta gigante que faz tudo. Resista a isso. Ferramentas pequenas e focadas são melhores por três razões:

  1. O Claude raciocina melhor sobre ferramentas pequenas. Uma ferramenta chamada get_court_status que retorna disponibilidade é mais fácil para o modelo raciocinar do que uma ferramenta chamada manage_facility que recebe um parâmetro mode e ramifica internamente.

  2. Ferramentas pequenas são mais fáceis de testar. Cada ferramenta é uma função TypeScript que você pode testar unitariamente de forma independente do LLM. Você deveria — erros de ferramentas são difíceis de depurar dentro de uma conversa ativa.

  3. O Claude pode paralelizar ferramentas pequenas. Se duas ferramentas não dependem uma da outra, o Claude pode chamá-las na mesma resposta e você as processa em paralelo. Isso só funciona se as ferramentas forem genuinamente independentes.

A exceção: ferramentas que precisam de acesso a muito estado interno compartilhado. Se a função precisa de 10 variáveis da mesma fonte de dados, uma ferramenta com um esquema mais rico supera 10 ferramentas que cada uma acessa o banco de dados separadamente.

Minha regra geral: comece com uma ferramenta por capacidade distinta. Combine ferramentas apenas quando vir o Claude chamá-las juntas em cada solicitação.

Implicações de custo

O tool use adiciona tokens. Cada definição de ferramenta vai para o contexto do prompt do sistema. Cada bloco tool_use e tool_result consome tokens no histórico da conversa. Para um loop agêntico multi-turno, isso se acumula rapidamente.

Para o verificador de disponibilidade da Pickleland, uma conversa típica executa 3–4 chamadas de API no total (mensagem inicial + 1–2 chamadas de ferramenta + resposta final), cada uma processando 600–900 tokens. Nos preços do Haiku, isso custa menos de $0,001 por consulta. Como explico no post sobre cálculo de custo de agentes de IA, o Haiku lida com tarefas de chamada de ferramentas bem definidas de forma confiável e é 10× mais barato que o Sonnet para o mesmo volume de tokens.

O agente de pesquisa de leads roda no Sonnet porque as decisões de julgamento — priorizar um lead, estimar adequação — requerem mais capacidade de raciocínio do que o Haiku oferece de forma confiável em entradas abertas. O cálculo ainda funciona porque roda com pouca frequência (algumas vezes por semana, não milhares por dia). A escolha do modelo segue a complexidade da tarefa, não preferência pessoal.

O ponto de falha que ninguém menciona

O ponto de falha mais comum que vejo no tool use em produção não é o Claude chamando a ferramenta errada. É a ferramenta retornando algo que o Claude não consegue raciocinar claramente.

Se sua ferramenta retorna um objeto de banco de dados bruto com 40 campos, o Claude fica confuso sobre quais campos importam. Se sua ferramenta lança uma exceção (que aparece como uma falha do Worker em vez de um resultado de ferramenta), o loop quebra silenciosamente. Se sua ferramenta retorna null quando quer dizer “sem resultados”, o Claude não sabe se deve tentar novamente ou desistir.

Três regras para resultados de ferramentas:

Retorne resultados enxutos e explícitos. { available: true, courts: ["Court 3", "Court 5"], price_per_hour: 20 } — não a linha completa do banco de dados.

Capture erros dentro da função da ferramenta e retorne-os como resultados estruturados. { error: "booking system timeout", retry: true } — não uma exceção lançada que faz o Worker falhar.

Torne “sem resultados” explícito. { available: false, next_available: "2026-07-23T14:00:00Z" } — não null ou um array vazio sem contexto.

O Claude raciocina muito melhor sobre sinais claros do que sobre valores de retorno ambíguos. Cada hora que passei depurando tool use em produção foi sobre resultados pouco claros, não sobre o raciocínio do modelo.

A conclusão do operador

O tool use é o recurso que transforma o Claude de um gerador de texto em um operador. Defina ferramentas focadas com esquemas de entrada claros. Processe todos os blocos tool_use em uma única resposta ao modelo. Execute o loop agêntico até que stop_reason === "end_turn". Retorne resultados limpos e enxutos de suas funções de ferramenta — não objetos de dados brutos, não exceções lançadas, não nulos ambíguos.

O modelo cuida do raciocínio. Seu código cuida das ações no mundo real. Mantenha esses dois trabalhos claramente separados e a arquitetura permanece sustentável mesmo quando você adiciona ferramentas.

Se você está construindo seu primeiro agente com tool use, comece com o padrão do verificador de disponibilidade acima — uma ferramenta, um propósito, um loop agêntico. Implante isso. Então adicione a segunda ferramenta.


Relacionado: O stack de agentes que uso para rodar 30+ agentes em produção · Haiku vs Sonnet: o cálculo de custo para tarefas de agentes · Agentes disparados por eventos vs agendados: qual padrão para qual trabalho

Construindo um agente com tool use e travando? Entre em contato — projeto e construo arquiteturas de agentes de produção para equipes de operadores.

FAQ

O tool use do Claude funciona com todos os modelos?

Sim — o tool use é suportado por todos os modelos Claude atuais. Claude Haiku lida com ferramentas bem definidas com esquemas claros de forma confiável e é a opção mais econômica para tipos de tarefas de alto volume. O Sonnet lida melhor com decisões de chamada de ferramentas mais ambíguas ou abertas. Comece com o Haiku; suba se a qualidade da saída não for suficiente.

Qual é a diferença entre o tool use do Claude e o function calling da OpenAI?

Mecanicamente idênticos. A OpenAI cunhou “function calling”; a Anthropic chama de “tool use”. Em ambos os casos: você define esquemas JSON, o modelo retorna chamadas estruturadas, seu código executa a função. A forma da API difere, mas o conceito é o mesmo.

O Claude pode chamar múltiplas ferramentas em uma única resposta?

Sim. O Claude pode retornar múltiplos blocos tool_use em uma única resposta assistant. Processe todos eles e retorne todos os resultados em uma única mensagem user. Veja o padrão de loop agêntico no exemplo da Pickleland acima — o loop for sobre response.content lida com isso corretamente.

Quantas ferramentas devo definir por agente?

Fico abaixo de 8–10 ferramentas por agente. Além disso, vi o Claude ocasionalmente escolher a ferramenta errada na primeira tentativa, o que desperdiça tokens em um loop de correção. Se você precisa de mais de 10 capacidades, divida o agente em múltiplos agentes com conjuntos de ferramentas especializados em vez de construir um agente que sabe tudo.

Devo usar tool use para obter saída estruturada?

Sim — o padrão de ferramenta de escrita save_research é mais limpo do que pedir ao Claude para retornar JSON em um bloco de texto e então fazer parse dele. Defina uma ferramenta de “ação final” com o esquema exato que você quer. O Claude a chamará com campos corretamente tipados quando terminar. Sem parser necessário.

Continue lendo

Posts relacionados

Continue lendo

Receba o manual de IA na sua caixa de entrada

Toda quarta-feira. 28.400+ operadores. Zero enrolação.

↵ ver todos os resultados esc esc para fechar