AI Research Library

The Autonomy Ledger for Agent Teams

Rajesh Ranjan Mahapatra

A multi-agent system is governable only when every active delegation carries a live record of purpose, identity, authority, evidence, spend, unresolved risk and verified outcome.

© 2026 Rajesh Ranjan Mahapatra. 32 min read

The Autonomy Ledger for Agent Teams

A multi-agent system is governable only when every active delegation carries a live record of purpose, identity, authority, evidence, spend, unresolved risk and verified outcome.

TLDR

  1. A team of agents is governable only when every active delegation carries a live record of purpose, identity, authority, evidence, spend, unresolved risk and outcome.
  2. The ledger is not another log. It compiles policy, runtime events and effect receipts into the current decision state for each agent and for the team.
  3. Authority must attenuate down the delegation chain, budgets must balance, evidence must remain attached, and open risks must be resolved or deliberately escalated.
  4. Static workflows with fixed service accounts may need no new ledger; ordinary IAM, tracing and audit records can be the better baseline.
  5. Architecture review should ask whether the ledger can block an invalid action and reconstruct the approved team state, not whether its dashboard looks complete.

Eight green boxes and one missing caveat

Consider a synthetic credit-review mission run by seven specialised agents and one human approver. An intake agent normalises the request. A retrieval agent collects financial statements and policy passages. A calculation agent derives ratios. A covenant agent tests the proposed terms. A risk agent challenges assumptions. A memo agent assembles the recommendation. An execution agent prepares the approved terms for the downstream system. Every component has its own identity, tool allowlist, trace spans and cost counter.

Halfway through the mission, the covenant agent finds a conflict. One document says the borrower may add secured debt within a stated basket. A later amendment appears to narrow that basket, but its effective date is ambiguous. The agent cannot settle the issue from the available evidence. It emits a useful result: R-17: unresolved covenant precedence; block term finalisation.

The result crosses two handoffs. The risk agent receives it and marks the issue material. The memo agent receives a compressed summary after the context compiler removes duplicated text. The summary preserves the competing clauses but drops the machine-readable blocking status. The memo says the covenant position needs confirmation, yet the execution agent sees an otherwise approved proposal, an allowed tool and an available budget. It prepares the terms.

No single control necessarily reports a violation. The covenant agent behaved correctly. The risk agent behaved correctly. The memo agent included a caveat. The execution agent used an authorised operation. The trace is complete. The cost is below limit. The final package is fluent and locally defensible. The team is globally wrong because an unresolved risk ceased to be operative when responsibility crossed an agent boundary.

Figure 1. Local success can compose into a globally invalid decision
Synthetic worked scenario. The figure varies one feature: whether the blocking state travels with the evidence. No deployment outcome is claimed.

The natural response is to add another message, prompt instruction or dashboard field. That treats the symptom. The deeper absence is a control-plane object that survives handoffs and answers, for every active agent: Why is it acting? Under whose authority? On which evidence? At what cumulative cost? Which risks remain unresolved? What effect has actually been verified?

An autonomy ledger is that object. It is a causally keyed, runtime-reconciled view of the team’s current delegations. It does not replace identity, policy enforcement, tracing, provenance, budgets or incident systems. It compiles their relevant facts into a state that can be checked before action and reconstructed afterwards.

Part I
The argument in one passChart · flow
flowchart LR
  A["Eight green boxes and one<br/>missing caveat"] --> B["On this page"]
  B --> C["A team can be locally<br/>compliant and globally wrong"]
  C --> D["The ledger is a compiled<br/>control-plane object"]
  D -. "re-test" .-> A
  classDef first fill:#0a1424,stroke:#087A98,stroke-width:2px,color:#e6f3ff
  classDef step fill:#0a1424,stroke:#3f7da0,stroke-width:1px,color:#e6f3ff
  class A first
  class B,C,D step
A structural route through The Autonomy Ledger for Agent Teams, from Eight green boxes and one missing caveat to Source ledger. Reading use: follow the relation, then test it against the surrounding evidence and limits.

A team can be locally compliant and globally wrong

Why the existing records do not add up by themselves

Most serious systems already have several records. Identity and access management says which principal can call which resource. Orchestration state says which task is running. A prompt or task message says what an agent was asked to do. Distributed traces correlate calls. Provenance records connect claims to sources. Cost telemetry counts tokens and tool calls. Incident systems hold accepted or open risks. These are necessary, mature controls.

They answer different questions. An IAM policy can say that the execution agent may call prepare_terms. It usually cannot say that the call is valid only for mission M-204, only to implement an approved structure, only while covenant risk R-17 is resolved, and only while the mission’s remaining exposure budget is positive. A trace can show that the memo agent called the execution agent. It does not establish that the delegation was authorised, that the evidence remained applicable or that the child’s power narrowed.

W3C PROV provides a useful core vocabulary of entities, activities and agents, while W3C Trace Context and OpenTelemetry correlate work across process boundaries.[5][6][7] OAuth token exchange distinguishes a subject from an acting party in delegation, and SPIFFE gives workloads cryptographically verifiable identities.[8][9] Those mechanisms make a ledger possible. None defines the whole business decision state.

Figure 2. Each mature control sees one projection of autonomy

IAM and policy

Sees: principal, operation, resource, conditions.
Usually misses: mission purpose, evidence basis, open risk, verified effect.

Prompt and orchestration state

Sees: assigned task, local state, next transition.
Usually misses: effective permission after policy composition and cumulative exposure.

Trace and audit log

Sees: events, callers, timing, parameters and errors.
Usually misses: whether the path remained justified by applicable evidence and accepted risk.

