error.code for the specific, stable reason.
Error envelope
Status codes
Nested config fields on agent writes
WhereverPOST /public-api/agents or PUT/PATCH /public-api/agents/{id} accepts a config object, it is a top-level, sibling field of the agent body and never a child of another: agent_settings, agent_settings_edits, toolbox, integrations, schedule, callback_settings, actions, ticket_conditions and time_entry_conditions.
Which of them a given body accepts is a separate question, answered by that body’s schema. agent_settings_edits is PUT/PATCH only, so send the full agent_settings on create; and the POST body is a discriminated union on autonomy_type, so each variant declares its own subset — a CONVERSATIONAL create takes no actions, a CHAINED_ACTIONS create no toolbox. Check the schema for your route and autonomy_type under Endpoints in the sidebar. A field the schema does not declare is ignored rather than rejected.
A tool that reaches an agent only at run time is dropped from toolbox on a create or update, and the rest of the write goes through. GET /public-api/schemas/tools never lists such a tool, under any filter: a permission group grants it and holds its settings, or Neo adds it by its own rule. To give an agent a tool a permission group grants, grant that group in integrations. A tool Neo adds by its own rule cannot be requested; Neo adds it wherever it applies.
Putting one config object directly inside another returns 400 validation_error and writes nothing. The check reads the immediate keys of each top-level config object, and of each actions entry. A container buried deeper than that — inside agent_settings_edits.custom_instructions, say — is ignored rather than rejected, which is why you read the agent back after a write. The message names both the field and the depth:
custom_instructions is long, so the closing brace is far from where the object opened.
The update response is the lean agent summary — id, name, state, timestamps — and carries no config. A
200 does not by itself prove a config field was applied; GET /public-api/agents/{id} to confirm.What’s next
Rate limits
How much you can call, and how to stay under the limit.
