Alejandro Rioja.
AI Agents

Por Que o Teu Agente de IA Continua a Falhar em Produção (E Como Corrigir)

Alejandro Rioja
Alejandro Rioja
6 min de leitura
TL;DR

A maioria das falhas de agentes em produção vem de cinco causas: prompts frágeis que não lidam com casos extremos, lógica de retry em falta para erros de API transitórios, sem observabilidade para ver o que está a falhar, loops descontrolados sem condição de saída e definições de ferramentas suficientemente ambíguas para que o modelo escolha a errada. Os cinco são corrigíveis sem mudar modelos ou frameworks.

Newsletter gratuita

Toda quarta-feira. 28.400+ operadores. Zero enrolação.

Índice

Atualizado junho 2026.

TL;DR: A maioria das falhas de agentes em produção vem de cinco causas: prompts frágeis que não lidam com casos extremos, lógica de retry em falta para erros de API transitórios, sem observabilidade para ver o que está a falhar, loops descontrolados sem condição de saída e definições de ferramentas suficientemente ambíguas para que o modelo escolha a errada. Os cinco são corrigíveis sem mudar modelos ou frameworks.

[Leitura do operador] Tenho mais de 30 agentes em produção. Já tive todas estas falhas. As que queimaram mais tempo não foram as exóticas — foram as falhas de infraestrutura chatas que pensei ter tratado.

Falha 1: Prompts frágeis que quebram em entradas de casos extremos

Um prompt que funciona nos teus casos de teste vai falhar em entradas que não antecipaste. Isso não é uma limitação do modelo — é um problema de escrita de instruções.

Sintomas: O agente produz output sem sentido, chama a ferramenta errada ou devolve JSON malformado quando a entrada é ligeiramente diferente do que testaste.

Causa raiz: O teu system prompt descreve apenas o caminho feliz. Não diz ao modelo o que fazer quando os dados estão em falta, malformados ou ambíguos.

Correção: Adiciona tratamento explícito de casos extremos ao teu system prompt:

code
If the input data is missing a required field, return:
{ "status": "error", "reason": "missing_field", "field": "<fieldname>" }
Do NOT attempt to infer or hallucinate missing values.

If you are uncertain which tool to call, call no tool and return:
{ "status": "clarification_needed", "question": "..." }

O modelo segue instruções explícitas para casos extremos de forma fiável. O erro é assumir que vai generalizar as instruções do caminho feliz para tratar os casos confusos.

Falha 2: Sem lógica de retry para erros de API transitórios

Cada API externa que o teu agente chama vai falhar em algum momento. A API do Claude, a Meta Graph API, a tua base de dados — todas devolvem erros 5xx, fazem timeout ou limitam a taxa. Se o teu agente não tem lógica de retry, um erro transitório mata toda a execução.

Sintomas: As execuções do agente falham aleatoriamente em diferentes passos. Os logs mostram um 503 ou 429 sem tentativa de seguimento.

Correção: Envolve cada chamada externa num retry com backoff exponencial:

typescript
async function withRetry<T>(fn: () => Promise<T>, retries = 3, baseDelayMs = 500): Promise<T> {
  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      return await fn();
    } catch (err: any) {
      const isTransient = err.status === 429 || err.status >= 500 || err.code === "ECONNRESET";
      if (!isTransient || attempt === retries) throw err;
      const delay = baseDelayMs * Math.pow(2, attempt) + Math.random() * 100;
      await new Promise((r) => setTimeout(r, delay));
    }
  }
  throw new Error("unreachable");
}

// Usage
const result = await withRetry(() => client.messages.create({ ... }));

Três retries com backoff exponencial trata ~99% das falhas transitórias. Adiciona isto a cada chamada externa e metade das tuas falhas aleatórias desaparece.

Falha 3: Sem observabilidade — não consegues ver o que está a falhar

Este é o modo de falha mais comum em produção e o que custa mais tempo a depurar: o agente falha silenciosamente ou produz output errado, e não tens ideia de onde na cadeia correu mal.

Sintomas: Sabes que algo está errado mas não consegues identificar o passo. Adds declarações console.log e reexecutas manualmente tentando reproduzir.

Correção: Logging estruturado em cada passo, com um ID de execução que rastreia toda a execução:

typescript
function createLogger(runId: string, agentName: string) {
  return {
    step: (step: string, data: object) =>
      console.log(JSON.stringify({ runId, agent: agentName, step, ts: new Date().toISOString(), ...data })),
    error: (step: string, err: unknown) =>
      console.error(JSON.stringify({ runId, agent: agentName, step, error: String(err), ts: new Date().toISOString() })),
  };
}

