Skip to navigation

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, 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 objectionHandlers no longer depends on the plan (2026-09-15).

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.

ScopeGET / HEADPOST / PUT / PATCH / DELETEAdmin-only routes
readYesNoNo
writeYesYesNo
fullYesYesYes

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

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.

capabilitieslist of strings or nullOptional

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.

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.

Allowed values:
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

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.

responseDelayMaxSecondsinteger or nullOptional0-86400

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.

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

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.

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. The value used before 2026-09-15 is still accepted as a synonym of engine. See CreateAgentInput.textNormalisationType.

Allowed values:
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.7-1.2

Speech rate, 0.7-1.2. Not applied by the current voice model (Eleven v4 Turbo); see CreateAgentInput.ttsSpeed.

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