Update an agent
Partially updates an agent and pushes the change to the voice provider. Only the fields sent are
changed and at least one must be defined; unknown keys are silently ignored. safety, privacy,
analysis and toolkitAccess are merged key by key with what is stored (see UpdateAgentInput);
channels, transferRules and the other arrays replace the stored value.
Retired fields (2026-09-15). escalationRules and skills are no longer part of the agent
contract. Sending either one — with any value, null and [] included — is refused with
400 VALIDATION_FAILED, and neither is returned by any agent endpoint any more. Omit them.
Use the hand-over tool (needs_human / request_help) instead of escalationRules, and
department instead of skills.
The response is the raw updated row (see AgentPatchedRow), which differs from the shape returned
by the GET endpoints: config blocks keep their column names (analysis_config,
supported_channels, …) and derived fields are absent. Re-read with GET /api/agents/{agentId} if
you need the decorated shape.
Approval gate. If the workspace has change approvals enabled and the agent is marked
high_risk, a change to any behaviour field is held for review and answers
409 AGENT_CHANGE_PENDING_APPROVAL with the id of the change request — nothing is saved. An admin
other than the proposer approves it via the agent change-requests endpoints, which applies it then.
A PATCH that touches only non-behaviour fields (for example name or ttsSpeed) is applied at once.
Side effects. Screens a changed prompt, first message or objection handlers for fraud (LLM
call). Saves the row, re-derives the voice-engine agent configuration (prompt, voice, tuning,
analysis, guardrails, privacy, transfers, duration cap) and records a version in the agent’s change
history. mcpEnabled: false detaches the MCP servers already attached. A changed
allowedToolkits, disabledTools or toolkitAccess queues a tool-surface sync with the connected
apps provider; the response then shows tool_surface_status: syncing (or pending_provisioning
while the agent is not provisioned yet). Changing category without sending analysis replaces the
analysis criteria with the new objective’s defaults. Writes an audit entry.
Consistency. The provider re-derive runs after the row is saved; if it fails the edit stays
saved and a periodic re-sync reconciles the provider later. For legacy agents that do not derive
from a category base, the provider is updated first and a provider failure answers 502 with
nothing saved.
Idempotency. Retrying the same body converges to the same stored state and is safe, but it re-runs fraud screening and the provider sync. On a high-risk agent each retry opens another pending change request.
Webhook events. agent.updated (the agent.created fields plus changed_fields, the names of the request fields that changed, never their values) once the change is saved; a change held for approval is announced when it is applied. Also audit.log_recorded (when subscribed). See Webhooks.
Access
- Required scope:
write. Signed-in users need the owner, admin or member role. - Rate limit: Agent mutations — 10 requests/min per workspace, shared with every agent, A/B variant, tool and knowledge write; the request also counts against the General API limit. See Rate limits.
- Plan: Available on every plan. Switching to a custom cloned voice requires Enterprise. Saving
objectionHandlersno longer depends on the plan (2026-09-15).
Authentication
Workspace API key: jl_ followed by 64 lowercase hex characters, created by the workspace owner in the
dashboard (Settings → API Keys) and sent as Authorization: Bearer jl_.... The plaintext is shown once,
at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys.
Operations restricted to admins or owners reject keys without the full scope with 403, and say so in
their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret —
that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds.
See Authentication.
Path parameters
UUID of the agent to update. An id from another workspace answers 404; a value that is not a UUID answers 400.
Request
New display name. Trimmed; blank is ignored.
Channels the agent may answer on. Replaces the whole list — send the complete set, not the channel you are adding. Behaviour field.
Connected-app slugs this agent may use (up to 300). null = no restriction (every connected app,
including ones connected later); [] = none. A change queues a tool-surface sync. Behaviour field.
Whether the agent may carry MCP servers. false also detaches the servers already attached;
true attaches nothing by itself. Behaviour field.
Per-app denylist of tool slugs (up to 500 per app), replacing the stored map. null and {} both
mean nothing is disabled. A change queues a tool-surface sync. Behaviour field.
Capability ids (from GET /api/agents/capabilities) this agent may use beyond its default tool
surface, replacing the stored list. null and [] both mean the default. An unknown id is
refused with 400. Applies only to customer-facing agents, never to the anonymous landing
agent, and every capability reads about and reaches only the person the agent is serving right
now, never the rest of the workspace’s contacts. That person must be verified: exactly one live
conversation on the agent, identified by the carrier’s caller number or an authenticated WhatsApp,
Instagram or Messenger sender. With two people live at once, or on the web widget or webchat,
capability tools refuse. Takes effect on the agent’s next tool call. Behaviour field.
Per-app access level merged into the stored map: read (read-only tools) or read_write. An app
not listed keeps its stored level, and an app never listed has read_write. null clears the map
(every app back to read_write). A change queues a tool-surface sync. Behaviour field.
New voice id. Trimmed; blank is ignored. A custom cloned voice requires Enterprise.
New main language; the same labels as on create are normalised. See CreateAgentInput.language.
Link a different objective template, or null to drop the template layer. Must be accessible to the workspace (400 otherwise). Behaviour field.
New objective (see CreateAgentInput.category), or null to fall back to the template’s
category. When it actually changes and analysis is not sent in the same request, the analysis
criteria are replaced with the new objective’s defaults. Behaviour field.
New workspace prompt layer, 10-8000 characters after trimming. Blank is ignored (it cannot be emptied here). Screened for fraud. Behaviour field.
New opening line. Trimmed; blank is ignored. Screened for fraud. Behaviour field.
Replaces the stored key/value strings (at most 50). Not currently applied to conversations.
New hard cap on voice call length, in seconds (30-3600). Behaviour field.
Pause before replying on text channels, in seconds (0-86400). The lower bound of the range when responseDelayMaxSeconds is set, a fixed pause otherwise. Above 0 it overrides human pacing; 0 with no maximum uses human pacing. Voice is unaffected.
Upper bound of the reply pause, in seconds (0-86400). When set, each reply waits a random time between responseDelaySeconds and this value. null clears it. A value below the minimum is rejected with 400. On Instagram and Messenger the pause never exceeds 12 seconds; a longer range is scaled to fit.
Text channels reply on a growing delay ladder (about 10 s, then 1 min, up to 2 min) instead of instantly. Turn off for lines where speed matters (OTP relays, outage notices). Voice is unaffected.
Replaces the stored objection map whole. At most 5 entries; an objection key is 1 to 100
characters and an answer 1 to 200 — over any of these the save is refused, not trimmed
(400 VALIDATION_FAILED, reason in error.details.fieldErrors.objectionHandlers).
Screened for fraud. Applied to conversations on the next prompt build, for an agent of any
category. Behaviour field.
New E.164 transfer destination (checked against the dial policy), or null to remove it. Behaviour field.
true/false sets this agent’s AI-disclosure decision; null clears it back to the country policy.
Replaces the in-call hand-off rules (up to 10). Behaviour field.
Routing department. Trimmed; null clears it, blank is ignored.
Guardrail topics, merged key by key (null on a key clears it; null for the block clears both). Behaviour field.
Privacy settings, merged key by key. No defaults are re-applied on update. Behaviour field.
Post-call analysis, merged per half: send only successEvaluation or only dataCollection to
replace that half; null on a half clears it. New criterion ids starting with qa_ are rejected
with 400. Behaviour field.
Expressive voice delivery. See CreateAgentInput.expressiveMode.
How numbers and symbols become speakable text. The value used before 2026-09-15 is still accepted as a synonym of engine. See CreateAgentInput.textNormalisationType.
Voice only — seconds of silence before the agent takes the turn (1-10).
How eagerly the voice agent takes the turn. See CreateAgentInput.turnEagerness.
Speech rate, 0.7-1.2. Not applied by the current voice model (Eleven v4 Turbo); see CreateAgentInput.ttsSpeed.
Voice stability, 0-1.
Adherence to the original voice, 0-1.
Marks the agent for change approval (effective only when the workspace has approvals enabled). Marking an agent applies at once; unmarking an agent that is already marked is itself held for approval.
Response
The updated row (raw, not decorated).
Response of PATCH /api/agents/{agentId}: the raw updated row. Unlike the other agent responses it
is NOT decorated — the JSON config columns keep their column names (supported_channels,
analysis_config, safety_config, privacy_config) and the derived fields (channels,
objective, analysis, safety, privacy, mcpEnabled, toolkitAccessEnforced, total_calls, …)
are absent. Every column of AgentRowBase is present.

