Approvers and approval modes
An approval binds a named person's decision to the exact request they saw. Approving records a decision; it never executes anything. The original agent must come back and resume, and Axiom rechecks its authority at that moment. See Approvals.
Approval modes
| Mode | How to configure it |
|---|---|
| Routine actions within a standing grant | Grant the operation with no require_approval rule. The action is allowed and dispatched at once. |
| Approval when a condition is met | A require_approval rule with when, e.g. params.amount gt "500". |
| Approval for every selected action | A require_approval rule with operations and no when. |
| Never, even with approval | A deny rule with hard: true (a ceiling). |
Rules can sit on the grant, in a project policy or in an enterprise (org) policy. See Grants and approval thresholds.
Map approvers
An approval requirement names a role. Eligible approvers are the people who hold that role in the action's tenant.
Console: Members and approvers at /app/tenants/:tid/members.
POST /v1/tenants/{tenant_id}/members
content-type: application/json
{ "email": "finance.manager@acme.example", "role": "finance_approver" }Roles you can assign here: tenant_admin, finance_approver, approver, auditor. The person must already have an Axiom account (they sign in once first); otherwise the call answers 404 no Axiom account uses that email. Remove a role with DELETE /v1/tenants/{tid}/members/{uid}/{role}.
The role name in the rule (approval.approver_role) must match a tenant role exactly. The sample grant uses finance_approver.
Org roles apply to the tenants the org owns. A person with an org-level role (for example the org approver role) is eligible for an approval that requires that role in any of the org's tenants, and is emailed like a tenant-level approver: eligibility for notification follows the same rule as eligibility to decide.
The same rule applies when the agent resumes: the eligibility recheck counts tenant-level and org-level holders of the role alike, so an approver who later loses the role (at either level) makes the resume close as approver_ineligible.
Multiple approvers and separation of duties
count(1–5) is the number of distinct people who must approve. The approval page says whether a second approver is required, and the action'sreason_codebecomessecond_approver_requiredafter the first approval. The same person cannot approve twice.With
separation_of_duties: truethese people are excluded from deciding:- the agent's owner (
owner_user_id), - the agent's sponsor (
sponsor_user_id), - the author of the policy version that required the approval.
An excluded person sees the request but the page explains why they cannot decide (
reason_code: separation_of_duties).- the agent's owner (
One denial from any eligible approver denies the action (
approval_denied) and cancels its other pending approvals.
Where approvers decide
The built-in approval page
When the requirement has no connector_id, Axiom emails every eligible approver (tenant-level and org-level holders of the role, minus anyone excluded by separation of duties) with a link to /approve/{approval_id} and the deadline, and the request appears in Approvals (/app/approvals, GET /v1/approvals).
The page shows: the summary ("Billing agent requests USD 25,000 against invoice 417 for customer Acme Corp"), tenant, agent and operator, resource, every approver-visible material field, the names of hidden fields (still bound by the digest), the policy trigger, the deadline, how many approvals are required and received, the request digest, and a receipt link once the provider confirms the result.
The decision references the digest shown:
POST /v1/approvals/{approval_id}/decision
content-type: application/json
{ "decision": "approved", "digest": "sha-256:…", "comment": "Duplicate charge confirmed" }If the request changed after the page was loaded, the digests differ and the decision is refused with 409 conflict (material_change): reload and review the current request.
Only people holding the approver role, tenant auditors and tenant admins can open the page; anyone else gets 404.
A native approval system (Control)
An org policy (or project policy) can route the request to an approval connector with approval.connector_id. Axiom creates the request in that system with the exact transaction and digest, then reads the decision back server to server. See Connectors.
The connector's system is then the system of record: a connector-routed approval can only be decided there. The Axiom approval page still shows the request, but refuses a decision with "this approval is decided in servicenow; Axiom records the decision by reading it back from there".
Not through MCP or chat
Axiom's MCP server lists pending approvals for a person (axiom_list_pending_approvals) with links to the approval page, but offers no tool to approve or deny. Slack and Teams appear in the connector catalog as notification channels marked "Planned, not yet available"; they do not send anything yet.
Verified decision records
Every decision is stored with how it was verified (axiom_session for the approval page, connector_readback for a native system) and Axiom signs its own observation of it with the observation key, preserving the native record reference. The receipt therefore names the actual signer: Axiom attests what it observed; it does not pretend the external system signed.
Eligibility is rechecked on resume
When the agent resumes, Axiom re-evaluates current policy. If a currently required approval is not satisfied by people who still hold the role, the resume is refused and the action is closed (approver_ineligible, or policy_stale if policy now requires more approvals than were collected). External approvers verified by connector readback count as eligible.