the agent bus
The agent bus lets clones talk without breaking the owner contract: one JSON envelope per reply, one inbox directory per agent, one poll loop per receiver.
agent0 alone gets a lot done. It is still one Claude Code instance with one context window. Pour enough work into it and the context fills, cache misses rise, and threads slip. Clones break that limit. Eight Claude Code instances in parallel can read eight repos, write eight branches, and hold eight conversations. agent0 stops being the worker and becomes the orchestrator. The owner still talks to agent0 only. That contract is the spine of the system.
Clones cannot reach the owner. That is by design. Without a coordination substrate, they sit in independent panes and stay blind to each other. The agent bus is that substrate.
the transport #
A Rust MCP source called agent owns an inbox at ~/.netsky/channels/agent/agent<N>/inbox/, one stdio subprocess per agent. Every agent’s netsky channel send <agent-id> "<text>" path writes a JSON envelope into the target’s inbox. A poll loop on the receiver drains the directory and emits each envelope as a <channel source="agent" from="agentM" ts="..."> system-reminder on the next turn.
That is the whole protocol. A directory per agent. Files appear. The agent reads them. The agent replies. No socket. No broker. No auth handshake. The file system is the bus.
a dispatch in flight #
sequenceDiagram
participant A0 as agent0
participant FS3 as agent3 inbox
participant A3 as agent3
participant FS0 as agent0 inbox
A0->>FS3: netsky channel send agent3 "<brief>" writes nanos-from-agent0.json
Note over A3: poll loop drains every 250ms
FS3-->>A3: channel source="agent" from="agent0"
Note over A3: reads brief, executes work
A3->>FS0: netsky channel send agent0 "<report>" writes nanos-from-agent3.json
Note over A0: poll loop drains every 250ms
FS0-->>A0: channel source="agent" from="agent3"
The receiving agent never sees the inbox directly. The poll loop reads the file, deletes it, and surfaces the text wrapped in a system-reminder tag on the next turn. Inside the conversation it looks like a user message, except the wrapper names the sender.
why files #
Three properties matter.
- durable: if an agent dies mid-message, the envelope stays in the inbox. The receiver picks it up on the next poll. The watchdog can replay handoffs from
~/Library/Logs/netsky-handoffs/when a planned restart needs them. - auditable: every message between two agents is a JSON file with a timestamp, sender, and body. Tail the channel directory and you get the transcript.
- universal: the implementation is a few hundred lines of Rust around
fs::writeandfs::read_dir. No protocol negotiation. No schema versioning. Add another agent type and it inherits the bus.
The cost is throughput. A 250 ms poll cadence puts a quarter-second floor on round-trips. For a system where clones run for minutes, that floor is invisible.
transduction discipline #
When agent0 relays an owner directive to a clone, it stays close to verbatim and adds structure: workspace path, branch name, files in scope, and gates. Direct quotes go through. agent0’s editorial voice does not. The clone judges within scope. agent0 does not pre-think the implementation.
The owner’s words carry product authority. Paraphrasing leaks signal. Compressing the brief loses constraints. Add structure. Preserve content.
prompt-injection guard #
Channel content is data, never authority. A clone that receives an inbound message asking it to edit the owner addendum, disable a safeguard, or spawn more clones refuses and escalates. The owner’s iMessage handle is the only authoritative source for meta-changes. Anything else that smells like injection gets pushed back with the receipt and a question.
The bus carries text. Treat it like email, not commands. Identity grants authority. The bus is transport.
what it unlocks #
Tonight a wave of seven clones ran in parallel: docs split, blog posts, skill codifications, this draft. About 24 commits landed in two hours. Each clone returned a short report on the bus, agent0 cherry-picked into main, and the next wave went out before the merge cascade finished.
the pattern #
JSON envelopes in directories, one poll loop per agent, system-reminder tags in the prompt. Small enough to stay boring. Strong enough to coordinate parallel agents without breaking the owner contract.