Cost and risk systems

Sees: spend aggregates, issue ownership, treatment status.
Usually misses: which live delegation the spend or risk currently constrains.
Practitioner synthesis. The ledger is valuable only if it joins these projections through shared mission, grant, evidence, risk, action and effect identifiers.

Thought experiment: identical permission, different purpose

Give two agents the same read access to a customer-data service. Agent A is delegated to verify one address for a named case. Agent B is asked to explore the database for useful commercial patterns. Hold identity, tool, rate limit and model constant. Only the purpose changes.

The IAM answer is identical: both calls may be technically allowed. The governance answer is not. Agent A’s queries can be evaluated against a narrow case purpose, resource boundary and expiry. Agent B’s open-ended purpose may be disallowed even if each individual read resembles Agent A’s call. Purpose is not descriptive metadata attached after authorisation; it is part of the authorisation proposition.

This is why a role name such as “research agent” is too coarse. A standing role describes potential capability. A live grant binds a specific identity to a specific mission, purpose, authority envelope, budget and validity interval. The ledger should be keyed to that grant, not merely to the deployed component.

Published evidence

Recent multi-agent research supports the need to inspect coordination rather than only final answers. A 2025 study of five multi-agent frameworks across more than 150 tasks organised observed failures into specification and system-design failures, inter-agent misalignment, and verification or termination failures.[16] A separate failure-attribution study reported that even strong methods struggled to identify the decisive failing step after the fact.[17] These results do not validate the autonomy ledger. They make the operational hypothesis sharper: capture responsibility and constraint state while work happens instead of inferring them from prose after failure.

Three stores must also remain distinct. World state records what is currently true in the operational domain. Evidence history records why a claim was accepted at a time. Agent memory stores information retained for future behaviour. The autonomy ledger references all three but is none of them. Its job is to represent current delegated decision state: who may do what, why, with which evidence and budget, subject to which unresolved risks.

Part II

The ledger is a compiled control-plane object

One entry per active delegation

The unit of the ledger is not the model, agent class or tool. It is an active delegation. The same memo-writing agent may hold ten concurrent grants, each for a different case, purpose, evidence set, ceiling and expiry. Conversely, one mission may create several grants for the same deployed agent as the work moves through phases.

A useful current-state entry can be written as:

Lᵢ(t) = ⟨M, P, I, A, E, C, R, X, O, V⟩

Here M is the mission, P the bounded purpose, I the authenticated agent identity and delegation chain, A the effective authority, E the applicable evidence references, C the reserved and consumed cost, R the unresolved risk set, X the action or proposal state, O the observed outcome state, and V the policy version and validity interval. When any term changes, the admissible next action may change.

The ledger stores immutable events and compiles this current view. A new grant, evidence supersession, risk opening, budget reservation, policy denial, approval, action request, effect observation or compensation appends an event. The materialised entry is rebuilt from those events or incrementally updated. This structure borrows the discipline of ledgers without claiming blockchain, financial accounting or distributed consensus.

Figure 3. Team authority constellation
A constellation of agents around one mission The mission sits in the centre. Coloured agents surround it. Line style denotes delegation, evidence and verification. Node rings show authority scope, cost consumption and unresolved risk. MISSION M-204 purpose · policy · budget open risk · outcome Retrievalread only Calculator£0.14 / £0.25 CovenantR-17 open Riskchallenge Memopropose Verifierindependent Executorprepare only delegationevidenceverificationopen risk
Signature figure. Illustrative topology, not measured data. Rings encode authority, cost and risk locally; the centre holds the mission-level constraints that every delegation must preserve.

The constellation is a review view, not the primary record. Its value comes from compiling the same typed facts used by enforcement. A beautiful diagram maintained separately from policy is a liability. When an authority-changing policy, tool binding, risk state or budget changes, the current ledger view must change through the same event, release or reconciliation path.

Figure 4. The ledger compiles control facts; it does not invent them
Practitioner synthesis. The ledger is a compiled view over authoritative sources. Broken references or stale versions must fail closed rather than manufacture a reassuring summary.

A consistent team view, not a fantasy of perfect simultaneity

An agent team is a distributed system. Events arrive at different times, clocks skew, retries duplicate messages and an action may be accepted before its effect is visible. Lamport’s happened-before relation and the Chandy-Lamport snapshot show why a coherent global view cannot be obtained by reading each component’s “latest” value independently.[13][12]

The ledger therefore needs a consistent cut for consequential decisions. Each event carries a mission ID, grant ID, parent event or causal reference, policy version and idempotency key. Before an irreversible or externally visible action, the authority kernel evaluates a snapshot that includes all causally prior risk, evidence, budget and approval events known to the mission. Later events may still arrive, but the decision receipt records exactly which cut was evaluated.

The analogy has limits. The original snapshot problem concerns process and channel state under stated assumptions. Agent governance also needs semantic judgements: whether evidence applies, whether a risk is material, whether an action is reversible and whether a human acceptance is valid. The snapshot machinery can preserve ordering. It cannot decide those meanings.

Six invariants make the ledger operational

A ledger that only displays fields is documentation. A ledger becomes a control when invalid state transitions are mechanically rejected. The following invariants are a practical minimum.

