Skip to main content

langchain-emilia

Before your LangChain agent does anything irreversible, a named human approves that exact action on their own device. Face ID / Touch ID / passkey. Fail-closed. Every approval mints a Trust Receipt that verifies offline — years later, with no account and no EMILIA server.

pip install langchain-emilia
export EP_API_KEY=ep_live_...  EP_ORG_ID=your-org
from langchain_emilia import EmiliaGuard, guard_tools

guard = EmiliaGuard()                                   # enforce mode
tools = guard_tools([transfer_funds, send_email, calculator], guard)
# hand `tools` to your agent exactly as before — nothing else changes

When the agent calls transfer_funds(amount=82000, beneficiary="Northwind"):

  1. Gate — the call is held pre-execution; EP policy returns allow, require_signoff, or deny.
  2. Signoff — on require_signoff, a named human approves on their own device. The approval is cryptographically bound to the exact action parameters — change one digit and it is invalid.
  3. Consume — the exact receipt is atomically consumed before the tool body; an already-consumed receipt cannot authorize another executor.
  4. Attest — after the tool returns, the adapter reports executor-observed invocation fields re-derived from the detached arguments actually handed to the tool; it does not reuse the approved plan as its own observation. This is attributable execution evidence, not proof of real-world effects. If the evidence write cannot be confirmed, the result is INDETERMINATE and the adapter says DO NOT RETRY.

Denials and pending holds are returned to the model as the tool's output ("EMILIA — BLOCKED … transfer_funds was NOT executed."), so the agent loop explains itself instead of crashing. The tool body never runs unless the gate allows it.

Why this is an executor-side precondition, not an "approval tool"

Approval tools the model calls have three failure modes: the model forgets to call them, approves action A then executes action B, or barrels past an error. langchain-emilia instead wraps the tool itself: the action digest is computed from the actual arguments at execution time and the gate runs before the tool body, unconditionally. The model-facing schema is unchanged; only the executor gains the gate.

Zero-setup dry run (observe mode)

No account, no network, nothing blocked — see what enforcement would cover:

guard = EmiliaGuard(mode="observe")
tools = guard_tools(my_tools, guard)
# ... run your agent, then:
for r in guard.records:
    print(r["tool"], r["digest"][:16], r["note"])

Configuration

Option Default Meaning
mode "enforce" "observe" = log-only local dry run, keyless
match money/external-action regex Callable[[str], bool] — which tool names are gated
action_types auto map tool name → EP action_type (see ACTION_TYPES)
wait_for_approval True block (≤ timeout) while the human approves; False = surface the signoff URL immediately
return_errors True denials become tool output for the model; False = raise EmiliaDenied / EmiliaApprovalPending
on_event None callback for observed/allowed/executed/denied/pending/unreachable/indeterminate events (SIEM hook)

EmiliaGateClient(api_key, org_id, base_url, signoff_timeout_s=280, poll_interval_s=3) reads EP_API_KEY / EP_ORG_ID / EP_BASE_URL from the environment by default.

Fail-closed semantics

Situation What happens
Policy denies Tool not executed; model told why
Human rejects on device Tool not executed; receipt records the rejection
Signoff window times out Tool not executed; signoff URL surfaced for retry
EMILIA unreachable / network error Tool not executed — never fail open
Consume is not confirmed Tool not executed — never fail open
Tool returns but execution attestation fails Tool may have executed; INDETERMINATE, do not retry
Tool name doesn't match match Runs ungated (scope your match deliberately)

Verify the evidence

Every allowed action carries a receipt_id. Anyone can verify it with zero trust in us or in you:

Try the human side yourself (no signup): https://www.emiliaprotocol.ai/try

Development

cd integrations/langchain-emilia
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
.venv/bin/pytest -q

Apache-2.0. The digest layer is pinned byte-for-byte to the JS verifier by cross-language vectors in tests/test_digest.py.

Building with LangChain.js instead? The JS sibling is @emilia-protocol/langchain — a thin gate Proxy for .invoke()-style tools on npm.

Metadata

Release files for langchain-emilia 0.2.2

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

Source distribution (sdist)

Source distribution for langchain-emilia 0.2.2
File Size Uploaded
langchain_emilia-0.2.2.tar.gz 17.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for langchain-emilia 0.2.2
File Interpreter ABI Platform
langchain_emilia-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 30.7 kB

Release files / langchain_emilia-0.2.2.tar.gz

Download URL langchain_emilia-0.2.2.tar.gz
Size 17.3 kB
Tags Source
SHA-256 checksum
How to use checksums
3d900ce2d561775542fb1a47def620f9cf1b4da59519e0486d83b67da233975c
BLAKE2b-256 checksum
How to use checksums
11ea86cf3c7a2467de8a6cbf8eb357aac12e622e56e919b0a9029429c3f00086
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 / langchain_emilia-0.2.2-py3-none-any.whl

Download URL langchain_emilia-0.2.2-py3-none-any.whl
Size 13.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
681bf1dd40179a7a3b40f92db95cd0440787d4a704fe1de9d97485422b9865e0
BLAKE2b-256 checksum
How to use checksums
ca259f30c4fd59e45d871b8254360fec4b2e0636581b25288aded512f2b93d83
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.2.2 This release

2 release files

0.2.0

2 release files

0.1.1

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