Update an agent

View as Markdown
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`, `skills`, `transferRules` and the other arrays replace the stored value. 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.** `audit.log_recorded` (when subscribed). See [Webhooks](/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](/rate-limits). - **Plan:** Available on every plan. Switching to a custom cloned voice requires Enterprise.

Authentication

AuthorizationBearer
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. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | 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](/authentication).

Path parameters

agentIdstringRequiredformat: "uuid"

UUID of the agent to update. An id from another workspace answers 404; a value that is not a UUID answers 400.

Request

This endpoint expects an object.
namestringOptional1-100 characters

New display name. Trimmed; blank is ignored.

channelslist of enumsOptional

Channels the agent may answer on. Replaces the whole list — send the complete set, not the channel you are adding. Behaviour field.

allowedToolkitslist of strings or nullOptional

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.

mcpEnabledbooleanOptional

Whether the agent may carry MCP servers. false also detaches the servers already attached; true attaches nothing by itself. Behaviour field.

disabledToolsmap from strings to lists of strings or nullOptional

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.

toolkitAccessmap from strings to enums or nullOptional

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.

voiceIdstringOptional>=1 character

New voice id. Trimmed; blank is ignored. A custom cloned voice requires Enterprise.

languageenumOptional

New main language; the same labels as on create are normalised. See CreateAgentInput.language.

templateIdstring or nullOptionalformat: "uuid"

Link a different objective template, or null to drop the template layer. Must be accessible to the workspace (400 otherwise). Behaviour field.

categoryenumOptional

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.

systemPromptstringOptional10-8000 characters

New workspace prompt layer, 10-8000 characters after trimming. Blank is ignored (it cannot be emptied here). Screened for fraud. Behaviour field.

firstMessagestringOptional1-500 characters

New opening line. Trimmed; blank is ignored. Screened for fraud. Behaviour field.

dynamicVariablesmap from strings to stringsOptional

Replaces the stored key/value strings (at most 50). Not currently applied to conversations.

maxCallDurationSecondsdoubleOptional30-3600

New hard cap on voice call length, in seconds (30-3600). Behaviour field.

responseDelaySecondsintegerOptional0-86400

Fixed pause before replying on text channels, in seconds (0-86400). Above 0 it overrides human pacing; 0 uses human pacing. Voice is unaffected.

humanPacingEnabledbooleanOptional

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.

objectionHandlersmap from strings to stringsOptional

Replaces the stored objection map (at most 50). Screened for fraud. Not currently applied to conversations. Behaviour field.

escalationRuleslist of objectsOptional
Replaces the stored escalation rules. Not currently applied to conversations. Behaviour field.
transferPhoneNumberstring or nullOptionalformat: "^\+[1-9]\d{1,14}$"

New E.164 transfer destination (checked against the dial policy), or null to remove it. Behaviour field.

discloseAiboolean or nullOptional

true/false sets this agent’s AI-disclosure decision; null clears it back to the country policy.

enableVoicemailDetectionbooleanOptional
Detect voicemail on outbound calls. Behaviour field.
transferRuleslist of objectsOptional

Replaces the in-call hand-off rules (up to 10). Behaviour field.

departmentstring or nullOptional1-100 characters

Routing department. Trimmed; null clears it, blank is ignored.

skillslist of stringsOptional

Replaces the routing skills (up to 50).

safetyobject or nullOptional

Guardrail topics, merged key by key (null on a key clears it; null for the block clears both). Behaviour field.

privacyobject or nullOptional

Privacy settings, merged key by key. No defaults are re-applied on update. Behaviour field.

analysisobject or nullOptional

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.

expressiveModebooleanOptional

Expressive voice delivery. See CreateAgentInput.expressiveMode.

toolCallSoundEnabledbooleanOptional
Sound while a tool runs on voice calls.
textNormalisationTypeenumOptional

How numbers and symbols become speakable text. See CreateAgentInput.textNormalisationType.

turnTimeoutdoubleOptional1-10

Voice only — seconds of silence before the agent takes the turn (1-10).

turnEagernessenumOptional

How eagerly the voice agent takes the turn. See CreateAgentInput.turnEagerness.

ttsSpeeddoubleOptional0.5-2

Speech rate, 0.5-2.

ttsStabilitydoubleOptional0-1

Voice stability, 0-1.

ttsSimilarityBoostdoubleOptional0-1

Adherence to the original voice, 0-1.

highRiskbooleanOptional

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).

dataobject

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.

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
404
Not Found Error
409
Conflict Error
429
Too Many Requests Error
502
Bad Gateway Error