200 OK, mas o cliente não recebe nada: três bugs de um agente n8n em produção

Exatamente 20 dias depois de resolver o primeiro bug, surgiu um segundo. Dessa vez a culpa não foi da LLM, mas das camadas em torno dela: caracteres invisíveis, verificações de validação e checkboxes desativadas na configuração. Três bugs, três naturezas diferentes: - **Tags de protocolo em vez de resposta**: o modelo GLM responde só com `[VERDICT:…] [TASK:NONE]`, o validador deixa passar como conteúdo válido, o Format Response remove as tags e o cliente recebe `\n\n \n` - **Limite de 1000 bytes do Meta**: um formulário em russo (nome, data, área, telefone) ocupa 1030 bytes — uma letra são 2 bytes, um emoji 3–4 — e a API falha com Bad Request - **Catálogo em vez de filtro**: o Schema Type não foi definido, o n8n derivou o schema a partir de outro schema em vez de um exemplo, o campo category acabou no fim da lista, e a ferramenta retorna todo o estoque

Processado por IA de Habr AI; editado por Hamidun News
200 OK, mas o cliente não recebe nada: três bugs de um agente n8n em produção
Fonte: Habr AI. Colagem: Hamidun News.
Ouvir artigo

Esta é a segunda história sobre um agente de IA em produção. Há 20 dias eu tinha resolvido o bug do Reasoning Lock: o modelo gastava tokens em raciocínio oculto e enviava uma string vazia ao cliente, mesmo com o status marcando sucesso. Adicionei um validador de resposta vazia e telemetria. Escrevi: "o log está vazio, as camadas estão funcionando". O log ficou em silêncio por 20 dias. Depois os gerentes enviaram novas reclamações vindas do cliente: a pessoa escreve no Direct e o agente fica mudo. Mas dessa vez a culpa não foi da LLM.

Arquitetura do projeto: O agente n8n roda em produção para um ateliê de joias. Durante a noite, recebe pedidos no Direct do [REDACTED]gram, conduz a conversa, coleta um formulário (nome, data de nascimento, área de atuação, telefone) e cria uma oportunidade no amoCRM. Stack: n8n (self-hosted) + Redis (memória das conversas, TTL de 30 dias) + LangChain. A LLM mudou: em vez do DeepSeek V4 Pro, agora é usado o z-ai/glm-5.3-flash via OpenRouter, com o qwen/qwen3.8-flash como reserva. O workflow cresceu de 64 para 88 nós, e foram implementados o tratamento de comentários e a lógica de retentativas.

Bug 1: Tags de protocolo em vez de uma resposta humana

Abri as execuções: tudo limpo. Nenhuma execução falhou. A hipótese de "o Reasoning Lock se repetiu" cai por terra: o modelo responde, e rápido. O único rastro no amoCRM: a cliente respondeu "Sim" às 20h06 a uma confirmação de pedido (enviada às 20h02), e depois só um registro em MESSENGER-ID — no Direct, silêncio total.

Abri o painel do OpenRouter: 871 tokens de completion, dos quais 766 eram de reasoning, deixando 105 tokens visíveis. Em volume, isso corresponde a tags de serviço do protocolo: `[VERDICT:ORDER:DATA|HOT] [NEED_MANAGER_CALL] [STAGE:PERSONAL]`

O modelo GLM respondeu, sim. Conforme o protocolo. Nenhuma palavra humana. O DeepSeek 4.0 PRO costumava se fechar; o GLM se revelou o aluno exemplar: não é preciso texto humano, basta entregar o formulário.

O validador não pegou o problema porque só checa se está vazio (o output não está vazio — passa). O invariante "conteúdo vazio + tokens gastos + finish_reason stop ≠ sucesso" também falhou: os tokens foram gastos (sim), o finish_reason era stop (sim), o conteúdo não estava vazio (sim). Ele checava a ausência de vazio, não a presença de texto humano.

Em seguida, o nó Format Response remove as tags por design, deixando `\n\n \n` (uma string não vazia para o n8n, caracteres para o Meta, nada para o cliente). A verificação antes do envio checa se o nó foi executado, não o conteúdo dele.

Bug 2: O limite de 1000 bytes do Meta quebra texto em russo

Depois do diagnóstico, surgiu um nó vermelho na etapa final de envio:

``` NodeApiError: Bad request - please check your parameters Send direct message1 ```

A falha ocorria no formulário: nome, data, área, telefone, parágrafos separados por `\n\n`. A mensagem mais longa da vida do agente. A documentação da API do Meta diz: Message text must be UTF-8 and be 1000 bytes or less. Não são caracteres — são bytes.

