Description
Claude Code (a tracked reference agent per .claude/rules/continuous-improvement.md) ships a documented "Agent Teams" feature: concurrently running sessions ("teammates"), addressable by name, communicating directly via a SendMessage tool backed by a per-teammate mailbox, sharing a common claim/complete task list. Claude Code's own docs explicitly distinguish this from ordinary subagents: subagents only return a final result to the calling session and never talk to each other; teammates message each other directly without going through the lead. Notably, this exact CI research cycle in Zeph's own repo is itself run via that outer pattern (rust-team lead + researcher + live-tester + arch-analyst teammates) — but the coordination is provided by the Claude Code harness running the session, not by Zeph's own zeph-subagent/zeph-orchestration crates.
A code-level audit of Zeph's own subagent system this cycle confirms three things:
- Concurrent/background spawning — present.
SubAgentManager::spawn (crates/zeph-subagent/src/manager/spawn.rs:520) is non-blocking, returns a task_id immediately (test: crates/zeph-subagent/src/manager/tests.rs:313, "spawn() must not block"). Many concurrent SubAgentHandles are tracked up to max_concurrent (crates/zeph-subagent/src/manager/mod.rs:279-289). zeph-orchestration's DagScheduler also runs multiple sub-agents in parallel per task (crates/zeph-orchestration/src/scheduler/mod.rs:196-226,198-205,527-535).
- Async completion notification (no polling) — present, but scoped to orchestration only.
SubAgentManager::spawn_for_task sends a TaskEvent on completion (crates/zeph-subagent/src/manager/spawn.rs:1139-1229, documented as enabling DagScheduler "to receive completion notifications without polling (ADR-027)"), consumed in crates/zeph-orchestration/src/scheduler/mod.rs:129,209-211 and scheduler/tick/mod.rs:455-456. Outside the DAG scheduler, the plain spawn + statuses()/collect() path is poll/borrow-based on a watch::Receiver (crates/zeph-subagent/src/manager/collect.rs:140-151), and collect() blocks on the join handle.
- Peer-to-peer / lead-to-subagent live messaging — absent. No mailbox, broadcast, or inter-sibling channel exists.
SubAgentHandle only exposes a status watch channel and a one-shot secret-approval channel (crates/zeph-subagent/src/manager/mod.rs:180-186). The only "agent-to-agent" primitive is crates/zeph-a2a (Google A2A protocol, crates/zeph-a2a/src/lib.rs:1-59), which delegates to external/remote peer agents over HTTP JSON-RPC — a cross-process delegation protocol, not a live mailbox between sibling subagents in the same spawn tree. Subagents only ever return a final transcript via collect(); they cannot address each other by name mid-run, and there is no shared task list independent of the DAG scheduler's static plan.
Checked for duplicates: #3714 (open, P3, LATTE adaptive task graphs — arXiv:2605.06320, about dynamic DAG mutation, not live messaging) and #4178 (closed, P4, message-sequence-chart coordination spec — arXiv:2604.17612, about formally verifying deadlock-freedom of an existing protocol) are related but distinct — both presuppose a messaging primitive that doesn't yet exist. This finding is the more foundational gap.
Reproduction Steps
- Read
crates/zeph-subagent/src/manager/mod.rs (SubAgentHandle fields) and spawn.rs/collect.rs.
- Observe no channel exists for a spawner or sibling to send an arbitrary message to a running subagent's agent loop mid-execution, and no shared claim/complete task list outside
zeph-orchestration's static DAG.
- Compare against Claude Code's documented Agent Teams:
SendMessage(to: <name>), shared task list, direct addressability.
Expected Behavior
A spawning agent or coordinator can send a message directly to a specific named, currently-running subagent, and subagents can message siblings or their spawner, independent of the DAG scheduler's static edges.
Actual Behavior
Subagents can only be spawned, polled/watched for status, and collected for a final result once finished. No live bidirectional messaging channel exists outside the DAG scheduler's narrow completion-event channel.
Environment
- Version: v0.22.0, HEAD
647607ec
- Affected crates: zeph-subagent, zeph-orchestration
Severity Note
Only one reference agent (Claude Code itself) was confirmed this cycle to have this exact capability as a first-class documented feature; the other 10 tracked reference agents were not individually re-verified for this specific capability this pass. Per the project's parity severity rubric (P2 requires 2+ reference projects with a capability users would notice; P3 is "useful feature, low urgency"), filed as P3 pending that confirmation in a future cycle.
Spec
.local/specs/046-subagent-peer-messaging-parity/spec.md
Description
Claude Code (a tracked reference agent per
.claude/rules/continuous-improvement.md) ships a documented "Agent Teams" feature: concurrently running sessions ("teammates"), addressable by name, communicating directly via aSendMessagetool backed by a per-teammate mailbox, sharing a common claim/complete task list. Claude Code's own docs explicitly distinguish this from ordinary subagents: subagents only return a final result to the calling session and never talk to each other; teammates message each other directly without going through the lead. Notably, this exact CI research cycle in Zeph's own repo is itself run via that outer pattern (rust-team lead + researcher + live-tester + arch-analyst teammates) — but the coordination is provided by the Claude Code harness running the session, not by Zeph's ownzeph-subagent/zeph-orchestrationcrates.A code-level audit of Zeph's own subagent system this cycle confirms three things:
SubAgentManager::spawn(crates/zeph-subagent/src/manager/spawn.rs:520) is non-blocking, returns atask_idimmediately (test:crates/zeph-subagent/src/manager/tests.rs:313,"spawn() must not block"). Many concurrentSubAgentHandles are tracked up tomax_concurrent(crates/zeph-subagent/src/manager/mod.rs:279-289).zeph-orchestration'sDagScheduleralso runs multiple sub-agents in parallel per task (crates/zeph-orchestration/src/scheduler/mod.rs:196-226,198-205,527-535).SubAgentManager::spawn_for_tasksends aTaskEventon completion (crates/zeph-subagent/src/manager/spawn.rs:1139-1229, documented as enablingDagScheduler"to receive completion notifications without polling (ADR-027)"), consumed incrates/zeph-orchestration/src/scheduler/mod.rs:129,209-211andscheduler/tick/mod.rs:455-456. Outside the DAG scheduler, the plainspawn+statuses()/collect()path is poll/borrow-based on awatch::Receiver(crates/zeph-subagent/src/manager/collect.rs:140-151), andcollect()blocks on the join handle.SubAgentHandleonly exposes a statuswatchchannel and a one-shot secret-approval channel (crates/zeph-subagent/src/manager/mod.rs:180-186). The only "agent-to-agent" primitive iscrates/zeph-a2a(Google A2A protocol,crates/zeph-a2a/src/lib.rs:1-59), which delegates to external/remote peer agents over HTTP JSON-RPC — a cross-process delegation protocol, not a live mailbox between sibling subagents in the same spawn tree. Subagents only ever return a final transcript viacollect(); they cannot address each other by name mid-run, and there is no shared task list independent of the DAG scheduler's static plan.Checked for duplicates: #3714 (open, P3, LATTE adaptive task graphs — arXiv:2605.06320, about dynamic DAG mutation, not live messaging) and #4178 (closed, P4, message-sequence-chart coordination spec — arXiv:2604.17612, about formally verifying deadlock-freedom of an existing protocol) are related but distinct — both presuppose a messaging primitive that doesn't yet exist. This finding is the more foundational gap.
Reproduction Steps
crates/zeph-subagent/src/manager/mod.rs(SubAgentHandlefields) andspawn.rs/collect.rs.zeph-orchestration's static DAG.SendMessage(to: <name>), shared task list, direct addressability.Expected Behavior
A spawning agent or coordinator can send a message directly to a specific named, currently-running subagent, and subagents can message siblings or their spawner, independent of the DAG scheduler's static edges.
Actual Behavior
Subagents can only be spawned, polled/watched for status, and collected for a final result once finished. No live bidirectional messaging channel exists outside the DAG scheduler's narrow completion-event channel.
Environment
647607ecSeverity Note
Only one reference agent (Claude Code itself) was confirmed this cycle to have this exact capability as a first-class documented feature; the other 10 tracked reference agents were not individually re-verified for this specific capability this pass. Per the project's parity severity rubric (P2 requires 2+ reference projects with a capability users would notice; P3 is "useful feature, low urgency"), filed as P3 pending that confirmation in a future cycle.
Spec
.local/specs/046-subagent-peer-messaging-parity/spec.md