From e65e5f40c91aeeab1cded49e489bb541c6d003dd Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 14 Jan 2026 20:05:29 +0000 Subject: [PATCH] fix(whatsapp): use conversation id for context isolation (#911) Thanks @tristanmanchester. Co-authored-by: Tristan Manchester --- CHANGELOG.md | 1 + .../reply/agent-runner-utils.test.ts | 41 +++++++++++++++++++ src/auto-reply/reply/agent-runner-utils.ts | 4 +- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/auto-reply/reply/agent-runner-utils.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index d9cc0119c..c6df2dc59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Telegram: split long captions into media + follow-up text messages. (#907) - thanks @jalehman. - Slack: drop Socket Mode events with mismatched `api_app_id`/`team_id`. (#889) — thanks @roshanasingh4. - Discord: isolate autoThread thread context. (#856) — thanks @davidguttman. +- WhatsApp: fix context isolation using wrong ID (was bot's number, now conversation ID). (#911) — thanks @tristanmanchester. ## 2026.1.13 diff --git a/src/auto-reply/reply/agent-runner-utils.test.ts b/src/auto-reply/reply/agent-runner-utils.test.ts new file mode 100644 index 000000000..c10a8f0e4 --- /dev/null +++ b/src/auto-reply/reply/agent-runner-utils.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from "vitest"; + +import type { ClawdbotConfig } from "../../config/config.js"; +import type { TemplateContext } from "../templating.js"; +import { buildThreadingToolContext } from "./agent-runner-utils.js"; + +describe("buildThreadingToolContext", () => { + const cfg = {} as ClawdbotConfig; + + it("uses conversation id for WhatsApp", () => { + const sessionCtx = { + Provider: "whatsapp", + From: "123@g.us", + To: "+15550001", + } as TemplateContext; + + const result = buildThreadingToolContext({ + sessionCtx, + config: cfg, + hasRepliedRef: undefined, + }); + + expect(result.currentChannelId).toBe("123@g.us"); + }); + + it("uses the recipient id for other channels", () => { + const sessionCtx = { + Provider: "telegram", + From: "user:42", + To: "chat:99", + } as TemplateContext; + + const result = buildThreadingToolContext({ + sessionCtx, + config: cfg, + hasRepliedRef: undefined, + }); + + expect(result.currentChannelId).toBe("chat:99"); + }); +}); diff --git a/src/auto-reply/reply/agent-runner-utils.ts b/src/auto-reply/reply/agent-runner-utils.ts index b4f1b2bc2..89a8ca2a8 100644 --- a/src/auto-reply/reply/agent-runner-utils.ts +++ b/src/auto-reply/reply/agent-runner-utils.ts @@ -25,13 +25,15 @@ export function buildThreadingToolContext(params: { if (!provider) return {}; const dock = getChannelDock(provider); if (!dock?.threading?.buildToolContext) return {}; + // WhatsApp context isolation keys off conversation id, not the bot's own number. + const threadingTo = provider === "whatsapp" ? sessionCtx.From ?? sessionCtx.To : sessionCtx.To; return ( dock.threading.buildToolContext({ cfg: config, accountId: sessionCtx.AccountId, context: { Channel: sessionCtx.Provider, - To: sessionCtx.To, + To: threadingTo, ReplyToId: sessionCtx.ReplyToId, ThreadLabel: sessionCtx.ThreadLabel, },