Skip to main content

EMILIA Protocol guard for LangChain tools: a named human approves the exact irreversible action (Face ID / passkey) before it executes — fail-closed, with offline-verifiable Trust Receipts.

Project description

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. Receipt — execution releases only after approval; the signed, Merkle-anchored receipt is permanent, offline-verifiable evidence.

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/denied/pending/unreachable 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
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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_emilia-0.1.0.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langchain_emilia-0.1.0-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file langchain_emilia-0.1.0.tar.gz.

File metadata

  • Download URL: langchain_emilia-0.1.0.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for langchain_emilia-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a03547e1b8d3abddaf0a8655222ed93d556d8150f4fe0effcfbaa08524955aea
MD5 0fdbe11acde24a5ad2d3730209118ffb
BLAKE2b-256 678075372aad5126b0821e3c8125813463e9339e2c2220fbfd036e59943099ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_emilia-0.1.0.tar.gz:

Publisher: publish-langchain-python.yml on emiliaprotocol/emilia-protocol

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langchain_emilia-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_emilia-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e6c87f1ced0ae51f70eac4cf148d7a5a5bc4e47e15d33652b0ae7d4d7218d124
MD5 2b35b108068e7dfe8366ca8d1f3d3328
BLAKE2b-256 0499b67b73b9a37c744d5a2116234be80a28123154e3482269ddb21e912bcc92

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_emilia-0.1.0-py3-none-any.whl:

Publisher: publish-langchain-python.yml on emiliaprotocol/emilia-protocol

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page