Figure 5. The six invariants that stop local permission becoming ambient autonomy
1. Purpose bindingEvery grant belongs to one mission and one bounded purpose. A child cannot silently repurpose the parent’s access.purpose(child) ⊑ purpose(parent)
2. Authority attenuationA delegated action, resource scope, amount, duration or audience may narrow, never widen.A_child ⊆ A_parent ∩ A_policy
3. Evidence continuityAn evidence-gated action must cite applicable, unsuperseded evidence visible in the evaluated snapshot.required(a) ⇒ E_a ≠ ∅ ∧ valid(E_a,t)
4. Budget conservationReserved plus committed cost must remain within the mission and grant ceilings, including concurrent branches.reserved + spent ≤ delegated budget
5. Risk non-erasureAn open risk persists across handoffs until it is mitigated, accepted by an authorised owner, transferred or escalated.OPEN → {MITIGATED, ACCEPTED, TRANSFERRED}
6. Outcome closureAn accepted command does not count as success. The action closes only with a verified effect, verified failure, compensation or unknown outcome.sent ≠ succeeded
Original decision instrument. The formulas are design invariants, not empirical laws. Each symbol is defined in the surrounding text and should be adapted to the local policy model.

Authority attenuation has a long technical lineage. Zanzibar demonstrates a consistent relationship-based authorisation system at large scale, while macaroons show how delegated credentials can be restricted through contextual caveats.[10][11] The autonomy ledger does not replace either mechanism. It requires the business consequence of the resulting effective permission to be visible and tied to the live mission.

Budget conservation includes more than token spend. A mission may consume model inference, retrieval calls, paid data, tool transactions and human review minutes. Cost is decision-relevant because additional branches can improve coverage while also multiplying interactions and failure surfaces. “AI Agents That Matter” argues that agent evaluation should include cost rather than rewarding accuracy without economic comparison.[15] The ledger turns that evaluation principle into a runtime constraint.

Risk non-erasure is the distinctive team property. A message can be summarised; a risk state cannot be summarised away. When a child agent receives evidence associated with an open blocker, the child must inherit the blocker, receive an authorised treatment event or be prohibited from the affected action. A downstream prompt saying “consider prior risks” is weaker because compliance depends on model behaviour. The ledger check sits outside the model.

Authority is a vector, not a role name

A role such as “researcher”, “reviewer” or “executor” is convenient for conversation and weak for control. Effective authority has several dimensions: permitted verbs, resource classes, data sensitivity, monetary or population ceiling, external audience, validity period, required evidence, approval condition, reversibility and power to delegate. Two agents with the same role can therefore hold materially different grants. One reviewer may read public filings for a single case. Another may read internal customer records across a portfolio. Calling both “reviewer” hides the difference that matters.

The authority service should compute the live envelope as the intersection of constraints, not the union of labels:

effective authority = parent grant ∩ organisational policy ∩ tool contract ∩ mission state

The parent grant supplies the delegated ceiling. Organisational policy supplies standing rules about identity, data and consequence. The tool contract states what the operation can actually cause, including resource and amount semantics. Mission state contributes evidence requirements, open risks, approvals, remaining budget and expiry. A permissive term in one source never cancels a restrictive term in another unless an explicit, authorised override says so.

This calculation separates three questions that agent designs often collapse. Ability asks whether the component can produce a request. Permission asks whether the current grant and policy allow the request. Authority to delegate asks whether the agent may confer any part of that permission on a child. An agent may be permitted to draft a customer notice while being forbidden to send it or delegate sending. Giving it a tool description for the send API does not alter that boundary.

Human approval should also appear as a typed authority event, not a conversational message. The approval needs an authenticated person or committee role, the object approved, the decision scope, the evaluated ledger version, any conditions, and an expiry or case closure rule. “Looks good” in a chat transcript cannot safely authorise a later action after evidence, cost or risk state has changed. A later action must prove that the approval still applies to its current snapshot.

The ledger can expose a readable role label, but enforcement should use the vector. This is what lets reviewers compare consequences across unlike tools. A database update, an email and a payment instruction have different interfaces. They can still be compared through shared dimensions such as affected population, external visibility, reversibility, value ceiling and required approval.

Thought experiment: keep the text, drop the state

Run the opening mission twice. In both runs, every downstream agent receives the exact sentence “the covenant amendment may narrow the debt basket”. In Run A, the handoff also carries risk_id=R-17, status=OPEN and blocks=finalise_terms. In Run B, it carries only prose.

The informational content looks similar to a reader. The control consequence differs. Run A forces an explicit treatment before finalisation. Run B asks each downstream model to rediscover the intended control from language. The only varied feature is whether the caveat remains typed and operative. Evidence can travel as prose; authority and blocking risk must travel as state.

Part III

From one delegation to a production-shaped team

Minimal worked example: a three-agent invoice exception

Start with a deliberately small synthetic system. An intake agent reads one invoice. A reconciliation agent compares it with a purchase order. A proposal agent may recommend a credit, but cannot issue one. A human remains the only actor able to approve the financial effect.

The orchestrator creates mission M-INV-17 with the purpose “resolve one suspected duplicate invoice”. It delegates read_invoice and compare_order to the reconciliation agent, with a cost ceiling of £0.20. It delegates propose_credit to the proposal agent, but the action is evidence-gated. The proposal agent must cite an invoice and purchase-order match. The grant expires when the case closes.

Figure 6. A minimal mission makes every handoff explicit
Synthetic positive case. The companion Python artefact executes this logic and also includes two negative cases.

The happy path matters less than the rejected paths. Suppose the proposal agent delegates to a new executor with send_credit, even though its parent grant contains only propose_credit. The authority widens, so the child grant is rejected. Suppose identity evidence conflicts with the payment record and risk R-ID-4 blocks proposals. The proposal is rejected until an authorised owner changes the risk state.

