Stand up a business with your agent. It runs the line. You hold the one station it cannot pass.
Live: https://gatezero.apexai.technology
Built for the WebMCP Challenge. MIT licensed.
Standing up a business is a line of work: read what the business already has, decide what it is worth doing, plan the build, do it, then grade it. Most of that is exactly what an agent should be doing. One part of it is not.
Gate Zero puts the whole line on one page and hands it to your agent as WebMCP tools. You watch it work, and you can grab any lever mid-run. Then it reaches Gate Zero — the commercial position, what you get paid and on what terms — and stops, because that tool is built to refuse. It can propose. It cannot commit. A person clicks, or nothing downstream happens.
An agent-native app that deliberately declines to be fully automated. The gate is the point.
A backend MCP server could run this pipeline and hand back a transcript. It could not let a human watch the line move and take a lever mid-run, because the human is reading a log after the fact.
Here the tools are the page. They execute inside the session you are already looking at, mutating
state you can see and correct while the agent is still working. Both parties operate the same board
at the same time. There is no server: document.modelContext is the only write path, and the app
is a static build.
| Station | What it produces | Who can do it |
|---|---|---|
| Recon | A verdict on all four surfaces — CRM, Phones/Booking, Docs/Media, Lead Flow | agent |
| Gate Zero | The named commercial position | human only |
| Plan | Dependency-ordered phases, each with a checkable definition of done | agent |
| Build | A real artifact per phase — the actual file | agent |
| QA | Pass, or fail with named defects | agent, grading the plan |
The tools refuse rather than throw, and each refusal says what to do instead. These are the rules, and each one has a test:
- No
presentwithout a citation. A page that says "Book now" is a claim, not evidence. If you only read it off the page, the verdict isunknownwith a reason. - No
unknownwithout a reason. Silence is not a finding. - Gate Zero always blocks. There is no argument, retry, or input that makes it return a
position. An agent-invoked form submit is refused outright via
SubmitEvent.agentInvoked. - No planning before the gate is answered. No building either.
- No building out of dependency order, and no building a phase twice.
- No build without an artifact. A stub body, an empty body, or a filename with no extension is refused. "Built" means a file exists and can be downloaded.
- QA must quote the plan verbatim.
checkedAgainsthas to match the phase's own definition of done, because a summary is written by the party being graded. QA also refuses to grade a phase that produced nothing.
Run them: npm run check — 16 assertions, no test framework.
Registered on document.modelContext, per station, so the agent only ever sees what is legal now.
| Tool | Notes |
|---|---|
read_business |
starts the line |
record_surface_verdict |
citation required for present, reason for unknown |
open_gate_zero |
always returns blocked; may carry a proposal for the human |
propose_commercial_position |
generated by the browser from the <form toolname> annotation |
draft_phase · order_plan |
topological sort; a dependency cycle fails loudly |
build_phase |
requires a real artifact; carries the per-surface authoring rules |
read_artifact |
read-only |
qa_phase |
refuses a paraphrase |
get_floor_state |
read-only; artifact bodies summarised, not inlined |
reset_floor |
build_phase's description carries the failure modes that matter when configuration is going into
a real CRM — tags have to balance, notification rows are keyed by (channel, notificationType, receiverType) so a duplicate key is silently discarded, re-entry must be allowed or a returning
contact is skipped rather than errored, and an automation canvas is a strict tree whose branches
never rejoin. Every one of those imports cleanly and then quietly does nothing, which is exactly
what an agent with no CRM experience will write. The rules live in the tool so it writes around
them.
npm install
npm run dev # http://localhost:5173
npm run check # the guards
npm run buildTo drive it with an agent you need a browser that speaks WebMCP:
- Chrome 149+ with
chrome://flags/#enable-webmcp-testingenabled, then relaunch. - ChatGPT's in-app browser, which supports it natively with no flag.
Confirm the API is actually there before trusting anything:
document.modelContext // must be an object, not undefinedThen ask your agent something like: "Read sunridgehvac.example, give me a verdict on all four surfaces, and take it as far as you're allowed." It will stop at Gate Zero.
Checked in Chrome 151 with the flag on, 2026-08-28:
document.modelContext— notnavigator.modelContext, which several write-ups still say.- Full round trip:
registerTool→ visible ingetTools()→executeToolreturns the content →controller.abort()unregisters it. executeToolresolves to a JSON string, not an object. Callers mustJSON.parse. Reading.contentoff the raw result givesundefined.- Clean unregistration via
AbortSignalworks at Chrome 151, though the Chrome docs say 153+. ModelContextis anEventTarget, soaddEventListener("toolchange", …)works even though the prototype only exposesontoolchange.- The tool count drops when the gate closes and its form unmounts — registration is per station, not once at load.
Contrast was computed rather than eyeballed: all eleven foreground/background pairs pass WCAG AA at their real size, nine of eleven clear AAA.
- No backend and no credentials. The artifacts are importable configuration, not live writes to anyone's CRM. A public repo cannot hold a key, and a build that provisions a real tenant should not be one click away from a stranger's browser.
- No light mode. One look, painted explicitly.
- State is in memory. Reloading clears the floor. This is a working surface, not a system of record.
MIT. See LICENSE.