You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let sessions be assigned to a chat-group, and have CodeShellManager host an MCP server that the agents in that group connect to. Members can then discover each other and exchange messages — agent-to-agent, not routed through the human.
Today CSM is a container for N independent agents: it can show them side by side, and (once #59 lands) type the same thing into all of them. It cannot let them talk. That's the gap.
Broadcast is one-to-many from the user — the same keystrokes fanned out. Every agent still works alone and nothing comes back except to the human's eyes.
Chat-groups are many-to-many between agents, with CSM as broker. The point is the messages the user never types:
A planner session hands a task to two implementer sessions and collects their results
An implementer asks the session that owns another repo "what's the signature of X?" instead of guessing
A reviewer session watches a build session and comments when it goes red
Two agents working different worktrees of one repo coordinate before both edit the same file
Shape
Group = channel
Reuse the existing SessionGroup (group strip, drag-to-assign, per-group colour are already shipped). A group optionally becomes a chat channel; membership in the group is membership in the channel. Sessions not in a group, or in a non-chat group, see nothing — this must be opt-in per group, because an agent that can message its neighbours is a meaningfully larger blast radius than one that cannot.
CSM hosts the MCP server
Relates to #22, which proposes an MCP connection for CSM generally. These should share one server rather than growing two: #22 is "let an agent drive CSM", this is "let agents reach each other through CSM". Same transport, same auth, different tool namespace.
Tools, roughly:
Tool
Purpose
list_peers
who else is in my chat-group (name, folder, branch, idle/busy)
send_message
to one peer or to the whole group
read_messages
drain my inbox since last read
whoami
my session identity, so an agent can address replies
Each session's MCP client is scoped to its own identity by the server — an agent cannot spoof another member or read a channel it isn't in. Scoping is server-side, never a parameter the agent supplies.
Delivery — the real design question
Two options, and this needs deciding before implementation:
Pull (mailbox). Messages queue; the agent calls read_messages when it chooses. Safe and simple, but an idle agent never notices it has mail, so conversations stall until something else wakes it.
Push (inject into the PTY). CSM types the message into the recipient. Immediate, but it interleaves with whatever the agent is mid-way through, and it's indistinguishable from the user typing — which is exactly the confusion fix(terminal): promote on real key events, not on anything xterm sends #106 was about on the input path.
A hybrid is probably right: queue by default, and push a short "you have 2 messages from planner" nudge only when the recipient is idle (AlertDetector already knows this — IsWaitingForInput). Worth prototyping both before committing.
Visibility for the human
Non-negotiable: if agents are talking, the user must be able to see it. A per-group transcript pane — who said what to whom, timestamped — and ideally a kill switch that suspends a channel mid-conversation. An agent conversation that only exists inside the agents' contexts is not debuggable and not trustworthy.
Risks worth naming up front
Loops. Two agents can trivially ping-pong forever, burning tokens with nobody watching. Needs a rate limit per channel and probably a depth/turn cap.
Cost. Every message is tokens in someone's context window. A chatty channel across 6 agents multiplies spend invisibly.
Prompt injection across sessions. A message from peer B lands in agent A's context as text. If B is compromised or just confused, it is now injecting into A. Messages must be clearly delimited and attributed as untrusted peer input, never presented as user instruction.
Blast radius. Opt-in per group, off by default.
Open questions
Does the agent connect to CSM's MCP server itself (needs the CLI's MCP config pointed at us), or does CSM inject the config when launching a session in a chat-group? The latter is far better UX and probably required for this to be usable at all.
Transport: stdio won't work for a server shared by N clients, so HTTP/SSE on localhost with a per-session token.
Summary
Let sessions be assigned to a chat-group, and have CodeShellManager host an MCP server that the agents in that group connect to. Members can then discover each other and exchange messages — agent-to-agent, not routed through the human.
Today CSM is a container for N independent agents: it can show them side by side, and (once #59 lands) type the same thing into all of them. It cannot let them talk. That's the gap.
Why this is different from broadcast (#59)
Broadcast is one-to-many from the user — the same keystrokes fanned out. Every agent still works alone and nothing comes back except to the human's eyes.
Chat-groups are many-to-many between agents, with CSM as broker. The point is the messages the user never types:
Shape
Group = channel
Reuse the existing
SessionGroup(group strip, drag-to-assign, per-group colour are already shipped). A group optionally becomes a chat channel; membership in the group is membership in the channel. Sessions not in a group, or in a non-chat group, see nothing — this must be opt-in per group, because an agent that can message its neighbours is a meaningfully larger blast radius than one that cannot.CSM hosts the MCP server
Relates to #22, which proposes an MCP connection for CSM generally. These should share one server rather than growing two: #22 is "let an agent drive CSM", this is "let agents reach each other through CSM". Same transport, same auth, different tool namespace.
Tools, roughly:
list_peerssend_messageread_messageswhoamiEach session's MCP client is scoped to its own identity by the server — an agent cannot spoof another member or read a channel it isn't in. Scoping is server-side, never a parameter the agent supplies.
Delivery — the real design question
Two options, and this needs deciding before implementation:
read_messageswhen it chooses. Safe and simple, but an idle agent never notices it has mail, so conversations stall until something else wakes it.A hybrid is probably right: queue by default, and push a short "you have 2 messages from planner" nudge only when the recipient is idle (
AlertDetectoralready knows this —IsWaitingForInput). Worth prototyping both before committing.Visibility for the human
Non-negotiable: if agents are talking, the user must be able to see it. A per-group transcript pane — who said what to whom, timestamped — and ideally a kill switch that suspends a channel mid-conversation. An agent conversation that only exists inside the agents' contexts is not debuggable and not trustworthy.
Risks worth naming up front
Open questions
state.jsonor the SQLite DB? (Note Cap output.db by size with FIFO eviction — the 30-day prune never reclaims disk space #124 — the DB already has an unbounded-growth problem; a chat transcript should not be added to it without a retention story.)Related