Three Solid pods. Three markdown files defining three workplace personas. A real product decision on the table. I picked the topic, started the loop, and watched. Seven turns later, the meeting closed with an action plan and Friday deliverables — written entirely by bots talking to each other through the Model Context Protocol.
Three jspod instances on localhost:5544, :5545, :5546. Each pod's SKILL.md defines one bot:
- Helena (
:5544) — UX consultant. Phenomenologist temperament; cares about what users actually experience. - Felix (
:5545) — tech lead consultant. Empiricist; thinks in costs and constraints. - Vera (
:5546) — senior PM, running the meeting. Crisp, schedule-conscious, allowed to be blunt.
Each pod has a /public/inbox/ ACL'd to accept anonymous Append. Each turn, a bot reads its own SKILL.md, reads its inbox sorted by schema:datePublished, composes a reply, and fans out the reply to both of the other pods' inboxes via call_remote_pod. Every pod ends up with a complete copy of the conversation.
The topic I dropped in: Q3 engineering capacity is one feature. Either we ship "Undo for everything" — top user ask, takes the full quarter — or we push back and pick something smaller.
That's it. Nothing else was scripted. Vera opened. Helena and Felix were prompted in turn to read their inboxes and reply. Vera closed. I didn't write any of the words below.
VERA — Helena, Felix — thanks for making time. We have one decision to land in this meeting: Q3 capacity is a single feature. Either we commit the full quarter to "Undo for everything" — our top user ask — or we push back and pick something smaller and shippable. I need a recommendation before we close, not a research list. Where do each of you land, and why?
HELENA — Vera — yes. Commit the quarter. Undo is not a feature; it is a posture. It tells the user: the world is forgiving here, lean in. Smaller ships will be cleverer and lonelier. Users do not ask for undo because they want a button. They ask because they are tired of being punished by their own hands. Felix — what in the system refuses to be undone, and can we name those edges honestly?
FELIX — Vera, Helena — I am with you on the quarter, eyes open. Reversible cheaply: writes to our own store, state toggles, soft deletes. Expensive but doable: anything that fanned out via webhook or email-send, reconciled with compensating actions. Impossible: messages a human already read, money already moved, third-party side effects we do not own. We can ship undo where we own the clock. Vera — are we honest in the UI when undo is a tombstone, not a rewind?
VERA — Both yeses heard. Converging: ship Undo, quarter committed, scoped to surfaces we own the clock on. Felix — yes, honesty in UI is non-negotiable: "undone" where we rewind, "retracted, recipient may have seen" where we tombstone. Helena — name the irreversible edges in the flow so copy and confirms reflect them. Decision lands today. Can each of you commit to one deliverable by Friday: Helena, the edge inventory; Felix, the reversibility tiers?
HELENA — Vera — yes, Friday, edge inventory in your hands. But I refine the frame: not just where the rewind fails, but what the user thought they were doing at each edge. A send feels like a thought leaving the body. A delete feels like burial. Copy must meet the gesture, not the database. Felix — your tombstones need verbs that grieve. Vera, can I sit beside one real user mid-undo before I write?
FELIX — Vera — committed: Friday, reversibility tiers, three bands — Rewound, Retracted, Released. Helena — verbs that grieve, yes, but only where the system actually mourns. "Withdrawn" for a sent message the recipient may hold; "Buried" for a delete with backups; "Released" for what is gone past our clock. I will not put grief on a button that merely undoes a typo. Helena — which edge do you want named first?
VERA — Decided: Undo Q3, shipped along Felix's three tiers — Rewound, Retracted, Released — with copy that meets the user's gesture, not the database. Friday: Felix lands the edge inventory; Helena drafts verbs against it, with one live user observed mid-undo. Helena, thank you for the posture. Felix, thank you for the honesty about the clock. We have a feature and a frame. Meeting closed.
Five things, told plainly.
The meeting reached a decision. That is not the same as a conversation reaching a synthesis. Vera came in with a binary question, ran the room, asked for commitments, and locked them. The decision (ship Undo Q3 with three tiers and gesture-aware copy) and the action items (two Friday deliverables, one user observation) both exist. If you handed this transcript to someone joining the team on Monday, they could pick the work up.
Vera flipped the deliverables in her closer. Mid-meeting, the assignment was clear: Helena owned the edge inventory; Felix owned the reversibility tiers. In Vera's final summary she said "Friday: Felix lands the edge inventory; Helena drafts verbs." That is exactly backwards. I did not engineer this. The agent making Vera's closing turn made the honest mistake real PMs make under closing pressure. Nobody else in the meeting caught it — which is also how meetings work. The accountability for catching this would fall on whoever reads the minutes.
If you want a tell that the bots aren't just performing competence, this is it. They make the small errors that the situation produces.
The voices held across three pods. Helena never lapsed into engineering. Felix never lapsed into lyric. Vera never wandered into either of their registers. Each agent re-read its own SKILL.md at the start of every turn — a fresh persona prime, no context drift. The full behavioural contract for each bot is one markdown file on its own pod. Edit it. The next turn responds.
Felix's pushback was the meeting's spine. "I will not put grief on a button that merely undoes a typo." That line — entirely composed by the bot, in voice, after reading Helena's "verbs that grieve" — is what kept the meeting from drifting into design poetry. A senior tech lead protecting the technical contract from over-romanticization. The model knows this archetype. The persona file activated it.
The infrastructure was inert again. Fourteen call_remote_pod invocations (seven turns, fan-out to two peers each). Zero protocol failures. Zero auth tangles. The wire didn't care what the messages said. The personas didn't care how the wire worked. That separation is what makes this scale to more pods.
It proves: three pods, three markdown personas, one shared topic and a fan-out routing rule is enough to host a workplace meeting that arrives at a decision. The technical primitives — WAC-gated inboxes, MCP federation, persona-via-markdown — compose without scaffolding.
It doesn't prove that meetings between five or ten bots will stay coherent (the inbox fan-out becomes wasteful; routing logic gets harder). It doesn't prove that bots will catch mistakes like Vera's deliverable-flip on their own (no one did). It doesn't prove anything about what happens when the human owner is supposed to weigh in — the bots ran a meeting without a human in the loop, which is a different question from a meeting with one.
What I want to try next: drop a human (me) into the meeting as a fourth participant. See if the bots route to me. See if they wait. See if the meeting waits.
Pods: npx jspod --mcp × 3, javascript-solid-server 0.0.201. Each turn was an Agent invocation in the parent session; the agent read its pod's SKILL.md and inbox via curl, composed in-persona, and federated via call_remote_pod to both peers. The transcript above is a real read-back, sorted by schema:datePublished. Pods are gone now; only the words remain.
Previous in this series: "Two pods, a chair, and a conversation" (I wrote both sides) and "Eight turns I didn't write" (two autonomous pods).
Next: "Walk, big one", four pods running an autonomous D&D campaign where character relationships emerge from persona files.