Blog

Orquestração de agentes de IA em produção

Um agente de IA sozinho é um protótipo. Ele funciona na demo, resolve o caso feliz e trava na primeira tool que dá timeout, no primeiro loop infinito de raciocínio ou no primeiro deploy que perde o estado no meio de uma tarefa longa. Produção exige outra coisa: um orquestrador que coordena vários agentes especializados, decide quem faz o que, executa ferramentas com falha controlada, guarda estado para retomar e mede cada passo. Este artigo mostra como sair do agente único monolítico para uma orquestração confiável: os padrões de coordenação (supervisor, sequencial, paralelo), como modelar estado durável, como blindar a chamada de tool, como cortar loop e custo com limites, e o que observar para não operar no escuro. O foco é engenharia de produção, não a demo de sexta à tarde.

2026-07-06 / IA Aplicada / 13 min

01

Por que um agente único não aguenta produção

O agente único com um prompt gigante e todas as tools no mesmo contexto é a arquitetura que mais rápido chega na demo e mais rápido quebra em produção. O contexto incha, o modelo confunde qual tool usar, o custo por chamada explode porque tudo entra no prompt, e uma tarefa que precisa de dez passos vira uma sequência de decisões onde qualquer erro no meio contamina o resto. Não existe onde intervir: é uma caixa preta que ou acerta tudo ou erra tudo.

Orquestrar é quebrar essa caixa preta em partes com responsabilidade única. Um agente que só classifica intenção. Um que só consulta a base. Um que só redige a resposta. Um supervisor que decide a ordem. Cada parte tem contexto menor, prompt focado, tools limitadas e ponto de observação próprio. Quando algo falha, você sabe qual agente falhou e por que, em vez de reprocessar a conversa inteira tentando adivinhar. É a mesma lógica de quebrar um monolito em serviços, aplicada ao raciocínio.

02

Os três padrões de coordenação

Não existe um jeito único de orquestrar. Há três padrões base, e a maioria dos sistemas reais combina os três. Escolher o padrão certo por etapa é o que separa uma orquestração enxuta de uma que gasta o dobro de tokens sem ganho.

PadrãoComo funcionaQuando usarCusto e risco
Sequencial (pipeline)Saída de um agente vira entrada do próximo, em ordem fixaEtapas com dependência clara: classificar -> buscar -> redigirBaixo custo, latência soma; um passo lento trava a cadeia
Supervisor (roteador)Um agente central decide para qual especialista mandar cada tarefaMuitas intenções distintas, cada uma com um agente próprioCusto do passo de roteamento; erro do supervisor propaga
Paralelo (fan-out)Vários agentes rodam ao mesmo tempo e um passo agregaSub-tarefas independentes: consultar 3 fontes de uma vezLatência = a mais lenta, mas custo soma todas em paralelo

Na prática você aninha os padrões. O supervisor roteia para um pipeline; dentro do pipeline, um passo faz fan-out para três consultas paralelas e agrega. A regra é usar paralelo só quando as sub-tarefas são de fato independentes (senão você paga o custo sem ganhar latência) e usar supervisor só quando há divergência real de intenção (senão um pipeline fixo é mais barato e mais previsível).

03

Estado durável: retomar de onde parou

O erro mais caro em agentes de produção é tratar o estado como algo que vive na memória do processo. Uma tarefa de agente pode levar segundos ou minutos, chamar várias tools e sobreviver a um deploy no meio. Se o estado está só na RAM, qualquer restart perde o progresso, e você ou reprocessa tudo (caro, e as tools com efeito colateral rodam duas vezes) ou perde a tarefa. Estado durável significa persistir cada passo concluído, de forma que o orquestrador consiga retomar exatamente de onde parou.

// orchestrator/state.js
// Estado da execucao persistido por passo. A chave e o runId;
// cada passo concluido e gravado antes de avancar, para retomar apos falha.

export function createRun(store, runId, input) {
  return store.put(runId, {
    runId,
    input,
    status: 'running',
    step: 0,
    // Historico append-only: cada entrada e um passo ja concluido.
    history: [],
    createdAt: null, // preenchido pela store, evita depender de relogio aqui
  });
}

// Grava o resultado de um passo ANTES de chamar o proximo agente.
// Assim, se o processo morrer no passo N+1, o passo N nao se perde.
export async function commitStep(store, runId, stepResult) {
  const run = await store.get(runId);
  run.history.push(stepResult);
  run.step += 1;
  await store.put(runId, run);
  return run;
}

