Skip to main content

arcaeon-ledger

Observability tools show you what your agent did. arcaeon-ledger lets you prove it.

Every record is hash-chained to the one before it. Edit a row, delete one, or reorder history, and every later link breaks — verify names the exact line. You own the record, and you can prove it wasn't altered. Zero dependencies, one JSONL file, two verbs.

pip install arcaeon-ledger      # then:  from arcaeon_ledger import Ledger
from arcaeon_ledger import Ledger

log = Ledger("agent.log.jsonl")
log.append({"tool": "web.search", "query": "weather in LA", "result_ok": True})
log.append({"tool": "payment", "amount": "49.00", "currency": "USD"})

log.verify()          # VerifyResult(ok=True, rows=2, chained=2, ...)

Tampering is caught, not hoped against:

# someone edits row 1's amount in the file by hand...
log.verify()          # VerifyResult(ok=False, first_break="line 1: chain mismatch")

CLI (wire it into CI or a pre-ship gate — a tampered log exits nonzero):

python -m arcaeon_ledger.cli append agent.log.jsonl '{"tool":"search","ok":true}'
python -m arcaeon_ledger.cli verify agent.log.jsonl        # exit 0 = intact, 1 = broken

Prove who acted, not just the order

A hash chain proves sequence integrity — it can't prove who wrote each entry or whether they were allowed to. Attach an authority block to bind the actor and their permission surface into the chained (tamper-evident) row:

from arcaeon_ledger import Ledger, authority

log = Ledger("agent.log.jsonl")
log.append(
    {"tool": "payment", "amount": "49.00"},
    authority=authority(
        "agent://billing-7",
        capability_version="v3",              # what they were allowed to do
        tool_schema={"name": "payment", "args": ["amount"]},  # hashed, not just named
        time_source="ntp",                    # trust surface of the clock
    ),
)

Now the audit question sharpens from "was this edited?" to "was this edited and was the writer authorized?" — editing the principal, capability, or schema hash breaks the chain like any other tamper. This composes tamper-evidence with permission-replay. (Shipped in response to community feedback on launch.)

Why this exists

The loudest unmet pain for agent builders in 2026 is the reliability/audit gap: an agent "completes" a task and the result is quietly wrong, and you can't reconstruct — or prove — what actually happened. Observability platforms trace runs; none give you a tamper-evident, portable, ownable record. Regulations (EU AI Act Art. 12, tamper-evident AI decision records) are starting to require exactly this. arcaeon-ledger is the smallest honest version: a cryptographically chained action log you drop in, own, and verify.

How the chain works

chain = sha256(prev_chain + canonical_json(row_without_chain))[:32]

Each row commits to the entire history before it. The first row chains from a fixed "genesis" seed. Rows without a chain field are tolerated only before the first chained row (so you can adopt it on an existing log); an unchained row appearing after the chain begins is itself flagged. On a mismatch, verify keeps going from the claimed value so it counts later damage honestly instead of cascading one break into noise.

What it proves — and the three things it doesn't

Being precise here is the product, not a disclaimer. A hash chain proves the recorded bytes were not altered in place after writing: mid-file edit, delete, and reorder all break it and verify names the row. It does not by itself prove three other things:

1. Truncation. Lop off the most recent rows and what remains verifies clean — no append-only chain catches this alone. Close it by publishing the head somewhere outside your own control, on a cadence:

pin = log.head().as_pin()
# -> "arcaeon-ledger head chain=9f3c… rows=204 as_of=2026-08-13T17:40:00Z"
# post `pin` to a git commit / public comment / notarization anchor.
# a reader compares a fresh head() against the last pin; a truncated or
# re-minted history disagrees. the MAX gap between pins is your security
# parameter, not the average — an attacker picks the gap.

2. Truth. The chain notarizes whatever was written — a tamper-evident record of a hallucination is still a hallucination with a checksum. To make a row speak about the world, hash a re-fetchable artefact (URL+bytes, a snapshot, tool stdout) and store that digest in the row, so a third party can re-get it and compare.

3. Authorship. authority() (above) records who-claimed-what, but it is data in the row, not a signature — a rewriter who re-mints from genesis re-mints it too. External head-anchoring (#1) is the thing a re-minter cannot advance.

Scoped honestly, the primitive is "this file was not rewritten in place" — small, true, and testable. The layers above (external anchoring via head(), artefact binding, signed authorship) are how you extend it toward a full evidence claim.

Drop it into any MCP agent

arcaeon-ledger ships a zero-dependency MCP server, so any MCP client (Claude Code, etc.) can give its agent tamper-evident logging with no code. Wire it in:

{
  "mcpServers": {
    "ledger": {
      "command": "python",
      "args": ["-m", "arcaeon_ledger.mcp_server", "--log", "agent.log.jsonl"]
    }
  }
}

The agent then has two tools: ledger_append(record) to log an action (returns its chain hash) and ledger_verify() to prove the whole log is intact (or get the exact tampered line back). MCP is JSON-RPC over stdio and this server speaks it directly — no SDK, no extra install.

Status

Core library, CLI, and a drop-in MCP server, all tested: the library against edit / delete / reorder tampering (test_ledger.py), the MCP server through a full initialize → tools/list → append → verify handshake including tamper detection over the wire. Extracted from a hash-chained action ledger running in production. External anchoring ships now via head() (publish the pin yourself); a hosted collection tier (retention, an automatic witness, compliance export) is the next layer.

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

arcaeon_ledger-0.2.1.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

arcaeon_ledger-0.2.1-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file arcaeon_ledger-0.2.1.tar.gz.

File metadata

  • Download URL: arcaeon_ledger-0.2.1.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for arcaeon_ledger-0.2.1.tar.gz
Algorithm Hash digest
SHA256 e8015212394081a2bea8374f97e585018b32f89d255757d9b5dbae05eea06d25
MD5 5b2869345d80dd1fb0765533d68e8b73
BLAKE2b-256 16eccc4c39a69a3e39f3e2721f37e9585648e748a82b6e3f335e4160ab9adc01

See more details on using hashes here.

File details

Details for the file arcaeon_ledger-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: arcaeon_ledger-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for arcaeon_ledger-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 125f6175188c6318f7fea9039e85921d722b732b7564ccff518efc55c451f720
MD5 5a9904ccbe8be02c6f43199fddbcc05d
BLAKE2b-256 aed1f8b69a93b66041c92af7cc2037ce9d14f199d10cd88a789af7efb623fdee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page