Agent Action Capsule · explain
13 / 16 · From the September deck

Every capsule type the plugin seals

The Mesh-LLM capsules plugin (release v0.1.4) seals more than one kind of record. Here is each kind, one line each, with its status read from the plugin source at a fixed commit. One exchange alone accounts for six of them.

One exchange producing six capsules across two nodes Two Mesh-LLM nodes running the capsules plugin: requester R on the left, provider P on the right, each with its own chain of records. Stage 1: R sends a request and P answers; R seals record 1, its exchange half with role requested, and P seals record 2, its exchange half with role served; both carry digests, not text. Stage 2: P pads its log to a multiple of 32 entries and signs a checkpoint; neither is a capsule. Stage 3: with record push on, which is off by default, P sends R a bundle holding record 2, an inclusion proof and the checkpoint. Stage 4: R checks the bundle, keeps P's half in a separate held store, and seals record 3, a received-half citation that cites record 2 by digest. Stage 5: R seals record 4, an inclusion citation that cites the proof and the checkpoint. Stage 6: R pushes its own half the same way and P would seal records 5 and 6, the same two citations; in v0.1.4 a client node's key cannot be configured, so P sends a signed refusal instead, as the nightly two-node run checks. Stage 7: a summary line: six capsules for one exchange, three in each chain; checkpoints and padding are log entries, not capsules. Node R · requester capsules plugin · its own chain Node P · provider capsules plugin · its own chain request (mesh) answer 1 · exchange half (requested) request · response digests 2 · exchange half (served) request · response digests pad to 32, then sign a checkpoint log entries, not capsules record-push/1 (off by default) half 2 + inclusion proof + checkpoint follows 3 · received-half citation cites half 2 by digest 4 · inclusion citation cites the proof + checkpoint half 1, pushed the same way P needs R's key 5 · received-half citation cites half 1 by digest 6 · inclusion citation cites the proof + checkpoint v0.1.4: a client node's id is new each start, so P signs a refusal instead of 5 and 6 Six capsules for one exchange: three in each chain. Checkpoints and padding are signed log entries, not capsules.

1What it is

Most records the plugin seals are Agent Action Capsules, signed with the node's own plugin key and chained onto that node's previous record; checkpoints, padding and a signed refusal of a pushed record are other shapes, and a referee's verdict is held beside the chain rather than in it.

One exchange makes up to six of them: each side's own half, then, on each side, a citation of the other's half and a citation of the proof that the half is in the other's log.

The other kinds record things that happen around exchanges: a peer stopped, a verdict, a refusal, a payment, one stage of a split model, and the owner's own cleanup.

2Design choices

Chosen: cite, never copy: a received half stays in a separate held store, and the receiver's chain gets its own record citing that half by digest.
Rejected: appending the other node's record into this node's chain, or editing this node's own half to add the other side. (capsules crates/evidence-plugin/src/producer/capsule.rs, seal_citing_record)
Chosen: later evidence goes in a later record. The inclusion proof arrives as a second citation; the earlier one is never touched.
Rejected: rewriting the earlier citation once the proof is checked. (producer/capsule.rs, seal_inclusion_citing_record; draft-mih-scitt-agent-action-capsule-05)
Chosen: padding is a record in the store, and the log treats it as an ordinary leaf. Anything that counts or lists records skips it.
Rejected: changing the checkpointed log itself, or letting checkpoints show the exact number of records between them. (draft-mih-agent-evidence-layer-00, “What a Checkpoint Reveals”; capsule-emit 0.0.6 src/padding.rs)
Chosen: a stop-routing record names the peer only as sha256(salt ‖ peer id), with a salt that stays on the node.
Rejected: naming the peer in clear: records are answered to peers that ask for them, so it would tell everyone who was stopped. (producer/capsule.rs, peer_commitment)
Chosen: a referee's signed verdict is held beside the ledger and delivered as it is; each node's chain cites it in a record of its own.
Rejected: writing the verdict into any one node's chain. (producer/capsule.rs, seal_verdict_record)
Chosen: no single-record delete. The owner can delete stored text, rebuild the index or start a new history, and each cleanup is itself a sealed record.
Rejected: deleting a record, which rewrites the chain, and anyone holding a checkpoint would see it. (crates/evidence-plugin/src/owner_maintenance.rs)

