Skip to content
Select themeSelect language

GET /api/governor/proposals — #708 K-08a: list EVERY open (draft) profile-version proposal across the workspace's profiles (the workspace-wide owner review inbox that backs the unified Inbox governor feed; the per-profile `/api/agent-profiles/{id}/proposals` backs the profile page). Owner-gated, reusing the SAME `proposals::list_open_for_workspace` service the chat `/governor` command calls.

GET
/api/governor/proposals
curl --request GET \
--url https://example.com/api/governor/proposals \
--cookie supacloud_session=<supacloud_session>

Open (draft) profile-version proposals across the workspace

Media typeapplication/json
Array<object>

A profile-version change proposal (migration 218 profile_version_proposal).

object
agent_profile_id
required
string format: uuid
created_at
required

When the proposal was opened (#976 — union-inbox sort key).

string format: date-time
id
required
string format: uuid
proposed_config
required

The candidate config, stored in AgentProfileInput shape so approval reuses the validated update_profile writer. Runtime stays serde_json::Value; the spec types it as [AgentProfileInput] (the FE reads name / fixed_model / model_policy off it).

object
avatar_kind
string | null
avatar_value
string | null
capability_allowlist
Array<string> | null
color
string | null
default_agent_type
string | null
description
string | null
effort_default

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.

string | null
enabled
boolean | null
execution_mode

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.

string | null
fixed_model
string | null
interactive_approval

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

boolean | null
max_turns

#1018 — per-profile DEFAULT for the harness turn limit (migration 340, positive). DOUBLE-Option: absent preserves the current value on update / leaves NULL (no default — the runner’s 500 applies) on create; an explicit null clears it; a value sets it. “Absent = unchanged” is load-bearing — the simple profiles tab sends a partial payload, and it must never null a stored default (the #858 W4a ops-cap pattern).

integer | null format: int32
mcp_memory_create

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.

boolean | null
mcp_ops_per_hour_cap

#858 W4a — per-profile override of the profile-hourly MCP Ops budget (migration 320; range 1–1000). Same DOUBLE-Option semantics as mcp_ops_per_task_cap. The workspace-daily Ops ceiling stays fixed.

integer | null format: int32
mcp_ops_per_task_cap

#858 W4a — per-profile override of the per-task/per-tool MCP Ops budget (migration 320; range 1–500). DOUBLE-Option: absent preserves the current value on update / leaves NULL (the ADR 0028 default, 10) on create; an explicit null clears the override back to the default; a value sets it. Admin-gated — the profile PUT already requires workspace admin.

integer | null format: int32
memory_policy
model_policy
string | null
name
required
string
persona_prompt
string | null
post_flight_checks
pr_template
string | null
pre_flight_checks
retry_policy
review_required
boolean | null
script_allowlist

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.

Array<string> | null
slug
string | null
tags
Array<string> | null
rationale
string | null
status
required
string
Examplegenerated
[
{
"agent_profile_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"created_at": "2026-04-15T12:00:00Z",
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"proposed_config": {
"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,
"max_turns": 1,
"mcp_memory_create": true,
"mcp_ops_per_hour_cap": 1,
"mcp_ops_per_task_cap": 1,
"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"
]
},
"rationale": "example",
"status": "example"
}
]

Authentication required

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Permission denied

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Structured server error

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden license_required license_expired bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited too_many_requests quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}