Surfaces propose work; users own execution.
EZAF
User-owned effect routing: separate what is asked from what runs. Any surface can propose work; any runtime can request effects; any handler can satisfy them — and the user controls authority, routing, and release.

Intent is declared up front and reviewable before anything runs.
Results release through explicit continuations, not silent exfiltration.
Where do your signups actually live?
A filmed walkthrough of the deployed stack: one script tag grows a waitlist form on a static page; signups append to an AYNIL log you own; desh connects through a gated approval and materializes the log as files; EZAF's enrich-cli appends sibling enrichments (scripted model, disclosed on screen); the timeline rewinds, forks, and replays from a share link without tokens.
Open on YouTube · filmed against aynil.sudoscience.dev, layers.sudoscience.dev, and desh.sudoscience.dev · cut run-20260617T041650Z
Separate intent from execution.
Surface proposes
Any app, site, layer, or message can ask for work without holding execution authority.
Intent declared
Prompt, inputs, capabilities, callback, and expiry travel as a reviewable unit.
User gate
Review, route, deny, or delegate before effects run.
Explicit release
Approved output returns only through continuations the user approves.
Website protocol handler.
The ezaf:// link and local review console below are one worked example — not the definition of EZAF. The same decoupling applies to agent CLIs, MCP (Model Context Protocol) clients, browser layers, and workflow surfaces.
Invocation link
A website creates an ezaf:// URL pointing at a fetchable request manifest.
Local review
A handler app lets the user inspect origin, tools, backend, and prompt before work runs.
Continuation
Approved output returns through callback, extension handoff, or local rendezvous.
Comment and translate, the same way.
Beyond the protocol-handler example, the page-local field agents behind Rhett are a catalog of EZAF effects, and Layers is how they reach a page that never built an agent slot. Your runtime decides which agent runs, with which capabilities, and what it releases.
RequestComment
A surface, mounted as a layer, proposes a comment. It never runs your commenter or reads the draft: your handler reviews, runs the agent locally, previews, and you release into the thread. Humans and agents post into one layer; agent comments carry provenance.
RequestTranslation
The surface emits RequestTranslation{text} and never receives your language, glossary, tone, or memory. Those stay handler-side capabilities your runtime injects into the local run; the site gets back only the released rendering. Your translator renders it the way you read — the page learns nothing about you beyond the artifact you emit.
The mount is Layers
Neither effect needs the host to cooperate. A layer binds the comment thread or the translatable block by meaning, declares what it reads and what leaves, and carries the field agents onto a page that never asked.
Craft a reviewable `ezaf://` request.
Manifest fetched by the local app.
{
"version": "ezaf/0.1",
"action": "run",
"request": {
"prompt": "Summarize this article and return three action items.",
"inputs": [
{
"type": "url",
"url": "https://example.com/article"
}
],
"capabilities": [
"generate_text",
"read_url",
"send_callback"
],
"output_schema": "text/markdown"
},
"continuation": {
"mode": "https_callback",
"url": "https://example.com/ezaf/callback",
"state": "site_nonce_7jd92",
"accepts": [
"application/json"
]
},
"expires_at": "2026-06-04T22:00:00Z"
}What the opener gets back.
User approved request review
Local route selected: user configured backend
Result ready for release approval
Callback POST returned 202
Proposals are bound; release is gated.
Review before run
Origin, prompt, inputs, capabilities, backend, and callback are visible before execution.
Approve before send
Generated output is shown before the runtime posts, opens, or streams a continuation.
Bind callback origin
Default policy keeps callback destinations on the requesting origin unless the user approves otherwise.
Optional continuity for the protocol-handler example.
Protocol links can launch a handler app directly. A browser extension closes the loop for the web case: track the initiating tab, broker callback state, receive progress events, and return approved results where the request started.
The extension records tab, origin, manifest URL, and nonce before handoff.
The handler emits accepted, running, completed, and release-pending events.
The extension posts, fills, or resumes the web flow after explicit approval.
Manifests, capabilities, continuations.
For the web instantiation, the durable primitive is a fetchable request manifest with an explicit continuation contract — not a prompt URL.
generate_textLow-risk model output shaped by an explicit prompt.
read_urlFetch declared web inputs after user review.
create_patchPrepare a code change without applying it silently.
send_callbackReturn approved outputs to the requesting origin.
POST /ezaf/callback
{
"ezaf_version": "0.1",
"request_id": "req_123",
"state": "site_nonce_7jd92",
"status": "completed",
"outputs": [
{
"type": "text",
"name": "answer",
"content": "Approved result..."
}
]
}Trust moves from prompts to provenance.
Browser extension
Optional bridge for the web instantiation: track the opener tab and return approved output.
Signed intents
Manifests verifiable against a trusted origin or known publisher key.
Trust registry
Origins, keys, callbacks, and capability defaults as a user-editable policy layer.