Skip to main content
Intelliger
AI Agent Authorization Engineering

Runtime Authorization for AI Agents: Decision Contract and Tests

Put deterministic AI agent authorization in the runtime path with a typed decision contract, bounded latency, fail-closed behavior and replay-safe tests.

An AI agent request passing through a deterministic runtime authorization checkpoint
Intelliger
9 minute read · Security expert review required before publication

Runtime authorization decides whether an AI agent may perform one exact action using current identity, authority, policy and business state. It runs after the agent has proposed structured arguments and before the side effect begins. Putting the check only in the prompt, planning layer or admin console leaves the execution boundary unprotected.

The AI agent authorization guide covers the complete architecture. This article specifies the live decision contract, latency path and failure tests.

Define a small decision contract

The policy service should not receive raw conversation history. It should receive verified and normalized facts.

type RuntimeDecisionInput = {
  principal: { id: string; tenantId: string; status: 'active' | 'blocked' };
  agent: { id: string; version: string };
  authority: { grantId: string; grantDigest: string };
  request: { action: string; resource: string; canonicalDigest: string };
  context: { now: string; riskClass: string; stateVersion: string };
};

type RuntimeDecision = {
  effect: 'allow' | 'deny' | 'approval_required';
  reasonCodes: string[];
  inputDigest: string;
  policyDigest: string;
  obligations: string[];
  expiresAt: string;
};

The enforcement point must compare the returned inputDigest with the request it will dispatch. This catches a time-of-check to time-of-use change. It must also reject expired decisions and unknown obligations. An allow with an unsupported obligation is not an allow.

Keep the model outside the allow path

The model may classify purpose, extract candidate fields or assign a review score. Convert those outputs into typed inputs and verify them against systems of record. A confidence score may route a request for review. It must not override a failed destination, mandate, approval or tenant check.

agent proposal
  -> schema validation
  -> identity and audience validation
  -> authority resolution
  -> current business-state lookup
  -> deterministic policy decision
  -> atomic replay and usage reservation
  -> exact-request comparison
  -> protected operation
  -> evidence record

OWASP's agentic threats and mitigations describes risks such as tool misuse, identity abuse and manipulated context. A runtime boundary limits the effect of a bad plan because the protected action still needs to satisfy external rules.

Budget latency by dependency

Fast authorization is not achieved by skipping checks. Package slow-changing trust state for local verification, use versioned policy bundles, and keep fresh mutable checks narrow.

DependencyTypical strategyFailure behavior for high-risk writes
keys and issuer metadatasigned cache with expirydeny if beyond allowed staleness
policylocal versioned bundledeny if required version is absent
revocationbounded-freshness cachedeny when freshness cannot be established
replay and usageatomic low-latency storedeny or hold when unavailable
business stateauthoritative servicedeny or require review when unknown
evidence sinkdurable local queueallow only if policy permits deferred delivery

Do not hide dependency failures behind a generic policy denial. Return stable internal reason codes while keeping external error detail minimal. Operators need to distinguish POLICY_BUNDLE_MISSING from ACTION_NOT_ALLOWED.

Run failure fixtures before production

Test the boundary with stale, conflicting and concurrent inputs:

  1. Revoke a grant between resolution and dispatch. The final freshness check must stop the action.
  2. Send the same nonce from two workers. One atomic claim may succeed.
  3. Return allow for a different request digest. The enforcement point must reject it.
  4. Remove the policy bundle during a sensitive write. The path must not fall through.
  5. Change a human-approved amount after approval. The decision must return approval_required again.
  6. Bypass the gateway through an internal route. Network and service identity controls must block it.

See AI agent permissions for the grant model and fail-open versus fail-closed behavior for outage classes. RFC 9700 supplies OAuth security practices, but transaction semantics remain an application concern.

OATI's developer-preview components support signed objects, deterministic evaluation examples and conformance fixtures. The public status does not claim completed independent review or customer production fleet operations. Inspect the OATI developer path before adapting the contract.

Runtime design questions

Should policy evaluation be local or remote?

Local evaluation reduces network latency and keeps decisions available during a control-plane interruption. It needs signed, versioned policy distribution and explicit freshness rules. Remote evaluation simplifies central updates but places a service and network call in every protected action. A hybrid design commonly evaluates a local bundle while querying narrow mutable state such as revocation, remaining uses or current supplier status. Measure the whole decision path under failure, not only the policy function.

When should the system reserve authority?

Reserve replay, usage and limited budget after the request is fully validated and before the external side effect. The reservation must bind the same request digest returned by policy. Define what releases a reservation: a pre-dispatch failure may release it, while a provider timeout usually leaves it held until reconciliation. Record each transition. Otherwise operators will be forced to choose between duplicate execution and permanently stranded capacity.

Can a cached allow decision be reused?

Only under an explicit rule that proves the request, authority, policy and relevant state are unchanged and the decision has not expired. Caching by tool name or agent ID is unsafe because two calls can carry different amounts, destinations or records. Material writes usually benefit more from locally cached policy inputs than from cached allow results. If results are cached, include the complete input digest and remaining obligations in the key.

What should the caller learn from a denial?

Give internal operators stable reason codes and enough correlation data to diagnose the control. Give an untrusted caller only the detail needed to recover safely. Revealing every permitted counterparty or exact remaining budget can help an attacker probe policy. Separate public error text from the protected decision event, and never include secrets or complete authority objects in either.

How is a policy release made safe?

Test the new bundle against saved allow, deny, approval and failure fixtures before signing it. Compare decisions with the previous bundle and require review for changed material outcomes. Roll out by tenant or action class, watch denial and dependency signals, and preserve the earlier bundle for receipt verification and incident reconstruction. A rollback should restore policy behavior without changing the recorded digest on earlier decisions.

One last acceptance test is easy to miss: send a request that policy allows, then change a protected field inside the adapter before the upstream call. The adapter must recompute or compare the request digest and stop. This proves runtime authorization protects the operation that will execute, not merely the object that reached the policy service.