From 44067ce926bfb5c099d78331dfdbc7b33d64e37e Mon Sep 17 00:00:00 2001 From: Poytr1 Date: Tue, 11 Aug 2026 22:54:10 +0800 Subject: [PATCH] revert(daemon): drop the #801 tool-precedence bullet after a live in-thread regression This reverts commit 29feb9b6e2021fbd88e4431ba46c764d0a81e5a6 (#801, the prompt-side mitigation for #800). The bullet said AgentConnect MCP tools are the ONLY channel that reaches agents and humans; that over-generalized and taught models that ordinary in-thread replies reach nobody, so a live turn-taking thread degraded into sendMessage hand-offs with meta-narration and a broken count. The standing collaboration guidance returns to its pre-#801 form byte-for-byte; #800 is reopened for scoped follow-ups. Co-Authored-By: Claude Fable 5 --- .../daemon/src/session/session-manager.ts | 9 ------- packages/daemon/test/session-manager.test.ts | 24 ------------------- 2 files changed, 33 deletions(-) diff --git a/packages/daemon/src/session/session-manager.ts b/packages/daemon/src/session/session-manager.ts index ba6fa15b6..cf957230c 100644 --- a/packages/daemon/src/session/session-manager.ts +++ b/packages/daemon/src/session/session-manager.ts @@ -817,17 +817,8 @@ export class SessionManager { // reach humans, post at a channel root, or reply into a parent session. It has no // visible in-thread form: speaking in the current conversation is an ordinary reply. // `toAgent` without a `channel` is the postless, channel-invisible wake. - // The precedence bullet leads for a measured reason (issue #800): on the Claude - // Code runtime the session also carries the runtime's own built-in `SendMessage` - // (agent-teams messaging) — a literal name match for a report-back instruction — - // and a child that picks it loses its parent report silently. Costs ~80 standing - // tokens per session. const collabAppend = `# Collaborating with other agents\n` + - `- AgentConnect's tools (the \`agentconnect\` MCP server, e.g. \`mcp__agentconnect__sendMessage\`) are the ` + - `ONLY channel that reaches other agents and humans here. Your runtime may offer built-in tools with similar ` + - `names (e.g. a bare \`SendMessage\`) — those do NOT reach AgentConnect and anything sent through them is ` + - `lost. Never use them for messaging, reporting back, or collaboration.\n` + `- To reach a specific agent privately, call \`sendMessage\` with ` + `\`{"toAgent":"","message":"..."}\` — it wakes ONLY that agent, delivered directly to it ` + `(nothing is posted to the channel). That bare form is FIRE-AND-FORGET: the peer answers inside its own ` + diff --git a/packages/daemon/test/session-manager.test.ts b/packages/daemon/test/session-manager.test.ts index 1b6bba82e..96dccde66 100644 --- a/packages/daemon/test/session-manager.test.ts +++ b/packages/daemon/test/session-manager.test.ts @@ -1934,30 +1934,6 @@ describe('SessionManager — collaboration preamble', () => { store.close() }) - it('leads the guidance with the tool-precedence rule naming the built-in SendMessage hazard (issue #800)', async () => { - // Measured (tool-surface A/B, 2026-08-09): a Claude Code child session also - // carries the runtime's own built-in `SendMessage` — a literal name match - // for a report-back instruction — and a child that picks it loses its - // parent report silently. The standing context must say, before anything - // else about collaboration, that AgentConnect's MCP tools are the only - // channel that reaches anyone and that similarly-named built-ins are lost. - const store = newStore() - const host = { newSession: vi.fn(async () => 'acp-1') } as any - const sm = new SessionManager({ store, hostFor: async () => host, agentById: () => agent, memory }) - const { blocks } = await sm.handle('bot-a', msg({ ts: '100.1', text: 'hi' })) - const first = (blocks[0] as any).text as string - expect(first).toContain('ONLY channel that reaches other agents and humans') - expect(first).toContain('mcp__agentconnect__sendMessage') - expect(first).toContain('a bare `SendMessage`') - expect(first).toContain('do NOT reach AgentConnect') - expect(first).toContain('Never use them for messaging, reporting back, or collaboration') - // It LEADS the collaboration section: the collision fires exactly when the - // model is choosing a messaging tool, so the warning must come first. - const section = first.slice(first.indexOf('# Collaborating with other agents')) - expect(section.indexOf('ONLY channel that reaches')).toBeLessThan(section.indexOf('To reach a specific agent')) - store.close() - }) - it('states the needsReply rule in the standing context, not only in the tool descriptor', async () => { // The descriptor is one input among many; this context is ALWAYS present and used to // present the bare `toAgent` form as the normal way to reach a peer privately, with no