Blog
AgentsLLMArchitectureKafka

Agentes LLM em produção: orquestração, tools e idempotência

·9 min de leitura

“Agente” virou palavra de marketing para qualquer chatbot com tools. Em produção, agente é loop de controle com estado: observar contexto, escolher ação (tool ou mensagem), aplicar efeitos colaterais, repetir — sob orçamento, auth e idempotência que o modelo não foi treinado para garantir.

Este estudo trata de desenhar loops que aguentam usuários reais, webhooks duplicados e outages parciais — sem fingir que o LLM é fonte da verdade do negócio.

Separar orquestração de geração

O modo de falha de agentes v1 é um único thread em que o modelo decide o que fazer e como dizer. Funis de CRM, aprovações e compliance precisam de transições determinísticas no código.

Divisão que dura:

| Camada | Dono de | Não deve ser dono de | |--------|---------|----------------------| | Orquestrador (máquina de estados, workflow) | Passo atual, tools permitidas, guards, handoff | Redação final | | LLM | Linguagem natural do passo, args de tool no schema | Se o pagamento foi capturado | | Tools | Efeitos colaterais com auth e validação | APIs “faça o que quiser” |

O modelo propõe; o orquestrador confirma mudança de estado depois que a tool succeeds. Se create_lead falha, a conversa fica em COLLECT_CONTACT, não num estado fictício “concluído”.

Tools são APIs, não enfeite de prompt

Cada tool exposta ao modelo é superfície pública:

  • Schemas estreitos (enums, tamanho máximo, campos obrigatórios). Rejeite chamadas fora do schema antes do banco.
  • Autorização no servidor em toda invocação — nunca confie no user id implícito do modelo.
  • Timeouts e rate limit por org; voz e SMS precisam de caps mais rígidos que chat admin interno.
  • Erros estruturados que o modelo leia (“SKU duplicado”, “escritório fechado”), não stack trace.
Chaves de idempotência em tools mutáveis (Idempotency-Key, dedupe em (org_id, client_request_id)) são obrigatórias quando webhook reentrega.

Estado: onde vive e o que logar

Estado de conversa fica no seu store (Postgres, motor de workflow), não só na janela de contexto. Persista no mínimo:

  • Passo atual e versão da definição do fluxo
  • Ids de entidades criadas na sessão (lead, ticket, rascunho de orçamento)
  • Metadata de canal (thread WhatsApp, id da chamada, Message-Id de e-mail)
Log de decisão: passo entrada, tools chamadas, passo saída, flag de override humano. É assim que você debuga “pulou qualificação” sem replay opaco de tokens.

Quando o contexto cresce, resuma com regras (campos estruturados primeiro, texto livre depois) em vez de despejar chat cru até o modelo esquecer o passo ativo.

Padrões de confiabilidade que de fato entram em uso

Human-in-the-loop para ações irreversíveis ou de alto valor: enviar orçamento, mudar preço, apagar dado. O agente prepara; humano ou motor de política aprova.

Compensação, não esperança: se o passo 3 passou e o 4 falhou, o workflow enfileira limpeza ou marca estado parcial — não peça ao modelo para “desfazer”.

Circuit breakers em backends de tool: após N falhas, modo degradado (coletar telefone, abrir ticket) em vez de loop infinito de tools.

Concorrência: duas abas ou ligação + webchat no mesmo lead exigem escritor único (lock de linha, session id ou política de merge). LLM não resolve race.

Fronteiras assíncronas

Nem todo efeito cabe na request que respondeu ao usuário. Padrão:

1. Caminho síncrono: validar, persistir intenção, devolver resposta visível. 2. Publicar evento (Kafka, SQS, etc.) para enriquecimento, sync CRM, segunda passada de LLM, campanhas outbound. 3. Consumer aplica com semântica at-least-once e handlers idempotentes.

Voz e chat ao vivo ficam em latência apertada; trabalho pesado escala em workers. O loop deve saber quais tools são inline vs só enqueue.

Observabilidade para agentes

APM padrão é necessário e insuficiente. Spans de domínio:

  • orchestrator.transition com estado from/to
  • tool.invoke com nome, latência, sucesso, org id (sem PII no span salvo política)
  • llm.completion com modelo, tokens, finish reason
  • Spans de retrieval se RAG alimenta o passo (chunk ids, contagem de hits)
Dashboards úteis: taxa de erro por tool, sessões presas (sem progresso em X horas), taxa de handoff, passos médios até conversão. Alerta em detecção de loop (mesma tool > N vezes no turno).

Segurança e abuso

Agentes multiplicam superfície: injection via docs recuperados, injection via conteúdo do usuário, exfiltração por “resume esta URL”. Mitigações que shipam:

  • Trate texto recuperado como não confiável; instruções de sistema não são anuladas por chunk (hierarquia de instrução + validação de saída onde couber).
  • Domínios allowlist para browse/fetch; sem SSRF arbitrário via tools.
  • Filtros de padrão de segredo antes de canal externo.
Red-team na camada de tools, não só na UI de chat.

Testar agentes

Teste unitário de transições do orquestrador sem LLM. Contract test de tools com fixtures. Integração com respostas gravadas. Eval de LLM em diálogos golden para tom e escolha de tool, não para conta.

Snapshot de prosa do modelo apodrece rápido; snapshot de sequência de estados (IDENTIFY → COLLECT → CREATE_LEAD) permanece estável.

Encerramento

Agentes em produção são software de workflow com LLM na frente. Máquinas de estado, tools rígidas, efeitos idempotentes, workers assíncronos e log de decisão tornam o sistema operável. O trabalho do modelo é comunicar dentro do passo atual — não ser o banco de registro.

Se você for acrescentar voz ou multicanal depois, mantenha um grafo de orquestração e troque adaptadores de canal; implementações paralelas por canal divergem em um trimestre.