Skip to content
2 min read · 454 words

API — Errors

Two error body shapes cover the whole API: a detail string for domain errors, and FastAPI's detail array for validation. This page tells clients exactly what to do with each code.

Body shapes

json
{ "detail": "This agent does not have email_analyzer tool enabled" }

A client that must render one message can use the frontend's normalization rule: string detail → show as-is; array detail → join the msg fields (API Proxy).

Code-by-code

CodeEmitted whenClient should
400bad upload (type/encoding/empty), invalid task status, delete-without-forcefix the request; the message is specific and user-showable
403agent lacks the required toolenable the tool on the agent (recreate with the right enabled_tools) or use a different agent — retrying is pointless
404agent / task / workflow-run ID doesn't existtreat as stale reference; refresh your list
422body fails Pydantic validationfix field-level issues from loc/msg
500LLM/embedding failure, JSON-parse failure, unexpected exceptioninspect detail (contains the exception text); check the failed ToolCall / run records; retrying may succeed for transient OpenAI errors — the server itself never retries
502(frontend proxy only) backend unreachablestart/point the backend; not emitted by FastAPI itself

The 200s that carry failure

Two success responses require client-side judgment:

  1. Chat fallbackPOST .../chat returns 200 with assistant_response = "Sorry, I could not generate a response right now." when the LLM failed. Detect via the string or by checking the run's status (why).
  2. RAG refusalPOST .../documents/ask returns 200 with the fixed refusal string; check retrieval_evaluation.has_answer (semantics).

Error observability

Server-side failures in tools/workflows always leave evidence before the 500 goes out: a failed ToolCall (with error_message), plus — for workflows — a failed run and a workflow_error step. Diagnose from the records, not just the response:

bash
curl http://localhost:8001/agents/1/tool-calls | jq '[.[] | select(.success=="false")]'
curl http://localhost:8001/agents/1/workflow-runs | jq '[.[] | select(.status=="failed")]'

Caveats for client authors

  • detail on 500s contains raw exception text — useful in dev, do not render to end users verbatim.
  • There are no error codes (machine-readable enums), only messages — match on status first, message second.
  • No rate-limit (429) or auth (401/403-auth) semantics exist yet; today's 403 means tool gating specifically.