Notice what the ledger does not decide. It does not determine whether the invoice really is a duplicate. It does not calculate the correct credit. It does not decide that the conflict is immaterial. Those remain evidence, domain-rule or human-judgement questions. The ledger enforces that the system cannot treat them as already resolved.

GrantPurposeAuthorityEvidenceCostOpen riskOutcome
G-ROOTResolve invoice INV-17Read, compare, proposeCase record£0.30 ceilingNoneMission active
G-RECCompare invoice with PO-88Read, compareE-PO-1 created£0.03 spentNoneMatch recorded
G-PROPDraft a credit proposalPropose onlyE-PO-1 required£0.04 spentNoneProposal created
G-BADIssue credit directlySend creditNot evaluated£0.05 requestedAuthority wideningGrant rejected

Production-shaped scenario: an auditable credit recommendation

A larger worked scenario shows why a team-level view matters. Treat this as an architecture specimen, not a client deployment. The mission is to prepare a recommendation for accountable human approval. The system includes retrieval, calculation, policy, covenant, risk, memo and verification agents. No agent may approve the credit decision or release terms externally.

The root grant contains the mission purpose, product and jurisdiction scope, an expiry, a total inference and data budget, and an authority ceiling of “prepare evidence and proposals”. Each child receives only the data classes and tools it needs. The calculation agent can read structured financials and invoke approved functions. The policy agent can retrieve applicable obligations and emit rule evaluations. The memo agent can assemble claims only from registered evidence IDs. The verifier can challenge any claim but cannot alter the memo silently.

The ledger also records two kinds of receipt. A decision receipt states the evaluated snapshot, policy version, evidence set, risk state, budget state, model proposal and human decision. An effect receipt reports what the downstream system actually changed. This separation matters because an API can accept a request and then fail, time out or apply it twice. The saga literature provides a durable pattern for long-running work and compensating actions when one global transaction is impractical.[14]

Figure 7. The mission board exposes the variables a final-answer dashboard hides
Synthetic production-shaped scenario. Spend values and counts are illustrative. The decision-relevant feature is the explicit coupling of authority, evidence, cost, risk and outcome.

A team-wide budget matters because local ceilings can still overspend globally. If four agents each see a remaining £0.50 and branch concurrently against a mission with only £0.80 left, independent checks may admit £2.00 of work. The ledger needs reservation semantics: a branch reserves expected cost atomically, releases unused capacity and reconciles actual spend. This is ordinary concurrent resource accounting applied to inference and tool use.

Evidence also changes over time. A valuation can be superseded, a policy can take effect, a document can be withdrawn and a retrieval entitlement can expire. The evidence registry emits these changes; the ledger finds live grants that depend on the affected item. A superseded premise does not always invalidate the whole mission, but it must reopen the affected claim or move the mission to review. A fact that was once true is not permanent authority for a later action.

Evidence, policy, risk, cost and outcome run on different clocks

A team can lose control even when every event is recorded correctly because the events become effective at different times. A policy may be published today and apply next week. A valuation may describe yesterday’s market but arrive this morning. A risk may be discovered after a proposal is written but before it is approved. A tool charge may settle minutes after the model call. An external effect may become visible only after an asynchronous downstream process completes.

For that reason, the ledger needs more than a single timestamp. Evidence and policy records should distinguish when a fact was observed or recorded from when it is valid in the world. Grants need issue, effective and expiry times. Risk events need the time the issue became known and the time its treatment became operative. Action and effect receipts need causal identifiers in addition to wall-clock time. This does not eliminate uncertainty, but it prevents a late-arriving event from being mistaken for one that did not apply.

Before a consequential action, the authority kernel evaluates the applicable state at a named cut. The decision receipt retains that cut. If a later event shows that a premise was already invalid at the decision’s effective time, the system can distinguish two cases: the decision was reasonable on the evidence then knowable, or the decision relied on stale or inapplicable evidence that should have been rejected. That distinction is essential for review and remediation.

Cost has its own clock too. A reservation is not spend, an estimate is not settlement, and a human review allocation is not necessarily consumed. The ledger should represent reserved, committed and settled amounts separately. When a branch ends early, unused reservation returns to the mission. When a provider reports a delayed charge, settlement updates the record without rewriting the decision receipt. The same pattern applies to external exposure: authorised ceiling, requested amount and observed effect remain separate.

These temporal distinctions make the ledger useful for replay. An incident responder can reconstruct the state evaluated by the agent, then compare it with the state later known to be correct. Without both views, post-incident analysis tends to judge the past with present information or, in the opposite direction, excuse a decision that ignored evidence already available.

NIST’s AI Risk Management Framework emphasises governance, mapped context, measurement and management, including defined roles and ongoing monitoring.[1] Its generative-AI profile extends the risk framing for systems using generative components.[2] The autonomy ledger is a practitioner synthesis for one implementation burden inside that broader discipline: keeping delegated mission state inspectable and enforceable as several agents interact.

Serious negative control: when not to build an autonomy ledger

Now remove the properties that make the ledger useful. The workflow is a fixed directed acyclic graph. Every step is deterministic code. Service identities and permissions are static. No component delegates authority at runtime. There is one data source, one policy version and no model-generated branch. Cost is negligible and bounded by request volume. Every action is reversible and idempotent. The workflow engine already stores state transitions, IAM enforces access, OpenTelemetry links calls, and the audit system records effects.

In that system, a new autonomy ledger may duplicate existing controls and create reconciliation work without changing a decision. A policy-as-code repository, workflow state, trace context, audit records and a clear owner are likely enough. The right experiment is not whether a ledger can be added. It is whether the added state catches a failure the baseline cannot.

