Canopy API: schemas
The request and response bodies of the operations in this API.
AnswerConsentDto
| Property | Type | Required | Description |
|---|
decision | ConsentDecision | yes | allow runs it once; always additionally records a standing grant for this capability, at the risk you were shown, so the autonomy dial stops asking about it; deny refuses it and lets the turn continue without it. always is accepted only where alwaysEligible was true on the ask — high/critical, approval-gated and org-wide actions confirm at every autonomy level, so nothing can make them silent, and answering always on one is refused (422) rather than quietly treated as allow. |
AutonomyDto
| Property | Type | Required | Description |
|---|
level | one of "ask", "flow", "trusted" | yes | The level actually in force: your choice, capped by the org. |
orgMaxAutonomy | one of "ask", "flow", "trusted" or null | yes | The org-admin ceiling, or null when the org has set none. |
requested | one of "ask", "flow", "trusted" | yes | What you chose, before the cap. It differing from level is the case a dial must show: "you asked for trusted, your org caps you at ask" is not the same fact as "you chose ask". |
AutonomyDtoDataEnvelope
CanopyThreadDto
| Property | Type | Required | Description |
|---|
projectContextId | string or null | yes | Switchable project context. Null means the thread is org-wide. |
sessionId | string | yes | agent-session-api session id (layer = org). |
threadId | string | yes | agent-session-api thread id. |
tier | one of "tier_a", "tier_b" | yes | Tier A hosts the loop in-service (no pod). Tier B is an escalated agent session. |
CanopyThreadDtoDataEnvelope
CapabilityRiskTier
Risk the gate acted on, after the verb.
Type: one of "low", "medium", "high", "critical"
ConsentDecision
allow runs it once; always additionally records a standing grant for this capability, at the risk you were shown, so the autonomy dial stops asking about it; deny refuses it and lets the turn continue without it. always is accepted only where alwaysEligible was true on the ask — high/critical, approval-gated and org-wide actions confirm at every autonomy level, so nothing can make them silent, and answering always on one is refused (422) rather than quietly treated as allow.
Type: one of "allow", "always", "deny"
ConsentReason
Why the gate stopped.
Type: string (9 values)
CreateCanopySessionDto
| Property | Type | Required | Description |
|---|
idempotencyKey | string | yes | |
launch | object | yes | |
title | string | no | Human-readable conversation title. Defaults to a generic Canopy title. |
CreateCanopyThreadDto
| Property | Type | Required | Description |
|---|
title | string | no | Thread title. |
EscalateDto
| Property | Type | Required | Description |
|---|
idempotencyKey | string | yes | |
launch | object | yes | |
reason | string | yes | Why this task needs a filesystem. Narrated into the conversation before anything is provisioned. |
title | string | no | Deep session title. |
EscalationDto
| Property | Type | Required | Description |
|---|
deepSessionId | string | yes | |
deepThreadId | string | yes | |
thread | CanopyThreadDto | yes | The thread AS IT NOW STANDS. Escalating flips tier to tier_b in the same transaction as the escalation row, so the server holds the authoritative answer the moment it returns — and returning only the deep-session ids left the frontend setting tier_b locally, an optimistic write standing in for a fact it was not told. Any surface that renders the tier now reads it from here. |
EscalationDtoDataEnvelope
OrgAutonomyCeilingDto
| Property | Type | Required | Description |
|---|
level | one of "ask", "flow", "trusted" or null | yes | The ceiling now in force for the org, or null if none. |
OrgAutonomyCeilingDtoDataEnvelope
PendingConsentDto
| Property | Type | Required | Description |
|---|
alwaysEligible | boolean | yes | Whether always may be answered to this ask. False for the confirmations no autonomy setting can silence — high/critical risk, requiresApproval, org-wide effects — so a surface can hide the button instead of offering an answer the API will refuse. |
capabilityRef | string | yes | |
effectiveRisk | CapabilityRiskTier | yes | Risk the gate acted on, after the verb. |
expiresAt | string | yes | When it stops being answerable in the normal flow. DAYS out — this is a pause, never a deny, and answering after it still reopens the turn. |
reason | ConsentReason | yes | Why the gate stopped. |
requestId | string | yes | Stable id every surface keys on, so answering on one device resolves the notification on the others rather than leaving a phantom. |
threadId | string | yes | The agent-session thread this ask belongs to — the SAME id every other Canopy route takes (POST /canopy/threads/:threadId/turns). Canopy's own row id is server-side and never leaves the service. |
turnId | string | yes | The turn this parks. Answering continues IT. |
PendingConsentDtoDataArrayEnvelope
RevokeStandingConsentDto
| Property | Type | Required | Description |
|---|
capabilityRef | string | yes | The capability to start asking about again. |
SendCanopyMessageDto
| Property | Type | Required | Description |
|---|
message | string | yes | The user message. |
SetAutonomyDto
| Property | Type | Required | Description |
|---|
level | one of "ask", "flow", "trusted" | yes | Ask confirms every write; Flow (default) previews low/medium writes then proceeds; Trusted runs them silently. High/critical, approval-gated and org-wide actions always confirm at every level. |
SetOrgAutonomyCeilingDto
| Property | Type | Required | Description |
|---|
level | one of "ask", "flow", "trusted" or null | yes | The highest level any user in this org may run at, or null to remove the ceiling. Applied at read time, so lowering it takes effect immediately for every user — including ones whose stored preference is above it and ones who never set a preference at all. |
SetProjectContextDto
| Property | Type | Required | Description |
|---|
projectId | string or null | yes | Project to point the conversation at, or null to return it to org-wide. |
StandingConsentGrantDto
| Property | Type | Required | Description |
|---|
capabilityRef | string | yes | The capability the grant covers. |
createdAt | string | yes | |
grantedFromRequestId | string | yes | The ask this grant came from. |
maxRisk | CapabilityRiskTier | yes | The risk you were shown when you granted it — a CEILING. If this capability ever becomes riskier than this, Canopy asks again instead of riding the old answer. |
StandingConsentGrantDtoDataArrayEnvelope
VistaAckDto
| Property | Type | Required | Description |
|---|
detail | string | no | Human-readable detail for the refusal. |
error | one of "no-panel", "invalid-args", "unknown-tool", "unknown-tab", "tab-refused" | no | Why the panel refused the call. Present when ok is false. |
ok | boolean | yes | Whether the panel performed the call. false carries a typed error. |
toolCallId | string | yes | The tool call being answered. Echo toolCallId from the tool_call_started row. |
toolName | one of "vista_open", "vista_update", "vista_close", "vista_list" | yes | The vista_* tool being answered. Echo toolName from the tool_call_started row. |
turnId | string | yes | The turn the relayed call belongs to. Echo turnId from the tool_call_started row being answered. |
value | object | no | The op-specific success value — { tabId }, { updated: true }, { closed: true } or { tabs }. Present when ok is true. |