const log = createLogger(crypto.randomUUID(), "newsletter-agent");
log.step("fetch_topic", { topicId: topic.id, topic: topic.name });
// ... do work ...
log.step("draft_complete", { subject: draft.subject, wordCount: draft.body.split(" ").length });

Se estás no Cloudflare Workers, estes logs vão para Logpush ou Workers Tail. Se estás a correr localmente ou num VPS, envia-os para um agregador de logs. O JSON estruturado significa que podes filtrar por runId para ver exatamente o que aconteceu numa única execução.

Falha 4: Loops descontrolados sem condição de saída

Loops agênticos — onde o modelo chama ferramentas e itera até que uma condição seja cumprida — podem correr para sempre se essa condição nunca for cumprida ou o modelo a identificar mal.

Sintomas: O agente gasta centenas de dólares em custos de API antes de fazer timeout. Ou executa a mesma chamada de ferramenta repetidamente sem progredir.

Correção: Tem sempre um limite de iteração rígido e uma verificação de progresso:

typescript
const MAX_ITERATIONS = 10;
let iterations = 0;
let lastToolCallName = "";
let sameToolCallCount = 0;

while (true) {
  iterations++;
  if (iterations > MAX_ITERATIONS) {
    log.error("loop", { reason: "exceeded_max_iterations" });
    break;
  }

  const response = await client.messages.create({ ... });

  // Detect stuck loops: same tool called 3x in a row
  const toolCall = response.content.find(b => b.type === "tool_use");
  if (toolCall?.name === lastToolCallName) {
    sameToolCallCount++;
    if (sameToolCallCount >= 3) {
      log.error("loop", { reason: "stuck_loop", tool: toolCall.name });
      break;
    }
  } else {
    sameToolCallCount = 0;
    lastToolCallName = toolCall?.name ?? "";
  }

  if (response.stop_reason === "end_turn") break;
}

Isto captura tanto o modo de falha de “correu demasiado tempo” como o de “girou no lugar”. O limite deve ser generoso o suficiente para o caminho feliz mas apertado o suficiente para limitar o raio de explosão.

Falha 5: Definições de ferramentas ambíguas que o modelo resolve mal

Se deres ao modelo duas ferramentas com descrições sobrepostas, às vezes vai chamar a errada. Isto é especialmente comum com ferramentas como search_database vs get_record ou send_email vs create_draft.

Sintomas: O modelo chama a categoria certa de ferramenta mas escolhe a específica errada. Ou chama uma ferramenta no contexto errado (usando uma ferramenta de escrita quando apenas a leitura era apropriada).

Correção: Torna as descrições de ferramentas mutuamente exclusivas e adiciona explicitamente “quando NÃO usar isto”:

typescript
const tools = [
  {
    name: "get_subscriber",
    description: "Fetch a single subscriber record by email. Use ONLY when you have a specific email address. Do NOT use for searching or listing subscribers.",
    input_schema: { ... }
  },
  {
    name: "search_subscribers",
    description: "Search subscribers by tag, segment, or status. Use when you need to find subscribers matching a criteria — NOT when you have a specific email address.",
    input_schema: { ... }
  }
];

A cláusula “NÃO usar quando X” é a parte que a maioria das pessoas ignora. É a parte mais importante. Os modelos são melhores a seguir restrições negativas explícitas do que a inferi-las de descrições positivas.

Mais uma coisa: testa os teus agentes com entradas más

A maioria dos agentes é testada apenas em entradas limpas de caminho feliz. A produção tem entradas sujas: strings vazias, campos nulos, casos extremos de Unicode, respostas de API que devolvem 200 mas com um esquema inesperado.

Adiciona uma suite de testes que exercita explicitamente:

Se o teu agente quebrar com alguma destas, corrige-o antes de ir ao ar. O ambiente de produção vai encontrar cada suposição que fizeste.

A conclusão do operador

A maioria das falhas de agentes em produção são problemas de infraestrutura a fazer-se passar por problemas de modelo. Antes de mudar modelos, adiciona retries, logging estruturado, limites de loop e tratamento explícito de casos extremos aos teus prompts. Corrige as definições de ferramentas ambíguas. Depois testa com entradas más. Faz tudo isso antes de culpar o modelo — na minha experiência, o modelo é geralmente a última coisa que precisa de mudar.

Continue lendo

Receba o manual de IA na sua caixa de entrada

Toda quarta-feira. 28.400+ operadores. Zero enrolação.

↵ ver todos os resultados esc esc para fechar