emilia-crewai
Guard CrewAI tools with the EMILIA Protocol — require an offline-verifiable authorization receipt (EP-RECEIPT-v1) before an irreversible tool runs.
missing receipt -> refused
valid receipt -> runs
replayed receipt -> refused (one-time consumption)
forged receipt -> refused
Verification is offline Ed25519 over canonical JSON via
emilia-verify — zero network, no
vendor in the loop. The approval becomes portable evidence an auditor can check
without trusting the operator. It is necessary, not sufficient: it composes with —
never replaces — your tool's own checks.
The base gate proves a pinned issuer signed an action-bound authorization claim. For a human-presence claim, require
assurance_class="class_a"and supply an independent assurance verifier pinned to the relying party's keys, RP, and origins.verify_assurancemust return an EXPLICIT affirmative:{"ok": True, "tier": ...}or the literalTrue. Anything else, a bare tier string included, is refused.
A signed expires_at on the receipt payload is an absolute validity boundary.
It is enforced independently of max_age_sec, so setting max_age_sec=None
does not revive a receipt past its own expiry, and an unparseable expires_at
fails closed.
The gate checks time again after assurance verification and reservation, just
before calling the tool. A slow verifier or store does not extend the receipt's
validity. If it expires before entry, the gate refuses the call and releases only
its unused reservation. A failed release remains a closed, uncertain state.
Install
pip install emilia-crewai # brings in emilia-verify
CrewAI remains a duck-typed optional peer and is not installed transitively. Install the CrewAI version selected by your application after auditing its own dependency graph. This avoids making EMILIA an installation path for CrewAI's currently unpatched optional ChromaDB dependency chain.
Quick start
Gate a CrewAI BaseTool instance — its _run now requires a receipt:
from emilia_crewai import guard_crewai_tool, using_receipt
guard_crewai_tool(
my_wire_tool,
action="payment.release",
trusted_keys=[ISSUER_SPKI_B64URL], # pin the issuer keys you trust
target_for=lambda to, amount: to, # optional semantic selector
assurance_class="class_a",
verify_assurance=verify_pinned_class_a_evidence,
)
# Bind the human-approved receipt for the agent step, then run as normal:
with using_receipt(receipt):
crew.kickoff() # my_wire_tool runs only with a valid, action-bound receipt
The high-level wrappers always bind the tool name and complete bound arguments;
target_for can add context but cannot weaken that binding. Use
bind_call_action() when minting the exact receipt action.
Or decorate a plain tool function:
from emilia_crewai import require_receipt, using_receipt
@require_receipt("payment.release", trusted_keys=[ISSUER_SPKI_B64URL])
def send_payment(to: str, amount: int) -> str:
return do_transfer(to, amount)
Lower-level gate (verify -> reserve -> execute -> commit yourself):
from emilia_crewai import ReceiptGate
gate = ReceiptGate("payment.release", trusted_keys=[ISSUER_SPKI_B64URL])
result = gate.run(receipt, lambda: do_transfer(to, amount), target=to)
run() consumes the receipt after any execution attempt, including an exception:
the external effect may have happened before its response was lost. Production
fleets must pass an atomic, ownership-fenced {reserve, commit, release} store;
the default is process-local. Call release() only when you can prove execution
never began.
This adapter supports synchronous, non-generator tools. It rejects known async
or generator functions before reserving authority. If a synchronous function
returns an awaitable or iterator, run() raises TypeError and keeps the receipt
consumed: it cannot safely hand delayed execution back to the caller. Do not wrap
an async tool in a synchronous lambda to bypass this restriction.
Multi-agent / quorum
For collective decisions (M-of-N agents or humans approving one action), EMILIA's
quorum produces a single composite, offline-verifiable receipt. See the
emilia_verify.verify_quorum primitive and draft-schrock-ep-quorum.
What it is / isn't
- Is: an offline gate for an action-bound issuer receipt, with an explicit Class-A/quorum verifier hook for independently established human ceremony.
- Isn't: authentication ("who is the agent"), access control, or a hosted runtime. It composes on top of whatever runtime you use.
Apache-2.0. Reference implementation, experimental. Part of the
EMILIA Protocol — an open
IETF-track authorization-receipt standard (draft-schrock-ep-authorization-receipts).
Metadata
Release files for emilia-crewai 0.3.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| emilia_crewai-0.3.5.tar.gz | 20.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| emilia_crewai-0.3.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.1 kB
Release files / emilia_crewai-0.3.5.tar.gz
| Download URL | emilia_crewai-0.3.5.tar.gz |
|---|---|
| Size | 20.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f6a69b7bbbbbfd6bc1db95bc01c7eeb82913d980c0129412337d2fabad93a2a4
|
|
BLAKE2b-256 checksum How to use checksums |
037e523afb65bc1a458ad301bfc82f702e1c67a4bb9dd1a0fb50a3b356fd9823
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency logRelease files / emilia_crewai-0.3.5-py3-none-any.whl
| Download URL | emilia_crewai-0.3.5-py3-none-any.whl |
|---|---|
| Size | 14.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
742a38d13ab12ef935cd6a4247055764b980ef402844840865aaa37beda87445
|
|
BLAKE2b-256 checksum How to use checksums |
cdab5a5f676584b337d58890a9fc98f5b6e4e9eb4f45be7afd47bb3511f6c732
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency log