Metadata-Version: 2.4
Name: aer1-openai-agents
Version: 0.1.11
Summary: One-line verifiable execution receipts for the OpenAI Agents SDK. Free, no API key, offline verification, chain-head anchoring to Nostr and Bitcoin.
License-Expression: Apache-2.0
Project-URL: Homepage, https://zambo.dev
Project-URL: IETF Draft, https://datatracker.ietf.org/doc/draft-zambo-aer1/
Keywords: aer-1,openai-agents,openai,ai-agents,ai-agent,verifiable-receipts,verifiable-receipt,execution-receipt,ai-agent-receipt,audit,tracing,audit-trail,agent-audit-trail,agent-accountability,mcp,zambo,agents,receipts,verifiable
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: openai-agents>=0.1.0
Provides-Extra: anchor
Requires-Dist: coincurve>=18.0; extra == "anchor"
Requires-Dist: websocket-client>=1.7; extra == "anchor"

# aer1-openai-agents

## 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](https://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-20](https://datatracker.ietf.org/doc/draft-zambo-aer1/20/). Project home: [zambo.dev](https://zambo.dev).

**Try it live:** [interactive demo](https://rambozambodotdev.gitlab.io/aer1-hub/try/). Mint a real verifiable receipt in your browser, no install, no signup.


One-line install, no API key, free forever: one line of integration turns any traced OpenAI Agents SDK run into an offline-verifiable workflow receipt (AER-1, an IETF Internet-Draft, Section 8) covering every model call, tool call, and agent step, hash-chained with a Merkle root over the whole run. Receipt chain heads can anchor to Nostr and Bitcoin, so anyone can later confirm the record was not changed, without trusting any server.

> For per-tool-call receipts, see [openai-agents-zambo](https://pypi.org/project/openai-agents-zambo/).

## The AER-1 framework collector family

The OpenAI Agents SDK 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.

- [aer1-openai-agents](https://pypi.org/project/aer1-openai-agents/), the OpenAI Agents SDK via its TracingProcessor
- [aer1-langchain](https://pypi.org/project/aer1-langchain/), LangChain chains, agents, tools, and retrievers via callback handler
- [aer1-llamaindex](https://pypi.org/project/aer1-llamaindex/), LlamaIndex agents via callback handler
- [aer1-smolagents](https://pypi.org/project/aer1-smolagents/), SmolAgents agents via step callbacks
- [aer1-crewai](https://pypi.org/project/aer1-crewai/), CrewAI crews via the event bus
- [aer1-langgraph](https://pypi.org/project/aer1-langgraph/), LangGraph swarms via callback handler
- [aer1-autogen](https://pypi.org/project/aer1-autogen/), AutoGen multi-agent chats
- [aer1-haystack](https://pypi.org/project/aer1-haystack/), Haystack 2.x pipelines via run wrapping
- [aer1-pydantic](https://pypi.org/project/aer1-pydantic/), Pydantic AI agents via run wrapping and manual tool-call recording
- [aer1-strands](https://pypi.org/project/aer1-strands/), Strands Agents via the typed hook system

See the [AER-1 implementation registry](https://rambozambodotdev.gitlab.io/registry.html) for every implementation.

## Install

```bash
pip install aer1-openai-agents
```

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

```python
# pip install aer1-openai-agents
import asyncio
from agents import Agent, Runner, function_tool
from agents.testing.model import ScriptedModel, assistant_message, function_call
from aer1_openai_agents import install

@function_tool
def get_weather(city: str) -> str:
    """Get the weather for a city."""
    return f"Sunny in {city}"

async def main():
    processor = install(goal="Check the weather")
    scripted = ScriptedModel(steps=[
        [function_call("get_weather", {"city": "Austin"}, call_id="call_1")],
        [assistant_message("It is sunny in Austin.")],
    ])
    agent = Agent(name="weather", instructions="Answer briefly.",
                  tools=[get_weather])
    agent.model = scripted  # swap for your real model in production

    result = await Runner.run(agent, "What is the weather in Austin?")
    receipt = processor.finalize(final_answer=result.final_output)
    assert processor.verify(receipt) == []  # VALID
    processor.save("receipt.json", receipt)

asyncio.run(main())
```

`install()` registers the receipt processor directly. Prefer the
standard path in production if you also want the SDK's own tracing
dashboard:

```python
from agents.tracing import add_trace_processor
from aer1_openai_agents import AER1TracingProcessor

processor = AER1TracingProcessor(goal="Summarize the quarterly report")
add_trace_processor(processor)
```

`install()` additionally skips the SDK's backend trace exporter, so no
trace data leaves your machine and proxy-heavy environments cannot fail
at registration time. Either way the integration is: register the
processor, run the agent, finalize. The processor implements the SDK's
`TracingProcessor` interface, the same pattern other observability
integrations use.

## What you get

A JSON receipt with the AER-1 Section 8 workflow members:

- `type`, `version`, `workflow_id`, `receipt_id`, `session_id`
- `goal`, `status`, `output_hash`, `verify_url`
- `steps`: one per ended SDK span (model calls, tool calls, agent
  boundaries, handoffs), each with `seq`, `receipt_id`, `tool`,
  `receipt_hash`, `started_at`, `ended_at`, `status`
- `merkle_root`: the Section 8.1 root over the ordered step receipt ids

Each step's `receipt_hash` is SHA-256 over the canonical JSON of the
span's observed content, so the hash commits to what the agent actually
did. `verify()` re-checks everything offline: all 14 Table 2/3 member
requirements, seq ordering 1..n, no duplicate step receipt ids, and the
Merkle root recomputed.

## Verify

```python
from aer1_openai_agents import verify_workflow_receipt

failures = verify_workflow_receipt(receipt)
assert failures == []  # empty means valid
```

The processor never touches the network and never changes agent behavior.
It only observes.

### Separate verification verdicts

For honest reporting, use `verify_receipt_verdicts()` instead of a
single boolean. Each dimension gets its own verdict; they are never
conflated:

```python
from aer1_openai_agents import verify_receipt_verdicts, verdicts_summary

verdicts = verify_receipt_verdicts(receipt)
print(verdicts_summary(verdicts))
# byte_integrity=pass schema_validity=pass issuer_authenticity=not_checked
# evidence_linkage=not_checked anchor_verification=not_checked
# chain_integrity=pass
```

| Dimension | What it checks | Collector behavior |
|---|---|---|
| `byte_integrity` | Merkle root matches the recomputed root | `pass` / `fail` |
| `schema_validity` | All required fields present and well-formed | `pass` / `fail` |
| `issuer_authenticity` | Cryptographic proof of who issued the receipt | Always `not_checked`; the collector does not verify signatures |
| `evidence_linkage` | Upstream evidence bytes match their digests | Always `not_checked`; the collector does not capture upstream evidence |
| `anchor_verification` | Anchor proof is valid and binds the root | `pass` / `fail` / `not_checked` (no proof provided) |
| `chain_integrity` | `seq` values are 1..n in order, no duplicate receipt ids | `pass` / `fail` |

Verdict values are `pass`, `fail`, `not_checked`, and `unavailable`.
`not_checked` is neither a successful check nor evidence of failure.

### What the commitment covers (and what it does not)

The `merkle_root` commits to the ordered list of step `receipt_id`
values. Each step `receipt_hash` commits to that step's tool name,
arguments, and observations. The `output_hash` commits to the final
answer bytes.

What this does **not** cover:

- The commitment does not prove the bytes are unchanged since issuance.
  An attacker able to replace both bytes and digest creates another
  matching pair. Continuity requires comparing against a digest from
  an independently trusted path.
- A matching hash does not prove the action ran, the data is true, or
  any external outcome occurred. It proves the supplied bytes agree
  with the supplied digest.
- The receipt records the collector's observations. It does not prove
  provider truth, correct reasoning, authorization, or business success.
- Without an anchor, truncation (deleting steps from the end and
  recomputing the root) is not detectable.

### Construction versions

This package uses these exact constructions (see `CONSTRUCTION_VERSIONS`
in the `verdicts` module):

- Merkle tree: `section-8.1-binary-merkle-v1`
- Step digest: `sha256-canonical-json-v1`
- Output commitment: `sha256-utf8-v1`
- Anchor proof: `aer1-anchor-proof-v1`

## Spec

Based on draft-zambo-aer1, Section 8 (verifiable workflow receipts).
Verification procedure documented at
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/<id>.

## License

Apache-2.0
