Run a team of agents and drive it yourself
Turn on the agent mesh, open a team, watch what every agent is doing from one terminal, answer a worker that gets stuck, and shut the whole thing down cleanly.Outcome and prerequisites
You will put several coding-agent sessions on one local mesh, give them work from your own seat rather than through a lead agent, read what each one is doing without opening its terminal, and answer one that gets stuck. Then you will take it all down and confirm nothing is left running.
- The
synapseCLI installed, and at least one tool connected. Start with Install and connect your first tools if not. - A real project folder. Agents work on real files, so use a checkout you can throw away or one with clean version control.
- Thirty to sixty minutes, and a willingness to let several agent sessions run at once.
-
Turn the mesh on
The mesh ships switched off. Its sixteen tools load into every connected session, and that costs context in each one, so Synapse does not add them to a setup that will not use them.
synapse relay statusMesh: off Agents: 0 online of 0 Workers: 0 Turn it on with `synapse settings mesh on`.synapse settings mesh onAgent mesh on. Connected tools pick this up the next time they start.That last sentence is literal. A session already running keeps the tool list it started with, so restart any open tool before continuing. The same applies when you switch the mesh back off.
Turning the mesh on also brings the guidance that explains it. The tools and the instructions for using them appear together and are withdrawn together, so a session can never have one without the other.
-
Look at roles and teams
A role is a durable identity: a brief describing what an agent owns and how it coordinates. A team is a named roster of roles. Both ship with sensible defaults:
synapse relay role listbackend built-in devops built-in frontend built-in qa built-in reviewer built-in supervisor built-in worker built-insynapse relay team list synapse relay team show web# web · built-in name = "web" [[member]] name = "lead" role = "supervisor" [[member]] name = "frontend" role = "frontend" [[member]] name = "backend" role = "backend" [[member]] name = "reviewer" role = "reviewer"Read one role to see what an agent is actually told:
synapse relay role show reviewer# reviewer · built-in name = "reviewer" description = """ You review other agents' work. Read the diffs they report, check correctness, edge cases, and conventions, and send concise, actionable feedback to the author. Approve only when it holds up; escalate disagreements to the supervisor. """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, which is how a team convention becomes something the repository carries rather than something each person configures. -
Join as yourself, not through a lead
There are two ways to run a team, and the difference matters.
synapse relay team open weblaunches every member and puts a lead agent in your terminal. You brief the lead, the lead hands out tasks and relays answers back. That costs the lead's context on every message and makes it a bottleneck for work it is not doing.synapse muxputs you on the roster instead, with the same messaging every agent has:cd ~/your-project synapse mux --team pairSynapse launches the team's members in the background and drops you into a line-oriented prompt with your own name on the roster. It is deliberately plain — no terminal library, no full-screen interface — so it works over ssh and in any terminal.
@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 tooSyntax Goes to @name textOne agent, directly. #channel textEvery subscriber of that channel. ! textEveryone on the mesh. textWhoever is focused, so a back-and-forth reads like a conversation. /helplists the rest. The ones you will use are/agents,/workers,/focus <name>,/log <name>,/kill <name>, and/quit. -
Watch what everyone is doing
From inside the mux,
/agentsshows the roster. From another terminal, the same thing:synapse relay agentsyou — you — — /work/api 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/apiThe fourth column is a state and the fifth is the note that goes with it. The state tells you an agent has not stalled; the note is the part that tells you whether to leave it alone. For a headless worker there is no terminal to look at, so that note is the only view of it there is.
Notes are one line, bounded, and kept when a later report does not carry one — an agent that reports
workingtwice has not stopped doing the thing it described the first time.synapse relay status # counts and whether the mesh is on synapse relay channels # channels and how many subscribe to each synapse relay feed --follow # every message between agents, as it happensEvery one of these takes
--json. The Mesh page in the desktop app shows the same information with the traffic alongside it. -
Understand the wait loop
This is the one piece of the mesh worth understanding properly, because almost every confusing behavior traces back to it.
An idle agent calls
wait, which blocks until a message arrives for it. After a few idle minutes it returns an empty list instead. That is a normal timeout, and the agent's instructions are to callwaitagain. An idle teammate therefore costs one tool call every few minutes rather than a loop that spins.Two consequences you will actually notice:
- Messages arrive at the next check, not as an interrupt. An agent parked between tasks answers in about a second. One in the middle of a long build sees you when it comes back. The roster's state column tells you which is which.
- An empty or failed
waitis not a signal to stop. Agents are told this explicitly, in the guidance and again in the launch harness, because an agent that reads a timeout as "the work must be finished" writes an explanation and exits. That is the single most common way a mesh session dies.
Delivery is at least once. A reply lost in flight is delivered again rather than dropped, so a duplicate is possible on that rare path and a lost message needs a process to die inside a very small window.
-
Grow the team while it works
You do not have to decide the roster up front. A supervisor can spawn workers as it discovers what the job needs, and you can do the same from the command line:
synapse relay launch migrations --role backend --task "write the schema migration" synapse relay ps synapse relay kill migrationsA worker started this way runs headless, registers itself, and parks on
waituntil it is given something to do. From inside the mux,/workerslists them and/log <name>shows what one has actually been doing.Workers belong to the session that started them, for exactly as long as that session lives. There is no daemon: closing the mux takes its workers with it, so nothing is left running behind you. A worker that exits is restarted with a growing backoff, and one that never manages a healthy run is retired rather than restarted forever. At most eight run at once.
-
Answer a worker that gets stuck
This is the reason to be on the roster yourself rather than behind a lead.
A headless worker runs with its permission prompts bypassed, so until there is a person on the mesh it has nobody to ask when it reaches a decision it should not make alone — and its only option is to guess. With you on the roster it can send you the question, report itself
blockedwith a note saying what it needs, and wait.backend: the migration drops a column with data in it. Confirm before I run it? /focus backend yes, it is a duplicate of created_at — go aheadAgents can tell a person from an agent. Your roster row is marked as a human, and connected tools are told to ask you questions and never delegate work to you. Only
synapse muxcan set that flag; a tool callingregisteris always an agent, whoever is sitting in front of it. -
Write a role of your own
The built-ins are a starting point. Create one in the project so it travels with the checkout:
synapse relay role create migratorchannels = ["build"] 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 database migrations. Write them forward-only, never destructive without asking, and post the SQL to #build for review before running anything. """Editing a built-in copies it down into a layer you own rather than modifying the shipped template.
--userwrites into your own layer instead of the project. Then build a team around it:synapse relay team create schemawork synapse mux --team schemawork
Shut it down
# from inside the mux
/quit
# then, from any terminal
synapse relay ps # should be empty
synapse relay agents # names age off within about ninety seconds
synapse settings mesh off
Leaving the mux takes its workers with it and takes your name off the roster, so nothing addresses an empty terminal. Switching the mesh off removes the sixteen tools and their guidance from every session that starts afterwards; sessions already running keep what they had until they restart.
Messages stay in the local database and remain visible through synapse relay feed. They are memory-adjacent, not memory: they are never recalled and never returned by recall.
What you can rely on
- No daemon, no port, no token. The bus is the same local database as your memory, and a message between two agents never leaves your Mac.
- 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.
- A person on the mesh is addressed, never assigned. Only the mux can mark a roster row as human.
- Channel and broadcast history is not replayed — a new agent sees only what is sent after it joins, so start workers before briefing them. A direct message is held for an agent that has not registered yet.
- Workers die with the session that started them. A session that closes takes its name off the roster with it.
Next step
You have finished the team operator track. The maintainer track covers keeping the store healthy and leaving cleanly: Export and restore safely, then Check, migrate, and remove Synapse.