// Ao reiniciar, retoma do ponto salvo em vez de recomecar do zero.
export async function resume(store, runId, agents) {
  const run = await store.get(runId);
  if (run.status !== 'running') return run;
  // O proximo agente e decidido pelo passo atual, nao pela memoria perdida.
  const next = agents[run.step];
  if (!next) return finish(store, run);
  return next.run(run);
}

A consequência prática: tools com efeito colateral (enviar mensagem, cobrar, criar pedido) precisam ser idempotentes ou registradas como concluídas no estado, para que a retomada não dispare a mesma ação de novo. Persistir o passo antes de avançar, e não depois, é o detalhe que garante que a retomada nunca pule nem repita um passo crítico.

04

Blindando a chamada de tool

A tool é onde o agente toca o mundo real, e por isso é onde mais falha. API externa cai, responde lento, devolve payload fora do contrato ou retorna erro transitório. Um agente de produção nunca chama uma tool crua: ele envolve toda chamada em timeout, retry com backoff, validação de saída e um caminho de degradação para quando a tool falha de vez. Sem isso, uma única API instável derruba a execução inteira.

// orchestrator/tool-runner.js
// Executa uma tool com timeout, retry com backoff e validacao de saida.
// Isola a falha da tool para que o orquestrador decida o que fazer.

export async function runTool(tool, args, opts = {}) {
  const { retries = 2, timeoutMs = 8000, backoffMs = 500 } = opts;

  for (let attempt = 0; attempt <= retries; attempt += 1) {
    try {
      const result = await withTimeout(tool.execute(args), timeoutMs);
      // Valida o contrato ANTES de devolver ao agente.
      if (!tool.validate(result)) {
        throw new Error('tool_output_invalid');
      }
      return { ok: true, result, attempts: attempt + 1 };
    } catch (err) {
      const transient = isTransient(err);
      // So faz retry em erro transitorio; erro de contrato nao adianta repetir.
      if (!transient || attempt === retries) {
        return { ok: false, error: err.message, attempts: attempt + 1 };
      }
      // Backoff exponencial simples entre tentativas.
      await sleep(backoffMs * 2 ** attempt);
    }
  }
}

function withTimeout(promise, ms) {
  return Promise.race([
    promise,
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('tool_timeout')), ms),
    ),
  ]);
}

O ponto sutil: retry só faz sentido em erro transitório (timeout, 503, conexão caiu). Erro de contrato ou 4xx não melhora repetindo, só queima tempo e tokens. E quando a tool falha de vez, o orquestrador precisa de um plano B explícito: responder com o que tem, escalar para humano, ou marcar a tarefa como parcial. O agente nunca deve inventar o resultado de uma tool que falhou, porque aí a falha vira alucinação silenciosa, que é pior que o erro visível.

05

Cortando loop, custo e divagação

Agente sem limite é um gerador de custo. Ele pode entrar em loop chamando a mesma tool, raciocinar em círculos, ou expandir o contexto até estourar o limite do modelo. Produção exige guardrails duros que cortam a execução antes de virar prejuízo. Esses limites não são opcionais nem "para depois": são o que impede uma única tarefa de consumir o orçamento de mil.

  • Limite de passos: um teto de iterações por execução (por exemplo, 12). Ao atingir, o orquestrador para e devolve o melhor resultado parcial em vez de rodar para sempre.
  • Orçamento de tokens por tarefa: some os tokens de todos os passos e aborte se passar do limite. Uma tarefa que já gastou o esperado provavelmente está em loop.
  • Detecção de repetição: se o agente chama a mesma tool com os mesmos argumentos duas vezes seguidas, é sinal de loop; interrompa e mude de estratégia.
  • Timeout de ponta a ponta: além do timeout por tool, um teto de tempo total da tarefa, para nada ficar pendurado indefinidamente segurando recurso.
  • Confiança mínima para agir: em ação com efeito colateral, exija que o agente esteja acima de um limiar de certeza; abaixo dele, escale para humano em vez de arriscar.

A filosofia é simples: prefira falhar de forma visível e barata a ter sucesso caro e imprevisível. Um limite atingido é um evento observável que você investiga e ajusta; um loop sem limite é uma fatura no fim do mês que ninguém entende. Cada guardrail que dispara deve virar log e métrica, para você saber quais tarefas batem no teto e por que.

06

Observabilidade: não operar no escuro

Orquestração sem tracing é impossível de depurar. Quando uma tarefa dá errado, você precisa ver a árvore inteira: qual agente rodou, qual tool chamou, o que cada passo custou em tokens e latência, onde parou. Sem isso, todo bug vira arqueologia. O modelo mental certo é o de tracing distribuído: cada execução é um trace, cada passo de agente ou tool é um span aninhado, com atributos de custo e resultado.

