Route 1: the direct MCP pattern
Pydantic AI speaks MCP natively, so the shortest path needs no Zambo package at all. Register the Zambo endpoint as an MCP server toolset and the agent gains Zambo's tools (153 on the full surface, 35 loaded by default) alongside its own. Calls execute on the server, and each one leaves a receipt because the executing layer makes the record.
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStreamableHTTP
zambo = MCPServerStreamableHTTP('https://zambo.dev/mcp') # no API key, no account
agent = Agent('openai:gpt-4o', toolsets=[zambo])
result = agent.run_sync('Check the live price of ETH and save what you find.')
# Every Zambo tool call in that run returned a verifiable AER-1 receipt.
The free tier covers 20 free calls per day, so a first Pydantic AI agent can run receipted today with no payment. The per-client connect steps for every MCP host live on zambo.dev/add, and the pattern behind this route is written up in MCP server receipts.
Route 2: wrap your own tools with aer1-pydantic
Route 1 receipts the calls your agent makes to Zambo's tools. If the work that matters runs through your own Pydantic AI tools, wrap those calls instead: aer1-pydantic on PyPI wraps the agent's tool calls so each one returns an AER-1 receipt as it runs, in the same format and checkable the same way.
pip install aer1-pydantic
Both routes produce the same object: one receipt per tool call, recording the tool that ran, a hash of the arguments it received, the exact result bytes and their SHA-256 digest, and a timestamp, published at a public URL. A run that mixes Zambo tools and wrapped local tools therefore checks as one record, not two systems.
A worked example: one real receipt
This is a real receipt from the public Zambo receipt store, opened and checked while this page was written: receipt d6949ef2-d6f7-46ec-a902-cf8be1ebeb7a, tool memory_remember, saved 2026-10-25T14:41:56.661Z, output hash sha256:716f3d7dc745c642ab467e4c999bc8a918e990c1abce72607393a476093aeca1. Its public page states the result has not changed since it was saved, and its commitment check reads: commitment matched.
- Read it: the receipt's public run page shows the saved result, the canonical bytes, and the checks.
- Check it: paste the receipt ID into the verifier at zambo.dev/verify, or call the public verify endpoint and compare the returned output hash with the one above. A match proves the saved result has not changed since it was saved.
- Yours looks the same: a receipted Pydantic AI call returns this same object shape, so the check you just ran is the check your users, clients, and reviewers will run on your agent's work.
Checking the run afterwards
- Per call: open the receipt URL and recompute the commitment from its canonical bytes, by hand or with the live verifier. A match means the saved record is the record made when the call ran.
- As an audit: the receipts are the audit trail, countable and checkable after the fact. The method is written up in how to audit AI agent tool calls, and the verifier walkthrough runs the procedure against a real public receipt.
- Full days covered: a Day Pass ($0.99) keeps every call receipted for 24 hours, past the 20 free calls per day on the free tier.
Pydantic AI execution receipts: FAQ
How do I add AER-1 receipts to a Pydantic AI agent?
Point the agent's tool calls at the Zambo MCP endpoint at zambo.dev/mcp, or wrap the calls with the aer1-pydantic package on PyPI, and every call returns an AER-1 receipt as it runs. The free tier covers 20 free calls per day, so a first Pydantic AI agent can run receipted today with no payment. Each receipt proves the saved result was not changed since it was saved.
Can I verify what my Pydantic AI agent actually ran?
Yes, from the receipts instead of from the agent's messages. Each call made through Zambo leaves a receipt recording the tool that ran, a hash of the arguments it was given, and the exact result bytes, committed under SHA-256 at execution time and published at a URL anyone can fetch. Recompute the commitment from the receipt's canonical bytes: a match means the saved record is the record made when the call ran. Work the agent describes but never executed has no receipt, so the gap between the story and the record is checkable rather than a matter of trust.
How do I audit a Pydantic AI agent's tool calls?
Audit the receipts, not the transcript. Collect one receipt per tool call, recompute each receipt's commitment from its canonical bytes, and for effects that matter read the outcome back in the system of record. Gaps in the sequence, a step whose bytes were edited, and calls the agent claims but cannot receipt all surface in the recompute. The full method is written up in how to audit AI agent tool calls.
What does a Pydantic AI run receipt contain?
One receipt per tool call, in the AER-1 format: the tool name, a hash of the arguments the call received, the exact result bytes and their SHA-256 digest, and a timestamp, plus the canonical bytes a verifier recomputes to check the record. Each receipt is published at a public URL. AER-1 is an open IETF Internet-Draft (draft-zambo-aer1-26), so the format is public text anyone can implement or verify against, with a public conformance corpus of 126 vectors and 129 checks checked by the aer1-verify kit (v1.5.7).