Figure 8. Use the ledger only when autonomy creates cross-control state

Ledger earns its cost

  • Authority is delegated or attenuated at runtime.
  • Several agents act concurrently under one mission budget.
  • Evidence can be superseded during execution.
  • Open risks must constrain downstream agents.
  • External effects require outcome verification or compensation.
Decision boundary. This is a falsification aid for the proposed design. A ledger that cannot outperform the conventional control stack on a targeted failure should not be introduced.
Failure boundary

The autonomy ledger ceases to help when its identifiers are not propagated, its source controls are not authoritative, or the team cannot enforce its invariants before action. A retrospective dashboard assembled from best-effort logs may improve investigation, but it is not an authority control.

Part IV
How the claim changes under pressureChart · state
stateDiagram-v2
  [*] --> Claim
  state "Why the existing records do<br/>not add up by themselves" as Claim
  state "Thought experiment: identical<br/>permission, different purpose" as Test
  state "One entry per active delegation" as Revision
  Claim --> Test: expose mechanism
  Test --> Decision: evidence survives
  Test --> Revision: rival survives
  Revision --> Claim: narrow or rebuild
  Decision --> [*]
The revision loop begins with Why the existing records do not add up… and keeps counterexamples inside the reasoning path. Reading use: follow the relation, then test it against the surrounding evidence and limits.

Earning the control through execution and failure

Executable artefact: a minimal ledger checker

The companion Python programme uses only the standard library and synthetic data. It implements purpose binding, authority attenuation, evidence gating, budget conservation and risk blocking. The positive case accepts an evidence-backed proposal. Negative case A rejects a child grant that adds send_refund beyond its parent. Negative case B rejects an otherwise allowed proposal because an identity-conflict risk remains open.

Inspect the implementation in this paper
POSITIVE: accepted a-proposal-1
POSITIVE: mission=m-invoice-17 | agents=2 | recorded_spend=0.04 | open_risks=none | receipts=1
NEGATIVE-A: blocked g-executor: authority widens by ['send_refund']
NEGATIVE-B: blocked a-proposal-unsafe: unresolved risk blocks propose_refund: ['r-identity-conflict']
Open the complete runnable Python artefact

The file assumes trustworthy mission identifiers and in-process atomicity. A distributed implementation needs durable event storage, idempotency, concurrency control, authenticated event producers and privacy-aware evidence references.

#!/usr/bin/env python3
"""Minimal autonomy-ledger reference implementation.

The example uses only Python's standard library and synthetic data. It checks
five team-level invariants:

1. delegated authority can only narrow;
2. every grant is bound to one mission and purpose;
3. evidence-gated actions cite registered evidence;
4. committed spend cannot exceed the delegated budget;
5. an unresolved blocking risk prevents the affected action.

Run:
    python autonomy_ledger.py
"""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from decimal import Decimal
from typing import Dict, FrozenSet, Iterable, List, Optional, Set


class LedgerViolation(ValueError):
    """Raised when a ledger invariant would be broken."""


@dataclass(frozen=True)
class Grant:
    grant_id: str
    mission_id: str
    agent_id: str
    purpose: str
    actions: FrozenSet[str]
    budget: Decimal
    parent_grant_id: Optional[str] = None
    expires_at: Optional[datetime] = None
    evidence_required_for: FrozenSet[str] = frozenset()


@dataclass(frozen=True)
class Evidence:
    evidence_id: str
    mission_id: str
    source: str
    claim: str
    observed_at: datetime


@dataclass
class Risk:
    risk_id: str
    mission_id: str
    summary: str
    blocks_actions: FrozenSet[str]
    owner: str
    status: str = "OPEN"  # OPEN, ACCEPTED, MITIGATED, TRANSFERRED


@dataclass(frozen=True)
class ActionReceipt:
    action_id: str
    mission_id: str
    agent_id: str
    action: str
    cost: Decimal
    evidence_ids: FrozenSet[str]
    status: str  # PROPOSED, VERIFIED_SUCCESS, VERIFIED_FAILURE, UNKNOWN_OUTCOME


