Update an agent
PATCH /api/v1/agents/{agent_uuid} — partial update via recursive deep-merge.
PATCH /api/v1/agents/{agent_uuid}Partially update a saved agent. The body is any subset of the Agent Config. It is deep-merged into the stored config, and the whole merged result is re-validated before it's written — an invalid merge result 400s without persisting anything.
Deep-merge rules
- Two objects at the same key merge recursively — nested keys you didn't touch are preserved. Sending
{ "llm": { "temperature": 0.7 } }changes onlytemperature;provider,model,maxTokens, andprewarmstay as they were. - Any list, scalar, or
nullat a key replaces the stored value wholesale. Lists are never element-merged — sendingtoolsswaps the entire array; sendinggreeting.firstMessagesswaps the whole variants list. contextVariablesreplaces wholesale even though it's an object — it's a user-keyed map, and recursive merging would make it append-only (you could add a key but never remove one). Always send the complete map you want.
Per-call changes use a transient agent, not PATCH
For "use this config for one call only," pass the full config inline as agent on POST /call instead of pointing at a saved agent. PATCH mutates the saved agent permanently and affects every future call — including active inbound numbers bound to it.
Authentication
X-API-Key: zsk_...Path parameters
| Param | Type | Description |
|---|---|---|
agent_uuid | string (UUID) | The uuid of the agent to update. |
Request body
Any subset of Agent Config fields. All optional.
| Behavior | Detail |
|---|---|
webhookSecret (top-level) | Write-only. Popped before merge/validation and written straight to the row as the HMAC key for webhook signatures. Never returned. |
| Merged result fails validation | 400 with invalid_agent_config details; nothing is persisted. |
Nested object block (e.g. llm, stt.soniox) | Deep-merged — only the sub-fields you send change. |
List field (e.g. tools, languages, userIdleMessages) | Replaced wholesale — send the full array you want. |
contextVariables | Replaced wholesale — send the complete map. |
Concurrent PATCHes are safe: the merge runs against a row-locked read, so two simultaneous updates can't silently drop each other's changes.
Response
200 OK with the full updated agent envelope — same shape as GET /agents/{agent_uuid} (uuid, status, createdAt, updatedAt, config).
Examples
Change the opener
greeting is an object, so this merges — but firstMessages inside it is a list and replaces wholesale:
curl -X PATCH https://dashboard.zoxa.ai/api/v1/agents/550e8400-e29b-41d4-a716-446655440000 \
-H "X-API-Key: zsk_..." \
-H "Content-Type: application/json" \
-d '{ "greeting": { "firstMessages": ["Hi, this is Aman from Acme."] } }'await fetch(`https://dashboard.zoxa.ai/api/v1/agents/${agentUuid}`, {
method: "PATCH",
headers: { "X-API-Key": "zsk_...", "Content-Type": "application/json" },
body: JSON.stringify({ greeting: { firstMessages: ["Hi, this is Aman from Acme."] } }),
});import httpx
httpx.patch(
f"https://dashboard.zoxa.ai/api/v1/agents/{agent_uuid}",
headers={"X-API-Key": "zsk_..."},
json={"greeting": {"firstMessages": ["Hi, this is Aman from Acme."]}},
)Nudge one LLM knob
{ "llm": { "temperature": 0.7 } }Only temperature changes — provider, model, maxTokens, and prewarm are preserved by the merge.
Swap the LLM entirely
{ "llm": { "provider": "anthropic", "model": "claude-sonnet-4-6", "temperature": 0.7 } }Switch the voice provider
tts.provider selects which per-provider block is active — the blocks all coexist, so switching back later restores your previous tuning:
{ "tts": { "provider": "sarvam", "voice": "ishita" } }Turn on filler words
{ "fillerWords": { "enabled": true, "words": "so, right, okay", "thresholdMs": 400 } }Errors
| Status | detail | When |
|---|---|---|
400 | { "error": "invalid_agent_config", "details": [...] } | The deep-merged config failed validation — nothing is persisted. |
400 | "No organization selected" | Auth missing org context. |
404 | "Agent not found" | UUID doesn't exist in your org. |
Related
GET /agents/{agent_uuid}DELETE /agents/{agent_uuid}- Agent Config schema — full field reference