Multi-agent harnesses need separate message channels

Today every message lands in one chat box. Upstream, downstream, sideways, peers and alerts each need their own channel.

Lately I've been wiring agents together using the same harnesses I use every day. One agent plans, a few others execute, one reviews, and I sit somewhere in the middle nudging things along. It works. It also gets confusing fast, and the models aren't the ones getting confused. I am.

Every message lands in the same chat box. A request from me, a status update from a sub-agent, a "please clarify" from the agent supervising this one, a note from a sibling agent, and a CI failure all look the same: a line of text in one long scroll. After twenty minutes I can't tell who asked for what. The agent can, since it has the whole context and can work out who said what. But I'm the one supervising this, and I end up reconstructing it by hand.

One fix is to have the agent build me a picture, using tools to draw who sent what to whom. That works, but it's a patch on top of the mess. The cleaner fix is to never mix the streams in the first place. Give each kind of communication its own channel, one I can read and audit on its own.

One interface, five relationships

Today's harnesses assume a single conversation: one human talking to one agent. Once agents talk to each other, that breaks. An agent in the middle of a team actually has five streams going at once:

  • Upstream: its supervisor. The agent (or person) that handed it the task, set the goal, and is waiting on the result. Upstream is always outside the work. It doesn't touch the code or the doc. Its job is the meta work of deciding what the work is, whether it's on track, and whether it's done. Messages here are about scope, priorities, and reporting back.
  • Downstream: the agents it manages. The workers it split the task across. Instructions go out, and progress, results, or blockers come back.
  • Sideways: the human co-working with it. Usually the person who owns the agent, sitting inside the same work and looking at the same files, the same diff, the same half-finished draft. There's no reporting line here, it's pairing. Sideways is the one channel where every message comes from a human, typed by a person rather than generated by an agent: "hey, actually do it this way," "why did you pick that," "stop, that's wrong."
  • Peers: other agents at the same level. Siblings under the same supervisor, or agents on a neighboring team. Nobody here is in charge of anybody. Messages are coordination: "I'm editing auth.ts, hold off," "what shape does your API return," "I already fixed that, skip it."
  • Alerts: things that aren't anyone talking. A build broke, a test went red, a timer fired, a webhook landed, a budget is nearly spent. Nobody is asking a question, but something changed and the agent may need to react.

The easiest pair to blur is upstream and sideways, since both can be a human giving direction. The difference is where they stand. Upstream stands outside the work and talks about it: goals, deadlines, sign-off. Sideways stands inside the work and talks in it: this line, this function, this paragraph. A supervisor asks "is the login flow done?" A co-worker says "that redirect is wrong, use the callback URL." The same person can play both roles, but any single message is one or the other.

These carry different authority, different urgency, and different expectations about a reply. Squashing all five into one stream is like running your whole job out of a single email thread with your manager, your reports, your cofounder, your teammates, and your pager all on it.

What goes wrong when they're mixed

  • Authority gets lost. An instruction from a sub-agent or a peer looks exactly like one from the human. The agent can usually tell "my worker suggests X" from "my owner says X" by context, but nothing guarantees it, and I can't check without rereading everything.
  • Replies go to the wrong place. The agent answers a downstream question somewhere only the human sees, or reports to its supervisor something that was meant for a worker.
  • Peers collide. Without a direct lateral channel, siblings coordinate through the supervisor, or not at all. Two agents edit the same file, or both fix the same bug, and the supervisor finds out afterwards.
  • Alerts drown, or hijack. A red build in the middle of a chat scroll gets missed. Or the reverse happens and the agent treats every notification as a new order, dropping its task to chase noise.
  • Humans can't step in cleanly. If I want to correct one agent mid-task, my message goes into the same queue as everything else. It isn't marked as coming from the person who's actually responsible.
  • The audit trail is mush. Looking back, nobody can rebuild who decided what, or what triggered it. That matters most exactly when something went wrong.

The first four can be patched, uncleanly. Tag each message with its sender, add a marker for "this came from my owner," prefix alerts with [ALERT], and the agent will mostly sort it out. The last two can't be patched that way, because they're about the human, not the agent. There are just too many messages arriving too fast, and anyone trying to step in or look back gets lost in the scroll. Tags don't help me if I still have to read a thousand tagged lines to find the one that matters.

What the harness should do

A smarter model won't fix this. The harness needs structure:

  1. Five channels in one context. The agent keeps a single working memory, but every message is tagged upstream, downstream, sideways, peer, or alert. The model sees the tag, and the harness enforces it. It's not a convention someone pastes into a prompt.
  2. Separate views for the human. Give me a pane or filter per channel. When I open an agent, I want to see what its boss asked, what its workers are saying, what its peers are negotiating, what fired, and what I said, without scrolling through all of it at once. Each channel is its own log, so I can audit one relationship at a time.
  3. Replies are addressed. When the agent responds, it picks a channel. "Report up," "instruct down," "answer my human," and "tell my peers" are different actions, not one generic send. Alerts don't get replies. They get acknowledged, handled, or escalated.
  4. Authority follows the channel. Upstream sets the goal and decides when it's met. Sideways from the owner can override how the work gets done, down to the line. Downstream is input, not orders. Peers can ask and inform but never command. Alerts carry facts, not instructions. The harness can enforce that ordering instead of hoping the model picks it up from tone.
  5. Alerts have their own rules. Severity, dedupe, and routing belong to the harness. A failing deploy should interrupt. A flaky lint warning can wait in the queue. The agent decides what to do about an alert, but it shouldn't have to work out whether an alert is a person.

We already do this everywhere else. Org charts have had it forever. Email has To, CC, and the boss's name in the header. Slack keeps DMs apart from channels, and nobody confuses a PagerDuty page with a message from their manager. We're building multi-agent systems on a chat UI that assumed a team of one.

Why now

Single-agent harnesses got good enough that people started chaining them. The chain is becoming the unit of work, and the chat box doesn't scale with it. I want the next harness I use to make it obvious, to the agent and to me, who is talking, and whether anyone is talking at all.

Upstream, downstream, sideways, peers, alerts. Five conversations in one context. I'd switch harnesses for that alone.

A plug

Do you run multiple agents together? Do you want to manage them across vendors, harnesses, and machines, all from one place? Do you want to do it from any browser and your phone? Try reminal.

#agents#harness#toolsreminal →