Skip to main content

EMILIA Protocol Python SDK

emilia-protocol is the synchronous, zero-runtime-dependency Python client for the deliberately narrow EMILIA API surface listed below. Version 0.11.0 uses the canonical emilia_protocol import namespace.

python -m pip install emilia-protocol==0.11.0
from emilia_protocol import EPClient

client = EPClient(api_key="ep_live_...")
decision = client.gate(
    entity_id="principal-123",
    action="payment.release",
    policy="strict",
    value_usd=82_000,
)
print(decision.decision)

All calls block until the HTTP response arrives. The SDK uses Python's standard library rather than httpx. It supports Python 3.9 and later.

Fail-closed mutation wrapper

require_receipt creates an enforce-mode receipt, confirms durable evidence, and consumes the exact action_hash before it calls your mutation. A callback that waits for a human signoff is coordination only: the server-side consume response remains the authority to proceed.

from emilia_protocol import EPClient, RequireReceiptParams

client = EPClient(api_key="ep_live_...")


def release_payment(context):
    # Execute the server-canonicalized action, not the caller's original draft.
    return payments.release(context.canonical_action)


def read_after_write(context):
    # Independently observe what the system of record actually executed.
    return payments.read_execution(context.result["execution_id"])


outcome = client.require_receipt(
    RequireReceiptParams(
        organization_id="org-123",
        action_type="large_payment_release",
        target_resource_id="payment-123",
        executing_system="payments-api",
        amount=82_000,
        currency="USD",
        after_state={"status": "released"},
        execution_reference_id="attempt-456",
        observed_action=read_after_write,
        execution_id=lambda result: result["execution_id"],
        fetch_evidence=True,
    ),
    release_payment,
)

if outcome.execution_status != "attested":
    # The receipt was already consumed and the mutation may have run.
    # Reconcile using the system of record; do not replay blindly.
    raise RuntimeError("execution evidence is incomplete; manual reconciliation required")

If no independent observation is supplied, the mutation can still run after successful receipt consumption, but the result is explicitly unobserved and no execution attestation is emitted. An attestation or evidence-fetch failure after the mutation returns indeterminate/do_not_retry state instead of pretending the action did not happen. A mutation exception likewise happens after one-time consumption; callers must reconcile before retrying.

For a signoff-required receipt, pass approver_id and an on_signoff_required callback that waits for the external approval ceremony. The wrapper still calls the consume endpoint after that callback, and it will not invoke the mutation unless the server confirms status == "consumed".

For a multi-party ceremony, pass a QuorumPolicy with role-bound approvers. The SDK asks the server to fan out those signoff seats, hands the full response to on_signoff_required, and still treats only successful one-time consumption as authority to invoke the mutation.

from emilia_protocol import QuorumApprover, QuorumPolicy

quorum = QuorumPolicy(
    required=2,
    approvers=[
        QuorumApprover(role="controller", approver="human-1"),
        QuorumApprover(role="treasurer", approver="human-2"),
    ],
    window_sec=600,
)

organization_id is optional on receipt requests. When omitted, the server derives it from the authenticated principal; when supplied, the server uses it only as a tenant-binding cross-check.

Supported API surface

Client method HTTP contract
initiate_handshake(...) POST /api/handshake
get_handshake(handshake_id) GET /api/handshake/{handshakeId}
present(...) POST /api/handshake/{handshakeId}/present
verify(handshake_id) POST /api/handshake/{handshakeId}/verify
revoke_handshake(handshake_id, reason) POST /api/handshake/{handshakeId}/revoke
gate(...) POST /api/trust/gate
create_trust_receipt(params) POST /api/v1/trust-receipts
get_trust_receipt(receipt_id) GET /api/v1/trust-receipts/{receiptId}
request_signoff(params) POST /api/v1/signoffs/request
consume_trust_receipt(receipt_id, params) POST /api/v1/trust-receipts/{receiptId}/consume
attest_execution(receipt_id, params) POST /api/v1/trust-receipts/{receiptId}/execution
get_trust_receipt_evidence(receipt_id) GET /api/v1/trust-receipts/{receiptId}/evidence
require_receipt(params, mutate) Orchestrates the v1 lifecycle above

The same surface is recorded in route-contract.json and tested against both the maintained OpenAPI documents and the repository's runtime route handlers.

Methods from older previews that are not backed by the current route contract are intentionally absent. That includes Eye helpers, handshake consumption, legacy signoff challenge/attestation helpers, cloud-approval prototypes, and receipt batching.

Handshake example

from emilia_protocol import EPClient, Party

client = EPClient(api_key="ep_live_...")
handshake = client.initiate_handshake(
    mode="mutual",
    policy_id="strict",
    parties=[
        Party(entity_ref="agent-a", role="initiator"),
        Party(entity_ref="service-b", role="responder"),
    ],
    action_type="payment.release",
    resource_ref="payment-123",
)

client.present(
    handshake.handshake_id,
    party_role="initiator",
    presentation_type="attestation",
    claims={"subject": "agent-a"},
)
verification = client.verify(handshake.handshake_id)
print(verification.outcome)

Configuration and errors

EPClient reads EP_API_KEY and EP_BASE_URL when constructor arguments are omitted. The default base URL is https://emiliaprotocol.ai. Remote cleartext HTTP is refused unless allow_insecure_http=True; loopback HTTP remains usable for local development.

from emilia_protocol import EPClient, EPError

client = EPClient(timeout=15, retries=2)
try:
    receipt = client.get_trust_receipt("tr_...")
except EPError as error:
    print(error.status, error.code, str(error))

Automatic retries apply only to read-only GET requests. State-changing POST requests are never replayed by the client.

The API package and import names differ by Python convention:

  • distribution: emilia-protocol
  • import: emilia_protocol

The short ep namespace was removed in 0.11.0 because it collides with an unrelated package on PyPI. Runtime availability of individual routes still depends on the EMILIA deployment selected by base_url.

Metadata

Release files for emilia-protocol 0.11.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for emilia-protocol 0.11.1
File Size Uploaded
emilia_protocol-0.11.1.tar.gz 20.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for emilia-protocol 0.11.1
File Interpreter ABI Platform
emilia_protocol-0.11.1-py3-none-any.whl Python 3 none any Details

Total release size: 36.2 kB

Release files / emilia_protocol-0.11.1.tar.gz

Download URL emilia_protocol-0.11.1.tar.gz
Size 20.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f3cb33a2b53c6dd277142638df5cae1dd3a592cbe9f58525dbe7b670fd885dd5
BLAKE2b-256 checksum
How to use checksums
871b686e8399c62efb229bfba861f7bfa36551309f704e4321e180339b599051
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 13, 2026.

Transparency log

Release files / emilia_protocol-0.11.1-py3-none-any.whl

Download URL emilia_protocol-0.11.1-py3-none-any.whl
Size 15.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
168adb50eb1204134821d2a4dc3761fc69a105a2d59e6405e13931861dd7264b
BLAKE2b-256 checksum
How to use checksums
79a5865af7e202a919209729313b33a2af0b3ee1a5ce6959e282cfcd20b3f5bf
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 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.1 This release

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page