Canopy API: schemas

The request and response bodies of the operations in this API.

AnswerConsentDto

PropertyTypeRequiredDescription
decisionConsentDecisionyesallow 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

PropertyTypeRequiredDescription
levelone of "ask", "flow", "trusted"yesThe level actually in force: your choice, capped by the org.
orgMaxAutonomyone of "ask", "flow", "trusted" or nullyesThe org-admin ceiling, or null when the org has set none.
requestedone of "ask", "flow", "trusted"yesWhat 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

PropertyTypeRequiredDescription
dataAutonomyDtoyes

CanopyThreadDto

PropertyTypeRequiredDescription
projectContextIdstring or nullyesSwitchable project context. Null means the thread is org-wide.
sessionIdstringyesagent-session-api session id (layer = org).
threadIdstringyesagent-session-api thread id.
tierone of "tier_a", "tier_b"yesTier A hosts the loop in-service (no pod). Tier B is an escalated agent session.

CanopyThreadDtoDataEnvelope

PropertyTypeRequiredDescription
dataCanopyThreadDtoyes

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

PropertyTypeRequiredDescription
idempotencyKeystringyes
launchobjectyes
titlestringnoHuman-readable conversation title. Defaults to a generic Canopy title.

CreateCanopyThreadDto

PropertyTypeRequiredDescription
titlestringnoThread title.

EscalateDto

PropertyTypeRequiredDescription
idempotencyKeystringyes
launchobjectyes
reasonstringyesWhy this task needs a filesystem. Narrated into the conversation before anything is provisioned.
titlestringnoDeep session title.

EscalationDto

PropertyTypeRequiredDescription
deepSessionIdstringyes
deepThreadIdstringyes
threadCanopyThreadDtoyesThe 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

PropertyTypeRequiredDescription
dataEscalationDtoyes

OrgAutonomyCeilingDto

PropertyTypeRequiredDescription
levelone of "ask", "flow", "trusted" or nullyesThe ceiling now in force for the org, or null if none.

OrgAutonomyCeilingDtoDataEnvelope

PropertyTypeRequiredDescription
dataOrgAutonomyCeilingDtoyes

PendingConsentDto

PropertyTypeRequiredDescription
alwaysEligiblebooleanyesWhether 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.
capabilityRefstringyes
effectiveRiskCapabilityRiskTieryesRisk the gate acted on, after the verb.
expiresAtstringyesWhen 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.
reasonConsentReasonyesWhy the gate stopped.
requestIdstringyesStable id every surface keys on, so answering on one device resolves the notification on the others rather than leaving a phantom.
threadIdstringyesThe 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.
turnIdstringyesThe turn this parks. Answering continues IT.

PendingConsentDtoDataArrayEnvelope

PropertyTypeRequiredDescription
dataarray of PendingConsentDtoyes

RevokeStandingConsentDto

PropertyTypeRequiredDescription
capabilityRefstringyesThe capability to start asking about again.

SendCanopyMessageDto

PropertyTypeRequiredDescription
messagestringyesThe user message.

SetAutonomyDto

PropertyTypeRequiredDescription
levelone of "ask", "flow", "trusted"yesAsk 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

PropertyTypeRequiredDescription
levelone of "ask", "flow", "trusted" or nullyesThe 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

PropertyTypeRequiredDescription
projectIdstring or nullyesProject to point the conversation at, or null to return it to org-wide.

StandingConsentGrantDto

PropertyTypeRequiredDescription
capabilityRefstringyesThe capability the grant covers.
createdAtstringyes
grantedFromRequestIdstringyesThe ask this grant came from.
maxRiskCapabilityRiskTieryesThe 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

PropertyTypeRequiredDescription
dataarray of StandingConsentGrantDtoyes

VistaAckDto

PropertyTypeRequiredDescription
detailstringnoHuman-readable detail for the refusal.
errorone of "no-panel", "invalid-args", "unknown-tool", "unknown-tab", "tab-refused"noWhy the panel refused the call. Present when ok is false.
okbooleanyesWhether the panel performed the call. false carries a typed error.
toolCallIdstringyesThe tool call being answered. Echo toolCallId from the tool_call_started row.
toolNameone of "vista_open", "vista_update", "vista_close", "vista_list"yesThe vista_* tool being answered. Echo toolName from the tool_call_started row.
turnIdstringyesThe turn the relayed call belongs to. Echo turnId from the tool_call_started row being answered.
valueobjectnoThe op-specific success value — { tabId }, { updated: true }, { closed: true } or { tabs }. Present when ok is true.