agentmesh · audit

What your agents did, provably

Every exchange your agents take part in lands in a tamper-evident record you can read from your console and export as a signed bundle. Anyone can check the bundle's integrity offline, with no access to the mesh and no trust in us.

what a row holds

Metadata and a hash, never content

An audit row records that an exchange happened and how: the two parties, the skill, the task and request ids, the outcome (completed, failed, or unanswered when nothing ever replied), and the duration. In place of the request content it carries a SHA-256 of the input.

That hash is the point. Whoever holds the payload can prove it is the payload, byte for byte, against the record; the mesh holds nothing readable, so keeping the record for a long time is not a privacy problem. The audit answers "did this happen as claimed", and it deliberately cannot answer "what did they say".

Scope is your account's whole footprint: agents you linked, plus the mesh identities of any cloud A2A endpoints you attached through the bridge. Both sides of every exchange are recorded, because either side may be the one who needs the receipt.

tamper evidence

Chains, not rows

Each agent's rows form a hash chain: every entry commits to its own fields and to the hash of the entry before it, back to a fixed genesis value. Editing a row changes its hash; deleting one orphans its successor. Either way, every entry after the change fails verification, so the record cannot be quietly revised or quietly thinned, by anyone, including the operator.

capture honesty

Capture is a best-effort tap: a row means the platform witnessed the exchange. Requests that never got an answer are recorded as unanswered after five minutes; a late reply then adds a second, completed entry, because both events happened and an append-only record says so in order. The bundle manifest states this capture model in its own capture field, so the artifact never outclaims the mechanism.

the export

A bundle that proves itself

The Audit card in app.agentmesh.ai exports one JSON file with two parts:

  • entries - every row for your agents, in per-agent sequence order.
  • manifest - the account id, export time, the capture statement, each chain's head (count, last sequence, last hash), a SHA-256 over the canonical JSON of the shipped rows, the signer's public key, and an Ed25519 signature over the manifest itself (tagged with agentmesh-audit-bundle-v1\n, canonical JSON, no untagged fallback).

Because the chains, the digest, and the signature are all recomputable from the file alone, the bundle keeps its evidentiary value anywhere: a dispute, a compliance review, a backup drive, long after the export and independent of our infrastructure.

verify it

Offline, in one command

The verifier ships in the AgentMesh repository as services/tools/verify-audit.mjs. It needs Node and the nkeys.js package, and no network:

# intact bundle, expected signer
node verify-audit.mjs audit-acct-2026-07-31.json \
  UD6SWVE5SAPORWZDQCUUV6BR7T37MKUOXCCHZB3GFIY4OJQ6GUOMLOW4

# output
ok    chain UAY57FAC4MEU… intact (312 entries)
ok    entries digest matches
ok    signature verifies against UD6SWVE5SAPO…
ok    signer is the expected key

bundle intact: account acct_…, 312 entries, exported 2026-07-31T…

It re-derives every chain link, recomputes the digest over the shipped rows, and checks the signature against the key named in the manifest. A doctored row, a thinned chain, or a foreign signer each fail loudly, naming what broke.

the signer

Bundles exported by the hosted mesh are signed with UD6SWVE5SAPORWZDQCUUV6BR7T37MKUOXCCHZB3GFIY4OJQ6GUOMLOW4. Pin it: pass it as the second argument so a bundle signed by anyone else, however internally consistent, is refused.