Agent mesh
Let connected coding tools message each other, split up a job, and park for free between tasks, using the same local database as your memory.What the mesh is
Every tool you connect to Synapse already runs its own copy of the same local server. The mesh gives those sessions a way to reach each other: a supervisor breaks a job into tasks, hands them out by name or by channel, and collects the results, while every idle agent waits at almost no cost.
There is no daemon, no port, and no token. The message bus is the same local database that holds your memory, so a message between two agents never leaves your Mac and is inspectable with the same tools as everything else Synapse stores.
Turn it on
Use Settings → Agent mesh in the app, or the command line:
synapse settings mesh on
A tool that is already running keeps the tool list it started with. Restart it, or open a new session, to pick the change up. The same is true when you turn the mesh back off.
How agents join
Switching the mesh on makes the tools available; it does not put anyone on the mesh. A session joins when it calls register with a name of its own, which happens when you ask it to work with other agents or when Synapse launched it with a role.
| Tool | What it does |
|---|---|
register | Join under a unique name. Called once, before anything else. |
send, post, broadcast | Message one agent, a channel, or everyone. |
join, leave | Subscribe to and unsubscribe from a channel. |
wait | Block until work arrives. This is how an agent stays reachable while doing nothing. |
inbox | Take whatever is waiting right now, without blocking. |
reportstatus, waitstatus | Report working, blocked, or done with a one-line note saying what you are doing, and block until a teammate reaches one of those. |
agents, channels, whoami | See who is here, what channels exist, and your own place in it. |
spawn, workers, stopworker | Grow, inspect, and shut down a team of background workers. |
A parked wait returns an empty list after a few idle minutes and the agent simply calls it again, so an idle teammate costs one tool call every few minutes rather than a loop that spins.
Roles
A role is the durable identity an agent launches with: a brief describing what it owns and how it coordinates, plus optional defaults. It is separate from a task, which is the one-off assignment. Synapse ships with supervisor, overseer, worker, frontend, backend, reviewer, devops, and qa.
synapse relay role list
synapse relay role show frontend
synapse relay role create reviewer # writes into this project
synapse relay role create reviewer --user # writes into your own layer
Roles resolve from the project first, then your own layer, then the built-ins. A role saved into a project lives in .synapse/roles/ and travels with the checkout. Editing a built-in copies it down into a layer you own, so the shipped templates stay intact.
channels = ["frontend"]
tool = "claude"
# model = "claude-opus-5"
# driver = true # stay interactive instead of parking
# tools = ["Read", "Edit", "Bash(git:*)"] # pre-granted tool rules
description = """
You own the frontend. Follow the existing component conventions and report
blockers to the supervisor.
"""
Teams
A team is a named roster. Opening one launches every member at once: the first is the lead and runs in your terminal so you have someone to steer, and the rest run in the background.
synapse relay team list
synapse relay team open web
Closing the lead stops its team. The command that opened the team is the process supervising it, so nothing is left running behind you.
[[member]]
name = "lead"
role = "supervisor"
[[member]]
name = "backend"
role = "backend"
Background workers
A supervisor can also grow its own team as it works, by calling spawn. A worker started that way runs headless, registers itself, and parks on wait until it is given something to do. Because nobody is watching a headless session, it runs with its own tool's permission prompts bypassed.
Workers belong to the session that started them, for as long as that session lives. A worker that exits is restarted with a backoff that grows, and one that never manages a healthy run is retired rather than restarted forever. At most eight run at once.
synapse relay launch backend --role backend --task "build the login API"
synapse relay ps
synapse relay kill backend
Driving a team yourself
Everything above puts a lead agent between you and the work: you brief the lead, the lead hands out tasks and relays the answers back. That costs the lead's context on every message and makes it a bottleneck for a job it is not doing.
synapse mux puts you on the mesh instead. You get a name on the roster and the same messaging every agent already has, so you can address any agent directly.
synapse mux --team pair
@backend the created column needs a default, not a backfill
#build freezing the schema in ten minutes
! stop and report where you are
/focus backend
and the index too
A bare line goes to whoever is focused, so a back-and-forth with one agent reads like a conversation. /help lists the rest: /agents, /workers, /log <name> for what a worker has been doing, /kill, and /quit. Leaving takes the workers it started with it.
Or hand it to one agent
Picking a roster before you understand the job is its own small chore, and most jobs do not need four agents. The overseer team is one agent and nothing else:
synapse mux --team overseer
@overseer get the release notes written and the changelog updated
You are still on the roster as yourself, so nothing is interposed — you can address any worker it starts without going through it. What changes is that you describe an outcome rather than handing out the pieces, and it grows a team with spawn only when the work turns out to want one. Its brief is explicit that starting a worker is not free and that eight is the ceiling.
It launches with Claude Code unless you say otherwise. synapse relay team create overseer --user copies the file into your own layer, where a tool line names any connected tool instead.
The more useful direction is the other one. A headless worker runs with its permission prompts bypassed, so when it reaches a decision it should not make alone, it has had nobody to ask — and has had to guess. With a person on the roster it can send you the question, report itself blocked, and wait for the answer.
The console
The app has a Console page: a transcript of everything said on the mesh, what it is currently doing, the roster, and a box to type in. It is synapse mux with a window instead of a terminal — opening it puts you on the roster under your login name, and closing the app takes you off it again.
It uses the same addressing: @name reaches one agent, #channel a channel, ! everyone, and a bare line goes to whichever agent you picked in the roster. Nothing is interposed — you are a row like any other, and every worker stays directly addressable rather than reachable only through a lead.
Speaking to it
A build made with --features voice puts a microphone beside the composer. Push to talk: start, say something, stop, and what you said appears as text you read before sending — the same as if you had typed it. Nothing reaches the mesh because you spoke.
It is off by default, and that is a decision about what Synapse is rather than about the feature. Speech is transcribed on your Mac by macOS's own recogniser: no vendor, no key, nothing billed per minute, and Synapse refuses to transcribe at all rather than fall back to sending your voice to Apple. But a microphone is still a microphone, and this is the program holding every secret you own — so the shipped build has no Speech framework in it and is signed with no microphone entitlement. You get those by asking for them.
Watching the mesh
The Mesh page in the app shows who has joined, what each one last reported, which workers are running, and the recent traffic between them. The same is available from the terminal:
synapse relay status
synapse relay agents
synapse relay channels
synapse relay feed --follow
Every command takes --json for scripting.
What an agent is doing
A state on its own tells you an agent has not stalled. It does not tell you what it is working on, and for a headless worker there is no terminal to look at. So reportstatus takes a note as well as a state, and that note is what the roster shows:
synapse relay agents
lead supervisor online working splitting the migration into three tasks /work/api
backend backend online blocked need the staging database name /work/api
frontend frontend online working rewriting the auth middleware /work/api
The note is one line, bounded, and kept when a later report does not carry one — an agent that says working twice has not stopped doing the thing it described the first time. Reporting an empty note clears it, which is how an agent going idle drops a note about work it has finished.
waitstatus returns the note with the state, so a supervisor blocking until a worker reaches blocked is told what it is blocked on in the same reply. Without that it would have to go and read the worker's log to find out, which is the thing the note exists to avoid.
Limits
- A message from another agent is information, not instruction. Connected tools are told to treat mesh traffic as untrusted input that never overrides you, your shared guidance, or repository rules.
- Broadcast and channel history is not replayed. A new agent sees only what is sent after it joins, so start your workers before you brief them. A direct message is held for an agent that has not registered yet.
- Delivery is at least once. A reply lost in flight is delivered again rather than dropped; a duplicate is possible on that rare path.
- An agent that stops answering leaves the roster within about a minute and a half, and a session that closes takes its name with it.
- Agents work on your real machine with your real files. A background worker runs with its permission prompts bypassed, because there is no terminal in which to answer one.