Os LLMs não acessam o seu código – eles entregam uma requisição, e você executa a função. Esse fato simples derruba o mito de que "o modelo chama magicamente minha rotina Python" e força os desenvolvedores a repensarem a depuração e a segurança.

O loop de despacho, passo a passo

Quando um modelo de linguagem (LLM) precisa de uma ferramenta, ele segue uma sequência determinística:

  1. Planejamento – o modelo decide que uma ação é necessária (ex: "reembolsar um pagamento").
  2. Geração de uma requisição – ele gera um texto estruturado — geralmente JSON — que nomeia a ferramenta e fornece os argumentos.
  3. Parsing – seu app ou um framework de suporte lê esse texto.
  4. Correspondência (Matching) – o framework procura o nome no registro das funções reais que você expôs.
  5. Validação – ele verifica se os argumentos correspondem ao schema da função e se o chamador está autorizado.
  6. Execução – a função correspondente é executada no seu ambiente, realizando o trabalho.
  7. Retorno – o resultado é empacotado e enviado de volta ao modelo para raciocínio adicional.

Pense no LLM como um planejador, no framework como um despachante e na função como o trabalhador que realmente move dados ou dinheiro.

Por que o mito da "mágica" persiste

A maioria dos desenvolvedores vê uma única linha de saída do modelo que se parece com uma chamada de função e assume que o modelo realizou a operação por conta própria. O termo "tool calling" nas documentações dos provedores soa como se o modelo estivesse invocando o código diretamente.

Na realidade, o modelo apenas produz texto que descreve uma chamada. O seu processo faz o trabalho pesado — busca, verificação de tipos, aplicação de permissões e tratamento de erros.

Frameworks que escondem os detalhes internos

Bibliotecas como PydanticAI e LangChain abstraem o loop para que você possa focar na lógica de negócio. Elas automaticamente:

  • Validam argumentos contra um schema (ex: um modelo Pydantic).
  • Aplicam permissões, garantindo que o usuário possa acionar a ferramenta.
  • Tentam novamente em caso de falha, voltando ao modelo quando uma ferramenta retorna um erro.
  • Protegem contra loops descontrolados, limitando o número de chamadas consecutivas de ferramentas.
  • Mantêm o estado da conversa, integrando os resultados das ferramentas ao diálogo.

Mesmo com esses auxiliares, o padrão permanece o mesmo: o modelo nunca executa código.

Suporte nativo a tool-calling dos provedores

Alguns provedores oferecem uma interface de "tool-calling" nativa que padroniza as definições de ferramentas e os formatos de requisição. Isso facilita a integração, mas não remove a etapa de despacho. Você ainda escreve (ou importa) o código que realmente executa a operação solicitada.

A depuração torna-se mais fácil quando você renomeia o problema

Em vez de culpar um "agente confuso", diga que o problema é que "a resposta do modelo não continha chamadas de ferramenta". A distinção é importante:

  • Sem chamada de ferramenta (No tool call) – o modelo respondeu diretamente ou falhou ao gerar uma requisição formatada corretamente.
  • Requisição malformada – o JSON está sintaticamente incorreto ou faltam campos obrigatórios, fazendo com que o despachante o rejeite.
  • Falha de validação – os argumentos não correspondem ao schema, disparando um erro antes da execução.

Categorizar as falhas permite registrar cada etapa do loop e identificar exatamente onde as coisas saíram do trilho.

Dicas práticas para um pipeline confiável

  • Trate a saída do modelo como uma entrada não confiável. Passe cada requisição por uma validação determinística antes de invocar qualquer código com efeitos colaterais.
  • Registre a requisição bruta (raw request) e o resultado de cada etapa de validação. Isso cria um rastro reproduzível quando algo der errado.
  • Defina limites explícitos para chamadas de ferramentas consecutivas; um loop descontrolado pode esgotar recursos ou atingir limites de taxa (rate limits).
  • Envolva cada função em um bloco try/except que retorne um objeto de erro estruturado que o modelo possa entender, incentivando uma nova tentativa ou um fallback gracioso.
  • Separe as verificações de permissão da lógica de negócio. Verifique os direitos do chamador antes da execução da função, especialmente para ações privilegiadas como "deletar usuário".
  • Use definições baseadas em schema (ex: modelos Pydantic) para que o framework possa gerar automaticamente o schema JSON que o modelo deve seguir.

O que observar a seguir

À medida que os provedores refinam as APIs de tool-calling nativas, espere contratos mais rígidos em torno dos formatos de requisição e códigos de erro mais detalhados. Essas mudanças facilitarão a validação e permitirão que os desenvolvedores construam barreiras de segurança mais rigorosas. Fique de olho nas atualizações das bibliotecas — muitas estão adicionando suporte nativo para os novos recursos dos provedores.

Conclusão

O LLM é um gerador de texto sofisticado, não um executor. Seu código permanece como a única autoridade que realiza ações, e o dispatcher que você constrói (ou importa) é o guardião que valida, autoriza e executa essas ações. Reformular o fluxo de trabalho elimina o mito da “mágica”, torna a depuração mais precisa e impõe a disciplina de segurança que todo sistema de produção exige.