Agent GuardProtocolMCPGovGuardFinGuardQuorumDemoTry itVerifyPricingDocsRequest Pilot
DEVELOPER GUIDE · THE DEMAND SIDE

Require a receipt in one endpoint.

No receipt, no irreversible action. Make your service refuse an irreversible call unless a valid authorization receipt rides with it. The caller gets a 402 that says exactly what to bring; a well-behaved agent obtains a receipt and retries; you verify it offline — no EMILIA backend, fail-closed.

See the runnable loopAgent Guard (the gate)
STEP 1 · THE ONE MIDDLEWARE

Wrap the irreversible endpoint.

Framework-agnostic Express-style middleware. Install npm i @emilia-protocol/require-receipt, then gate the one route that does something it can’t take back:

import { requireEmiliaReceipt } from '@emilia-protocol/require-receipt';

app.post(
  '/release-payment',
  requireEmiliaReceipt({
    trustedKeys: [process.env.EMILIA_ISSUER_PUBKEY], // base64url SPKI you trust
    action: 'payment.release',
    maxAgeSec: 900,
  }),
  (req, res) => {
    // Only reached if a fresh, untampered, action-bound receipt from a
    // trusted issuer was presented. req.emiliaReceipt holds the verified claim.
    res.json({ released: true, receipt: req.emiliaReceipt.receipt_id });
  },
);
STEP 2 · THE 402 LOOP

The agent self-serves the proof.

No receipt? The service answers 402 and tells the agent exactly what to bring — like a browser handling 401. A well-behaved agent obtains a receipt and retries, no human in the support loop:

→ POST /release-payment            (no receipt)
← 402 EMILIA Receipt Required
  WWW-Authenticate: EMILIA realm="agent-actions", action="payment.release"
  { required: { action: "payment.release",
                header: "X-EMILIA-Receipt: base64(...)" } }

→ POST /release-payment            X-EMILIA-Receipt: base64(<receipt>)
← 200 { released: true }

Run the whole loop end to end from a clean checkout: node examples/402-loop.mjs · or see a receipt issued + verified offline in 30s: npx @emilia-protocol/crash-test

STEP 3 · VERIFY OFFLINE

Check it yourself — no one’s word for it.

The same package exports verifyEmiliaReceipt(doc, opts) for programmatic checks, and any receipt verifies from the terminal with npx @emilia-protocol/verify receipt.json — asymmetric, offline, open-source (Apache-2.0). For MCP servers, @emilia-protocol/mcp-guard applies the same demand hook to a tool-call handler.

MCP tool guardingHow auditors verify
FREQUENTLY ASKED
Why would a service add 402 friction?

Because it converts "trust me, a human approved this" into portable, offline-checkable evidence — and it lets well-behaved agents self-serve authorization with no human in the support loop. 402 deliberately rides the same "challenge-to-transact" rail as agent-commerce conventions (x402 / AP2).

Do I need an EMILIA backend to verify?

No. Verification is offline and asymmetric: you hold the issuer public keys you trust and check the receipt locally. Nothing calls home. The middleware fails closed — no valid receipt, no irreversible action.

What about MCP tool calls?

Use @emilia-protocol/mcp-guard: it wraps an MCP tool-call handler so irreversible tool calls route through signoff and emit a receipt while everything else passes through — the same demand hook, returning a 402-style refusal.

The middleware fails closed: an absent, expired, tampered, or untrusted-issuer receipt is refused. Offline verification proves the receipt is authentic, intact, and bound to the exact action; it does not assert the decision was correct or identity beyond the enrollment layer. Open standard (Apache-2.0), IETF Internet-Drafts.

Require a Receipt in One Endpoint — the 402 loop for agent tools | EMILIA Protocol