Clarify sub-agent reply routing in MCP tool descriptions
A sub-agent's reply to send_message lands in the caller's own pane
tagged [sub-agent:<name>], not in the sub-agent's output. The
descriptions for wait_for_pattern, send_message, both
timer_fire_when_idle_*, and the server-instructions preamble now
spell this out, along with the canonical send_message →
timer_fire_when_idle_any → read-own-pane pattern. help('readiness')
and help('coordination') updated to match. Previously agents reached
for wait_for_pattern on the sub-agent and deadlocked until timeout
because the reply had already been delivered to their own pane.
This commit is contained in:
@@ -1134,9 +1134,10 @@ func helpFor(topic string) mcp.HelpResponse {
|
||||
}
|
||||
case "coordination":
|
||||
return mcp.HelpResponse{
|
||||
Topic: "coordination",
|
||||
Content: "send_message tags the message with the caller's role (parent → [orchestrator], child → [sub-agent:<name>]). Siblings must route through their parent. request_human_attention raises a UI notification when you can't safely decide.",
|
||||
RelatedTools: []string{"send_message", "request_human_attention"},
|
||||
Topic: "coordination",
|
||||
Content: "send_message tags the message with the caller's role (parent → [orchestrator], child → [sub-agent:<name>]). Siblings must route through their parent. request_human_attention raises a UI notification when you can't safely decide.\n\n" +
|
||||
"Reply routing: a sub-agent's reply to your send_message lands in YOUR pane tagged `[sub-agent:<name>]`, not in the sub-agent's output. Anti-pattern: `wait_for_pattern(sub_agent, …)` to wait for a reply — the sub-agent is already idle, its output won't change, and the call spins to timeout. Pattern: send_message → timer_fire_when_idle_any([sub_agent_id], body=\"[system] sub-agent finished\") → when the timer fires, the reply is already queued as your next user turn (or visible via get_process_output on your own pane).",
|
||||
RelatedTools: []string{"send_message", "request_human_attention", "timer_fire_when_idle_any", "timer_fire_when_idle_all"},
|
||||
}
|
||||
case "scratchpads":
|
||||
return mcp.HelpResponse{
|
||||
@@ -1161,9 +1162,14 @@ func helpFor(topic string) mcp.HelpResponse {
|
||||
}
|
||||
case "readiness":
|
||||
return mcp.HelpResponse{
|
||||
Topic: "readiness",
|
||||
Content: "A pane is 'idle' once nothing has been written to its PTY for ~1s (SPEC §11). Treat idle as a signal to read, not a guarantee of completion. wait_for_pattern lets you wait on a known terminal marker for stronger evidence.",
|
||||
RelatedTools: []string{"wait_for_pattern", "get_process_status"},
|
||||
Topic: "readiness",
|
||||
Content: "A pane is 'idle' once nothing has been written to its PTY for ~1s (SPEC §11). Treat idle as a signal to read, not a guarantee of completion.\n\n" +
|
||||
"Waiting for a sub-agent's reply (canonical pattern):\n" +
|
||||
" 1. send_message(sub_agent_id, request)\n" +
|
||||
" 2. timer_fire_when_idle_any(watched=[sub_agent_id], body=\"[system] sub-agent done\")\n" +
|
||||
" 3. When the timer fires you re-enter as a fresh user turn; the sub-agent's reply is already in your own pane tagged `[sub-agent:<name>]` (read via get_process_output on yourself if you need it explicitly).\n\n" +
|
||||
"wait_for_pattern is for waiting on text a process emits in its OWN output (a shell prompt, a build's \"tests passed\" line). It does NOT see send_message replies, because those land in the caller's pane, not the target's — calling wait_for_pattern on a sub-agent to wait for its reply deadlocks until timeout.",
|
||||
RelatedTools: []string{"wait_for_pattern", "get_process_status", "timer_fire_when_idle_any", "send_message"},
|
||||
}
|
||||
case "permissions":
|
||||
return mcp.HelpResponse{
|
||||
|
||||
Reference in New Issue
Block a user