Pular para o conteúdo principal

Diagnóstico

Toda falha fica registrada. Comece pela execução, não pelos seus logs.

# Todas as execuções falhas do último dia
curl "https://api.inbox.kobana.com.br/v1/workflow-runs?status=failed&created_at[gte]=2026-09-08T00:00:00Z" \
--cert ./client.crt --key ./client.key -H "Authorization: Bearer $JWT"

# Tudo sobre uma delas
curl "https://api.inbox.kobana.com.br/v1/workflow-runs/$RUN_ID" \
--cert ./client.crt --key ./client.key -H "Authorization: Bearer $JWT"

WorkflowRun.error lista todos os passos que falharam, um por linha, cada um prefixado com sua posição (step 2: …), então a execução já diz onde olhar antes de você abrir os passos.

"O e-mail foi processado mas nada aconteceu no meu sistema"​

Verifique, nesta ordem:

  1. Existe execução? GET /v1/workflow-runs?email_id=…. Se a lista vier vazia, o agente não devolveu workflow — a análise está em Email.agent_metadata, e o problema é de prompt, não de integração.
  2. Existe execução com summary.total: 0 e erro invalid workflow …? O agente emitiu algo que não validou. O valor problemático está em definition.
  3. Caso contrário, a execução existe e o error dela nomeia o passo que falhou.

Catálogo de erros​

errorO que aconteceuO que fazer
invalid workflow at `0.url`: …O array do agente não validou. Nada foi enviado.Leia definition. Normalmente é url faltando, um type diferente de request, ou um header reservado. Corrija o prompt.
workflow exceeds 20 stepsO agente produziu mais passos que o teto.Divida o trabalho, ou faça o prompt condensar em menos chamadas.
secret `X` is not defined in this workspaceUma referência ${{secrets.X}} não tem secret correspondente. Nada foi enviado.GET /v1/secrets e compare. Erro de digitação no prompt, secret excluído, ou o secret está em outro workspace — eles nunca são compartilhados.
\`steps.2.response.body.id\` refers to a step that has not run yetReferência para frente — um passo que vem depois. (Referência a um passo que falhou ou foi pulado não falha o passo: ele fica skipped.)Passos só enxergam passos anteriores. Reordene, ou corrija o índice.
\`steps.0.response.body.data.id\` could not be resolvedO caminho não existe naquela resposta.Olhe o response.body do passo 0 — o formato do destino provavelmente não é o que o prompt supôs.
\`steps.0.response.body.id\` resolved to nullO caminho existe mas é nulo.Mesmo caso acima: o destino não devolveu id, normalmente porque a chamada não fez o que você imagina.
expected status 201, got 422O destino recusou o payload.O response.body daquele passo tem o motivo. Problema de payload — corrija o prompt ou o mapeamento.
expected status 200, got 401A credencial foi recusada.Rotacione com PUT /v1/secrets (mesma key). Confira se last_used_at avançou — se não avançou, o passo nunca chegou a usar aquele secret.
timeout after 30000msO destino não respondeu em 30s.Problema do destino. A requisição pode ter sido processada mesmo assim — trate a operação como desconhecida, não como falha.
expected status 2xx, got 302O destino respondeu um redirecionamento.Redirects nunca são seguidos — um 302 para um host privado furaria todos os checks — então um 3xx é simplesmente um status que não bate. Aponte o passo para a URL final.
url not allowed: private_ipA URL resolvida aponta para endereço privado, loopback, link-local ou de metadados.Esperado para hosts internos: workflows só alcançam a internet pública. Exponha um endpoint, ou use um webhook e chame você mesmo de volta.
url not allowed: http_not_allowedhttp:// puro fora de desenvolvimento.Use https://.
url not allowed: dns_failureO hostname não resolve.Erro de digitação, ou um nome que só resolve dentro da sua rede.
unsupported step type `delay` Um passo guardado tem um tipo que esta versão não executa.Só existe request hoje.

Lendo a requisição guardada​

Cada passo guarda a requisição como enviada — depois da substituição de placeholders, com valores de secret trocados por [REDACTED]:

{
"position": 0,
"status": "failed",
"request": {
"url": "https://erp.example.com/payables",
"headers": { "Authorization": "Bearer [REDACTED]", "content-type": "application/json" },
"body": "{\"supplier\":\"ACME\",\"amount\":1250.5}"
},
"response": {
"status": 422,
"expected_status": 201,
"body": "{\"error\":\"supplier not found\"}"
},
"error": "expected status 201, got 422"
}

Dois campos respondem a duas perguntas diferentes:

  • request no passo — o que de fato enviamos. Use contra problemas do lado do destino.
  • definition na execução — o que o agente escreveu, com placeholders sem resolver. Use contra problemas de prompt.

[REDACTED] não é uma máscara sobre um valor que poderíamos mostrar: o texto original nunca foi gravado. Não tente recuperar uma credencial a partir de uma execução.

Status que não são falha​

SituaçãoSignificado
Passo skippedEle referencia um passo que não teve sucesso (falhou ou foi pulado) — o error diz depends on step N, which did not succeed. Nunca foi enviado.
Execução running por muito tempoA execução foi interrompida no meio (restart de worker). Ela não é reexecutada, porque alguns passos podem já ter chegado aos seus sistemas. Reexecutar é decisão humana — POST /v1/emails/{id}/reprocess recomeça o pipeline inteiro, chamada ao agente inclusive.
Execução pendingNa fila, ainda não iniciada. Normal por alguns segundos.
summary.succeeded: 2 com status: failedO passo 1 falhou, o passo 2 dependia dele e foi pulado, os passos 0 e 3 são independentes e deram certo. Esses dois aconteceram nos seus sistemas.

Essa última linha é a que precisa ficar clara: uma execução falha não significa que nada aconteceu. Efeitos parciais são reais, e não existe rollback — passos independentes rodam mesmo quando outro falha, e um passo só depende do que ele referencia. Desenhe a cadeia de forma que cada passo seja aceitável de acontecer sem os outros que ele não referencia (criar, depois anexar, depois notificar — não notificar, depois criar).

Acompanhando continuamente​

Assine um webhook em workflow.run.failed em vez de ficar consultando:

{
"event": { "slug": "workflow.run.failed" },
"data": {
"workflow_run_id": "9c8b7a65-…",
"summary": { "total": 3, "succeeded": 1, "error": 2 },
"failed_step": 1,
"failed_steps": [1],
"error": "expected status 201, got 422",
"email": { "id": "…", "subject": "…" },
"agent_run": { "id": "…", "llm_model": "…" }
}
}

Os snapshots de email e agent_run vêm junto, então um alerta pode carregar o assunto e o modelo sem uma chamada extra.