Update Staged Agent Settings
Update this agent's staged (not necessarily published) prompt, LLM provider binding, conversation storage, evaluation, widget, and custom-variable settings. Reflects unpublished staged state - see GET /agents/{agent_id}/versions/latest for what's actually live.
Authorization
OAuth2AuthorizationCodeBearer In: header
Path Parameters
uuidQuery Parameters
trueRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
The Versioned-surface subset of what PATCH /agents/{id} used to accept in one schema - system_prompt, first_message, llm_provider, conversation_storage_enabled, evaluation settings, widget settings, and custom_variables. Every field independently optional, same omitted-means-don't-touch contract as every other patch schema in this file. voice is deliberately not here - see PATCH /agents/{id}/stage/voice's own schema instead.
conversation_storage_enabled is the owner-facing off switch the conversation-persistence design spec's "on by default" scope decision rests on - it is the mitigation that makes storing full transcripts by default acceptable, so it has to be writable from this route.
evaluation_enabled, extraction_field_defs, and evaluation_criteria_defs
are independently optional - each may be sent alone or omitted. This
works because Agent.extraction_field_defs and Agent.evaluation_criteria_defs
are non-nullable JSONB columns with an empty-list default: the database
never distinguishes "unset" from "empty", so an omitted field here
unambiguously means "don't touch it" and an explicit [] unambiguously
means "clear it" - there is no third state to disambiguate, so no
model_validator is needed to detect a partial submission.
widget_enabled, widget_public, widget_accent_color, widget_orb_color_1,
and widget_orb_color_2 follow the same independently-optional pattern
as the evaluation-settings group above - none is ambiguous between
"omitted" and "cleared", since all three color columns are genuinely
nullable and the two booleans default False rather than needing a
distinct "unset" state.
widget_allowed_domains follows the list-field pattern instead (like
extraction_field_defs/evaluation_criteria_defs above): the column is a
non-nullable JSONB with an empty-list default, so an omitted field here
unambiguously means "don't touch it" and an explicit [] unambiguously
means "clear/unrestrict it" - no validator needed.
widget_style_overrides follows the same list-field pattern as
widget_allowed_domains (non-nullable JSONB dict, empty-dict default -
omitted means "don't touch it", {} means "reset to the widget's own
built-in defaults"), with an added key-allowlist validator since this
dict's keys are a styling convention shared with two renderers (see
WIDGET_STYLE_OVERRIDE_KEYS above), not free-form.
widget_embed_key is deliberately absent from this schema: it is never
owner-supplied, only generated/rotated via its own dedicated action
route (POST /agents/{agent_id}/stage/widget/regenerate-key) - an
owner-chosen value would be guessable, defeating its purpose as an
unguessable public identifier.
custom_variables follows the same list-field pattern as
widget_allowed_domains (non-nullable JSONB dict, empty-dict default -
omitted means "don't touch it", {} means "clear everything"), with
an added key-grammar validator: names must be plain identifiers
(letters, digits, underscore only), since a "." or "[" would be
ambiguous with the {{config.name}} path syntax the value is
interpolated into at workflow run time.
llm_provider binds (or rebinds) the agent's LLM provider, mirroring deployment_id's own "omitted means don't touch" semantics - there is no way to explicitly clear it back to unbound via this PATCH, matching deployment_id (an agent only ever moves from unbound to bound, or from one bound value to another, never back to unbound).
llm_credential_id picks one of the org's credentials for the bound provider explicitly; null (the default) lets resolution fall through to the org's default and then the platform's metered key. Pass an explicit null to clear an earlier choice.
See docs/superpowers/specs/2026-09-05-agent-config-versioning-design.md's API surface section: this is the "stage" half of what PATCH /agents/{id} used to do in one call, the other half (deployment_id, a2a_open, a2a_discoverable) staying on that original endpoint since neither is part of the Versioned surface.
Response Body
application/json
application/json
application/json
application/json
curl -X PATCH "https://example.com/v1/agents/497f6eca-6276-4993-bfeb-53cbbbba6f08/stage/agent" \ -H "Content-Type: application/json" \ -d '{}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", "deployment_id": "6ef0ac85-9892-4664-a2a5-58bf2af5a8a6", "llm_provider": "string", "llm_credential_id": "9f53723b-12ec-46a5-bdaa-fe324d964044", "org_id": "a40f5d1f-d889-42e9-94ea-b9b33585fc6b", "event_org_id": "38381290-8ff7-413c-a0d2-e750a21c5122", "system_prompt": "string", "first_message": "string", "a2a_open": true, "a2a_discoverable": true, "conversation_storage_enabled": true, "voice": { "pipeline_mode": "string", "language": "string", "voice_id": "2235c634-e4db-4ad6-aa15-066fb69b1c8f", "stt_credential_id": "eb187100-9387-457a-a988-b0410c4a2c25", "tts_credential_id": "e0d3c1fd-2fa1-4193-a64f-4bf411783f94", "realtime_credential_id": "0abad67d-3a88-469c-b861-de9ea624ac84", "silence_end_call_timeout_secs": 0, "cascade": { "stt_provider": "string", "stt_model": "string", "tts_provider": "string", "tts_model": "string", "enable_interruptions": true, "min_words_before_interruption": 0, "vad_confidence": 0, "vad_start_secs": 0, "vad_stop_secs": 0, "vad_min_volume": 0, "turn_model": "string", "eagerness": "string", "turn_timeout_secs": 0, "asr_keywords": [ "string" ], "filter_background_speech": true, "input_audio_format": "string", "interruption_ignore_terms": [ "string" ], "transcribe_on_disabled_interruptions": true }, "s2s": { "realtime_provider": "string", "realtime_model": "string", "turn_detection_type": "string", "turn_threshold": 0, "prefix_padding_ms": 0, "silence_duration_ms": 0, "eagerness": "string" } }, "has_workflow": false, "state_schema": {}, "evaluation_enabled": true, "extraction_field_defs": [ { "name": "string", "type": "string", "description": "string", "enum_values": [ "string" ] } ], "evaluation_criteria_defs": [ { "name": "string", "description": "string" } ], "pii_redaction_enabled": true, "widget_enabled": true, "widget_public": true, "widget_embed_key": "string", "widget_accent_color": "string", "widget_orb_color_1": "string", "widget_orb_color_2": "string", "widget_allowed_domains": [ "string" ], "widget_placement": "string", "widget_style_overrides": { "property1": "string", "property2": "string" }, "custom_variables": { "property1": "string", "property2": "string" }, "max_conversation_duration_seconds": 0, "max_duration_message": "string", "conversation_retention_days": 0, "store_call_audio": true, "client_events": [ "string" ], "chat_mode_enabled": true, "dtmf_enabled": true, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}{ "detail": "string", "code": "string"}{ "detail": "string", "code": "string"}{ "detail": [ { "loc": [ "string" ], "msg": "string", "type": "string" } ]}