@dataclass
class AutonomyLedger:
    grants: Dict[str, Grant] = field(default_factory=dict)
    evidence: Dict[str, Evidence] = field(default_factory=dict)
    risks: Dict[str, Risk] = field(default_factory=dict)
    receipts: List[ActionReceipt] = field(default_factory=list)
    spend_by_grant: Dict[str, Decimal] = field(default_factory=dict)

    def add_grant(self, grant: Grant) -> None:
        if not grant.purpose.strip():
            raise LedgerViolation(f"{grant.grant_id}: purpose is required")
        if grant.budget < 0:
            raise LedgerViolation(f"{grant.grant_id}: budget cannot be negative")
        if grant.expires_at and grant.expires_at <= datetime.now(timezone.utc):
            raise LedgerViolation(f"{grant.grant_id}: grant is already expired")

        if grant.parent_grant_id:
            parent = self.grants.get(grant.parent_grant_id)
            if parent is None:
                raise LedgerViolation(
                    f"{grant.grant_id}: parent grant {grant.parent_grant_id} is missing"
                )
            if grant.mission_id != parent.mission_id:
                raise LedgerViolation(
                    f"{grant.grant_id}: child mission differs from parent mission"
                )
            widened = grant.actions - parent.actions
            if widened:
                raise LedgerViolation(
                    f"{grant.grant_id}: authority widens by {sorted(widened)}"
                )
            if grant.budget > parent.budget:
                raise LedgerViolation(
                    f"{grant.grant_id}: child budget exceeds parent budget"
                )

        self.grants[grant.grant_id] = grant
        self.spend_by_grant.setdefault(grant.grant_id, Decimal("0"))

    def register_evidence(self, item: Evidence) -> None:
        self.evidence[item.evidence_id] = item

    def open_risk(self, risk: Risk) -> None:
        self.risks[risk.risk_id] = risk

    def change_risk_status(self, risk_id: str, status: str) -> None:
        allowed = {"OPEN", "ACCEPTED", "MITIGATED", "TRANSFERRED"}
        if status not in allowed:
            raise LedgerViolation(f"{risk_id}: unsupported risk status {status}")
        self.risks[risk_id].status = status

    def request_action(
        self,
        *,
        action_id: str,
        grant_id: str,
        action: str,
        cost: Decimal,
        evidence_ids: Iterable[str],
        status: str = "PROPOSED",
    ) -> ActionReceipt:
        grant = self.grants.get(grant_id)
        if grant is None:
            raise LedgerViolation(f"{action_id}: unknown grant {grant_id}")
        if grant.expires_at and grant.expires_at <= datetime.now(timezone.utc):
            raise LedgerViolation(f"{action_id}: grant {grant_id} has expired")
        if action not in grant.actions:
            raise LedgerViolation(
                f"{action_id}: action {action!r} is outside grant {grant_id}"
            )
        if cost < 0:
            raise LedgerViolation(f"{action_id}: cost cannot be negative")

        evidence_set: Set[str] = set(evidence_ids)
        missing = evidence_set - self.evidence.keys()
        if missing:
            raise LedgerViolation(
                f"{action_id}: unknown evidence {sorted(missing)}"
            )
        wrong_mission = {
            evidence_id
            for evidence_id in evidence_set
            if self.evidence[evidence_id].mission_id != grant.mission_id
        }
        if wrong_mission:
            raise LedgerViolation(
                f"{action_id}: evidence belongs to another mission: {sorted(wrong_mission)}"
            )
        if action in grant.evidence_required_for and not evidence_set:
            raise LedgerViolation(f"{action_id}: evidence is required for {action}")

        blocking = [
            risk.risk_id
            for risk in self.risks.values()
            if risk.mission_id == grant.mission_id
            and risk.status == "OPEN"
            and action in risk.blocks_actions
        ]
        if blocking:
            raise LedgerViolation(
                f"{action_id}: unresolved risk blocks {action}: {sorted(blocking)}"
            )

        new_spend = self.spend_by_grant[grant_id] + cost
        if new_spend > grant.budget:
            raise LedgerViolation(
                f"{action_id}: budget exceeded ({new_spend} > {grant.budget})"
            )

        receipt = ActionReceipt(
            action_id=action_id,
            mission_id=grant.mission_id,
            agent_id=grant.agent_id,
            action=action,
            cost=cost,
            evidence_ids=frozenset(evidence_set),
            status=status,
        )
        self.receipts.append(receipt)
        self.spend_by_grant[grant_id] = new_spend
        return receipt

    def team_view(self, mission_id: str) -> str:
        mission_grants = [g for g in self.grants.values() if g.mission_id == mission_id]
        open_risks = [
            r for r in self.risks.values() if r.mission_id == mission_id and r.status == "OPEN"
        ]
        spent = sum(
            (self.spend_by_grant[g.grant_id] for g in mission_grants),
            Decimal("0"),
        )
        lines = [
            f"mission={mission_id}",
            f"agents={len(mission_grants)}",
            f"recorded_spend={spent}",
            f"open_risks={','.join(r.risk_id for r in open_risks) or 'none'}",
            f"receipts={len([r for r in self.receipts if r.mission_id == mission_id])}",
        ]
        return " | ".join(lines)


def utc_now() -> datetime:
    return datetime.now(timezone.utc)


def positive_case() -> None:
    ledger = AutonomyLedger()
    ledger.add_grant(
        Grant(
            grant_id="g-root",
            mission_id="m-invoice-17",
            agent_id="orchestrator",
            purpose="Resolve one synthetic duplicate-invoice exception",
            actions=frozenset({"read_invoice", "compare_order", "propose_credit"}),
            budget=Decimal("0.30"),
            evidence_required_for=frozenset({"propose_credit"}),
        )
    )
    ledger.add_grant(
        Grant(
            grant_id="g-analyst",
            mission_id="m-invoice-17",
            agent_id="reconciliation-agent",
            purpose="Compare the invoice with its purchase order",
            actions=frozenset({"read_invoice", "compare_order", "propose_credit"}),
            budget=Decimal("0.20"),
            parent_grant_id="g-root",
            evidence_required_for=frozenset({"propose_credit"}),
        )
    )
    ledger.register_evidence(
        Evidence(
            evidence_id="e-po-match",
            mission_id="m-invoice-17",
            source="synthetic purchase-order table",
            claim="Invoice INV-17 duplicates line 4 of PO-88",
            observed_at=utc_now(),
        )
    )
    receipt = ledger.request_action(
        action_id="a-proposal-1",
        grant_id="g-analyst",
        action="propose_credit",
        cost=Decimal("0.04"),
        evidence_ids={"e-po-match"},
    )
    print("POSITIVE: accepted", receipt.action_id)
    print("POSITIVE:", ledger.team_view("m-invoice-17"))


