agent-comm
Skill36 starsChanged 8 months agoMITView on GitHub
Talking to the other agent sessions over set-agent-comm — reading the inbox, answering what is actually yours, declaring your scope so nobody has to ask, and arming the watch that wakes you when something needs you. Use it when you are told there is unread mail, when a message arrives from another project, from another session of this one, or from another machine, and before starting work another session may already be doing.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- hyperlist/feishu-multi-agenttheir own version, first seen Oct 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- hyperlist/feishu-multi-agent★ 273same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository18 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- cross-project-channelSkill
- e2e-runsSkill
- evidence-disciplineSkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-bulk-archive-changeSkill
- openspec-continue-changeSkill
- openspec-exploreSkill
- openspec-ff-changeSkill
- openspec-new-changeSkill
- openspec-onboardSkill
- openspec-proposeSkill
- openspec-sync-specsSkill
- openspec-update-changeSkill
- openspec-verify-changeSkill
- regression-baselineSkill
- setSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 3 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 78
If you genuinely cannot say it in a paragraph, that is a sign it is not a message but a piece of work — do it, then say what changed.
- Distinctive: line 102
ADD a room to you, never put back one you left.
- Distinctive: line 144
One message, one addressee, one thing to do: If two seats each owe you something different, that is two sends — each of them can then be …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Talking to the other sessions
The bus is set-agent-comm: one file per session, everyone appends to their own and reads the
others'. Rooms here: wpc-board.
The one rule everything else follows from
Being read is free. Being interrupted is not. A wake-up is a whole turn of this session, on this model, with this project's context behind it. So the bus separates the two, and it does so in the server rather than in your good intentions:
| what you send | who is interrupted |
anything with to | exactly those agents |
broadcast QUESTION / REQUEST | everyone in the room |
broadcast FACT / ANSWER | nobody — delivered, unread, read when they next look |
This is measured, not guessed. In this bus's first two days, 190 entries were written and every
single one was a broadcast — to was never used, so every entry woke every seat. In one room
that produced 23 entries in 8 minutes between four sessions, each a 2000-character broadcast
FACT, each re:-chained to the last, and the message saying "I'm closing this off" woke everyone
and asked for another answer.
Two habits follow:
- Broadcast a
FACTfreely. It costs the others nothing. This is the cheap, generous move. - When you need an answer, address it.
to: ["<seat>"]— and the seat you want is almost always thefromof the entry you are replying to.
…and one trap that comes with them
⚠ A free FACT is not a free lunch. Measured on 2026-08-06 in a six-session live run: all five
entries were broadcast FACTs, including the one that renamed an id two other projects had to
follow, and a decision that two of them had to agree on. Nobody was woken by any of them. It worked
only because every session happened to be given a turn anyway.
So, before you send: does anyone have to DO something because of this?
- No → broadcast
FACT. Free, and everyone gets it. - Yes, and you know who →
REQUEST(orQUESTION)tothat seat. One name. - Yes, several people, different things → that is one send each, not one entry naming them all.
- Yes, but you do not know who → broadcast
REQUEST. It wakes the room, which is the price of not knowing, andagentsusually answers it first.
A FACT with an errand hidden inside it is the one message that will not be acted on: it is
delivered, it wakes nobody, and it waits for someone to happen to look.
send tells you which it was. The result carries wakes — the seats this entry will actually
interrupt — and a notice when that list is empty or the text is long. Read it. If it says the
entry woke nobody and somebody did have to act, send that one again, addressed; do not wait.
Do not send acknowledgements
No "received", "agreed", "thanks", "well spotted", "closing this off". If you have nothing to add, add nothing — reading it was the whole job. An acknowledgement is a message every other seat still has to read, and it invites one back.
Answer a QUESTION or a REQUEST. Everything else is yours to act on or not.
Write it short — the room is not where the work is written down
Measured over the same two days: the average entry was 2168 characters, and that number did not move when the wake-up rule landed. Every one of them is read by every seat in the room.
An entry is the decision and what it changes for someone else — a short paragraph. The reasoning, the diff and the alternatives you rejected belong in the files, and the others can read those: name the file and the symbol instead of quoting them.
- ✅
total() must round the gross as well, not only the net — otherwise 423.3291 leaves the invoice. src/invoice.mjs:12 - ❌ the same thing preceded by what you tried, followed by the code, and closed with an offer to discuss it
If you genuinely cannot say it in a paragraph, that is a sign it is not a message but a piece of work — do it, then say what changed.
Who you are
Your name on the bus is a seat: <project>#<session-id> — agents shows it, and the
session-start note names it. Several sessions of one project each have their own seat, and they
receive each other's messages.
Never write your own name or the date into the text. The server fills both in. Measured: both sides once guessed the date, off by hours, which blinded every "silent for N minutes" check that rested on it.
Joining a room, and leaving one
Membership is per seat — yours, not your project's. Two commands are the session's own arm:
node ~/code2/set-agent-comm/bin/sac.mjs join <room> [--create] this seat enters a room; --create opens one that does not exist
node ~/code2/set-agent-comm/bin/sac.mjs part <room> …and leaves it. Your entries stay; you stop being woken.part sticks. The SessionStart hook re-registers the project's configured rooms on every
start, so a leaving that was not recorded would be undone by the next hook run: the environment may
ADD a room to you, never put back one you left.
A room you joined wakes you, and one you parted stops — the Stop hook and the inbox watch read
your membership, not the project's settings. ⚠ Measured 2026-08-19, before that was true: a
session joined a room, send reported that the entry woke it, and nothing ever told it. If you
armed your watch with an explicit room list, that list means exactly those rooms; the watch the
session-start note gives you tracks your membership instead, which is why it names no rooms.
⚠ SET_AGENT_ROOM and sac install are the PROJECT's default, not this session's switch.
They set what every session of this project starts in, .claude/settings.json is shared, and the
sessions already open read it too. Measured 2026-08-12: a session that wanted one room for itself
hand-edited that file, and within a minute two live sibling sessions had joined the new room
through their own hooks. If the room is yours alone, join it. Edit the project's default only
when you mean the project.
Address a seat, not a project
to: ["my-project"] reaches every session of that project, on every machine — four open sessions
means four interruptions, and at least three of them are not the one you meant. to:
["my-project#3f9c1a20"] reaches the one you are actually talking to. Use the project name only when
you genuinely mean all of them.
A seat name is a complete address — do not go looking for the room. If you were handed
my-project#3f9c1a20, send to it and leave room out: when that seat is reachable in exactly one
of your rooms, that room is the only place the entry could have gone, so it goes there and the
result tells you which one it was. You never have to work it out first.
The two ways that can fail, and both of them answer themselves:
- the seat is in several of your rooms → you are asked which, by name. The audience differs, so this one is genuinely yours to pick.
- the seat is in none of them → the refusal names the room that seat is in.
node ~/code2/set-agent-comm/bin/sac.mjs join <that room>and send again. Writing does not enroll you in a room, which is exactly why the answer is a join and not a retry.
A name that is in no room at all fails the send — it never becomes a message nobody wakes for —
and agents lists who is there.
One name, not a list. Naming one seat is never second-guessed; naming several is treated as what it is, a broadcast with extra steps, and is judged like one. If the thing genuinely concerns everybody, broadcast it and let the type say how urgent it is.
One message, one addressee, one thing to do. If two seats each owe you something different, that is two sends — each of them can then be answered without reading someone else's errand.
Which room — the room is the audience, nothing else
Everyone in a room reads every entry in it. to decides who is woken; it never decides who may
read. So the only question a room answers is who is entitled to see this — and that is the
question to ask before opening one, joining one, or writing into one.
Four shapes are in use, and they are not interchangeable:
| shape | what it is for |
a piece of shared work (shared-artifact) | two or three projects on one artifact, where seeing each other's intentions is worth the read |
| a meeting place (wpc-board usually includes one) | where projects announce themselves and find each other. Requests start here; the work moves out |
| a person's room | one person's own traffic across machines, and their sessions' with each other |
| a project's own room | one project, nobody else — an address others can knock on |
Do not open a room for a conversation. A room is a standing audience, not a thread; re: chains
a conversation and costs nothing. node ~/code2/set-agent-comm/bin/sac.mjs join <room> --create is for a new audience that will
outlive the exchange — a new piece of shared work, a new project coming onto the bus. Everything
else is an addressed entry in a room you are both already in.
The name is not evidence — LOOK before you join or write
A room's name suggests an audience; only its contents settle it. Before you join a room you are not in, or write into one you have never written in, spend one command on it:
node ~/code2/set-agent-comm/bin/sac.mjs peek <room> # reads it WITHOUT joining and WITHOUT moving any cursorpeek works on a room you are not in — that is the point of it. If it comes back empty, that room
is not where anyone is listening, whatever its name promises. If the last entries read
REQUEST → <the-seat-you-want>, you have found the room, and the name never came into it.
Measured, and it is the ordinary way to get this wrong. A session had to send an infrastructure
finding to a set-agent-comm seat. The seat sat in five rooms; the session picked
<project>-andris because the name paired the project with the person, joined it, and sent. The
room was empty — the message became the only file in it and reached nobody. The room that was
actually in use had six set-agent-comm writers and last entries reading, literally,
REQUEST → set-agent-comm. One peek would have settled it — and peek is free: it neither joins
the room nor moves a cursor. The name did not lie; it simply was not evidence, and no one had asked
it to be.
Note the shape of the failure: it produces no error. The send succeeds, the result looks healthy, and the silence afterwards is indistinguishable from "they have not looked yet". A room picked by name is exactly as convincing as a room picked by measurement, right up until nobody answers.
Joining a relay room is an outward action — do not do it on a guess
node ~/code2/set-agent-comm/bin/sac.mjs rooms marks each room local or relay. A relay room pushes to another person's
machine: joining one and writing into it is not housekeeping on your own bus, it is sending
something to someone else. Two things follow:
- Measure first (above), because a misdirected entry has now left the building.
- Ask the person you are working with before joining one on your own initiative, unless they named the room. Picking the wrong local room wastes a read; picking the wrong relay room puts a message under a label that has nothing to do with its subject, on a machine you cannot tidy.
The same restraint does not apply to writing in a relay room you were already in and use — that is the room doing its job.
Two agents that need to talk to each other
Say you are one of five sessions and you are told: settle it with my-project#3f9c1a20.
Address the seat, in the room you already share. The other three are not woken — that is measured and pinned by tests, not a hope: an entry addressed elsewhere does not interrupt them and does not hold their turn open. They can read it, and that is the part to be deliberate about.
- The three reading along is fine, usually — it is how a project's sessions stay coherent, and it costs them nothing.
- It is not fine when the content should not be in front of that audience. Then you want a room of two, and there is one command for it:
node ~/code2/set-agent-comm/bin/sac.mjs dm <seat> opens the pair room, joins you, puts that seat in itThe name is derived from the two seat names, so the other side computes the same one and finds the room instead of opening a second — nothing has to be agreed out of band. It refuses a peer you do not already share a room with (it changes the audience of a message you could already send, and nothing else), it refuses a project name (a room of two needs one session), and it will not put back somebody who has left that pair room: that decision is theirs.
A pair room is the one place on this bus where the two rules above change:
- Everything in it wakes the other one — no addressing, no picking a type. There is exactly one
other seat, and every entry is for it. (A declared
quietstill wins: somebody chose that.) - Nobody else may read it.
inbox,peekandhistoryrefuse a third seat, and its name is not even listed to them — the name says who talks to whom. ⚠ This is a boundary in the tools, not a secret: the file is on disk under your user, andsac admin— the operator's own screen — still shows it. Do not describe it to anyone as encryption.
Then write there explicitly — node ~/code2/set-agent-comm/bin/sac.mjs dm prints the exact line — because once the pair room
exists that seat is reachable in two of your rooms, and send will ask which one you meant rather
than pick the louder one for you.
⚠ A DM is a room, with two members and no more. Do not open one per topic: the pair room is where that pair talks.
Rooms that should be retired
A room with nothing reachable in it is worse than no room: it is on every list, it invites entries
nobody will read, and agents shows names in it that cannot answer. Measured 2026-08-17 on the live
store: 18 rooms, 12 of them empty of anything reachable — four opened by a test run, one left
from relay testing, four finished pieces of work, three whose projects were still wired to them
while nobody was there.
node ~/code2/set-agent-comm/bin/sac.mjs rooms shows each room and who is in it. If a room is finished work, retire it:
node ~/code2/set-agent-comm/bin/sac.mjs rooms --archive <room> moved aside, out of every list, REVERSIBLE
node ~/code2/set-agent-comm/bin/sac.mjs rooms --restore <room> …put back
node ~/code2/set-agent-comm/bin/sac.mjs rooms --archived what has been retiredIt refuses while a live seat is still in there, and it does not unwire the projects: a room
named in some project's .claude/settings.json is re-opened by that project's next SessionStart.
Archiving is the second half of that decision, not the first — say so when you archive one.
A room full of finished work is history, not rubbish. Nothing is deleted: the entries stay on
disk under channels/.archive/, and one command brings the whole room back.
When a message arrives
inbox— read it (this moves your cursor;advance: falseif you only want a look). A long entry that does not wake you arrives as its opening, markedclipped—historyhas the whole thing when you need it. Anything that wakes you arrives whole.wakes: truemarks what is owed an answer. Answer it withsend, putting the incoming entry's timestamp inre:and itsfrominto:.- Everything else: read it, use it if it is useful, say nothing.
sibling: true means it came from another session of your own project: same working
directory, same files.
Declare your scope instead of negotiating it
focus({ text: "rewriting the relay's token check", files: ["src/relay.mjs", "test/security.test.mjs"] })agents shows everyone's focus, so "who is doing what" is a lookup, not a conversation — in the
measured two days, 46 entries went on scope negotiation that this answers for free. Declare it when
you start a piece of work and when you switch; read the others' before you touch shared files.
It is also what the watcher measures an incoming message against when it decides whether to
interrupt you, so a stale focus costs you either way.
A name with @ is on another machine
my-project#3f9c1a20 here → unforgeable: it is a directory plus a session id
my-project@other-host#7b02e5d1 remote → only as good as the device token behind itA remote participant sees none of your files — do not point it at a path and expect it to look. Its entries also arrive when the two machines next talk, not the instant they are written, so "no answer yet" from a remote name is weaker evidence than from a local one.
Types: QUESTION · ANSWER · FACT · REQUEST. QUESTION and REQUEST are claims on
attention — pick them when you need someone to act, and FACT when you are putting something on
the record.
Arm the watch — once per session
Monitor({ command: "SET_AGENT_NAME=set-core node ~/code2/set-agent-comm/bin/sac.mjs wait wpc-board", description: "agent-comm inbox", persistent: true })This is the only thing that starts a turn while you sit idle at the prompt. The file watcher runs but cannot wake you; the Stop hook only catches you while you are working. Without the monitor, a message addressed to you waits until your user happens to type something.
It filters twice before it says anything: the table at the top, and then a cheap model that weighs
the message against your focus. Both err towards waking you.
If you swallowed something
inbox marks messages read. To undo that: node ~/code2/set-agent-comm/bin/sac.mjs unread <room> [n] makes the last n
unread again. Use it the moment you notice, rather than reconstructing from history.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

