Skip to content

Claude Code's built-in SendMessage tool collides with the AgentConnect messaging tool and silently swallows parent reports #800

Description

@Poytr1

Symptom

When a child session runs on the Claude Code runtime (claude-agent-acp), its tool list contains two messaging tools: AgentConnect's mcp__agentconnect__sendMessage (or an evaluation façade) and Claude Code's own built-in SendMessage tool (its agent-teams / subagent messaging feature, kind: "other", _meta.claudeCode.toolName: "SendMessage").

When the child is instructed to report a result back (the needsReply report-back directive), the built-in tool is a literal name match for the instruction — and the model picks it. The call "succeeds" inside Claude Code's own system, but the message never reaches the AgentConnect daemon: the parent session waits forever, and from the parent's view the child "completed its turn but returned no message".

Evidence (tool-surface A/B, 2026-08-09, 6 parent-session trials)

  • 3 of 6 first attempts across both arms went to the built-in SendMessage instead of the AgentConnect tool; 2 of 6 trials lost the answer entirely this way (one per arm).

  • The failing arm-B trial's artifacts contain zero occurrences of the string sendMessage in any text delivered to the child — the model was never taught that name in-session. The recorded call is unambiguous:

    {"title": "SendMessage", "kind": "other",
     "_meta": {"claudeCode": {"toolName": "SendMessage"}}}

    So this is not prompt leakage and not a tool-schema comprehension failure; it is a name collision inside the session's tool list. Both surface designs (production sendMessage and the primitives post façade) failed identically, which localizes the cause upstream of either.

  • Method and full numbers: docs/designs/messaging-primitives-ab.md (PR test(evals): tool-surface A/B — shipped sendMessage vs messaging-primitives post #791). Related earlier finding (same delivery hazard, prose variant): the delegate-and-forward case in evals/test/delegate-and-forward-real.test.ts, where a headless child answered in ordinary prose and the answer was silently dropped.

Impact

Any production agent whose runtime is Claude Code can mis-route a parent report into the runtime's own messaging system. The failure is silent: no error, no delivery, no wake — the worst failure mode for delegation flows.

Proposed fixes (complementary, ordered by how directly they remove the cause)

  1. Suppress the runtime's built-in messaging tools for AgentConnect-managed sessions. For sessions the daemon owns, Claude Code's SendMessage (and any sibling agent-teams messaging tools) is always the wrong answer and should not be offered. Investigate whether claude-agent-acp supports tool filtering (e.g. a disallowed-tools setting) and pass it from the runtime config; if it does not, file the capability request upstream.
  2. Reply-hint the report-back directive (pi-intercom pattern): embed the exact, pre-filled call — mcp__agentconnect__sendMessage({"sessionId": "<filled>", "message": "..."}) — in the directive text instead of describing the tool by name, so the correct target is copy-paste unambiguous.
  3. Inferred reply as a safety net (pi-intercom pattern): when a child session carries exactly one pending report-back obligation and its turn ends without having called the report tool, deliver its final ordinary output to the parent session (explicitly marked as inferred). This also fixes the prose-answer variant of the same hazard.

Fixes 2 and 3 make the system immune to the collision; fix 1 removes the collision itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions