Swarm Protocol
Look up the bundle a delegated hop presents, the order a verifier checks it in, and the graph rules that reject it whole.
On this page
When one agent delegates to another, the hop carries a bundle of signed records: the task graph, the hop’s continuation token and witness chain, and the route, budget, revocation, and terminal records they name. A verifier accepts the bundle whole or refuses it whole.
The verifier checks those relationships against caller-pinned issuer keys, so anyone holding the bundle can inspect who authorized each hop, how authority narrowed, where a task may run, and how its budget is accounted for. Swarm Authority describes the operating model around it.
Synopsis
A hop presents one bundle, and verify_swarm_authority_bundle accepts it whole or rejects it.
pub struct SwarmAuthorityBundle {
pub task_graph: SwarmTaskGraph,
pub continuation_tokens: Vec<SwarmContinuationToken>,
pub witness_chains: Vec<SwarmDelegationWitnessChain>,
pub join_receipts: Vec<SwarmJoinReceipt>,
pub route_plan_receipts: Vec<SwarmRoutePlanReceipt>,
pub budget_pool: SwarmBudgetPool,
pub revocation_epoch: SwarmRevocationEpoch,
#[serde(default)]
pub terminal_receipts: Vec<SwarmTerminalGraphReceipt>,
pub now_unix_ms: u64,
}The bundle is chio-swarm/v1. Validate each artifact against the schema identifier it carries; a change to the shape or meaning of any required field mints a new version identifier.
Try budget pool, deny-private-network, or continuation_fresh. Each entry has its own link.
Bundle artifacts
a1task-child-aa2task-child-ba3task-child-c
The graph indexes the rest of the bundle
task-child-a names continuation-child-a, route-child-a, and budget-child-a, and witness-child-a covers its edge. The graph names budget-pool-swarm-valid and revocation-epoch-swarm-valid. The verifier accepts the bundle whole or refuses it, with no partial report. Swarm Protocol.
The drawing is the signed valid-recursive-delegation fixture. task-root delegates to task-child-a, task-child-b, and task-child-c under a signed maxDepth of 2 and maxFanout of 3, and the results meet at join-child-results, whose next task is task-root. task-child-a names continuation-child-a, route-child-a, and budget-child-a, and witness-child-a covers its edge. The graph names budget-pool-swarm-valid and revocation-epoch-swarm-valid.
The pool holds 10,000 usd_minor units, with 2,500 allocated to each child. The terminal graph receipt lists all four tasks, the one join, and the three route plans, and its rollup of 7,500 active units equals the allocations summed by dimension.
The registry tracks 9 schema files under chio-swarm/v1. Every artifact has a closed field shape. Signatures authenticate the graph and the signed delegation, route, revocation, and terminal records. The budget pool is unsigned and is checked through its graph and allocation bindings, and the verifier report is derived output. Each entry links to the page that specifies its fields.
Chio Swarm Task Graph
The signed DAG the whole bundle belongs to, carrying the structural ceilings a verifier enforces across every task and every hop.
Fields and behavior: Task graphs.
Chio Swarm Continuation Token
chio.swarm.continuation-token.v1
That one hop was authorized, binding the child task to its graph digest, its single parent context, its route, its allocation, and the revocation epoch it was checked against.
Fields and behavior: Continuations.
Chio Swarm Delegation Witness Chain
chio.swarm.delegation-witness-chain.v1
That authority only ever narrowed from parent to child across the hop, with a checked scope subset proof and a pinned signature at every step.
Fields and behavior: Witness chains.
Chio Swarm Join Receipt
That a fan-in fired against exactly the parent set the graph declared for it, under the predicate that fan-in carries.
Fields and behavior: Terminal receipts.
Chio Swarm Route Plan Receipt
chio.swarm.route-plan-receipt.v1
That egress for one task was pinned to a chosen route, bridge, and target before dispatch, under the single egress constraint the protocol defines.
Fields and behavior: Route plans.
Chio Swarm Budget Pool
An unsigned pool checked through the signed graph and its continuation allocations. It records each task’s spending ceiling and accounting rollup; allocations must balance within the pool total. A market purchase names the pool by its projection digest rather than by the pool JSON.
Fields and behavior: Budgets.
Chio Swarm Revocation Epoch
chio.swarm.revocation-epoch.v1
The signed revocation epoch the bundle was checked against. Its content digest and pinned-key signature make changes detectable.
Fields and behavior: Revocation epochs.
Chio Swarm Terminal Graph Receipt
chio.swarm.terminal-graph-receipt.v1
That the graph closed over exactly the task set, the fan-in set, and the route set it declared, with a final spend rollup that reconciles against the pool.
Fields and behavior: Terminal receipts.
Chio Swarm Authority Verifier Report
chio.swarm.authority-verifier-report.v1
The verifier’s derived output: an accepted verdict, one entry per continuation-bearing task, and the claim ids for the checks that ran. The report does not carry its own signature.
Fields and behavior: Swarm authority.
An accepted report carries claim ids drawn from a closed set of 8: claim.swarm.task_graph_bound, claim.swarm.continuation_fresh, claim.swarm.attenuation_witness_chain_bound, claim.swarm.route_plan_bound, claim.swarm.join_receipt_bound, claim.swarm.budget_pool_bound, claim.swarm.revocation_epoch_bound, and claim.swarm.terminal_graph_receipt_bound. Every acceptance carries all of them except claim.swarm.join_receipt_bound, which appears only when the graph has a fan-in and the bundle carries its fan-in receipt.
Verification order
A verifier runs these steps in this order. Any failing step rejects the bundle immediately and produces no partial report.
- Reject if the trusted witness issuer key set is empty, before any artifact is read.
- Validate task-graph shape, then its signature.
- Require at least one continuation token and one witness chain.
- Validate and index route plan receipts, then join receipts, then the budget pool, then the revocation epoch, in that order.
- Validate terminal graph receipts against the task, route, fan-in, and budget indexes.
- Validate continuation tokens against the task graph canonical sha256, witness chains, routes, budget allocations, and the revocation epoch.
- Validate that witness chains cover every task-graph hop exactly once, with continuous scope hashes and capability digests hop to hop.
- Assemble the verifier report: one hop report per continuation-bearing task, plus the claim ids for the checks that ran.
Step 4 binds its artifacts in two ways. Route plan receipts, join receipts, and the revocation epoch each carry an issuer and a signature, and a verifier checks the signature against a pinned key. The budget pool carries neither. It binds to the bundle through the signed graph, which names the graph the pool must belong to and the pool identifier itself, and through the allocations the continuation tokens draw on, so its trust comes from those bindings alone.
Invariants
A bundle that conforms to its schemas still has to pass the structural rules below. Each is checked in code, and a bundle that breaks any one of them is rejected whole.
- Single root. A task graph MUST contain exactly one task at root depth, that task MUST have no parent, and every task below root depth MUST name one. Checked by
validate_roots. - Acyclic. The graph MUST be acyclic. A verifier walks it depth first and rejects on re-entry to a task already on the current path. Checked by
validate_acyclicandvisit_task. - Exact depth arithmetic. Every hop target MUST sit at exactly the source depth plus one. Depth overflow MUST reject instead of wrapping. Checked by
validate_edge_depths, and stated inspec/PROTOCOL.mdsection 6.4.2. - Signed ceilings, enforced graph-wide. The depth ceiling and the fan-out ceiling MUST sit inside the signed body, so widening either one requires a fresh signature from a pinned key. A verifier MUST enforce both across the whole graph: any task deeper than the depth ceiling rejects the bundle, and so does any task with more outgoing hops than the fan-out ceiling. The fan-out ceiling MUST be positive. Checked by
validate_graph_limits. - Exactly one parent context per hop. Each continuation token MUST name either a direct parent task or a fan-in receipt. Naming both rejects. Naming neither rejects. Checked by
validate_continuation_parent. - Witness coverage exactly once per hop. Every hop in the graph MUST be covered by exactly one witness chain. A missing chain rejects and a duplicate chain rejects. Every chain MUST terminate on a hop the graph declares. Checked by
validate_witness_chains. - Budget balance and budget ceiling. Each allocation’s own five-way unit rollup MUST equal its ceiling exactly, and arithmetic overflow MUST reject instead of clamping. The allocation ceilings summed MUST NOT exceed the pool total. A terminal receipt’s per-dimension rollup MUST equal the sum over allocations exactly, and its total MUST NOT exceed the pool total. Checked by
validate_budget_allocation_units,validate_budget_pool, andvalidate_terminal_budget_rollups. A cognition-marketpool_sha256MUST hash the RFC 8785 canonical bytes of thechio.swarm.budget-pool-digest-projection.v1preimage, never the wire serialization of the pool. That preimage carries the projection identifier, the source pool schema, the pool id, graph id, and currency, and the allocations in their original order; the pool total and every allocation unit field MUST be the shortest unsigned base-10 string, with0as the only representation carrying a leading zero. Built byswarm_budget_pool_digest_projection_bytesand hashed byswarm_budget_pool_sha256. - Closed egress constraint set. A route plan receipt MUST carry a non-empty, duplicate-free constraint list, and every entry MUST be
deny-private-network. That is the whole set: any other string rejects the bundle as an unsupported constraint, and the schemaenumlists the same one value. Checked byvalidate_route_plan_egress_constraints. Route plans carries the rest of the receipt.
Example runs
The agent-os example mints a three-task incident graph and its supporting records, signs each signed artifact family, verifies the bundle, and then refuses four tampered copies of it. Every key and artifact is minted in process, so the run touches no store and no trust anchor on disk.
chio new agent-os --example agent-os && cd agent-os$ cargo run --locked --example agent_oschio swarm authority · one task graph, verified before any child runs task graph swarm-incident-42 orchestrator depth 0 scope 6ab7b09faf2a route - budget holds the pool researcher depth 1 scope c5a04ca641ec route route-researcher budget 2500 of 10000 units writer depth 1 scope c5a04ca641ec route route-writer budget 2500 of 10000 units join researcher + writer -> orchestrator (all_success) verdict verified (3 tasks, 2 continuations, 1 joins, 2 routes) researcher continuation continuation-researcher witness witness-researcher (1 hop) writer continuation continuation-writer witness witness-writer (1 hop) claims claim.swarm.task_graph_bound, claim.swarm.continuation_fresh, claim.swarm.attenuation_witness_chain_bound, claim.swarm.route_plan_bound, claim.swarm.join_receipt_bound, claim.swarm.budget_pool_bound, claim.swarm.revocation_epoch_bound, claim.swarm.terminal_graph_receipt_bound then someone tries to add an edge from the writer back to the orchestrator rejected: swarm task graph cycle at task-orchestrator hide a hop by understating the writer's depth rejected: swarm task depth mismatch: task-researcher -> task-writer allocate 5,000 units out of a 100 unit pool rejected: swarm budget allocations exceed pool total run the researcher after its task was revoked rejected: swarm task is revoked: task-researcher
The same refusals replay through the CLI on bundles you generate. chio proof fixture generate writes the valid bundle, every negative bundle of its family, and a trust file that pins only the fixture keys those bundles need:
chio proof fixture generate recursive-runtime-swarm --with-negatives --out ./swarmgenerated recursive-runtime-swarm ./swarm trust ./swarm/trust.toml (fixture profile, 4 roles) negatives 11 under ./swarm/negatives
The proof doctor loads the valid bundle and the negative bundles beside it, and reports whether each was rejected for the reason its fixture pins, which checks more than rejection alone.
chio proof doctor --scenario swarm-authority --in ./swarm --trust ./swarm/trust.tomlchio proof doctor swarm-authority [passed] swarm_recursive_delegation: transaction passport verified [passed] swarm_stale_continuation: transaction passport rejected [passed] swarm_budget_allocations_exceed_pool: transaction passport rejected [passed] swarm_graph_cycle: transaction passport rejected [passed] swarm_join_parent_set_mismatch: transaction passport rejected [passed] swarm_replayed_continuation_nonce: transaction passport rejected [passed] swarm_revoked_task: transaction passport rejected [passed] swarm_stale_route_plan: transaction passport rejected [passed] swarm_route_plan_mismatch: transaction passport rejected [passed] swarm_witness_child_scope_mismatch: transaction passport rejected trust ./swarm/trust.toml (fixture keys) verdict: passed
The refusals in that output are the verifier’s own sentences. Swarm denial codes indexes every one of them back to the check that produced it, and chio proof verify ./swarm/negatives/ --trust ./swarm/trust.toml --expect refuse replays the 11 signed negative bundles in one command.
Evidence and boundaries
One function decides admission. The runtime admission hook, the proof room, and the CLI proof path all call verify_swarm_authority_bundle, so the workspace holds one definition of acceptance. Acceptance is whole or absent: any failing check returns immediately, and the authority-verifier-report schema pins a single verdict value, so a partial report has no representation.
An empty trusted key set rejects the bundle before any artifact is read (require_trusted_witness_issuer_keys), and a bundle carrying no continuation token or no witness chain is refused, so a well formed graph with no delegation in it never verifies (require_signed_swarm_delegation_evidence). Each claim id is backed by signed negative fixtures, written under ./swarm/negatives/ by the generate step above:
| Claim id | Refused case | Negative fixture |
|---|---|---|
claim. | A back hop from a child to the root | graph-cycle/ |
claim. | A stale token, or a reused nonce | stale-, replayed- |
claim. | A child scope that differs from the signed scope | witness- |
claim. | A stale route plan, or an unsupported constraint | stale-, egress- |
claim. | A fan-in that omits a declared parent | join- |
claim. | Allocations that outrun the pool total | budget- |
claim. | A revoked task in the bundle | revoked-task/ |
Regression tests cover the same cases, including a revocation epoch that names a subject the bundle’s authority rests on and a terminal rollup that fails to reconcile against its allocations. Widening a ceiling and re-sealing every downstream token against the new graph digest still fails. 12 fixture scenarios ship, 11 of them negative; the randomized conformance test starts from the signed positive fixture, mutates it case by case, and asserts the rejection message each mutation is expected to produce.
- The spec is the contract.
spec/PROTOCOL.mdsection 6.4.2 states the same admission binding, the same two ceilings, and the same depth arithmetic as the code, and a third-party implementation is held to that text. - Schemas publish the shape. The 9 schemas are hash-pinned in
spec/schemas/MANIFEST.sha256and closed to unknown fields. Acceptance is decided by the verifier’s checks. - Refusals are sentences.
SwarmAuthorityErrorcarries two variants over free-form text. Swarm denial codes maps each sentence to the runtime code that replaces it. - Verification is the specified contract. Issuance is a separate contract; the crate’s minting and signing helpers serve fixtures, examples, and tests.
- Spend is bounded by the pool. The ceilings bound depth per task and outgoing hops per source, and leave the total task count open: a full tree at both ceilings is well formed and grows exponentially in the depth ceiling. The pool is the quantitative bound on spend.
Specification and implementation sources
The protocol is spec/PROTOCOL.md section 6.4.2, version 1.0, and the schemas under spec/schemas/chio-swarm/v1/ in the Chio repository. The keywords MUST, SHOULD, and MAY are normative.
- Verifier:
crates/kernel/chio-swarm-authority/src/verifier.rswithverifier/witness.rs(validate_witness_chains),verifier/util.rs, andverifier/budget_accounting.rs; the egress constraint check atverifier.rs:979, mirrored inspec/schemas/chio-swarm/v1/route-plan-receipt.schema.json:70. - Bundle types and the
CLAIM_SWARM_*constants:crates/kernel/chio-swarm-authority/src/types.rs. - Budget-pool digest projection:
crates/kernel/chio-swarm-authority/src/finding_pool.rs. - Error type:
crates/kernel/chio-swarm-authority/src/error.rs. Issuance scope:crates/kernel/chio-swarm-authority/ARCHITECTURE.md. - Callers:
crates/kernel/chio-runtime-core/src/admission_hook/swarm_authority.rsandcrates/products/chio-proof-room/src/source_verifier.rs. - Worked example:
crates/kernel/chio-swarm-authority/examples/agent_os.rs. - Regression tests:
swarm_authority_stage0_rejects_graph_cycle,swarm_authority_stage0_rejects_witness_child_scope_mismatch,swarm_authority_stage0_rejects_join_parent_set_mismatch,swarm_authority_stage0_rejects_budget_allocations_exceeding_pool,swarm_authority_stage0_rejects_terminal_budget_rollup_mismatch,swarm_authority_stage0_rejects_revoked_task,swarm_authority_stage0_rejects_revoked_authority_subject, andswarm_authority_stage0_rejects_task_graph_tampering_after_continuations_are_resealed. - Randomized conformance:
crates/tooling/chio-conformance/tests/r_t03_recursive_swarm_conformance.rs:132-138over thevalid-recursive-delegationfixture. Claim bindings:crates/core/chio-core-types/tests/claim_registry_integrity.rs.