Inspiration

Agent usage keeps growing, but the shape of it generally doesn't change; go to a chat window, describe the thing, then wait until it comes back. This means the agent is never working in the room with you.

That's what I wanted to experience: where the agent and user are on the same surface at the same time, simultaneously reaching for things. And more specifically, when the agent isn't the app's own. Notion's AI works, but it still doesn't feel like you're working together with it.

What it does

It's an infinite sticky-note canvas. Open it in multiple windows, and now you have several people each with their own agent, all editing the same board live. There's no server holding state, the tabs sync directly, and the board lives in the browser.

Any agent with WebMCP capabilities can join by calling the eleven tools the page puts up. It can read the board, ask what's changed since it last looked, ask what the humans are doing right now, arrange things, draw links between them, annotate, collapse a cluster into a summary, add notes, or propose reorganizing the whole thing.

An important part is that it can refuse agent actions, taking into account interactions between humans and other agents.

How we built it

Some brainstorming and then AI building tools. Stack was React 19, Vite, TypeScript, React Flow for the canvas, Zustand for scene state, and Yjs with awareness for peer sync over BroadcastChannel.

Also, agent actions all go through one wrapper that gives them a body on screen, which includes a cursor, a visibly held note, and motion that takes time. Without that, an agent taking actions just looks like notes teleporting.

Challenges we ran into

  • The biggest one was realizing that a refusal has to be a return value and not an error. If you throw at a model it just tries again. If you tell it what it ran into and who got there first, it usually does something sensible instead. That changed the shape of every tool.

  • WebMCP also has no way for a tool to ask the user anything, which is awkward when your whole thesis is asking permission. The handler for the destructive tool ends up just sitting there and waiting while a dialog goes up in every tab. Deciding that silence should count as a refusal rather than approval took longer to settle than the code did.

  • Then there was a bug where the two tabs weren't in the same room at all. The room was keyed off the whole URL, so a tab carrying an extra query parameter quietly joined a room of its own. Both windows looked perfect on their own, which is what made it bad. Every cross-tab guarantee was untested and I didn't know it.

Accomplishments that I'm proud of

I think this is a good exploration into how multi human-agent interactions working together in the same room would look like in the future. It doesn't run with a server, and you can actually see multiple agents working side by side with humans.

What I learned

Notion's last write wins policy works for now, but what'll happen when dozens of agents are working on the same thing at the same time? I think that's what the future holds and it makes me realize that the current systems are not built at all for that kind of scale.

Why WebMCP Fits

This is about an agent being outranked; by a hand, by the room, or by the board moving while it thought. None of that exists outside the page: a hand on a note lives 300ms and never reaches a database. A server can't see it, and automation is the user, so there's nobody to yield to. WebMCP is the only shape where the agent is a guest.

What's next for Co-Presence

Not too sure to be honest, but I can envision this system being used for other applications as well, not just note taking.

Built With

  • react-19
  • react-flow
  • react-flow-for-the-canvas
  • typescript
  • vite
  • yjs
  • zustand
  • zustand-for-scene-state
Share this project:

Updates

Submission history