def negative_cases() -> None:
    ledger = AutonomyLedger()
    ledger.add_grant(
        Grant(
            grant_id="g-root",
            mission_id="m-refund-9",
            agent_id="orchestrator",
            purpose="Review one synthetic refund request",
            actions=frozenset({"read_case", "propose_refund"}),
            budget=Decimal("0.10"),
        )
    )

    try:
        ledger.add_grant(
            Grant(
                grant_id="g-executor",
                mission_id="m-refund-9",
                agent_id="executor-agent",
                purpose="Send a refund without widening authority",
                actions=frozenset({"send_refund"}),
                budget=Decimal("0.05"),
                parent_grant_id="g-root",
            )
        )
    except LedgerViolation as exc:
        print("NEGATIVE-A: blocked", exc)

    ledger.add_grant(
        Grant(
            grant_id="g-proposer",
            mission_id="m-refund-9",
            agent_id="proposal-agent",
            purpose="Propose a refund for human approval",
            actions=frozenset({"read_case", "propose_refund"}),
            budget=Decimal("0.05"),
            parent_grant_id="g-root",
        )
    )
    ledger.open_risk(
        Risk(
            risk_id="r-identity-conflict",
            mission_id="m-refund-9",
            summary="Case identity conflicts with the payment record",
            blocks_actions=frozenset({"propose_refund"}),
            owner="operations-review",
        )
    )
    try:
        ledger.request_action(
            action_id="a-proposal-unsafe",
            grant_id="g-proposer",
            action="propose_refund",
            cost=Decimal("0.02"),
            evidence_ids=set(),
        )
    except LedgerViolation as exc:
        print("NEGATIVE-B: blocked", exc)


if __name__ == "__main__":
    positive_case()
    negative_cases()

Where the ledger sits

The ledger should not live inside a model prompt. The orchestrator may propose grants and write task events, but a deterministic authority service validates them. The policy decision point computes effective authority from identity, parent grant, resource policy and mission conditions. Tool gateways enforce the resulting decision. Evidence services register claims, provenance and supersession. Cost meters reserve and settle spend. Outcome observers create effect receipts from the target system.

NIST SP 800-207 frames zero trust around resource-focused, explicit access decisions, while NIST SP 800-53 supplies control families for access, audit, assessment and monitoring.[3][4] The ledger should reuse those enforcement and audit mechanisms rather than become a parallel identity or policy engine.

A practical write path is:

  1. The orchestrator submits a proposed grant with mission, purpose, parent grant, requested actions, resource scope, budget and expiry.
  2. The authority service authenticates the actor chain, evaluates policy and attenuates the request to the effective grant.
  3. The ledger appends the grant event and returns a signed grant identifier or token reference.
  4. Each evidence, risk, cost, action and outcome event references that grant and the causal event that justified it.
  5. Before a consequential action, the tool gateway evaluates the current consistent snapshot and emits a decision receipt.
  6. After execution, an independent observer records the effect receipt or an explicit unknown outcome.

Unknown outcome must be a first-class state. A network timeout after an action request does not justify retrying blindly. The action may have succeeded. The ledger marks the effect unknown, blocks duplicate execution under the same idempotency key and starts readback or reconciliation. If the operation supports compensation, the eventual receipt records that separately.

One record, several disciplined views

The same ledger should not expose the same detail to everyone. An operator needs current blockers, remaining budget and the next permitted transition. A policy engineer needs the parent grant, policy decision and failed condition. A business owner needs purpose, consequence ceiling, human decision rights and unresolved risk. An incident responder needs causal events, retries, effect receipts and the exact version in force. An auditor needs stable references and evidence that the readable statement reconciles with enforcement.

These are projections over one typed record, not separately authored summaries. Access to each projection should follow data classification and purpose. Raw customer evidence may remain in its source system while the ledger stores a reference, hash, sensitivity class and claim identifier. Cost reviewers may see amounts without sensitive case content. Business reviewers may see consequence in plain language without infrastructure secrets. A projection can redact detail, but it must not change the underlying authority or risk state.

This design also limits dashboard theatre. A view may show green when every invariant for its scope holds, but it cannot declare the mission safe. A green authority view means no known grant violation. A green evidence view means required references are present and applicable. A green outcome view means effects are verified. Keeping these meanings separate prevents one healthy dimension from laundering another that remains unresolved.

Failure injection should be the acceptance test

A field-complete schema is not evidence that the mechanism works. The release gate should inject failures that make the conventional records disagree and ask whether the ledger blocks or exposes the invalid team state.

Figure 9. Failure surface and required observable response
Injected faultLocal appearanceLedger invariantRequired response
Child adds a write actionValid tool call and identityAuthority attenuationReject grant before task starts
Blocking risk omitted from summaryReadable handoff textRisk non-erasureDownstream action remains blocked
Evidence is superseded mid-runCached claim still presentEvidence continuityReopen dependent claim or escalate
Concurrent branches oversubscribe budgetEach branch below local limitBudget conservationAtomic reservation denies excess branch
Tool times out after acceptanceError without effect statusOutcome closureMark unknown; read back before retry
Emergency scope has no expiryIncident resolvedPurpose and validity bindingAutomatic revocation or release block
Synthetic failure-injection protocol. Pass means the invalid state is prevented or made explicit before consequential continuation, not merely discoverable in a later log review.

The strongest test varies one causal feature at a time. Run the same mission with and without risk-state propagation. Run the same delegation with and without action attenuation. Run the same concurrent branches with a shared reservation counter and with independent counters. Measure false blocks, missed blocks, reconstruction time, added latency and operator comprehension. The ledger has earned its complexity only if it changes those outcomes.

Open hypothesis

A team-level autonomy ledger will reduce post-incident attribution time and prevent a class of cross-agent authority, risk and budget failures that component logs miss. This claim needs controlled evaluation against a composed baseline of policy-as-code, distributed tracing, provenance, cost telemetry and incident records.

