SamePage is one running surface where a person and an agent work on shared state. The agent can author the surface, the person can drag and mark it, and the host stamps every write with the participant who made it.
The surface describes layout as relations such as "right of" and "top edges aligned." Coordinates never cross the agent boundary. A rendered report or a chat preview is not a same page because the person cannot act on the same artifact or dispute it in place.
Because the host stamps every write, a session is also a record: who put each
thing on the page, who disputed it, and who agreed. Getting on the same page
and being able to prove you were on it are the same mechanism. The stakes rise
in that order wherever agents work beside people: first who contributed what,
then what was decided and by whom, then what was committed and under whose
authority. The record's shape is published early on purpose, as
docs/record-shape-v0.1.md with a validator
crate, so any surface can adopt it. Trust labels are part of the schema: a
claim the host cannot verify stays labeled as claimed instead of hardening
into fact.
The room example below is one surface built this way. The general case is any place a person and an agent need to look at the same thing and settle what they see.
- Agent-authored views: panes over a typed view vocabulary, no frontend build step.
- Human marks and notes: a browser-only channel refused to agents by the shared action dispatcher.
- Relational read-back: the agent reads the surface and its changes without receiving browser coordinates.
- MCP attachment: an outside terminal agent joins through the runtime's
authenticated
POST /mcpendpoint under its own name.
- Host-stamped bylines: human and attached-agent identities are minted or admitted by the host, not accepted from action input.
- Transport-derived authority: what a request may act as comes from its credentials. The request body can narrow that authority, never widen it, and ambiguity fails closed.
- Record shape v0.1:
crates/ag-ui-recordvalidates a session record against the published shape, including hash-linked settlement receipts.
crates/
samepage public crate-name placeholder
ag-ui-core AG-UI protocol types
ag-ui-surface application runtime, actions, identity, and MCP
ag-ui-record session-record shape validator
ag-ui-canvas* shared canvas state and rendering
ag-ui-component* portable component contract and host
ag-ui-eval deterministic and real-agent evaluation runner
examples/
same-page-room runnable shared room on port 8100
same-page-atlas runnable shared map of a project on port 8098
docs/
ag-ui-surface-spec.md
ag-ui-extension-architecture.md
evaluation-layers.md
record-shape-v0.1.md
demo-runbook.md
The root Cargo.toml is the source of truth for workspace members.
Both apps compile part of themselves to WebAssembly on first run. Install the three pieces once:
rustup target add wasm32-unknown-unknown
cargo install wasm-pack
cargo install wasm-opt --lockedCheck they are on your PATH with wasm-pack --version && wasm-opt --version.
The room starts without them but reports its protocol client as unavailable.
The map refuses to start without both.
From the repository root:
AGUI_MCP_TOKEN=local-room-token cargo run -p same-page-roomOpen http://127.0.0.1:8100. There is no frontend build step: the typed
protocol client builds itself on first run if wasm-pack is on PATH
(install it with cargo install wasm-pack); without it, the room still
starts and the page reports the protocol as unavailable instead of guessing
at it in JavaScript.
The room starts without an in-page model by default. Your own coding agent joins from outside over MCP, and it needs the room's token to do that.
The token is a password you make up for this room. It is not an API key,
you do not sign up for it, and no service issues it. Pick any string, start the
room with it in AGUI_MCP_TOKEN, and give the same string to the agent you
want to let in. local-room-token above is only a placeholder; any value
works, as long as the room and the agent use the same one.
The agent sends that value as Authorization: Bearer <your value> to
POST /mcp. If you start the room without AGUI_MCP_TOKEN, it makes up a
random one per process that only its own subprocess can see, so no outside
agent can attach. The atlas uses AGUI_MCP_TOKEN the same way and prints the
exact attach command, token included, when it starts.
Initialization returns an Mcp-Session-Id. Every later MCP request must send
that header and MCP-Protocol-Version: 2025-06-18. Omitting the session header
does not borrow another participant's identity. The host signs resulting
writes with the generic agent byline.
Read AGENTS.md for the attachment contract and repository rules.
The room agent's standing contract is
examples/same-page-room/prompt.md.
The room is one shared surface. The atlas is another: instead of panes it draws a map of a project, agent and person editing the same CRDT document. From the repository root:
AGUI_MCP_TOKEN=local-map-token cargo run -p same-page-atlasOpen http://127.0.0.1:8098. The first run builds the browser replica with
build-web.sh, which needs wasm-pack and wasm-opt from
Before you start.
The map is most useful on code you can judge. Point it at a project you already know well, so you can tell at a glance whether the picture is right:
AGUI_PROJECT_ROOT=/path/to/your/project \
AGUI_MCP_TOKEN=local-map-token cargo run -p same-page-atlasThe canvas starts blank: "0 components · 0 relationships". The map does not draw your project for you yet. The picture comes from your own coding agent, attached over MCP with the token you picked, the same way as the room (AGENTS.md has the attach steps). Once it is attached, ask it:
Read the map with
atlas_read. Then draw this project's architecture withatlas_diagram: one container per major part, cards bound to real files withpathandlines, and links for how the parts depend on each other. Read the map again and fix every item under PROBLEMS withatlas_placeuntil PAGE VALIDATION says passed.
The header reads "Page checks passed" when the layout has no overlaps or
unroutable links. The extractor behind the map reads Rust and
JavaScript/TypeScript projects today; crates/samepage-extract documents what
it can and cannot see.
To see the same picture shown in the demo, run the map on this repository
(leave out AGUI_PROJECT_ROOT) and ask your agent to draw how the room and
the map relate: a container for the shared runtime (crates/ag-ui-surface),
one each for examples/same-page-room and examples/same-page-atlas, and one
for the project both read, with cards bound to the files that implement each
part. The same request above works; name those four parts in it.
In Map and Cement mode a strip along the bottom reads "Found in the code, not in the agreement" with a count: every binary, listener, and spawned process the extractor found that no card claims yet. It starts collapsed to that one line; Show opens the cards, each with Claim and Remove buttons. The count depends on the project and drops as cards claim lanes. Explain mode hides the strip.
The map has three modes, always visible in the header alongside a page-check status such as "Page checks passed":
- Explain is a sketch. The agent lays out what it believes a project looks like, with no source binding yet.
- Map is where a card earns proof. A verified card is bound to a real file, revision, and line range the host checked; an undeclared card is a lane the extractor found in the running project (a listener, a spawned process) that no card has claimed yet, and cannot be dismissed as long as it is unaccounted for.
- Cement turns an agreed part of the map into G8 obligations: checks that start red and turn green only as the real code that satisfies them gets built.
The room is about one project at a time. By default that is this repository. To get on the same page about a different one, name its root at launch:
AGUI_PROJECT_ROOT=/path/to/your/project \
AGUI_MCP_TOKEN=local-room-token cargo run -p same-page-roomEvery source pane then reads files under that root and nowhere else, and the
"what this workspace can run" pane lists that project's runnable packages.
Today that catalog understands Cargo workspaces only. A single-crate or
non-Rust project shows no runnable packages until its files are opened through
source panes.
The run command above does not return. An agent running it in the foreground blocks on it. The recipe for an agent is:
- Start the room in the background and capture its log.
- Wait for the line
listening on http://127.0.0.1:8100. - Open that address for the person, or tell them to.
- Attach over
POST /mcpwith the same token, as described in AGENTS.md, and callread_roombefore writing anything.
The person looks at the browser. The agent looks at read_room. That is the
whole point: two seats, one artifact.
This section is informational. It describes planned work, not shipped behavior.
The map above is an example application exported from the lab where it was
designed. It carries everything built there, including parts that will not
ship by default, such as image segmentation and agent ink. Its browser
replica is one WebAssembly binary with all of it inside: 1,501,801 bytes
(stat -f %z examples/same-page-atlas/web/pkg/same_page_atlas_web_bg.wasm
after a first run on macOS).
The plan is to break it apart:
- Composable primitives. The pieces every capability relies on stay in the host and load for every page: identity and authority, actions and MCP attach, the shared CRDT document, and the record of who did what.
- Capabilities with plain names. Each capability becomes its own module
that registers against those primitives and does not depend on the others:
map(cards, links, containers, layout, page checks),sources(binding a card to file lines, drift, trust tiers, the legend),lanes(the found-in-the-code strip),cement(Explain, Map, Cement and the handoff to G8),sketch(shapes, arrows, text,.excalidrawin and out), andpanes(the room's view vocabulary). - Lazy loading. Each capability ships as a separate WebAssembly module that loads only when a page uses it, so a user downloads the capabilities their task needs instead of one binary with everything.
- One default. A single SamePage app, not a set of examples, whose first
run looks like the demo:
map,sources,lanes,cement, andsketchon the user's own project. Image segmentation stays out of SamePage as a separate crate. Agent ink is out of the default until it earns a place.
When that lands, the two examples here are replaced by the one app, and this README changes to match.
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p same-page-room
cargo test -p same-page-atlas
cargo test -p ag-ui-recordCompiler and test success do not prove browser rendering or a real agent loop. Those are separate claims and need separate evidence.
The enforcement layer is G8, pronounced "gate". It turns what people and agents agreed on here into machine-checked obligations that coding agents build against. Cement the agreement before the code exists. Every gate starts red. Building the code is the act of turning the gates green, and a gate that goes red again is drift.
The internal crates still carry their ag-ui-* extraction names while the
public API consolidates under SamePage.
MIT