Skip to content

Agents API errors

The Agents endpoints return errors using a flat envelope: a short error label plus a message field with the specific cause. This differs from the OpenAI-compatible nested envelope used by /v1/responses and /v1/conversations/*.

{
"error": "Not found",
"message": "Agent 18d20df4-d9b3-4cb0-a009-9f11ec9c5d3d not found."
}
StatuserrorCause
400Bad RequestMalformed request body — e.g. missing agentId on POST /v1/agents/runs, or a body that fails Zod schema validation.
401UnauthorizedMissing, malformed, or revoked API key. Emitted by the auth middleware; the body is {"error": "Unauthorized", "message": "..."}.
403ForbiddenThe API key owner’s API access is disabled ("API key has been disabled…", any endpoint), or, on POST /v1/agents/create, the caller belongs to groups and none allow agent creation.
404Not foundagentId does not exist or is not visible to the caller; runId does not exist or the caller cannot read the underlying conversation. Per-agent permission denials also collapse to 404 — Kindo does not distinguish “missing” from “forbidden” on this surface.
413—JSON request body exceeds the 50 MB (52,428,800-byte) limit. This check runs before the endpoint and returns {"message":"Request body too large. Maximum size is 50 MB."}.
422Unprocessable EntityBody parsed, but the request cannot be executed — required inputs[].name entries declared by the agent are missing from the request.
429Too Many RequestsOrg or user rate limit. Honors Retry-After when present.
500Internal Server ErrorUnexpected Kindo-side failure.

Unknown inputs[].name entries on POST /v1/agents/runs are silently dropped rather than rejected — only the missing-required case produces a 422. Re-fetch GET /v1/agents/{agentId} to confirm the canonical label list if a run isn’t picking up the values you expected.

A 422 Unprocessable Entity here means the request omitted a required inputs[].name declared on the agent. The labels are case-sensitive and must match exactly. Fetch GET /v1/agents/{agentId} to confirm the canonical list before retrying. (Triggers do not block this endpoint — an agent with hasTriggers: true can still be run directly.)

A 404 Not found here means the agentId is unknown to the caller — either it does not exist, or the user group does not grant access. Permission failures intentionally collapse to 404 and are not distinguished from “missing” in the response.

A 400 Bad Request means the body isn’t a valid agent definition, or the definition references a secret, Knowledge Store or static content item, or skill that doesn’t exist in your organization or that you can’t use or attach, or a tool uses an integration that is not set up on this Kindo deployment. No agent is created. See Create an agent.

A 403 Forbidden with the message “API key has been disabled” means the API key owner’s API access is turned off; this can happen on any endpoint. Any other 403 here means the API key’s user belongs to groups and none allow agent creation.

A 404 Not found here means either the runId is bogus, the caller cannot read the underlying conversation, or the run has been pruned by retention. The three cases are not distinguished in the response envelope.

A run that finished with status: "failure" is not an HTTP error — it returns 200 with a status payload. Inspect the status field, not the HTTP code, to detect agent-level failures.

A 404 Not found means the run does not exist or the caller lacks access — the same collapse-to-404 behavior as GET /v1/runs/{runId}. The two cases are intentionally indistinguishable.

A 400 Bad Request indicates a malformed runId (not a valid UUID).

Error behavior mirrors GET /v1/runs/{runId} — a 404 Not found means the run does not exist or the caller lacks access. The two cases are intentionally indistinguishable.

A 400 Bad Request indicates a malformed runId (not a valid UUID).

After POST /v1/agents/runs accepts a run, an applicable agent or department budget can refuse a model request during execution and fail the run. GET /v1/runs/{runId} still returns HTTP 200, with status: "failure" and result: null.

Do not restart the run while the budget still blocks it. A restart can be accepted and return a new run ID, but a model request in that run can be refused again. See When a budget blocks a request for budget scope and recovery.