From 1298bd4e1bdb7cd28dea6ddd8e3de7f2f43be36d Mon Sep 17 00:00:00 2001 From: justinhuangcode Date: Mon, 23 Feb 2026 17:41:12 +0000 Subject: [PATCH] fix(matrix): skip reasoning-only messages in reply delivery When `includeReasoning` is active (or `reasoningLevel` falls back to the model default), the agent emits reasoning blocks as separate reply payloads prefixed with "Reasoning:\n". Matrix has no dedicated reasoning lane, so these internal thinking traces leak into the chat as regular user-visible messages. Filter out pure-reasoning payloads (those starting with "Reasoning:\n" or a `` tag) before delivery so internal reasoning never reaches the Matrix room. Fixes #24411 Co-Authored-By: Claude Opus 4.6 --- .../matrix/src/matrix/monitor/replies.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/extensions/matrix/src/matrix/monitor/replies.ts b/extensions/matrix/src/matrix/monitor/replies.ts index 643e95cd4..c86c7dde6 100644 --- a/extensions/matrix/src/matrix/monitor/replies.ts +++ b/extensions/matrix/src/matrix/monitor/replies.ts @@ -41,6 +41,11 @@ export async function deliverMatrixReplies(params: { params.runtime.error?.("matrix reply missing text/media"); continue; } + // Skip pure reasoning messages so internal thinking traces are never delivered. + if (reply.text && isReasoningOnlyMessage(reply.text)) { + logVerbose("matrix reply is reasoning-only; skipping"); + continue; + } const replyToIdRaw = reply.replyToId?.trim(); const replyToId = params.threadId || params.replyToMode === "off" ? undefined : replyToIdRaw; const rawText = reply.text ?? ""; @@ -98,3 +103,22 @@ export async function deliverMatrixReplies(params: { } } } + +const REASONING_PREFIX = "Reasoning:\n"; +const THINKING_TAG_RE = /^\s*<\s*(?:think(?:ing)?|thought|antthinking)\b/i; + +/** + * Detect messages that contain only reasoning/thinking content and no user-facing answer. + * These are emitted by the agent when `includeReasoning` is active but should not + * be forwarded to channels that do not support a dedicated reasoning lane. + */ +function isReasoningOnlyMessage(text: string): boolean { + const trimmed = text.trim(); + if (trimmed.startsWith(REASONING_PREFIX)) { + return true; + } + if (THINKING_TAG_RE.test(trimmed)) { + return true; + } + return false; +}