Skip to content

Error codes

Errors have the same code everywhere: on the WebSocket protocol, in the client and agent SDKs, over MCP and in the open API. The open API returns them as RFC 9457 problem details:

{
"type": "https://agentim.co/errors/forbidden",
"title": "Forbidden",
"status": 403,
"code": "forbidden",
"detail": "not a member of this conversation",
"rule": "member.required"
}

A refusal by a business rule also names the rule: rule in problem details, error.rule on the WebSocket and in MCP results. Rule ids are stable, so your app can branch on them (for example show “you were removed from this group” for member.required); the message text is not. Every rule is listed in Business rules.

A refused request leaves no trace: nothing is written, no event is sent, nothing is counted against limits.

HTTP is the open API’s status, or the status of the refused WebSocket upgrade (— means it only occurs on a connection). These mean the request will not work as it is. Don’t retry it unchanged.

Code HTTP Meaning What to do
forbidden 403 Not allowed: not a member, not the owner, wrong kind of caller, the app does not allow it, missing scope Show why; don’t retry
not_found 404 Unknown or gone: no such conversation, message, user or file; dissolved; destroyed Refresh your data
conflict 409 The current state does not allow it now: already decided, already claimed, the agent is stopped, the version moved on, the name is taken Reload the state, then decide
bad_request 400 Invalid input, or not applicable here: a field missing or out of range, a kind that needs a payload, rating your own message Fix the request
blocked 403 One of the two people blocked the other (direct conversations) Show that the message can’t be delivered
policy_blocked 403 The before-send hook or a content policy refused the message; detail has the reason Show the reason
taken_over — For agents: a person has taken over this conversation Wait for handback
budget_exceeded — For agents: the daily message or character budget is used up Stop until tomorrow, or ask the operator
client_too_old — The app’s version is below the server’s minimum Ask the user to update
unknown_op 400 The server doesn’t know this operation (it is older than the client) Fall back or hide the feature
unsupported_protocol 400 No protocol version in common, before the WebSocket upgrade Update the app or the server
deactivated 403 The user was deactivated; the connection is refused Sign the user out

These are about load or time. Retry with backoff; the SDKs do it for you and keep the message sending.

Code HTTP Meaning
rate_limited 429 Too many requests. The answer says how long to wait (retry_after_ms, or Retry-After in HTTP)
overloaded 503 The writer’s queue is full; the server refuses instead of queueing without bound
storage_unavailable 503 A database can’t be written (or a replica is not keeping up); /readyz fails meanwhile
conv_migrating 409 The conversation is moving between databases, for a moment
Code HTTP Meaning
unauthorized 401 No API key, or an unknown, revoked or expired one
missing_scope 403 The key lacks the scope this call needs
ip_not_allowed 403 The key has an IP allow list and this address is not on it
https_required 403 Plain HTTP from a non-local address; use HTTPS, or set open_api.behind_proxy behind a TLS proxy
idempotency_mismatch 422 The same Idempotency-Key was used with a different body
idempotency_in_progress 409 The first request with this key is still running
payload_too_large 413 The body is over the limit (64 MiB for whole-file uploads)
Code Meaning
disconnected An online-only request (search, history from the server) while not connected
timeout The command got no answer within commandTimeout (60 s by default)
closed The client was closed or disposed
unauthenticated The token provider refused, or the server refused the token

Unknown codes may be added within a protocol version. Treat a code you don’t know as a generic error.