`PUT /api/agent-profiles/{id}` — update an agent profile's runbook fields PLUS the optional flattened autonomy override (workspace-admin).
const url = 'https://example.com/api/agent-profiles/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0';const options = { method: 'PUT', headers: { cookie: 'supacloud_session=<supacloud_session>', 'Content-Type': 'application/json' }, body: '{"avatar_kind":"example","avatar_value":"example","capability_allowlist":["example"],"color":"example","default_agent_type":"example","description":"example","effort_default":"example","enabled":true,"execution_mode":"example","fixed_model":"example","interactive_approval":true,"mcp_memory_create":true,"memory_policy":"example","model_policy":"example","name":"example","persona_prompt":"example","post_flight_checks":"example","pr_template":"example","pre_flight_checks":"example","retry_policy":"example","review_required":true,"script_allowlist":["example"],"slug":"example","tags":["example"],"autonomy_level":1,"autonomy_overrides":"example","required_worker_group_ids":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://example.com/api/agent-profiles/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0 \ --header 'Content-Type: application/json' \ --cookie supacloud_session=<supacloud_session> \ --data '{ "avatar_kind": "example", "avatar_value": "example", "capability_allowlist": [ "example" ], "color": "example", "default_agent_type": "example", "description": "example", "effort_default": "example", "enabled": true, "execution_mode": "example", "fixed_model": "example", "interactive_approval": true, "mcp_memory_create": true, "memory_policy": "example", "model_policy": "example", "name": "example", "persona_prompt": "example", "post_flight_checks": "example", "pr_template": "example", "pre_flight_checks": "example", "retry_policy": "example", "review_required": true, "script_allowlist": [ "example" ], "slug": "example", "tags": [ "example" ], "autonomy_level": 1, "autonomy_overrides": "example", "required_worker_group_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ] }'Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”The PUT body for an agent profile: the runbook fields (flattened at the top
level) PLUS the ADR 0045 Stage 4 autonomy override (autonomy_level /
autonomy_overrides, also top-level). Splitting the autonomy fields into an
[AutonomyPatch] keeps them OUT of [agent_profiles::AgentProfileInput] (whose
many construction sites stay source-compatible) while the FE still sends ONE
flat object. Absent autonomy fields ⇒ no autonomy change.
object
ADR 0045 §3.6 — default reasoning effort
(minimal | low | medium | high | max). Optional; preserves the current
value on update, leaves None (inherit the runner default) on create.
Issue #364 / ADR 0039 (D7); #708 who-3 — normal | workflow (ultracode
RETIRED to the effort axis). Optional; preserves the current value on update,
defaults to normal on create.
ADR 0045 §3.2 — opt this profile into the interactive tool-approval gate
(resolve_interactive_approvals_for_run). Optional; preserves the current
value on update, defaults to false on create. #708 W5 wired this WRITE
path (it was read-only before — the create/update never persisted it).
ADR 0049 (#547 / #548) — opt-in gate for the agent memory.create MCP
tool. Optional; preserves the current value on update, defaults to false
(fail-closed) on create. A workspace admin sets this on the profile editor
to open the unreviewed direct-write path.
The script-run allowlist. Optional; absent preserves the current value on update
/ leaves None (OPEN — every script allowed) on create; a value (incl. [],
fail-closed) sets it. Mirrors capability_allowlist. #708 W9 wired this so a
workspace manifest round-trips it — the manifest apply supplies a fail-closed
Some([]) default (never the open None) when the manifest omits it.
ADR 0046 RUNG 1b — the profile’s worker-group OVERRIDE binding (the head of the
profile→project→task first-non-null chain). DOUBLE-Option: absent leaves it
untouched; null clears it to inherit (column NULL); a value (incl. []) sets
the override. Workspace admin (the update handler already gates on it).
Examplegenerated
{ "avatar_kind": "example", "avatar_value": "example", "capability_allowlist": [ "example" ], "color": "example", "default_agent_type": "example", "description": "example", "effort_default": "example", "enabled": true, "execution_mode": "example", "fixed_model": "example", "interactive_approval": true, "mcp_memory_create": true, "memory_policy": "example", "model_policy": "example", "name": "example", "persona_prompt": "example", "post_flight_checks": "example", "pr_template": "example", "pre_flight_checks": "example", "retry_policy": "example", "review_required": true, "script_allowlist": [ "example" ], "slug": "example", "tags": [ "example" ], "autonomy_level": 1, "autonomy_overrides": "example", "required_worker_group_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ]}Responses
Section titled “Responses”object
ADR 0045 §3.1 Stage 4 — OPTIONAL profile autonomy override (mig 214, nullable
SMALLINT). None = inherit the project/workspace level (sits between project
and workspace in the §3.1 precedence chain). #[serde(default)] keeps old
AgentProfileVersion JSON snapshots (pre-214) deserializable — they default to
None (a no-op).
ADR 0045 §3.1 — per-axis Advanced override vector (mig 214, JSONB NOT NULL DEFAULT '{}'). Empty {} = no per-axis override; the editor reads an
optional level key. #[serde(default)] keeps old snapshots deserializable.
Runtime stays serde_json::Value; the spec types it as an open map.
object
Avatar rendering kind (color | initial | icon | image). Runtime String;
the spec narrows it to the closed [AvatarKind] the editor offers.
ADR 0045 §3.6 — the profile’s default reasoning effort (migration
208, effort_default TEXT). Canonical lowercase string
(minimal | low | medium | high | max); None means “inherit the
runner default”. #[serde(default)] keeps old AgentProfileVersion
JSON snapshots (written before this column existed) deserializable —
they default to None (a no-op). Runtime stays String; the spec
narrows it to the closed canonical [sc_types::Effort]
(its lowercase wire form matches this column’s DB CHECK set).
Issue #364 / ADR 0039 (D7) — Claude execution mode lever (normal | workflow;
ultracode was RETIRED from this dimension by #708 who-3, migration 285 — it
survives only as the top EFFORT stage). #[serde(default = ...)] keeps old
AgentProfileVersion JSON snapshots (written before this column existed)
deserializable; they default to "normal" (a no-op). Runtime String; the
spec narrows it to the closed [ExecutionMode].
ADR 0045 §3.2 Stage 3 — when true, a task running under this profile arms
the interactive-approval gate (the runner’s canUseTool / pre-exec hook
pauses on a dangerous tool call, an open question, or a visual before/after
and waits for a human Approve/Reject; migration 213). false is today’s
behaviour (no gate). #[serde(default)] keeps old AgentProfileVersion
JSON snapshots (written before this column existed) deserializable — they
default to false (a no-op).
Issue #242 — when true, this profile’s capability_allowlist is the
workspace fallback MCP tool set for profile-less / empty-allowlist
tasks. At most one profile per team carries this flag (enforced by the
partial unique index uq_agent_profiles_workspace_default in
migration 119).
ADR 0049 (#547 / #548) — opt-in gate for the agent memory.create MCP tool
(migration 249, BOOLEAN NOT NULL DEFAULT false). When false (the default
for every profile) a task running under this profile CANNOT directly create a
memory — memory.create fails closed; only a workspace admin enabling this on
the profile editor opens the unreviewed direct-write path. Distinct from
memory_policy.allow_propose_create (the default-true review-first gate).
#[serde(default)] keeps old AgentProfileVersion JSON snapshots (written
before this column existed) deserializable — they default to false (a no-op).
The fixed memory-policy knobs the editor reads. Runtime stays
serde_json::Value; the spec types it as [AgentMemoryPolicy].
object
Model-selection policy (manual | fixed | auto). Runtime String; the spec
narrows it to the closed [ModelPolicy].
Forward-compatible list of post-flight check entries (e.g. the
kind:"visual_verify" gate). Runtime stays serde_json::Value; spec-typed
as an array of open maps.
object
Forward-compatible list of pre-flight check entries (each an open object,
e.g. a kind-discriminated gate). Runtime stays serde_json::Value; the
spec types it as an array of open maps so the value is not stripped.
object
ADR 0046 RUNG 1b — OPTIONAL profile worker-group affinity override (mig 227,
nullable UUID[]). None = inherit (the head of the first-non-null
profile->project->task chain — NULL contributes nothing); Some(vec![]) = an
explicit “no affinity from this source”. Resolved into the task’s
required_labels by services::runners::groups. #[serde(default)] keeps old
AgentProfileVersion JSON snapshots (pre-227) deserializable.
NB: this binding is intentionally EXCLUDED from agent-profile version snapshot/restore — it is dispatch-routing scope (a live operational binding), not part of the profile’s behavioural definition, so a version restore does not carry or revert it (ADR 0046 RUNG 1b review).
Open retry-policy bag. Runtime stays serde_json::Value; spec-typed as an
open map.
object
Issue #217 / ADR 0028 — optional slug whitelist for the script.run
MCP tool. NULL means any script in the workspace is callable; a
non-NULL array (including empty) is an explicit whitelist.
Example
{ "avatar_kind": "color", "effort_default": "minimal", "execution_mode": "normal", "model_policy": "manual"}