From cb1de711385413d75e5c6ec34c1cd21261c654db Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 24 Feb 2026 04:13:29 +0000 Subject: [PATCH] fix(subagents): preserve non-internal announce origin channels (#23030) (thanks @mcinteerj) --- CHANGELOG.md | 1 + src/agents/subagent-announce.format.test.ts | 29 +++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9307e7437fd..84e9e857953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai - Infra/Windows TOCTOU: handle Windows `dev=0` edge cases in same-file identity checks. (#24939) - Exec/Bash tools: clamp poll sleep duration to non-negative values in process polling loops. (#24889) - Subagents/Announce queue: add exponential backoff when queue-drain delivery fails to reduce retry storms. (#24783) +- Subagents/Announce routing: preserve non-internal requester channels when resolving announce origin so stale session channel hints do not override spawn-time routing context. (#23030) Thanks @mcinteerj. - Config/Kilo Gateway: Kilo provider flow now surfaces an updated list of models. (#24921) thanks @gumadeiras. - Agents/Tool warnings: suppress `sessions_send` relay errors from chat-facing warning payloads to avoid leaking transient inter-session transport failures. (#24740) Thanks @Glucksberg. - WhatsApp/Logging: redact outbound recipient identifiers in WhatsApp outbound + heartbeat logs and remove message/poll preview text from those log lines. (#24980) Thanks @coygeek. diff --git a/src/agents/subagent-announce.format.test.ts b/src/agents/subagent-announce.format.test.ts index b486dff75c8..7f01e6da90a 100644 --- a/src/agents/subagent-announce.format.test.ts +++ b/src/agents/subagent-announce.format.test.ts @@ -1628,6 +1628,35 @@ describe("subagent announce formatting", () => { expect(call?.params?.to).toBe("telegram:123"); }); + it("preserves non-internal requesterOrigin channel over stale session lastChannel", async () => { + embeddedRunMock.isEmbeddedPiRunActive.mockReturnValue(true); + embeddedRunMock.isEmbeddedPiRunStreaming.mockReturnValue(false); + sessionStore = { + "agent:main:main": { + sessionId: "session-stale-custom", + lastChannel: "whatsapp", + queueMode: "collect", + queueDebounceMs: 0, + }, + }; + + const didAnnounce = await runSubagentAnnounceFlow({ + childSessionKey: "agent:main:subagent:test", + childRunId: "run-stale-custom-channel", + requesterSessionKey: "main", + requesterOrigin: { channel: "custombridge", to: "room:42" }, + requesterDisplayKey: "main", + ...defaultOutcomeAnnounce, + }); + + expect(didAnnounce).toBe(true); + expect(agentSpy).toHaveBeenCalledTimes(1); + + const call = agentSpy.mock.calls[0]?.[0] as { params?: Record }; + expect(call?.params?.channel).toBe("custombridge"); + expect(call?.params?.to).toBe("room:42"); + }); + it("routes or falls back for ended parent subagent sessions (#18037)", async () => { const cases = [ {