Tool calling
Tool calling é o contrato entre o LLM e o mundo: o modelo devolve JSON estruturado (nome + argumentos), o runtime valida contra schema e executa. É o que transforma texto em ação.
O que é
Tool calling (também chamado de ) é a interface pela qual um LLM devolve, em vez de (ou além de) texto, uma chamada de função estruturada: nome da ferramenta + argumentos em JSON. O runtime recebe, valida os argumentos contra um schema, executa e devolve o resultado ao contexto.
O modelo nunca executa nada por conta própria. Ele só propõe — 'eu chamaria get_weather com { city: 'São Paulo' }'. A execução, autorização, retry e auditoria ficam com o runtime. Esquecer quem executa é o erro mais caro que aparece em produção.
O schema JSON: o contrato
Cada ferramenta é declarada para o modelo por um schema JSON com nome, descrição e parâmetros tipados. O LLM usa esse schema como gramática: ele sabe o nome, sabe o formato dos argumentos e usa a descrição para decidir quando faz sentido chamar.
A descrição é a parte mais negligenciada. O LLM não lê código: ele lê a string. 'Obtém o clima de uma cidade' é melhor que 'get_weather', porque o modelo decide quando chamar baseado em prosa. Schemas com descrições ruins geram chamadas certas ou erradas.
{
"name": "get_weather",
"description": "Obtém a temperatura atual e a previsão para os próximos 3 dias em uma cidade.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Nome da cidade, em português ou inglês (ex: 'São Paulo', 'Lisbon')."
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius"
}
},
"required": ["city"]
}
}Validação de argumentos: a sua responsabilidade
Quando o modelo devolve uma chamada de função, o runtime recebe um JSON que pode estar errado: tipo errado, campo faltando, valor fora do enum, string onde devia ser número. Validar antes de executar é não-negociável — é a fronteira entre o modelo, que propõe, e o seu código, que executa com permissões reais.
Em Python, Pydantic é o caminho padrão: declare um modelo, chame model_validate(model_dump), e o Pydantic levanta ValidationError com a lista exata de campos e o motivo. Em TypeScript, o par natural é Zod, com safeParse retornando { success, data, error }.
from pydantic import BaseModel, Field, ValidationError
class GetWeatherArgs(BaseModel):
city: str = Field(..., min_length=1)
unit: str = Field("celsius", pattern=r"^(celsius|fahrenheit)$")
def call_tool(name: str, raw_args: dict):
if name != "get_weather":
raise ValueError(f"ferramenta desconhecida: {name}")
try:
args = GetWeatherArgs.model_validate(raw_args)
except ValidationError as e:
return {"error": "invalid_args", "details": e.errors()}
return fetch_weather(args.city, args.unit)O fluxo completo, fim a fim
A chamada de ferramenta atravessa cinco etapas, cada uma com uma resposta possível e um caminho de erro distinto. Sem ver os cinco, parece mágica — e os bugs não-estão.
1. declaração: a lista de schemas é entregue ao LLM junto do prompt.
2. proposta: o LLM devolve tool_calls com name + JSON arguments.
3. validação: o runtime parseia e valida contra o schema — falha aqui significa 'o modelo alucinou'; trate como erro e devolva o motivo ao LLM.
4. execução: o runtime chama a função real (HTTP, DB, comando) com permissões e timeout.
5. observação: o resultado vira uma mensagem tool no contexto; o LLM usa para a próxima decisão.
import Anthropic from '@anthropic-ai/sdk';
import { z } from 'zod';
const GetWeather = z.object({
city: z.string().min(1),
unit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
});
async function run(anthropic: Anthropic, userMessage: string) {
const tools = [{
name: 'get_weather',
description: 'Obtém o clima atual de uma cidade.',
input_schema: /* shape JSON do schema */,
}];
let msg = await anthropic.messages.create({
model: 'claude-opus-4', max_tokens: 1024, tools,
messages: [{ role: 'user', content: userMessage }],
});
if (msg.stop_reason === 'tool_use') {
const call = msg.content.find((b) => b.type === 'tool_use');
const parsed = GetWeather.safeParse(call.input);
if (!parsed.success) return { error: 'invalid_args', issues: parsed.error.issues };
const result = await fetchWeather(parsed.data.city, parsed.data.unit);
msg = await anthropic.messages.create({
model: 'claude-opus-4', max_tokens: 1024, tools,
messages: [
{ role: 'user', content: userMessage },
{ role: 'assistant',content: msg.content },
{ role: 'user', content: [{ type: 'tool_result', tool_use_id: call.id, content: JSON.stringify(result) }] },
],
});
}
return msg;
}Por que não dá para pular a validação
- o modelo pode inventar campos: ele viu 1000 schemas diferentes, não garante consistência
- tipos são garantidos, valores não: ele sabe que 'unit' é string, mas pode mandar 'celcius' (typo) por 2s
- enums são a fronteira mais comum de erro: o modelo raramente respeita o enum sem prompt explícito
- validação é barata: custa microssegundos; execução não validada pode permitir ordem de execução crítica
Pontos fortes e limitações
- forte: o schema força estrutura — o modelo não precisa 'tentar' produzir JSON válido; ele está produzindo tokens dentro de uma gramática
- forte: erros de validação devolvem mensagem rica para o modelo, que quase sempre se corrige no próximo turno
- fraco: descrição ruim leva a chamadas certas ou erradas — escrever schema bom é trabalho de design
- fraco: a chamada é opaca para o usuário — se ele não ler o trace, não sabe que ferramenta rodou
- fraco: paralelismo depende do provedor — alguns permitem várias tool_calls em uma resposta, outros só uma
conexões no mapa
- Agent frameworkshabilitaTool calling
- Tool callingfala o protocoloMCP - model context protocol
atualizado em 14/10/2026 · fontes para aprofundar · reportar erro
em outros domínios
- Context engineering para agents de códigovibecodingferramentas e permissões decidem o que o agente consegue fazer
- SASTappsecpega injeção em código; aqui o alvo é o argumento da ferramenta
- Automação de segurança e playbooks como códigosecengação disparada por modelo precisa dos mesmos freios de um playbook
Estude antes
Desbloqueia
teste o que entendeu
Carregando perguntas…