Skip to main content
AI agent accountability means that every action an agent takes can be traced to a named human or team, was checked against a policy before it ran, and was recorded afterwards. theAuth enforces this at runtime: each agent has its own identity, permissions are checked before the action, and access can be revoked immediately. A RACI matrix says who should be responsible and accountable. An agent never reads it. The matrix only matters if the runtime enforces it, so this page maps each RACI idea to an API that exists today.
Features marked Planned are not shipped. Everything else on this page is backed by code in the current SDK.

Who is accountable when an AI agent acts?

The human or team that owns the agent. In theAuth every agent is created with an ownerId that must match a real user row, and every audit row stores the agent that acted. Delegation records who gave what to whom, so you can walk back from a sub-agent to the agent that delegated to it and to that agent’s owner.
A sub-agent has its own ownerId, but the accountable human is the owner of the root agent in its delegation chain. delegate() returns that owner as rootOwnerId and the agent ids from the root down as path, and policy.evaluate() returns the same lineage on decision.principal.
When an agent has several active inbound chains, the earliest created one is followed. See Delegation chains.

How do you give an AI agent an identity?

Create it as its own principal, not as a copy of a user session. An agent has a stable id, a hashed bearer token, a type, an expiry and a status. It has no password and no browser session.
Tokens rotate with theauth.agent.rotate(agentId), and the old token stops working at once. See Agent identity. For agents that call your MCP servers, see MCP OAuth 2.1.

How do you limit what an AI agent can do?

Check every action before it runs. authorize() evaluates the agent’s permissions and any it received through delegation, then returns allowed or not. policy.evaluate() does the same and returns a three-way decision: allow, deny or escalate. Constraints narrow a permission: a call rate, argument patterns, a time window, an IP allowlist, and human approval.
A requireApproval permission is always denied by authorize(). Your code reads the reason, opens an approval request and runs the action itself after a human approves. policy.evaluate() returns escalate for the same permission instead, which is easier to branch on. See Approval flows and Permissions. To let a sub-agent act within a narrower scope, delegate a subset with a short expiry. Constraints on the delegated permissions are stored and enforced, and a child can only tighten what its parent holds: requireApproval is OR-ed, maxCallsPerHour takes the lower value, and lists are intersected.

Escalate above an amount

The amount threshold is a risk-tier rule, not a numeric permission constraint. You pass the amount in context.risk, and a tier in the policy config decides what an action of that size requires. A permitted action that lands in an approval or step_up tier becomes escalate.
Risk fields are amount, currency, dataClass, irreversible and extras. A rule can match on minAmount, currency, dataClasses and irreversible, and the strongest matching requirement wins. Risk only escalates an action that would otherwise be allowed. Cumulative spend is not tracked. See Policy engine.

Act only for the owner

Pass the owner the request claims to act for as subject.ownerId. If it differs from the agent’s ownerId, evaluate() denies with POLICY_OWNER_MISMATCH. A revoked, suspended or expired agent is denied with POLICY_AGENT_INACTIVE. Both checks run before the decision cache, so they take effect at once.
For the combining rules, see Policy engine. For ready-made rules, see Policy templates, including a spending limit with human approval (template 08) and acting only for the owner (template 09).

How do you ask a human before the agent acts?

Use requireApproval or a risk tier, then the approval module. The request stores the agent, the owner, the action, the resource and the arguments. The human’s answer and their identifier are stored on the request. Calling policy.evaluate(input, { openApproval: true }) opens the request for you on escalate and returns its id as decision.escalation.approvalRequestId. Otherwise open it yourself:
Delivering the notification is your application’s job, through webhookUrl or onApprovalNeeded. See Approval flows.

How do you audit AI agent actions?

Every decision about a known agent writes an audit row, with the action, resource, arguments and result (allowed, denied or escalated). Rows also carry subject_id (the accountable human), actor_id (the agent), policy_version (from policy.policyVersion), approver_id, delegation_chain, input_provenance and hash_version. Turn on the hash chain to make edits and deletions detectable, then verify, replay and export.
The export is a JSONL file plus a manifest signed with your HMAC key, and verifyAuditExport checks it later without a database. See Tamper-evident audit trail and Audit log. The decision row and the approval answer are separate rows. The decision row holds the inputs, the policy version and the lineage. The approval row holds approver_id. Replay merges them in time order. Three limits apply:
  • input_provenance is a column the caller fills in through recordAuditEvent. Nothing in the SDK populates it automatically.
  • Audit writes from recordAuditEvent (policy decisions, delegation, approval and SCIM events) are best effort. They never throw, failures are counted by getAuditWriteFailures, and the next successful write is preceded by an audit.write_failed row.
  • Chained rows hash keyed pseudonyms of the ids, so GDPR erasure can blank raw ids without breaking verification. Whoever holds the key can still link a pseudonym to an id.

How do you revoke an AI agent?

Call theauth.agent.revoke(agentId). The agent’s token is rejected on its next call and every later authorize() attempt is written as a denied row with the reason agent_revoked. policy.evaluate() denies a revoked or expired agent with POLICY_AGENT_INACTIVE. Revocation is permanent. To cut off a sub-agent without touching its parent, revoke the delegation:
Revoking an agent does not terminate an operation that already passed authorization. See Agent identity and Cascading revocation.

What is not shipped yet?

These are planned and are not available in the SDK today.
  • Planned: revoking an agent that cascades to everything it delegated. In the TypeScript package, agent.revoke() only changes the agent’s status, so revoke the delegation chains explicitly, as above. The chain rows stay active until you do.
  • Planned: the approver on the same row as the decision. Today the approver is on the approval’s own audit row.
  • Planned: automatic input_provenance. The column exists and you can write it, but the SDK does not fill it.

FAQ

Is an AI agent a user?

No. An agent has no email, password or session. It has a token and a permission set, and it belongs to a user through ownerId.

Does a RACI matrix replace runtime enforcement?

No. The matrix records intent. The checks above are what make the intent hold when an agent runs unattended. Use the RACI template to write the matrix, then enforce each cell.

Can an agent approve its own action?

The approval module records who answered through the identifier your application passes to approve(). theAuth does not stop your code from passing an agent identifier there, so authenticate the approver as a human in your handler.

Are denied attempts recorded?

Yes, for known agents, including requests from revoked or expired agents. Unknown agent ids and unknown tokens write no row, because the audit table requires a real agent. See what gets recorded.

Can I prove the audit log was not edited?

With audit.tamperEvident on, verifyAuditChain reports edits, gaps and reordering. Deleting the newest rows is only detectable against a saved chain head. Policy decisions, delegations and approvals are all chained. See the limits.

Does it work with MCP?

Yes. Agents that call MCP servers authenticate through MCP OAuth 2.1 and are checked with the same permissions and audit trail.

Next steps

RACI template

A RACI table for agent action classes, with the enforcement for each cell.

Policy engine

How decisions are combined and cached.

Trust scoring

A score you can use in your own approval rules.

Budget policies

Spend and call caps per agent.
Last modified on October 16, 2026