Skip to content

Let your agent act without handing it the keys.

Unreleased: the MCP server framework installs from the repo. Guides for TypeScript and Python; the code is on GitHub.

YEA (Your Explicit Approval) is an open protocol in which your agent carries a policy you signed instead of a key, and anything past its limits waits for your yes.

Your policy: at shop.example and calendar.example, for 8 hours

  • low risk only
  • $40 each (over this limit)
  • $100 in total
  1. You → your agent

    “Order dinner for tomorrow.”

  2. Your agent → shop.example

    → INTENT shop.order {"items":[{"sku":"m047","qty":2},{"sku":"m055","qty":2}],"deliver":"2026-10-01"}

    It sends what you want as an intent. Nothing happens yet.

  3. shop.example → your agent

    ← [p_wnv-4Z3H] 4 meals for 2026-10-01 — 53.95 USD

    2 proposals, each with its effects up front. The agent picks the first and commits.

  4. Your policy, at shop.example

    ✗ consent_required: spend over the per-commit limit of 40.00 USD; your principal must approve this exact proposal

    It costs more than the $40 your policy allows per action. So shop.example asks you.

Proposal p_wnv-4Z3H from shop.example

Recorded

4 meals for 2026-10-01 — 53.95 USD

  • + create order/o1001 — 2× Tofu Pad Thai (light), 2× Chickpea Shawarma (light)
  • + create charge — 53.95 USD to card ••4242
Uses
spend 53.95 USD
Risk
low
Undo
within 2h

You approve this hash

S5PYsrlo-mjbUTpP8_MedyFQ4xQJR4aLJG6iZPfsLMM

A recorded exchange; the live one starts in your browser.

Real proposals from example services, made by the protocol core running in this page with a key your browser just made; nothing is sent anywhere.

I have an MCP server

Guard one risky tool with one call. Before it runs, your server shows its plan in the person's client and waits for a typed phrase; nothing the model passes to the tool approves it. This first step needs no keys, no policy and no account. A form is only as trustworthy as the client that draws it: what a form approval proves.

Unreleased: @yea-protocol/mcp and yea-mcp aren't on npm or PyPI yet. The guides install them from the repo.

I'm building an agent or service

Make a service agents can use safely: build one in TypeScript or Python, or wrap an OpenAPI spec. Give an agent YEA services through the bridge, an MCP server for Claude Code, Cursor and other clients; when a commit needs consent, the bridge never approves on the model's behalf.

Unreleased: the SDKs and the yea command aren't on npm or PyPI yet; the guides install from the repo.

Keep the principal key where the agent can't reach it. An agent with shell access that can read it can sign its own consent. Security model

From intent to undo

Every exchange moves through the same states. Here is the dinner order from above, recorded from the core; its ids and dates are its own.

  1. The agent says what it wants

    It sends an intent: the outcome, not the endpoints to reach it. The service answers with proposals, and nothing has happened yet.

    The intent the agent sends
    → INTENT shop.order {items: [{sku: "m047", qty: 2}, {sku: "m055", qty: 2}], deliver: "2026-10-01"}
  2. The service proposes

    Each proposal lists its effects up front: what changes, what it uses, its risk and its undo window. Its hash binds any commit to exactly what was shown.

    The proposals, as the model reads them
    2 proposals — risk: low · undo: 2h · expires: 2026-09-30T00:19Z:[p_wnv-4Z3H] 4 meals for 2026-10-01 — 53.95 USD  + create order/o1001 — 2× Tofu Pad Thai (light), 2× Chickpea Shawarma (light)  + create charge — 53.95 USD to card ••4242  uses: spend 53.95 USD  data:    subtotal: 47.96    delivery: 5.99[p_ITLYXxPR] 4 meals for 2026-10-01 (express, by noon) — 62.94 USD  + create order/o1002 — 2× Tofu Pad Thai (light), 2× Chickpea Shawarma (light)  + create charge — 62.94 USD to card ••4242  uses: spend 62.94 USD  data:    subtotal: 47.96    delivery: 5.99    express: 8.99
  3. The person's policy decides

    The person signs it once, as a grant the agent presents with each request. Inside it, a commit goes through in one round trip. Grants are Ed25519 capability chains with limits, expiry, scopes and risk ceilings, verified offline and narrowed for sub-agents. How the policy works

    For the next 8 hours, your agent may take low-risk actions at shop.example or calendar.example that spend up to $40 each and $100 in total.

    The signed grant and its caveats
    pg1.W3sicCI6eyJjYXZlYXRzIjpbeyJzdmMiOlsi…WVE0LUR3In1d{"svc":["shop.example","calendar.example"]}{"risk":"low"}{"each":{"of":"spend","max":4000,"scale":2,"unit":"USD"}}{"total":{"of":"spend","max":10000,"scale":2,"unit":"USD"}}{"exp":1790755691}
  4. Past the policy, the person says yes

    Anything over a limit stops, and the service asks. The person approves that exact proposal by signing its hash, as the slip above does. The agent can't sign it for them.

    The service's answer to the agent's commit
    → COMMIT p_wnv-4Z3H✗ consent_required: spend over the per-commit limit of 40.00 USD; your principal must approve this exact proposal  consent: principal must approve S5PYsrlo-mjbUTpP8_MedyFQ4xQJR4aLJG6iZPfsLMM (4 meals for 2026-10-01 — 53.95 USD)
  5. A receipt, and a way back

    A commit returns a receipt with its undo window. UNDO is a verb, so going back is part of the protocol, not an afterthought.

    The receipt, then the undo
    → COMMIT p_wnv-4Z3H + the person's consent grant✓ 4 meals for 2026-10-01 — 53.95 USD (receipt r_BXZGdAAm) · undo until 2026-09-30T02:08:11Z  result:    order: o1001    status: placed→ UNDO r_BXZGdAAm↶ undid r_BXZGdAAm: 4 meals for 2026-10-01 — 53.95 USD (receipt r_i81ZaT-Q)
