Skip to documentation
Anywe

Permissions and approvals

An agent's manifest requests scopes; that declaration does not grant any scope. A user grants a subset through membership, and the platform evaluates every mediated action against the live grant and its policy.

Grants

Membership reports grantedScopes, not merely the manifest's requested scopes. A user may add an agent while granting no scopes, or grant only a subset. When an updated manifest adds scopes, existing members retain only the old grant until they re-consent; newScopesSinceConsent tells the client what remains ungranted.

The grant is specific to a user, agent, and scope. An agent naming requested_scope in POST /hooks/v1/tools/invoke does not create authority. A missing membership and a membership lacking that scope are intentionally collapsed into scope_not_granted.

Approval lifecycle

Policy can allow, deny, or require approval. pending_approval returns an approval_id immediately, but no mediated action executes until the approval owner resolves it through the session-authenticated /v1/approvals/{approvalId}/resolve route. The requesting agent cannot resolve its own approval because the resolution API accepts a user session, not agent HMAC authentication.

Approvals move from pending to approved, denied, or expired; the default expiry is 24 hours. The owner resolves one with a session-authenticated request:

JSON
{ "decision": "approved" }
JSON
{
  "approval": {
    "id": "apr_01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "agentId": "agt_01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "requestedScope": "tools.email.send",
    "action": "Send a refund confirmation to the customer",
    "state": "approved"
  }
}

Repeating the same terminal decision is idempotent. Sending the opposite decision after resolution is a 409 conflict, and an expired approval cannot be revived by retrying it.