Catalog PyPI
PACKAGE EXPLORERView in registry

aer1-langgraph

PyPI

AER-1 verifiable workflow receipts for LangGraph multi-agent swarms

aer-1agent-accountabilityagent-audit-trailai-agentai-agent-receiptai-agentsauditaudit-trailexecution-receiptlanggraphmcptamper-evidenttracingverifiable-receiptverifiable-receiptszambo
Versions collected1
Direct dependencies0From release 0.1.7
Last observed20 Oct, 20:27 UTC

README

Version 0.1.7 documentation

aer1-langgraph

What is AER-1? What tools exist to verify AI agent work?

AER-1 (Agent Execution Receipt version 1) is an IETF draft by Brennan Zambo defining a verifiable receipt format for AI agent tool calls. Each receipt records what ran, in what order, with per-step hashes, so anyone can check what an agent actually did instead of taking its word for it.

Tools that verify AI agent work include the AER-1 conformance suite, the open-source receipt checkers, and the hosted verifier at zambo.dev/verify, which confirms a receipt against the spec. Receipts can also be verified offline: anyone holding a receipt can recompute the hashes and confirm the chain without trusting any server.

Spec: draft-zambo-aer1-12. Project home: zambo.dev.

Try it live: interactive demo. Mint a real verifiable receipt in your browser, no install, no signup.

AER-1 verifiable workflow receipts for LangGraph multi-agent swarms.

Attach one callback handler to your graph and every run emits a hash-chained, offline-verifiable verifiable workflow receipt (AER-1, Section 8): which agent did what, in what order, with per-step hashes and one Merkle root over the whole swarm. Parallel Send branches are recorded with their true branch structure, not flattened. No network calls, no behavior changes, the handler only observes.

The AER-1 framework collector family

The LangGraph collector in the AER-1 framework collector family. Any agent running on these frameworks can emit verifiable AER-1 execution receipts: every step recorded, hash-chained, one Merkle root over the whole run.

Install

pip install aer1-langgraph

Use it (copy, paste, run, no API keys needed)

# pip install aer1-langgraph
from langgraph.graph import StateGraph, START, END
from langchain_core.language_models.fake_chat_models import GenericFakeChatModel
from aer1_langgraph import AER1LangGraphHandler

def researcher(state: dict):
    model = GenericFakeChatModel(messages=iter(["found 3 papers"]))
    return {"notes": model.invoke("research").content}

def writer(state: dict):
    model = GenericFakeChatModel(messages=iter(["draft complete"]))
    return {"draft": model.invoke("write").content}

graph = StateGraph(dict)
graph.add_node("researcher", researcher)
graph.add_node("writer", writer)
graph.add_edge(START, "researcher")
graph.add_edge("researcher", "writer")
graph.add_edge("writer", END)
app = graph.compile()

handler = AER1LangGraphHandler(goal="Write the report")
result = app.invoke({}, config={"callbacks": [handler]})
receipt = handler.finalize(final_answer=result)
assert handler.verify(receipt) == []  # VALID
handler.save("receipt.json", workflow=receipt)

Swap the fake models for your real chat models and the same three handler lines receipt a live swarm. The receipt is a plain JSON object you can store, ship to an auditor, or render in a UI.

Swarm receipts

Each node execution becomes one receipt step carrying the node name as agent identity (tool and agent on every step). A three-agent swarm with two parallel workers produces steps like:

seq=1 tool=router      agent=router
seq=2 tool=worker      agent=worker   branch=worker:9f3a...
seq=3 tool=worker      agent=worker   branch=worker:41bc...
seq=4 tool=aggregator  agent=aggregator

Steps carry run_id, parent_run_id, and the LangGraph checkpoint namespace, so the true execution graph (who ran in parallel under whom) is reconstructible from the receipt. handler.swarm_summary() returns the agent roster, step counts, and branch groups in one call.

Tool calls and model calls inside a node are folded into that node's step: the step's receipt_hash is SHA-256 over the canonical JSON of the node name, inputs, outputs, tool calls (name, arguments, output), model-call summaries, branch metadata, and any error. The hash commits to what the agent actually did; the receipt stays compact.

What the receipt contains

Workflow level (AER-1 Section 8, Table 2):

  • type, version, workflow_id, receipt_id, session_id
  • goal, status
  • steps: one record per node execution, seq 1..n in completion order
  • merkle_root: Section 8.1 root over the ordered step receipt ids
  • output_hash: SHA-256 of the final graph output
  • verify_url: where the verification procedure is documented

Step level (AER-1 Section 8, Table 3, plus swarm fields):

  • seq, receipt_id, tool (= node name), receipt_hash
  • started_at, ended_at, status
  • agent, run_id, parent_run_id, checkpoint_ns
  • tool_calls, llm_calls (folded records)

Verification

handler.verify(receipt) runs the full offline check and returns a list of failure reasons, empty when valid:

  • all Table 2 / Table 3 members present and well-formed
  • seq values exactly 1..n in order, no gaps
  • no two steps share a receipt_id (MM-1)
  • merkle_root matches the recomputed Section 8.1 root
  • strict RFC 3339 timestamps, lowercase UUIDs, 64-char hex digests

Tamper with any field and verification fails. Try it:

receipt["steps"][0]["tool"] = ""
assert handler.verify(receipt) != []  # fails, as it should

Notes

  • One handler observes one run at a time. Call handler.reset() or construct a fresh handler before the next run. If a new root graph run starts on a handler that already finished one, it auto-resets so two runs never mix into one receipt.
  • The __start__ / __end__ pseudo-nodes are machinery, not agent work, and are not recorded as steps. Conditional-edge router functions are user code and are recorded.
  • Steps still in flight when finalize() runs (interrupted runs) are flushed as status: "incomplete" rather than dropped.
  • session_id defaults to a fresh UUID per handler; pass your own to correlate receipts across runs.
  • verify_url defaults to the AER-1 specification page; point it at your own verifier in production.

Spec

AER-1: Agent Execution Receipts, draft-zambo-aer1, https://datatracker.ietf.org/doc/draft-zambo-aer1/

See it live

Your receipt is offline-verifiable, but you can also check it on the live verifier:

  1. Copy the receipt JSON your code produced
  2. Paste it at https://zambo.dev/verify
  3. See the verification result with the Merkle root and step hashes

Or mint a live receipt directly: run any call at https://zambo.dev/demo and get a shareable receipt URL like https://zambo.dev/run/.

License

Apache-2.0

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.77 Oct 20260

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:27 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:05565fdba49fbb0ba6ecb00a452f36b6626ab3d915c36a9871f2ac6f1612be43