Semorel - client-side AI agent SDK
Let trusted AI agents
use your app - safely,
in-session.
Semorel is a drop-in, client-side SDK. Agents read what is on your live app right now and can invoke only the actions you authorize - no scraping, no screenshots, no backend changes.
<!-- drop the SDK into a running app -->
<script src="semorel.js"></script>
// reading is automatic, from the page's
// own HTML5 / ARIA / JSON-LD semantics.
// invoking stays opt-in, per action.

What you get
One tag in. Agents that read, and act only where you say.
Semorel gives an agent the meaning of what is on screen and a short, curated set of actions - governed by your rules, confirmed outside the page.
Adopt
One tag to adopt
Drop a single script into your running app. No backend changes, no rewrite, no parallel state to hand-author.
Read
Reads your app's own meaning
It reads the semantics your app already declares - not screenshots, not scraped pixels.
Invoke
Actions are opt-in
Nothing is callable until you curate and authorize it, one action at a time.
Consent
Confirm outside the page
Sensitive actions prompt in the browser extension, where a web page cannot click Allow for you.
Govern
Policy, redaction and consent
Rules you declare decide what leaves the app; passwords and hidden fields stay out by default.
Provider-agnostic
Works with your agent
Anthropic, OpenAI, Gemini, Ollama and more - swappable live, mid-session.
The model, in order
Derive, curate, invoke.
Semorel follows one ordered path. The DataDocument is derived from the meaning your app already declares, you curate the short set of actions an agent may use, then the agent invokes only what you authorized - nothing is callable by default.
01
Derive
DataDocument read from your app's own semantics
02
Curate
You author the short set of opt-in actions
03
Invoke
The agent calls only what you authorized
How it reads
Read by derivation, not by scraping.
- Reads the meaning your app already declares
- No screenshots, OCR or scraped pixels
- Survives a redesign or an A/B test
SemanticsWho stays in control
The app stays in control of what leaves it.
- Curated, opt-in actions - nothing callable by default
- Passwords and hidden fields redacted by default
- Confirmation prompts render outside the page
ConsentWhere it fits
Where Semorel fits.
Semorel is not a replacement for server-side MCP - it is the situational half, reading live in-session state a backend never sees. Here is how the ways to drive an app trade off, plainly.
Fair read: server-side MCP owns the backend, and an agent connected to both gets backend reach and live in-session context through one coherent, MCP-compatible model. Semorel adds the situational surface the server never sees - it is the complement to MCP, not a competitor. Tesseron / WebMCP and accessibility automation keep their own real strengths.
Under the hood
Read by derivation, invoke by curation.
The story above is the plain version. For evaluators, here is how it actually holds together - a client-side SDK that reads the app's own semantics, curates the actions you choose, and keeps the consent boundary outside the page. It is MCP-compatible: the same tools / resources vocabulary, but the surface lives inside the running session.
From ViewDocument to DataDocument
Every app renders a ViewDocument - pixels built for humans, brittle to read. Semorel derives the other one: a canonical, semantic projection of what the app means right now, read from the declarative signals the app already emits. A snapshot plus a MutationObserver diff stream keeps it live.
Review your booking
form: payment
method: card - save card
{
"screen": "booking_review",
"entities": {
"booking": {
"destination": "Dubai",
"amount": 120000,
"departure": "2026-06-12"
}
},
"forms": { "payment": { ... } }
}
// snapshot + a diff stream, so agents track
// live state without re-reading it all.
Derived from
Reading is automatic, invoking is a decision
The two halves have different cost and safety profiles, so Semorel treats them differently: deriving state is on by default; invoking an action is opt-in, per action. The only per-screen work is filling in handler bodies - not authoring registration boilerplate.
Derive
automaticDrop in the SDK. A DOM walker builds the DataDocument and discovers action candidates from the semantics the page already declares - no parallel state object to hand-author.
Curate
you authorRun semorel discover to generate typed *PageActions stubs, then fill in a manifest and a handler body. One class per route, in a dedicated src/semorel/ folder.
Invoke
opt-inNothing is callable until the app marks it agent-eligible. The agent reads the document, finds the curated tools, and invokes only what you authorized.
{
"name": "confirm_booking",
"description": "Confirms the displayed booking.",
"requires_confirmation": true,
"input_schema": { "type": "object" }
}
// curated metadata, reviewable in a PR
// diff as a security artifact.
useSemorelTool("confirm_booking", {
requiresConfirmation: true,
handler: confirmBooking
});
// mark it invocable, attach a handler,
// require confirmation. that is all.
The consent boundary sits outside the page
A Chrome side panel presents the app's tools over an MCP-compatible surface. When an agent calls an action marked requires_confirmation, the prompt renders in the extension chrome - outside the page's React tree. A malicious page cannot reach in to auto-click Allow.
Book SFO -> JFK on 2026-06-01, cheapest.
reading DataDocument
Found trip.book. This action needs confirmation.
confirm - trip.book
SFO -> JFK, 2026-06-01. Charge 420 USD to saved card?
rendered in extension chrome - the page cannot click this
Seven packages, DOM walker to agent
- @semorel/coreRegistry, DataDocument, MCP dispatcher, redaction, policy
- @semorel/webDOM extractor + the drop-in script bundle
- @semorel/reactSemorelProvider + router / query / hook-form adapters
- @semorel/clidiscover / check / init - codegen and CI drift
- @semorel/agentReference MCP client
- @semorel/extensionChrome side panel - Chat / Audit / Logs / Settings
- @semorel/bridgeLocal daemon that connects vendor MCP hosts
Provider-agnostic: Claude Code and Codex connect via a local bridge daemon; Anthropic, OpenAI, Gemini and Ollama connect directly; Groq via an OpenAI-compatible path.
A CLI that scaffolds, a CI gate that catches drift
This is what makes an app agent-drivable without hand-registering every action. semorel discover walks your routes and generates typed *PageActions.ts stubs - regeneration is lossless, preserving every dev-edited handler. semorel check fails the build when the on-disk manifest drifts from the captured semantics.
$ semorel discover
// walks routes, captures candidates
create src/semorel/HomePageActions.ts
create src/semorel/ResultsPageActions.ts
✓ 2 files - dev-edited handlers preserved
$ semorel check --audit-file results.json
✓ / in sync
✗ trip.book in audit, not in manifest
error: manifest drift - exit 1
// exit 1 fails the CI job.
export class HomePageActions extends AuthoredActions {
tripSearch() {
const action = new AuthoredAction({
name: "trip.search",
inputSchema: { type: "object" },
});
action.invoke = this.tripSearchInvoke; // fill this in
}
}
// pages stay Semorel-unaware; you edit
// only files under src/semorel/.
Policy modes, from live to locked down
Policy is an in-app layer, enforced before any state or action reaches an agent, with conservative defaults that respect what the author already declared. Pick the posture that fits your risk.
The auto-derived DataDocument flows to trusted agents, subject to your redaction rules. The pragmatic default for reading, which is observable in dev tools anyway.
Redaction defaults (declared intent)
- <input type="password">excluded
- aria-hidden="true"excluded
- [data-semorel="private"]excluded
Semorel enforces what you declare; it does not heuristically pattern-match for PII. A preview run sits alongside your existing GDPR / SOC2 / HIPAA / PCI review.
Request a pilot
Make your web app agent-drivable - safely, semantically, in-session.
Semorel is provider-agnostic and complementary to server-side MCP - a live, situational surface from inside the running session. It is private and unpublished today: access is clone-and-build, with no public npm or download command. If you are building agent-native workflows, we would like to compare notes.
Private / unpublished - clone-and-build access only