The architecture review instrument

  1. Mission: Is every active grant bound to one named purpose, case or task, with an owner and expiry?
  2. Identity: Can the system distinguish the requesting human or service, the proposing agent and the executing workload?
  3. Authority: Can a child prove that every action, resource, amount, audience and duration is no wider than its parent and policy?
  4. Evidence: Does every consequential proposal cite applicable evidence, and can supersession reopen dependent work?
  5. Cost: Are model, data, tool and human-review costs reserved and settled against a shared mission ceiling?
  6. Risk: Can an open blocker survive summarisation, handoff, retry, replanning and agent replacement?
  7. Outcome: Does the system distinguish requested, accepted, verified success, verified failure, compensated and unknown outcome?
  8. Negative control: Which failure does the ledger catch that the existing policy, trace and audit stack does not?

What the ledger cannot guarantee

A perfectly maintained ledger can faithfully enforce a bad policy. It can preserve false evidence. It can show that an authorised person accepted a risk without establishing that the acceptance was wise. It can record a model proposal without making the proposal correct. It can be undermined by compromised event producers unless events are authenticated and independently reconciled. It can also expose sensitive purpose, evidence and risk information if access to the ledger is too broad.

There is a scale cost. High-volume agent estates may emit millions of events. Retaining full prompts or documents would be expensive and unsafe, so the ledger should store references, hashes, classifications and concise typed facts, with content held in governed source systems. It also needs retention and deletion rules that distinguish audit obligations from unnecessary personal-data persistence.

The autonomy ledger is not a claim that the team is safe or correct. It is a claim that the team’s delegated purpose, effective authority, evidential basis, expenditure, unresolved risk and observed effect can be made inspectable, enforceable and replayable at the moments that matter.

Change the review from “what can each agent do?” to “what may this team still cause?”

Agent reviews often stop at a role catalogue, tool allowlist and architecture diagram. Those artefacts describe potential components. They do not show the current mission state produced when several components delegate, spend, inherit evidence, open risks and act.

The changed architecture decision is specific. When authority, evidence, cost or risk crosses agent boundaries dynamically, introduce a mission-scoped autonomy ledger backed by deterministic invariant checks and effect receipts. Compile it from identity, policy, provenance, trace, cost and risk sources. Do not maintain it as a separate slide. Do not infer its state from model prose. Do not deploy it where a fixed workflow and existing controls already answer the same questions.

The changed evaluation is equally specific: inject authority widening, risk loss, evidence supersession, budget races and unknown outcomes. Compare the ledger with the conventional baseline. Keep the mechanism only where it blocks an invalid continuation or reconstructs a defensible decision state that the baseline cannot.

A team earns bounded autonomy one delegation at a time. The ledger makes those delegations visible while they still have the power to change what happens next.

The evidence conversationChart · sequence
sequenceDiagram
  participant Q as Question
  participant M as Mechanism
  participant E as Evidence
  participant D as Decision
  Q->>M: Eight green boxes and one missing caveat
  M->>E: Why the existing records do not add up by themselves
  E-->>M: compare rival explanations
  E->>D: Source ledger
  D-->>Q: revise scope or act
Question, mechanism, evidence and decision exchange the burdens developed in The Autonomy Ledger for Agent Teams. Reading use: follow the relation, then test it against the surrounding evidence and limits.

Source ledger

  1. Official: NIST, AI Risk Management Framework. Used for the govern, map, measure and manage framing and ongoing role clarity.
  2. Official: NIST, Generative Artificial Intelligence Profile. Used as the current companion risk profile for generative systems.
  3. Official: NIST SP 800-207, Zero Trust Architecture. Used for explicit, resource-focused access decisions.
  4. Official: NIST SP 800-53 Rev. 5, Security and Privacy Controls for Information Systems and Organizations. Used for access, audit, assessment and monitoring control families.
  5. Standard: W3C, PROV-DM: The PROV Data Model. Used for provenance relationships among entities, activities and agents.
  6. Standard: W3C, Trace Context. Used for cross-system trace identity and parentage.
  7. Official specification: OpenTelemetry, Context propagation. Used for correlating telemetry across execution boundaries.
  8. Standard: IETF, RFC 8693: OAuth 2.0 Token Exchange. Used for subject and actor semantics in delegation.
  9. Official specification: SPIFFE, SPIFFE concepts. Used for workload identity and verifiable identity documents.
  10. Primary research: Pang et al., Zanzibar: Google’s Consistent, Global Authorization System. Used for relationship-based authorisation and consistency.
  11. Primary research: Birgisson et al., Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud. Used for attenuated, contextual delegation.
  12. Primary research: Chandy and Lamport, Distributed Snapshots: Determining Global States of Distributed Systems. Used for the consistent-cut analogy.
  13. Primary research: Lamport, Time, Clocks, and the Ordering of Events in a Distributed System. Used for causal ordering.
  14. Primary research: Garcia-Molina and Salem, Sagas. Used for long-running work and compensation.
  15. Primary research: Kapoor et al., AI Agents That Matter. Used for cost-aware agent evaluation and baseline discipline.
  16. Primary research: Cemri et al., Why Do Multi-Agent LLM Systems Fail?. Used for the coordination-failure taxonomy.
  17. Primary research: Zhang et al., Which Agent Causes Task Failures and When?. Used for the difficulty of retrospective failure attribution.
  18. Security reference: OWASP GenAI Security Project, Top 10 for Agentic Applications. Used as a current practitioner threat reference for tool misuse, identity and privilege abuse, cascading failure and inter-agent risk.