Tool calls: como um modelo decide chamar uma função

Um modelo não executa ferramenta nenhuma. Ele só pede.

Tool calling é o mecanismo que transforma um modelo de linguagem em um agente capaz de agir no mundo: ler um arquivo, consultar uma API, rodar um comando. Mas o modelo nunca toca em nada — ele apenas emite uma intenção estruturada, e quem executa é o seu código.

TL;DR Você descreve ferramentas pro modelo em JSON Schema. O modelo, quando acha útil, responde com um bloco tool_use em vez de texto. Seu código executa, devolve o resultado como tool_result, e o modelo continua. O ciclo repete até ele responder em texto puro.

O ciclo básico

A conversa com tool use não é mais um turno entre usuário e assistente — é um loop. A cada rodada o modelo escolhe entre responder ao usuário ou pedir uma ferramenta. Quem fecha o loop é o seu código, não o modelo.

  1. Você manda a mensagem do usuário + lista de ferramentas disponíveis.
  2. Modelo decide: responder direto, ou emitir um tool_use.
  3. Se foi tool_use: você executa a função, devolve tool_result.
  4. Modelo recebe o resultado e decide de novo — pode encadear várias chamadas.
  5. Quando ele responde em texto puro, o turno acabou.

O formato

Cada ferramenta é descrita como um nome, uma descrição e um JSON Schema dos parâmetros. A descrição é o que o modelo usa pra decidir quando chamar — ela é prompt, não documentação técnica.

Anthropic SDK · Python
tools = [{
    "name": "get_weather",
    "description": "Retorna o clima atual de uma cidade. Use quando o usuário "
                   "perguntar sobre temperatura, chuva ou condições do tempo.",
    "input_schema": {
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "Nome da cidade"},
            "unit": {"type": "string", "enum": ["c", "f"]}
        },
        "required": ["city"]
    }
}]

A resposta do modelo, quando ele decide chamar, vem com stop_reason: "tool_use":

{
  "stop_reason": "tool_use",
  "content": [
    {"type": "text", "text": "Vou checar isso pra você."},
    {"type": "tool_use", "id": "toolu_01A...", "name": "get_weather",
     "input": {"city": "São Paulo", "unit": "c"}}
  ]
}

O que costuma dar errado

Descrição preguiçosa. Se a description é só "busca dados", o modelo chama em hora errada — ou não chama. Trate description como prompt: diga quando usar e quando não usar.
Esquecer de devolver tool_result. Toda tool_use precisa de um tool_result correspondente (mesmo tool_use_id) na próxima mensagem. Senão a API rejeita.
Loops infinitos. O modelo pode insistir em chamar a mesma ferramenta. Use um limite de iterações no seu loop e devolva erro claro quando a ferramenta falha — o modelo se adapta melhor com um erro explícito do que com silêncio.

Chamadas paralelas

Modelos modernos podem emitir várias tool_use num único turno. Isso é ouro: se você precisa de três coisas independentes (clima, agenda, e-mail), o modelo pede as três de uma vez e seu código executa em paralelo. Latência cai bastante.

Página de teste — gerada pra calibrar threads do remote control, não pra valer como referência definitiva.