Decisions and Attributes
Allowly evaluates one authorization edge:
user + agent + scope + optional resource/context/cost
Your app creates the authorization, stores the authorization_id, calls /v1/check before the agent action, and enforces the returned decision.
Supported decision verbs
These are the live runtime decisions returned by /v1/check.
| Decision | Meaning | What your app should do |
|---|---|---|
allow | The authorization is active and the requested scope is permitted. | Run the action. |
deny | The action is not permitted. | Do not run the action. Branch on reason for UX/support. |
confirm | The authorization exists, but this scope requires explicit user confirmation for this action. | Prompt the user, approve or deny the nonce, then re-check before running. |
escalate | The authorization exists, but this scope requires third-party approval. Pro+ only. | Route the escalation to the configured approver, resolve it, then re-check before running. |
Reason codes
| Decision | Reason | When it appears |
|---|---|---|
allow | authorization_granted_scope_active | Scope is authorized and no confirm step is required. |
allow | authorization_granted_via_confirmation | User approved a matching confirm nonce and the confirmation window is still active. |
allow | authorization_granted_via_escalation | A matching escalation was approved and the approval window is still active. |
deny | authorization_not_found | authorization_id does not exist in this workspace. |
deny | authorization_revoked | Authorization was revoked. |
deny | authorization_expired | Authorization expired. |
deny | scope_not_authorized | Scope is not in the authorization, or a scope constraint failed. |
deny | resource_tombstoned | Workspace tombstone blocks this resource. |
deny | rate_limit_exceeded | Scope max_per_day counter reached its limit. |
deny | budget_exceeded | The estimated cost would exceed the authorization budget. |
deny | escalation_rejected | A matching escalation was rejected. |
confirm | scope_requires_user_confirmation | Scope is listed in requires_confirm_for and no active confirmation exists. |
escalate | escalation_required | Scope is listed in requires_escalation_for and no active approval exists. |
Authorization attributes
Set these when you create an authorization.
| Attribute | Type | Required | Notes |
|---|---|---|---|
user_id | string | yes | Opaque internal user ID or SDK email HMAC helper output. Do not use raw email, phone, or legal name by default. |
agent_id | string | yes for inline authorizations | Opaque agent/workflow ID. Omit when using bundle_id. |
bundle_id | string | yes for bundle flow | Reusable agent scope bundle. If present, omit agent_id and scopes. |
scopes | array | yes for inline authorizations | Array of { name, constraints? } scope entries. |
requires_confirm_for | string array | no | Scope names that should return confirm before allowing. Must be included in scopes. |
requires_escalation_for | string array | no | Pro+ scope names that should return escalate before allowing. Must be included in scopes. |
escalation_targets | object | no | Optional map from scope name to approver label such as manager, security, or compliance. |
expires_at | RFC 3339 timestamp | yes | Authorizations must expire; there are no perpetual authorizations. |
budget_limit_micros | integer | no | Pro+ authorization-level spend cap in micro-USD. See Budget Gate. |
metadata | object | no | Opaque data copied into the authorization receipt context. |
Budget attribute
budget_limit_micros is a Pro+ authorization attribute. It is not a decision verb.
When an authorization has a budget cap, each budgeted /check call includes estimated_cost_micros. Allowly compares the estimated action cost to the remaining authorization budget before the action runs:
- under budget: the check continues to the normal decision path (
allow,confirm, orescalate) - over budget: the check returns
denywithreason: "budget_exceeded" - every evaluated budget result is recorded in the signed receipt context
Use budget for estimated agent action cost, such as model calls, paid APIs, enrichment jobs, or tool usage. See Budget Gate for request and response examples.
Scope attributes and constraints
Each scope entry has a name and optional constraints.
{
"name": "email.send",
"constraints": {
"max_per_day": 5,
"resource_pattern": "gmail:thread:*",
"allowed_initiators": ["user"]
}
}
| Constraint | Type | Effect |
|---|---|---|
max_per_day | integer | Allows only this many successful allow decisions per UTC day for this authorization + scope. Denied and confirm responses do not consume the counter. |
resource_pattern | string | Requires /v1/check.resource to match this fnmatch-style pattern. Mismatch returns deny / scope_not_authorized. |
allowed_initiators | string array | Requires /v1/check.context.initiated_by to be one of these values. Mismatch returns deny / scope_not_authorized. |
Constraints are evaluated only after the authorization exists, is active, and includes the requested scope.
Check request attributes
Send these to /v1/check.
| Attribute | Type | Required | Notes |
|---|---|---|---|
authorization_id | string | yes | Stored ID from POST /v1/authorizations. |
scopes | string array | yes | One or more scope names. Response is keyed by scope name. Duplicate scopes are rejected. |
resource | string or null | no | Resource identifier such as gmail:thread:abc. Used by resource_pattern and tombstones. |
session_id | string or null | no | Customer session label copied into the signed receipt context. |
context | object | no | Opaque runtime facts. context.initiated_by is used by allowed_initiators. |
estimated_cost_micros | integer | required for budgeted authorizations | Estimated cost in micro-USD. Launch budget checks support exactly one scope. |
user_id and agent_id are not accepted in /v1/check; Allowly looks them up from the authorization to avoid spoofing.
Check result attributes
Each result in the results map can include:
| Attribute | Type | When present |
|---|---|---|
decision | string | Always. |
reason | string | Always. |
receipt | object | Always. Pending by default, signed if ?wait=true completes in time. |
budget | object | When budget was evaluated. |
confirm_nonce | string | Only when decision is confirm. |
confirm_expires_at | RFC 3339 timestamp | Only when decision is confirm. |
confirm_prompt_hint | string | Only when decision is confirm. |
escalation | object | Only when decision is escalate. Contains escalation ID, status, target, and expiry. |
escalation_id | string | Only when decision is escalate. |
escalation_to | string | Only when decision is escalate and a target was configured. |
escalation_expires_at | RFC 3339 timestamp | Only when decision is escalate. |
SDK-local fallback results add SDK fields such as is_fallback / isFallback and fallback_mode / fallbackMode. A fallback result has no signed Allowly receipt because Allowly did not make that decision.
Evaluation order
For each requested scope, Allowly evaluates:
- Authorization exists.
- Authorization is not revoked.
- Authorization is not expired.
- Scope is included in the authorization.
- Scope constraints match
resourceandcontext. - Resource is not tombstoned.
- Rate limit is not exceeded.
- Budget cap is not exceeded.
- Escalation approval is active, or
escalateis returned for scopes that require escalation. - Confirmation is active, or
confirmis returned for scopes that require confirmation. - Otherwise, return
allow.