Errors
One error envelope, and every code the agents API and the config read can answer with.
Every refusal has the same three fields, on both surfaces:
{
"error": "This API key cannot manage agents: it lacks the manageAgents scope",
"code": "FORBIDDEN",
"timestamp": 1789569967913
}| Field | Type | Description |
|---|---|---|
error | string | A human-readable sentence. Do not match on it; it may be reworded |
code | string | The stable machine-readable code. Switch on this |
timestamp | integer | Milliseconds since the Unix epoch, at the moment of the failure |
Codes
| Status | code | Meaning |
|---|---|---|
| 401 | AUTHENTICATION_ERROR | No key, or an invalid, revoked or expired one |
| 403 | FORBIDDEN | On /agents, the key does not have the manage-agents permission. On the config read, the key's permissions.cores does not reach this agent |
| 429 | RATE_LIMITED | Over 120 requests a minute on /agents. Wait Retry-After seconds |
| 413 | PAYLOAD_TOO_LARGE | The request body is over 400 KiB for an agent, or about 1.5 MB for a file. The body is cut off while it is read |
| 400 | INVALID_JSON, INVALID_BODY | The body is not JSON, or not an object |
| 400 | UNKNOWN_FIELD | The body carries a field this route does not take: slug, routingKey, or a misspelling |
| 400 | INVALID_SLUG | The slug is not lowercase letters, digits and hyphens (^[a-z0-9-]+$), or is over 100 characters |
| 400 | INVALID_DIRECTORY | The directory is not ^[a-z0-9][a-z0-9-]*$, or is over 64 characters. On the write and delete routes, an empty ?directory= lands here rather than defaulting to main. The list route never reads the parameter |
| 400 | INVALID_PATH | The path is neither entries.json nor lowercase [a-z0-9._/-] ending in .md, holds .., or is over 200 characters |
| 400 | INVALID_NAME | The name is not a string or null, or holds a NUL character or an unpaired surrogate |
| 400 | INVALID_INSTRUCTION_SOURCE | Not repo or database |
| 400 | INVALID_TIMEZONE | Not a zone the IANA database knows |
| 400 | INVALID_PHONE_NUMBER, INVALID_TRANSFER_NUMBER | Not E.164 |
| 400 | INVALID_VARIABLES | variables is not an object of name to string, a name is not ^[A-Za-z_][A-Za-z0-9_]*$ within 64 characters, or a value holds a NUL character or an unpaired surrogate |
| 413 | VARIABLES_TOO_LARGE | The whole variables map is over 64 KiB as the column stores it |
| 400 | INVALID_CONTENT | The content is not a string, or holds a NUL character or an unpaired surrogate |
| 413 | CONTENT_TOO_LARGE | The file is over 256 KiB of UTF-8 |
| 400 | INVALID_ENTRIES | entries.json is not an object whose values are prompt paths: lowercase [a-z0-9._/-] ending in .md, with no .. segment |
| 404 | NOT_FOUND | No agent with this slug, or none on this routing key, in the organization. An agent in another organization gets the same answer |
| 404 | FILE_NOT_FOUND | No file at this path |
| 409 | NO_INSTRUCTIONS | Switching an agent to database, or creating one on it, while it has no file stored. The config read answers the same for a database agent with nothing stored |
| 409 | LAST_INSTRUCTION_FILE | Deleting the only file of an agent on database. Switch it to repo first |
| 409 | IS_DEPLOYMENT | DELETE /agents/{slug} on a core whose kind is deployment. That row is a running service, not an agent this API retires |
| 500 | DATABASE_ERROR | A query failed inside Subcore. Retry; if it persists, report it |
Handling them
Retry 429 and 500. Do not retry the other 4xx codes: a 400, 401,
403, 404 or 409 means the request itself needs to change, and sending it
again unchanged will fail the same way. On a 429, wait the number of seconds
in Retry-After.
Two of the 409s are about order. NO_INSTRUCTIONS means write a file first,
then switch. LAST_INSTRUCTION_FILE means switch the agent to repo first,
then delete. See the two guards.
IS_DEPLOYMENT is not about order, and no sequence of calls gets past it. It
means the slug names one of your running deployments rather than an agent, and
deleting it here is refused outright. Check
kind on the row first.
Switch on code, not on error. The sentences are written for a person reading
a log and are not part of the contract.
A 404 NOT_FOUND never confirms an agent across organizations. A slug or
routing key that exists in another organization gets the same answer as one
that exists nowhere, so a 404 on an agent you expected to find usually means
the key and the agent belong to different organizations.