Agents
An agent writes through the same protocol as a person: the same envelopes, attribution, and ACLs. How much authority you give it is the choice. Review its work on a branch, or let it write to the room directly under a scoped policy.
@mmstack/meshnpm
#Review a branch
An agent's write is a sample that can be wrong, so the safe default is to keep it behind a person's approval. mesh.fork() gives the agent a fork of the synced store. Its writes stay on the fork, off the room. ops() is the staged change as data, ready to render for a reviewer. commit() emits it to the room; discard() drops it.
import { store } from '@mmstack/primitives';
import { meshSync } from '@mmstack/mesh';
const board = store<Board>(initialBoard());
const mesh = meshSync(board, { room: 'board-42', writer: userId, transport });
const proposal = mesh.fork(); // the agent's branch, off the room
runAgent(proposal.store); // it writes here
proposal.ops(); // StoreOp[] for the reviewer to see
proposal.commit(); // approve: emits as concurrent writes; a mid-review room edit is never steamrolled
// proposal.rebase(); // re-observe the room, then commit on top
// proposal.discard(); // reject: drops the staged writes The commit cites what the fork observed when it forked, so an edit that lands on the room while a person reviews stays a concurrent value the merge policy decides, never silently overwritten by the approval. Call rebase() to re-observe the room first when you want the proposal to apply on top of the latest instead. The reviewer reads and writes normal store values, and the agent never touches the room directly. This is the fit for a write that should be seen before it lands.
#Write as a peer
A trusted, in-scope agent can join the room directly. Give it a narrower ctx and a policy, and the relay ejects any write outside its scope, the same tripwire that guards a human peer.
meshSync(board, {
room: 'board-42',
writer: agentId,
transport,
ctx: { kind: 'agent', claims: { scope: 'pricing' } },
policy: pricingScopeOnly, // the relay ejects a write outside 'pricing'
});A live agent inherits the same conflict rules as everyone else. An agent writes faster than a person, so on a shared field it can win a last-writer-wins race often. The relay rate-limits throughput, which is not the same as fairness on a contested value. Reach for the branch when a field carries real weight.
#Attribution and identity
An agent's writer is an opaque id, the same shape a person gets. Natural identity never enters the envelope. Keep the mapping from id to identity in your own table. For an agent you keep that mapping for accountability. For a person you can sever it to satisfy an erasure request, and the journal stays intact and anonymous because the write history never held the identity.