3What it shows / what it does not

Shows

  • Which kinds of record a node can hold for one exchange, and in whose chain each one sits.
  • That each capsule in a node's chain was signed by that node's plugin key and links to the record before it.
  • For a citation: that the citing node held a copy of the other side's half that passed its checks, and, for an inclusion citation, a checked inclusion proof under the other side's signed checkpoint.
  • For each kind, its status in the plugin source at a named commit, with the reason where it does not run yet.

Does not show

  • That what a record claims is true. A record says what its signer observed or asserted.
  • The other side's half inside the citing node's chain: only its digest is there.
  • An exact record count from two checkpoints: padding blurs it to within the bucket.
  • A verdict, a refused verdict delivery or a stage record sealed on a stock mesh-llm release: none has run there yet (see Status).
  • That a missing settlement record means “unpaid”: it means no payment event was observed.

4Example

What a provider pushes for records 3 and 4 to cite: its served half, an inclusion proof and the covering checkpoint. This bundle was written by the plugin's own generator test as a cross-language fixture, so it has no live host's node ids (served_by_node_id: unknown). Trimmed: … marks where members are left out; every value shown is verbatim.

{
  "record_push_bundle": 1,
  "capsule": {
    "spec_version": "draft-mih-scitt-agent-action-capsule-05",
    …
    "capsule_id": "ddd8685c1b578b39c9163a5c748ac7148108663719227f7636b2a113a1dd34dc",
    …
    "action_type": "decide",
    …
    "developer": "capsule-emit-mesh/0.1.0",
    …
    "model_attestation": {
      …
      "compute_attestation": {
        "agent_input_digest": "6d139f1403cd84518768857efed6c375c0e3fe1af3f250cd3a5c59ea87a0323c",
        "agent_output_digest": "a8461110d26a1ceb91765128a3f8a648e86238810f4bdf27a330deb8681f9d87",
        …
        "epistemic_type": "producer_claim",
        "x-mesh-poc-v1": {
          …
          "serving_provenance": { "served_by_node_id": "unknown", …, "exchange_id": "e-1", …, "seq": 2, "prev_seq": 1, … },
          "role": "served",
          …
        },
        "store_nonce": "e372af496774c05c301d3185c83a4a98396b355ca87df2dfb07f8754def62dfe"
      }
    },
    "effect": {
      …
      "type": "inference_completion",
      …
      "request_digest": "6d139f1403cd84518768857efed6c375c0e3fe1af3f250cd3a5c59ea87a0323c",
      "response_digest": "a8461110d26a1ceb91765128a3f8a648e86238810f4bdf27a330deb8681f9d87",
      …
    },
    "assurance": { "attestation_mode": "self_attested", …, "ledger_mode": "chained" },
    …
    "chain": { "parent_capsule_id": "6f1165b4e8f487815ea9bae5674c61ebe50862efa903ba8b0733c227f5303a1e", "relation": "follows" },
    "signature": "d284584ca3…",
    "key_id": "9e4480104975505a70ec6fc913efff2884a93af380a657adf39babf91fbe1fe1"
  },
  "inclusion": {
    "leaf_index": 1,
    "proof": { "v": 1, "kind": "inclusion", "size": 3, "leaf_index": 1,
               "witness": ["8ec22eba289ccb94b3a7f9504ae4e648f91b4518bee10bb9b0da1e9a38d2af84"],
               "peaks_left": [], "peaks_right": [] }
  },
  "checkpoint": {
    "v": 1, "kind": "mmr_checkpoint", "log_id": "rust-node", "mmr_size": 3,
    "root": "f85629f081a79ba7b416e4ea5f1dec66c73bed90fb19e4c2b2af5e4df432f524",
    "prev_size": 0, "prev_root": "",
    "key_id": "9e4480104975505a70ec6fc913efff2884a93af380a657adf39babf91fbe1fe1",
    "timestamp": "2026-09-30T03:38:00.000Z",
    "signature": "802a4a60a953709b…"
  }
}
FieldTypeMeaning
record_push_bundleintegerBundle format version: one record plus the evidence the receiver checks it against.
capsule_idhexSHA-256 of the record's canonical (JCS) bytes, without its id, signature and key id. A received-half citation cites the half by this digest.
developerstringThe producer that sealed it: capsule-emit-mesh/ plus the plugin crate's version when the record was sealed. Records from v0.1.4 keep this prefix.
rolestringserved: this is the provider's half (record 2). The requester's half says requested.
agent_input/output_digesthexDigests of the request and the response; the text itself is not in the record.
effect.typestringinference_completion: the effect the record is about.
request/response_digesthexThe same two digests on the effect, where a receiver compares them with its own half.
served_by_node_idstringThe node that served. unknown here: a generator, not a host, produced this exchange.
store_noncehexA fresh 256-bit random value committed into capsule_id, so someone holding an inclusion proof cannot confirm a neighbouring record by guessing its content and recomputing its digest.
chainobjectThe previous record in this node's own chain, with the relation follows.
key_idhexThe plugin key that signed the record (and, here, the checkpoint).
inclusion.proofobjectAn inclusion proof for leaf 1 in a log of size 3. witness is the sibling hash on the path, not an outside witness.
checkpointobjectA signed checkpoint (mmr_checkpoint) of the sender's log: its size and root. Not a capsule.