Em UTF-8, uma letra em russo ocupa 2 bytes, um emoji ocupa 3–4 bytes (✨ = 3, 💎 = 4). 1000 bytes equivalem a aproximadamente 500–550 caracteres de texto em russo. Testei um texto em russo de 570 caracteres: ele ocupou 1030 bytes. Um formulário com nome, data, área, três parágrafos e um "Está tudo certo?" ultrapassa esse limite facilmente. O mais frustrante: `\n\n` não é um bug, são parágrafos normais, como no Word — um pipeline ajustado para raciocínio tropeçou numa simples quebra de linha.

Bug 3: Catálogo em vez de filtro — Schema Type errado

Enquanto eu resolvia o problema do envio, chegou outra reclamação dos gerentes: "o agente está mostrando o que não deveria". Pedem brincos, ele despeja meio catálogo; pedem relógios, meio catálogo de novo.

O nó-ferramenta get_product_catalog1 é responsável pelo catálogo. O Specify Input Schema estava ativado, mas o Schema Type não tinha sido definido. O n8n usa o padrão: "Generate From JSON Example" (me dê um exemplo e eu deduzo o schema). Mas o campo jsonSchemaExample não continha um exemplo de dados — continha o próprio JSON Schema, com campos como type, properties, required, category (com enum: bracelets, earrings, necklaces, luch, candles) e description.

O n8n não valida o conteúdo: aceitou de boa fé o schema como exemplo e derivou um schema a partir de outro schema. As chaves de nível superior type, properties, required se tornaram o exemplo do objeto, e category acabou no fim da lista. A ferramenta lê inputData.json.category, recebe undefined e cai no padrão all. Qualquer pedido retorna todo o estoque em vez de um filtro. Um clique para corrigir (Schema Type → "Define using JSON Schema"), uma hora e meia para descobrir.

Conclusão

Três naturezas diferentes para um mesmo problema: o modelo responde com tags de protocolo em vez de texto, a API tem um limite rígido em bytes em vez de caracteres, e a configuração da ferramenta se escondia atrás de um padrão errado. Um nó verde é o pior tipo de nó vermelho — pelo menos com uma falha você sabe onde procurar.

História

Perguntas frequentes sobre a notícia

O que se sabe sobre Bug 1: Tags de protocolo em vez de uma resposta humana?

Abri as execuções: tudo limpo. Nenhuma execução falhou. A hipótese de "o Reasoning Lock se repetiu" cai por terra: o modelo responde, e rápido. O único rastro no amoCRM: a cliente respondeu "Sim" às 20h06 a uma confirmação de pedido (enviada às 20h02), e depois só um registro em MESSENGER-ID — no Direct, silêncio total. Abri o painel do OpenRouter: 871 tokens de completion, dos quais 766 eram de reasoning, deixando 105 tokens visíveis. Em volume, isso corresponde a tags de serviço do protocolo: `[VERDICT:ORDER:DATA|HOT] [NEED_MANAGER_CALL] [STAGE:PERSONAL]` O modelo GLM res

O que se sabe sobre Bug 2: O limite de 1000 bytes do Meta quebra texto em russo?

Depois do diagnóstico, surgiu um nó vermelho na etapa final de envio: ``` NodeApiError: Bad request - please check your parameters Send direct message1 ``` A falha ocorria no formulário: nome, data, área, telefone, parágrafos separados por `\n\n`. A mensagem mais longa da vida do agente. A documentação da API do Meta diz: Message text must be UTF-8 and be 1000 bytes or less. Não são caracteres — são bytes. Em UTF-8, uma letra em russo ocupa 2 bytes, um emoji ocupa 3–4 bytes (✨ = 3, 💎 = 4). 1000 bytes equivalem a aproximadamente 500–550 caracteres de texto em russo. Testei

O que se sabe sobre Bug 3: Catálogo em vez de filtro — Schema Type errado?

Enquanto eu resolvia o problema do envio, chegou outra reclamação dos gerentes: "o agente está mostrando o que não deveria". Pedem brincos, ele despeja meio catálogo; pedem relógios, meio catálogo de novo. O nó-ferramenta get_product_catalog1 é responsável pelo catálogo. O Specify Input Schema estava ativado, mas o Schema Type não tinha sido definido. O n8n usa o padrão: "Generate From JSON Example" (me dê um exemplo e eu deduzo o schema). Mas o campo jsonSchemaExample não continha um exemplo de dados — continha o próprio JSON Schema, com campos como type, properties, requi

ZK
Zhemal Khamidun — CPO da Alpina Digital, gerente de produto do AlpinaGPT. Cria produtos de IA desde 2019. O Hamidun News é um projeto pessoal que virou um agregador em produção com mais de 6.000 leitores.
✦ Autonomous AI Agents

Delegate Deep Research, Coding & Workflows to an AI Agent

Deploy autonomous multi-step execution with NomadNet Agent (agent.nomadnet.ai) — automated web research, data synthesis, code generation, and complex task orchestration.

Launch NomadNet Agent →NomadNet AI Platform
O que você acha?
Carregando comentários…