---
title: "Use case: Answer whether an agent was allowed to do that, after the fact"
canonical_url: "https://tokenobserve.com/use-cases/prove-an-agent-was-authorised"
published: 2026-09-02
last_updated: 2026-10-21
---

# Use case: Answer whether an agent was allowed to do that, after the fact

Keep the decision rather than only the outcome. In Token Observe, every governed request opens a trace before anything is decided, and the record names which role and which resource pattern allowed the call, or which delegation link refused it, alongside the policies that matched and the human who approved what.

## The stated limit

A trace is not a transcript: No prompt or reply text at all, unless you switch capture on

## This morning's configuration cannot answer last quarter's question.

The current configuration answers what the agent may do today. The access review recorded that agent X holds role Y, which certifies almost nothing, because role Y is editable and the review does not say what was in it. The application log records that the call succeeded and not why. And the refusals, the interesting evidence, are missing entirely.

## The steps, in this order

1. Make the inventory the enforcement point. Register every agent with a named owner, a team and a declared purpose, and let the gateway resolve that row on every call. There is only one list.
2. Recertify against a digest. A reviewer submits the snapshot digest they inspected, and the store re-derives it inside the insert transaction. A concurrent edit returns a 409.
3. Keep the decision, not the outcome. Confirm your traces carry the reason strings: allowed by which role and pattern, refused at which link, denied by default, or blocked by which policy.
4. Seal the history while it is short. Every role creation, edit and deletion is written to the hash-chained audit log with the acting user. Waiting costs a permanently weaker prefix.

### The trace opens before the verdict, so a refusal is evidence too.

The trace id is minted at step 3 of the eleven-step request path (before unicode sanitisation, before the scanners and before the verdict), so a request blocked a millisecond later is recorded rather than missing. What lands on it is the reason as well as the verdict: an allow names the role and pattern, and a refusal on a delegation chain names the earliest failing link and out of how many.

- Refusals are recorded: A tool call denied for want of a grant opens a trace, records the denial and closes as blocked. The probe stays visible to an investigation.
- The on-behalf-of setting: Off resolves no principal. Shadow computes the intersection and writes what it would have refused, never blocked. Only enforce refuses anything.
- A failed run is recorded as failed: An interrupted stream closes as an error and its partial usage is still metered. A failed run recorded as a success is a record that lies.
- An empty timeline means something: A trace with no steps is a request rejected at authentication, before the pipeline started, and the page says so.

### A review binds a digest of the permissions, not the role id.

Each referenced role is bound by name, permission count and a SHA-256 over its normalised permissions rather than by its identifier, which is what makes the attestation mean something six months later. Editing a role changes the live digest immediately and marks every affected review stale, while the historical snapshot is untouched.

## What this still does not solve

- A delegation chain and an on-behalf-of principal are asserted rather than proven. Both arrive as request headers with no signed claim behind them.
- Under the default configuration the audit chain is unkeyed, so an operator with write access can rewrite an entry, recompute every downstream hash, and have verification report valid.
- The search cannot aggregate, group or correlate across traces, so a question about patterns across a population is a code change.
- Retention and erasure act on the live primary database only. A restored pre-erasure backup can resurrect erased traces and lose the row that recorded the erasure.

## Questions and answers

Q: Why does editing a role make an agent's review stale?
A: Because the review attests what the agent could do, not which identifiers it referenced. The snapshot binds each role's name, permission count and a SHA-256 over its normalised permissions, so widening a role marks every agent referencing it stale. Binding role ids only would let a reviewer's name sit beside a permission set they never saw.

Q: Does an expired recertification stop the agent?
A: No, and that is a deliberate limit. Token Observe derives and exposes the posture and does not auto-suspend. Automatic suspension would turn a compliance calendar into an availability control, which needs a grace period, a named escalation owner and a dry-run path.

Q: Can we prove the record was not edited after the fact?
A: To a stated degree. Governance-plane changes are hash-chained, so an edit breaks verification at a named sequence. But unkeyed, which is the default, a writer who recomputes every downstream hash produces a chain that verifies clean, and the repository ships a forgery test asserting exactly that.