Source: Mesh-LLM/capsules:vectors/record_push_bundle_rust.json @ b4e24453f572b2d9fe8f2cefbd0f35a5eb54b0ad (tag v0.1.4); provenance in vectors/SOURCES.md at the same commit.

5Status

Read on 2026-10-19 from Mesh-LLM/capsules v0.1.4 (b4e24453f572b2d9fe8f2cefbd0f35a5eb54b0ad). Unreleased main (efcada74026a2e18b9e62d77432888a31bbe9de4) seals the same set of kinds. Host releases checked against Mesh-LLM/mesh-llm tags up to v0.78.1 and main at 60697c61755b7280c22d3ab9d9bcf5b663e8ae3b.
live the code path runs on a stock mesh-llm release (0.78) with the settings shown; the evidence line says whether any check reads the record itself · off by default the operator turns it on · built, not live in the release, but no run on a stock host is recorded, or the host does not yet supply what it needs · not a capsule a log entry or message of another shape.

KindWhat it is forStatus today
Exchange halfWhat this node asked for (requested) or answered (served), by digest. live
Sealed for every exchange by default. Nightly run of two stock mesh-llm 0.78.0 nodes (.github/workflows/e2e.yml, src/two_node_e2e.rs); four paid exchanges between two nodes running this release (CHANGELOG.md 0.1.4).
Received-half citationI received the other side's half and it passed my checks; cites it by digest. liveoff by default
Sealed for each pushed half that passes the checks (src/record_push_bridge.rs). The nightly run turns record push on and checks that the requester holds each provider record and shows it as confirmed (two_node_e2e.rs, the_host_names_both_sides_and_the_requester_holds_the_providers_record); no check reads the citing record itself.
Inclusion citationThe other side's half is in their signed log; cites the proof and checkpoint. liveoff by default
Sealed when a pushed bundle's proof and checkpoint verify (record_push_bridge.rs, seal_inclusion_citing_record_for_push). The nightly run pushes bundles with checkpoints on; no check reads this record.
CheckpointSigns the log's size and root at a point in time. livenot a capsule
On by default: every 300 s or 100 records, and on demand when a record is pushed (capsule-emit 0.0.6 src/checkpoint.rs; src/checkpoint_cadence.rs). Sent to a witness only if the operator names one; none by default (INSTALL.md). No live-host check reads checkpoints.
PaddingHides how busy the node is between two checkpoints. livenot a capsule
On by default, to a multiple of 32 before each checkpoint; CAPSULES_CHECKPOINT_PAD_BUCKET=0 turns it off. A padding record carries only a nonce and is never counted or served as a record (capsule-emit 0.0.6 src/padding.rs; src/evidence_routes.rs). No live-host check reads padding.
Stop routingI stopped (or resumed) sending to a peer, and the rule and verdicts behind it. off by defaultbuilt, not live
The rule asks the host to block a peer, which mesh-llm 0.78 supports (#2142) if the operator sets allow_peer_blocks; but the rule counts only referee-signed verdicts, which have not run live (below) (src/routing_rule.rs). A block the operator makes is sealed only when the host calls the plugin's mesh_local_routing_choice, which no mesh-llm release or main at 60697c61755b7280c22d3ab9d9bcf5b663e8ae3b does (src/routing_choice_bridge.rs). The peer is named by salted digest only.
Verdict (each node's record)The referee's record of a verdict it issued, and each judged node's record of a verdict delivered to it. off by defaultbuilt, not live
Pairs exist only when a client marks two requests with x-mesh-twin-bracket, which mesh-llm 0.78 carries (#2144). The plugin's own notes: “A referee verdict on live hosts waits on 0.1.5; until then it is covered by tests only” (CHANGELOG.md 0.1.4).
RefusalA signed “no”: a pushed record this node would not hold, or a courier's record that a verdict's receiver refused it. livenot a capsule push refusal
built, not live refused verdict delivery
A push refusal goes back to the sender signed by the node's key; an unsigned line is also logged in rejected-record-pushes.jsonl (src/record_push_receive.rs). The nightly run checks that log: each push from the client node refused, with the reason signature_unverified (two_node_e2e.rs). A refused verdict delivery is a capsule in the courier's chain (src/adjudication_records.rs), waiting on verdicts above.
SettlementTies a payment event, and each side's settlement leg, to its exchange. built, not liveoff by default
Sealed on paid exchanges from the host's payment events, which ship in mesh-llm 0.78 (#2108, #2109, #2169); payments are the operator's choice. No recorded run shows a settlement record sealed: the 0.1.4 check of paid exchanges names only the exchange halves, and the nightly run has no payments (CHANGELOG.md 0.1.4; src/settlement_legs.rs). No record means no payment event observed, never “unpaid”.
Stage recordOne slice of a model split across peers, and the coordinator's record citing the slices. built, not live
The plugin listens for skippy.stage.v1 events (src/split_stage.rs, src/producer/stage.rs). No mesh-llm release emits them to plugins, nor does main at 60697c61755b7280c22d3ab9d9bcf5b663e8ae3b; README.md lists the host change as proposed.
Owner maintenanceCleanup the owner did on their own log: stored text deleted, index rebuilt, a history closed or started. built, not live
Sealed when the owner runs a cleanup from the Evidence page (src/owner_maintenance.rs). Never served to peers (docs/SHARING-POLICY.md). No live-host check names this record.
Referee-signed verdictThe ruling itself, signed with the referee's own key, held beside the ledger and cited by each chain. off by defaultbuilt, not live
In v0.1.4 the referee signs the verdict with its own key (src/referee/service.rs → seal_verdict_record). Tests also check a verdict signed by a reference referee (tests/fixtures/referee-verdict.json). Same 0.1.5 note as the verdict row.

All plugin paths are under Mesh-LLM/capsules:crates/evidence-plugin/ unless they start with docs/, .github/ or a top-level file, @ b4e24453f572b2d9fe8f2cefbd0f35a5eb54b0ad. capsule-emit 0.0.6 is the crates.io release v0.1.4 depends on.

6Specs