`POST /api/agent-profiles/{id}/workspace-default` — promote a profile to the workspace default (or clear it) (#708 who-4; #242/ADR 0033 — a task with no `agent_profile_id` resolves to this default, so it drives WHO). Atomic (clears the team's other defaults + sets one). Workspace-admin gated.
const url = 'https://example.com/api/agent-profiles/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/workspace-default';const options = { method: 'POST', headers: { cookie: 'supacloud_session=<supacloud_session>', 'Content-Type': 'application/json' }, body: '{"enabled":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/api/agent-profiles/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/workspace-default \ --header 'Content-Type: application/json' \ --cookie supacloud_session=<supacloud_session> \ --data '{ "enabled": true }'Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”The POST body for promoting/clearing the workspace-default agent profile
(#708 who-4). enabled defaults to true (promote); false clears the
workspace default entirely.
object
Examplegenerated
{ "enabled": true}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).
#838 — per-profile DEFAULT for the subagent concurrency ceiling (migration
358, nullable; 1..=64). The env build folds task.config.max_subagents ?? profile.max_subagents ?? workspace_settings.default_max_subagents ?? (no env), so this is the middle tier: the launch override still wins, and with
every tier absent no SUBAGENT_MAX_PARALLEL is emitted and the harness keeps
its own default. None = today’s behaviour.
The ceiling is only as strong as the harness allows — codex takes a real
per-session cap, the rest receive it as an instruction — which is why the UI
labels it from model_capabilities.subagent_cap_level instead of implying a
guarantee. #[serde(default)] keeps pre-358 AgentProfileVersion snapshots
deserializable.
#1018 — per-profile DEFAULT for the harness turn limit (migration 340,
nullable; > 0). The env build folds task.config.max_turns ?? profile.max_turns ?? (no env) — the task config stays the per-launch
override, and with both absent no MAX_TURNS env is emitted so the
runner default (500, DEFAULT_MAX_TURNS) applies. None = today’s
behaviour. #[serde(default)] keeps pre-340 AgentProfileVersion
snapshots deserializable.
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).
#858 W4a — per-profile override of the rolling profile-hourly MCP Ops
budget (migration 320, nullable; range 1–1000). None = the ADR 0028
default (30). The workspace-daily Ops ceiling (100/day) is NOT overridable.
#[serde(default)] keeps pre-320 snapshots deserializable.
#858 W4a — per-profile override of the per-task/per-tool MCP Ops budget
(migration 320, nullable; range 1–500). None = the ADR 0028 default (10).
Admin-gated via the profile PUT; a long-lived coordinator session raises it
deliberately instead of the global default weakening. #[serde(default)]
keeps pre-320 AgentProfileVersion snapshots deserializable.
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).
#1176 — the profile’s RESOURCE CLASS (migration 361, nullable;
normal | heavy). The middle tier of task.config.resource_class ?? profile.resource_class ?? workspace_settings.default_resource_class ?? normal.
It sits on the profile because a profile already decides WHO runs — harness, model, effort, MCP allowlist, per-profile Ops caps — and how much machine that work needs is the same kind of fact. “The audit profile is heavy” is a statement about the work, not about one launch.
A class is not just memory: it also weighs more in the workspace
concurrency allowance, so raising it does not raise the host’s peak
footprint. None = today’s behaviour. Runtime stays String; the spec
narrows it to the closed [sc_types::ResourceClass]. #[serde(default)]
keeps pre-361 AgentProfileVersion snapshots deserializable.
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.
#1175 (migration 363, nullable) — the profile’s TOOL-GATE deny budget in
minutes. The middle tier of task.config.tool_approval_deny_minutes ?? profile ?? workspace_settings.default_tool_approval_deny_minutes ?? 1440.
It sits on the profile for the same reason the resource class does: a
profile already decides WHO runs and how far it may go unattended, and how
long that runbook’s gate may wait before an explicit deny policy expires
is the same kind of fact. None = today’s behaviour.
It NEVER affects a hold gate, which is the default for every
runner-raised gate and carries no deadline at all (#1164).
Example
{ "avatar_kind": "color", "effort_default": "minimal", "execution_mode": "normal", "model_policy": "manual", "resource_class": "normal"}