Metadata-Version: 2.5
Name: agno-aer1
Version: 0.1.0
Summary: AER-1 verifiable execution receipts for Agno agents: one checkable receipt per tool call.
Project-URL: Homepage, https://zambo.dev
Project-URL: Spec (IETF draft), https://datatracker.ietf.org/doc/draft-zambo-aer1/
Project-URL: Conformance kit, https://gitlab.com/rambozambodotdev/zambo
Author: Brennan Zambo
License: MIT
License-File: LICENSE
Keywords: aer-1,agno,ai-agents,audit,receipts,verification
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: agno>=3.0
Description-Content-Type: text/markdown

# agno-aer1

Every tool call your Agno agent makes, recorded as an AER-1 verifiable execution receipt. Four lines of code. No new infrastructure.

AER-1 is an open IETF Internet-Draft (draft-zambo-aer1) defining a small vocabulary for recording one AI agent tool call as a portable, independently checkable receipt. A receipt proves the recorded result was not changed. It does not prove the tool was correct.

## Install

```bash
pip install agno-aer1
```

## 10-minute quickstart

```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno_aer1 import AER1Recorder

recorder = AER1Recorder()
agent = Agent(
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[...],
    tool_hooks=[recorder],
)
agent.run("What is 17 * 24?")

print(f"{len(recorder.receipts)} receipts recorded")
recorder.save("receipts.jsonl")
```

That is the whole integration. `tool_hooks` is Agno's native middleware seam for tool execution (the same seam observability integrations use): each hook wraps a tool call, sees the function name and arguments, runs the tool, and observes the result. The recorder sits in that chain and emits one receipt per call, then returns the result untouched.

## What a receipt looks like

```json
{
  "id": "3f9a2c1e-7b4d-4f8a-9c2e-1a5b6d7e8f90",
  "receipt_schema_version": "0.3",
  "created_at": "2026-10-05T22:30:00.123456Z",
  "tool": {"name": "calculator", "version": "3.1.1", "scope": "public"},
  "provenance_class": "EXECUTED BY AGNO",
  "canonical_bytes": "eyJpbnB1dHMiOi...",
  "output_hash": "sha256:9f2c...",
  "verification_status": "verified"
}
```

The canonical bytes are a deterministic JSON payload (`tool`, `inputs`, `output`). Anyone can base64-decode them, recompute SHA-256, and compare with `output_hash`. That is the entire verification procedure.

## Verify a receipt yourself

```python
from agno_aer1 import verify_receipt

failures = verify_receipt(recorder.receipts[0])
assert failures == [], failures
print("receipt checks out")
```

## Honest boundaries

- A receipt proves the recorded bytes were not changed. It does not prove the tool was correct, or that the model chose the right tool.
- Tool calls that raise produce no receipt; the error propagates exactly as Agno handles it without the recorder.
- If you enable Agno's tool-result cache, cache replays also pass through the middleware and emit receipts. Each receipt still commits to the exact bytes the agent observed.
- The recorder never changes a tool result. If receipt construction itself ever fails, the tool result is still returned untouched.

## Links

- AER-1 spec (IETF Internet-Draft): https://datatracker.ietf.org/doc/draft-zambo-aer1/
- Conformance kit: https://gitlab.com/rambozambodotdev/zambo
- Zambo: https://zambo.dev