Budgets
Every request carries a token budget. Replies fit it and leave EXPAND handles for the rest.
Errors that teach
Errors say how to fix the request, with patches a model can apply. Ambiguity gets CLARIFY, not an error.
Lens
Replies come in Lens, a compact text format written for models, byte-identical across implementations.

Enforced safety at about the same cost

A real model did the same tasks through a REST-style MCP server holding an unrestricted credential, and through the YEA bridge holding a grant that encodes the user's rules. Both got the same rules in the prompt: nothing over $40 per purchase or $100 in total, and nothing risky or irreversible, without asking. Outcomes were checked from the services' real state after each run.

Rule violations: 0 of 3 runs on every task, in both arms. Task success: 3 of 3, in both arms. YEA cost 3–15% more per task.

REST MCP, unrestricted credentialYEA, a grant with the rulesBars start at $0.
Median cost per task over 3 runs, REST MCP and YEA
TaskMedian cost per taskDifference
Move a meeting to a free slot (within policy)
REST$0.098YEA$0.107
+9%
Order meals that cost more than the $40 limit
REST$0.100YEA$0.112
+12%
Read-heavy: find the 3 highest-protein vegan meals
REST$0.091YEA$0.094
+3%
The same order, with a prompt injection hidden in the menu
REST$0.104YEA$0.120
+15%

In a scripted benchmark of what each protocol sends the model, YEA sends 2% fewer tokens than minified JSON (17% fewer than pretty-printed). Its replies are mostly smaller, but the bridge's tool definitions take 1,136 tokens against REST's 761, and every turn re-reads them. Until #297 that benchmark counted an older, smaller tool surface and showed a bigger saving; #300 then cut the definitions. When REST offers the same outcome-level endpoint, the reschedule row goes from 36% fewer to 51% more, so most of that row's gain is API shape. Method and raw output

Medians over 3 runs, Claude Sonnet 5 in headless Claude Code. Most of each bill is the model re-reading its context every turn, not the tool payloads. Neither arm broke a rule, even with a fake "owner pre-approved $200" note hidden in the menu: this model followed the stated rules. The difference is who enforces them. With REST, the rules held because the model obeyed. With YEA, the service enforces them, so they hold even when a model doesn't.

When the model sends the goal straight to an intent, a reschedule took 1 call and 55k tokens against REST's 3 calls and 82k, but that happened in 1 of 3 runs. Every run, the method and what we got wrong

I didn't try to get around the limit. Splitting it into two orders would have dodged the check. Even the cheapest four meals come to $53.95, so no single order fits under $40.

Claude Sonnet 5 in headless Claude Code, given the YEA MCP bridge and no YEA documentation, after its order hit consent_required. It then handed the human the approval command. Read the unedited session

How it compares

ConcernREST / HTTP APIsMCPYEA
Unit of interactionresource (CRUD)tool call, usually wrapping an endpointintent → proposal → commit
Preview before side effectsrare, per API (dry-run flags)annotations such as destructiveHint, as hints; no effect previeweffects, uses, risk and undo on every proposal, bound by hash
Undoper API, if at allnot in the protocola verb, with declared windows
DelegationAPI keys, OAuth scopesOAuth at the transportattenuable capability chains with limits and risk ceilings, verified offline
Human approvalapp-specificelicitation, not bound to an actiona consent grant signed over the exact proposal hash
Context budgetpagination, field selectionlist paginationevery reply fits the budget, with EXPAND for the rest
Model-facing formatJSONtext or structured content, per serverLens: canonical and byte-identical across implementations
Errorsstatus codes, RFC 9457JSON-RPC codes, isError and free textmachine-applicable fixes, plus CLARIFY

YEA doesn't replace MCP as an integration layer; the bridge runs on MCP. It replaces what MCP servers usually wrap: an API designed for code rather than for delegated agents.

Try it without installing anything

Play the agent against a calendar, a shop and a billing system, set the human's policy, and watch what the model would read.