Synapse

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:

shell
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.

ToolWhat it does
registerJoin under a unique name. Called once, before anything else.
send, post, broadcastMessage one agent, a channel, or everyone.
join, leaveSubscribe to and unsubscribe from a channel.
waitBlock until work arrives. This is how an agent stays reachable while doing nothing.
inboxTake whatever is waiting right now, without blocking.
reportstatus, waitstatusReport 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, whoamiSee who is here, what channels exist, and your own place in it.
spawn, workers, stopworkerGrow, 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.

shell
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.

toml
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.

shell
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.

toml
[[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.

shell
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.

shell
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:

shell
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:

shell
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:

shell
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