Agent door

Write approvals

Every agent write is held for a human by default. Nothing an agent submits changes a record until a workspace admin approves it — unless the workspace has explicitly, and provably, opted a grant out.

The agent door is human-above-the-loop for writes. When an agent calls a write tool, the door validates the request and then parks it for approval rather than applying it. The target record is byte-unchanged; a workspace admin decides whether it lands.

The default hold

A write tool call returns a pending result, not a mutation:

{
  "status": "pending_approval",
  "approval_id": "…",
  "message": "The write was validated and is held for human approval.
              Nothing has been changed yet; poll get_approval_status."
}

The validated write is stored in an approval queue with a snapshot of the target as it was at request time. An admin reviews it in the dashboard and either approves or denies it.

Polling with get_approval_status

The agent polls get_approval_status with the approval_id to follow the decision. An agent sees only its own grant's approvals. The status is one of:

StatusMeaning
pending_approvalWaiting for a human decision.
applyingApproved; the write is being applied.
appliedThe write landed.
deniedAn admin declined it. Terminal.
expiredThe target changed, or the grant/issuer went away, before it could apply. Terminal.
failedAn unexpected error while applying. Terminal.

What the apply step re-checks

Approval is not a blind replay. When an admin approves a held write, the door re-verifies, at apply time, that the grant, its trusted issuer, and the exact write capability are all still live, and re-fetches the live target bound to the approval's own organization. If the target changed since it was parked, or any authority behind it was revoked, the write resolves to expired rather than applying stale intent.

Auto-approve requires a proven key binding

A workspace can opt a grant into direct apply (skip the hold), but this is deliberately hard to reach:

  • The grant must carry the auto_approve_writes opt-in, set by a workspace admin.
  • and the calling session must be sender-constrained — bound to a client-held key, issuer-confirmed, with a fresh DPoP proof on the request that carries the write (see Authentication).

If the opt-in is set but the session cannot prove the key binding, the write is held anyway — the response marks it auto_approve_unavailable: "sender_constrained_auth_required". A bearer token alone, a stolen assertion, or a grant flag by itself can never produce an un-held write.

Today's write surface

One write tool ships today: update_action_item, which requests a change to an action item's lifecycle fields (status, assignee, due date, resolution notes) under the same transition rules the dashboard enforces. See the Tools reference.