aer1-crewai
AER-1 verifiable workflow receipts for CrewAI.
Attach one listener and every crew run emits a hash-chained, offline-verifiable verifiable workflow receipt (AER-1, Section 8): what the crew did, in what order, with per-step hashes and a Merkle root over the whole run. It hooks CrewAI's own event bus, so there is no monkey-patching, no behavior change, and no network calls. The listener only observes. It complements CrewAI's built-in observability; it does not replace it.
The AER-1 framework collector family
The CrewAI 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-smolagents ��� SmolAgents agents via step callbacks
- aer1-openai-agents ��� the OpenAI Agents SDK via its TracingProcessor
- aer1-crewai ��� CrewAI crews via the event bus
- aer1-langgraph ��� LangGraph swarms via callback handler
- aer1-autogen ��� AutoGen multi-agent chats
Plus the aer1 metapackage: pip install aer1, then import aer1; aer1.instrument(). One line, zero config, auto-detects your framework.
Install
pip install aer1-crewai
Use it (two lines)
from aer1_crewai import AER1CrewAIListener
from crewai import Crew
listener = AER1CrewAIListener(goal="Research AER-1 adoption") # line 1
crew = Crew(agents=[...], tasks=[...])
result = crew.kickoff()
receipt = listener.finalize(final_answer=result.raw) # line 2
assert listener.verify(receipt) == [] # VALID
listener.save("receipt.json", workflow=receipt)
Keep the listener referenced for the whole process. Constructing it
registers its handlers on CrewAI's global event bus; dropping the
reference can unregister them.
That is the whole integration. The receipt is a plain JSON object you can store, ship to an auditor, or render in a UI.
What gets recorded
One receipt step per observed event, in arrival order:
ToolUsageFinishedEventbecomes a step named for the tool, with the tool arguments, output, agent role, and task name hashed in, andstarted_at/ended_attaken from the event's own timestamps.ToolUsageErrorEventbecomes the same step withstatus: "error".TaskCompletedEvent/TaskFailedEventbecometool: "task"steps carrying the task name and output.
What the receipt contains
Workflow level (AER-1 Section 8, Table 2):
type,version,workflow_id,receipt_id,session_idgoal,statussteps: one record per observed event, seq 1..n in ordermerkle_root: Section 8.1 root over the ordered step receipt idsoutput_hash: SHA-256 of the final answerverify_url: where the verification procedure is documented
Step level (AER-1 Section 8, Table 3):
seq,receipt_id,tool,receipt_hash,started_at,ended_at,status
Each step receipt_hash is SHA-256 over the canonical JSON of what the
step actually did. The hash commits to the content; the receipt stays
compact.
Verification
listener.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
seqvalues exactly 1..n in order, no gaps- no two steps share a
receipt_id(MM-1) merkle_rootmatches 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 listener.verify(receipt) != [] # fails, as it should
Notes
- One listener observes every crew run in the process. Call
reset()between runs if you want one receipt per run from a shared listener. session_iddefaults to a fresh UUID per listener; pass your own to correlate receipts across runs.verify_urldefaults to the AER-1 specification page; point it at your own verifier in production.- If
final_answeris omitted,finalize()uses the output captured from the crew kickoff completed event when available.
Spec
AER-1: Agent Execution Receipts, draft-zambo-aer1,
https://datatracker.ietf.org/doc/draft-zambo-aer1/
License
Apache-2.0
Metadata
Release files for aer1-crewai 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aer1_crewai-0.1.1.tar.gz | 11.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aer1_crewai-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.0 kB
Release files / aer1_crewai-0.1.1.tar.gz
| Download URL | aer1_crewai-0.1.1.tar.gz |
|---|---|
| Size | 11.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a97dc254eaf3062b93a3d02fbc022facc4bf79c1645fc02c1901f13f744b6b61
|
|
BLAKE2b-256 checksum How to use checksums |
738acfd59c93330bdbb25395ef220a779077bf4296ded30effba8ff59377c5e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
rambo-pypi-grab/0.1.0
|
Release files / aer1_crewai-0.1.1-py3-none-any.whl
| Download URL | aer1_crewai-0.1.1-py3-none-any.whl |
|---|---|
| Size | 8.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c1a640a6b2331ba8e1b0cdc45e38fc8eb53b868df0e1c94122496dbcf0a6cc07
|
|
BLAKE2b-256 checksum How to use checksums |
c0b3468b02e66e444ee846f48e43bc285c74d3ab322659b1ca0a3c27fe276531
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
rambo-pypi-grab/0.1.0
|