Trace de uma execução orquestrada

  Run abc123  (tarefa: "trocar meu pedido")
    |
    +-- span: supervisor            12 tok-in / 40 tok-out   90ms
    |     roteou -> agente "pedidos"
    |
    +-- span: agente pedidos        320 tok-in / 85 tok-out  240ms
    |     |
    |     +-- span: tool getOrder   ok    retry=0            310ms
    |     +-- span: tool checkStock ok    retry=1            720ms  <- lenta
    |
    +-- span: agente redator        410 tok-in / 190 tok-out 300ms
    |
    v
  status: ok    total: 632 tok-out   custo: US$ 0,004   1,66s
  1. Gere um runId por execução e propague em todos os passos, para amarrar o trace inteiro a uma tarefa.
  2. Emita um span por agente e por tool, com tokens de entrada e saída, latência, número de retries e status.
  3. Registre a decisão do supervisor: para qual agente roteou e por que, senão o roteamento vira caixa preta.
  4. Agregue custo e latência por execução e por tipo de tarefa, para achar qual jornada está cara ou lenta.
  5. Alerte em sinais que importam: taxa de tarefas que batem o limite de passos, retries de tool acima do normal, custo por tarefa subindo.

Com o trace, um problema que seria horas de adivinhação vira minutos: você abre a tarefa que falhou, vê que a tool checkStock deu retry e estourou o timeout, e sabe exatamente onde agir. Sem o trace, você só tem "o bot respondeu errado" e nenhum caminho até a causa. Observabilidade não é enfeite; é o que torna a orquestração operável.

07

Do protótipo à produção sem reescrever tudo

A boa notícia é que você não precisa de um framework pesado para chegar lá. Um orquestrador de produção cabe em poucas peças bem definidas, e a maioria dos frameworks só embrulha esses mesmos conceitos. O caminho prático é evoluir o protótipo por camadas, adicionando confiabilidade sem jogar fora o que já funciona.

  • Comece separando o agente único em papéis: extraia o roteamento e um ou dois especialistas antes de otimizar qualquer coisa.
  • Adicione estado durável cedo: é o que mais dificulta refatorar depois, porque muda a forma como cada passo é chamado.
  • Envolva toda tool no runner com timeout e retry desde o primeiro dia; é barato de adicionar e caro de esquecer.
  • Ponha os guardrails de passo, custo e timeout antes de abrir para tráfego real, nunca depois do primeiro susto de fatura.
  • Instrumente o tracing junto com a primeira versão orquestrada; retro-encaixar observabilidade é sempre mais trabalhoso que nascer com ela.

A diferença entre o agente de demo e o de produção não está na inteligência do modelo, está na engenharia ao redor dele: coordenação clara, estado que sobrevive à falha, tools blindadas, limites que cortam o desperdício e tracing que te deixa enxergar. Quem trata isso como detalhe descobre o custo em produção, no pior momento possível.

FAQ

Perguntas frequentes

Preciso de um framework de agentes para orquestrar?

Não para começar. Os conceitos que importam (supervisor, estado durável, runner de tool com retry, guardrails e tracing) cabem em poucas centenas de linhas e são os mesmos que os frameworks embrulham. Um framework ajuda quando o time cresce e você quer padronizar, mas adotar um cedo demais esconde o funcionamento e dificulta depurar. Entenda as peças primeiro; escolha o framework depois, sabendo o que ele resolve.

Quando uso vários agentes em vez de um só?

Quando o contexto ou as tools de um único agente começam a competir. Se um prompt precisa cobrir intenções muito distintas, ou se a lista de tools ficou grande a ponto de o modelo confundir qual usar, separar em agentes com contexto menor e escopo focado melhora precisão e reduz custo. Não separe por separar: um pipeline fixo de dois passos costuma ser mais barato e previsível que um enxame de agentes quando a tarefa é linear.

Como controlo o custo de uma orquestração com vários agentes?

Com limites duros e tracing por passo. Ponha teto de iterações, orçamento de tokens por tarefa, detecção de repetição e timeout de ponta a ponta, para nenhuma tarefa rodar sem freio. Em paralelo, emita um span por agente e por tool com tokens e latência, agregue custo por tipo de tarefa e alerte quando ele sobe. O custo foge quando ninguém olha; com limite e trace ele vira um número que você gerencia.

Orquestração é a engenharia que transforma agente de demo em agente de produção

Coordenação clara, estado durável, tools blindadas, guardrails de custo e tracing por passo são o que faz um agente de IA aguentar produção. Posso desenhar e montar essa orquestração no seu produto, do roteamento ao tracing, integrada ao seu stack e pronta para escalar.