Cloud|

Action approvals

How Cloud records, decides, and uses one approval for exactly the Action a person saw.

6 min read Updated 2026-10-10 #identity#approvals#capabilities#audit

When Cloud asks a person to approve an Action, it records the question as one approval request owned by the platform. The Assistant chat, cld, and code in Assistant Studio ask through the same record, so one decision answers the question wherever the person gives it.

An application does not opt in. When the Assistant, in a chat or in cld assistant, or code in Assistant Studio calls a Capability Action without approval: "none", Cloud asks first, as described in Approve Capability Actions. The application declares its Actions, an optional review, and its approval sentence; Cloud does the rest. A direct call with a person's own credential, such as cld capabilities action or a request to /api/capabilities, does not ask: the person makes that call themselves.

What a request records

Field Meaning
Scope The application that owns the effect and the Action, taken from the capability ID, never from the caller
Approval scope The app-owned scope from the review, used for remembered approvals
Requester Who asked: an Assistant turn and its tool call, or a Studio capability call
Approver The person who may decide: the owner of the chat, or the person running the Studio code
Level standard when the person may remember the approval of this call, otherwise confirm
Sentence and review What the person read, as a snapshot in their language
Input and review digests SHA-256 over the canonical Action input and over the review snapshot
Status pending, then approved, rejected, expired, or cancelled; approved becomes consumed when the Action runs
Decided via The credential the decision came with: web_session, app_session, oauth, api_key, or invocation
Expiry When an undecided request stops accepting a decision

The level follows what the call offers. An Action with approval: "rememberable" whose review names an approval scope for the arguments, a tool whose policy allows remembering, and a website request are standard. Every other approval is confirm: an Action without approval, which includes every destructive and open-world Action, and a call of a rememberable Action whose review leaves out the scope, because that call asks every time. Cloud records the level; every place where the person can decide today accepts both levels.

Decide once

  • First decision wins. Two decisions that arrive at the same time, for example from two open tabs, cannot both apply. The second one gets the existing conflict answer of its route, or succeeds unchanged when it repeats the same decision.
  • Only the approver decides. Another account gets the same answer as for a request that does not exist.
  • One question, one request. When Cloud asks the same question again, for example after a restart, it keeps the request and the snapshot it recorded first. A decision on it never applies to a changed effect; that effect asks again, as described below.
  • Requests expire. A chat request accepts a decision for 24 hours, like the turn that waits for it. A Studio capability call waits up to one day. No request waits longer than 24 hours.
  • Ending the wait cancels the request. When a turn ends, its open requests and the approvals no call used are cancelled. A Studio capability call that is still open after one day is abandoned, and its request with it.

Rejecting is always possible while the request is open, also when the owning application is unavailable.

Use an approval once, for what was shown

An approval is used directly before the Action runs, not when the person decides. At that moment Cloud computes the input digest from the real input again and runs the Action's review again. Both must match the snapshot the person saw. Then the request changes from approved to consumed in one step, so no other call can use it.

Situation Assistant chat Studio code
Review and input unchanged The Action runs The Action runs
The review changed, for example a draft got another recipient Cloud asks again with the current review; nothing runs The call fails with CONFLICT; the person can still decline
The approval was already used, for example after a restart during the Action The call ends with an error and does not run again; a new call asks again The stored result is returned, or CONFLICT

Asking again about a changed review keeps the call's idempotency key, so an application that already performed the effect does not perform it a second time.

A turn that continues after a later question of the same call runs the tool from its start again, and that run uses the call's earlier approvals again. It is the same call, not a second one.

Where an approval is used depends on who runs the effect. A chat uses it right before the tool or Action runs. When code in Assistant Studio asks through the chat, the Studio capability call uses its own request as it runs. A website request from code uses the chat's request when the chat hands the decision to it; Assistant sends each such request at most once.

The input digest binds only the input. When an Action's input refers to state that can change, such as a draft ID, only the repeated review protects the person, and only for what the review shows. Give such Actions a revision in their input, as Mail's draft.send does with expectedRevision, and check it in the Action.

Audit

Every decision writes an audit event auth.action.approve or auth.action.deny. Its target is the approval request, labelled <appId>.<action>, and its metadata names the level, the requester, and the decidedVia channel. Assistant tool calls also keep the channel next to their approval state.

Approval requests are deleted with the capability execution records, 90 days after they expired.

Remembered approvals stay separate

Approve for this chat, Always approve, and allowed websites are still stored as preferences in Assistant and resolve a later call without a new request. Only a person in a signed-in browser session can remember a website. Scheduled tasks and mandates never ask and never use a remembered approval; see Background mandates.

Platform-owned service

@k2b/cloud/services/approvals holds the table, its migration, and the request, decide, and consume functions that Core and Assistant use. It is platform-owned, not an application API: applications receive approvals through their Capability Actions.

Upgrade

Core creates the approvals.requests table on start and gives every chat approval that is still open a request, with the same digests the running Assistant computes. A Studio capability call that was waiting during the upgrade receives its request when the person decides, and keeps the one day it had to wait. People see no change, except that a chat Action whose review changed since the question asks again instead of running. See Deployment requirements for the upgrade order.

Connect a coding agent

The Cloud skill provides compact working instructions. MCP supplies exact current documentation when details matter.

CLI command
bunx skills add https://docs.example.com

This command installs the working instructions published by this website in the selected coding agent.

For exact, current details, also connect the MCP server through one of the agent tabs.

Installation uses the open-source Vercel Skills CLI.

The skill and MCP complement each other: the skill describes workflows, while MCP supplies current documentation.