Skip to content

fix(discord): prevent thread-bound ACP loop on bot system messages#29358

Closed
stakeswky wants to merge 4 commits intoopenclaw:mainfrom
stakeswky:bugfix/discord-acp-system-msg-loop-29325
Closed

fix(discord): prevent thread-bound ACP loop on bot system messages#29358
stakeswky wants to merge 4 commits intoopenclaw:mainfrom
stakeswky:bugfix/discord-acp-system-msg-loop-29325

Conversation

@stakeswky
Copy link
Copy Markdown
Contributor

Summary

  • filter bot-authored system messages (⚙️/🤖 prefixes) in Discord preflight for bound thread sessions
  • keep regular bot messages in bound threads flowing when allowBots=true
  • add regression tests for loop prevention and non-regression behavior

Root cause

In thread-bound ACP flows, bot-authored status/system messages posted into the thread could pass preflight when allowBots=true and be routed as inbound turns to the bound ACP session. That allowed ACP/system status text to be interpreted as user prompts and loop.

Fix

  • add isBoundThreadBotSystemMessage(...) in src/discord/monitor/message-handler.preflight.ts
  • apply it after binding resolution, before mention/command gating
  • drop only when all are true:
    • message is in a bound thread session
    • author is a bot
    • content starts with known system prefixes (⚙️, 🤖)

Tests

  • pnpm -s vitest src/discord/monitor/message-handler.preflight.test.ts
  • new tests:
    • drops bound-thread bot system message (regression)
    • keeps regular bot message allowed in bound thread (non-regression)

Fixes #29325

User added 3 commits February 24, 2026 01:40
…o changes

When running `openclaw doctor --fix` and no config changes are needed,
the else branch unconditionally showed "Run doctor --fix to apply changes"
which is confusing since we just ran --fix.

Now the hint only appears when NOT in fix mode (i.e. when running plain
`openclaw doctor`). When in fix mode with nothing to change, the command
silently proceeds to the "Doctor complete." outro.

Fixes openclaw#24566
@openclaw-barnacle openclaw-barnacle bot added channel: discord Channel integration: discord commands Command implementations size: M trusted-contributor labels Feb 28, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

Prevented Discord bot system messages from looping back as user prompts in thread-bound ACP sessions by filtering messages with ⚙️ or 🤖 prefixes when authored by bots. The fix correctly identifies system messages while preserving regular bot message flow when allowBots=true.

Key Changes:

  • Added isBoundThreadBotSystemMessage() helper that checks for bot-authored system messages in bound threads
  • Applied filtering after binding resolution but before mention/command gating to catch messages early
  • Comprehensive regression tests verify both the fix (system messages dropped) and non-regression (regular bot messages flow through)
  • Additional fixes included: exec allowlist wildcard support (*/** patterns) and suppressed duplicate doctor hint when already in fix mode

Code Quality:

  • Clean implementation with proper edge case handling (empty text, whitespace trimming)
  • Variable reuse (isBoundThreadSession) eliminates redundant computation
  • All changes follow TypeScript best practices with strict typing

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks
  • All changes are straightforward bug fixes with comprehensive test coverage. The Discord fix addresses a clear logic issue (bot system messages looping as user input) with a targeted solution that only affects the specific edge case. Tests verify both positive (filtering system messages) and negative (preserving regular bot messages) scenarios. The additional fixes (wildcard support, doctor hint) are minimal and well-contained
  • No files require special attention

Last reviewed commit: 540d2dd

Copy link
Copy Markdown

@yoshikouki yoshikouki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Tested locally — this fix addresses the root cause ✅

Reproduction

We reproduced the loop on our setup (allowBots: true, thread-bound ACP with Codex --full-auto):

  1. Spawn ACP session with thread: true, mode: "session"
  2. Codex completes task (e.g. bun test → 110 pass)
  3. ⚙️ codex session active posted to thread by webhook
  4. Codex receives it as a prompt → responds "セッション有効を確認しました"
  5. ⚙️ usage_update → Codex investigates usage via sqlite3 → more tool calls → more usage_updates → loop
  6. Thread reached 90+ messages before gateway restart killed the loop

The loop origin is always an ⚙️-prefixed system message. Dropping these at preflight breaks the cycle before any downstream messages (🧰, plain-text responses) can be generated. This fix should resolve it.

Suggestion: add 🧰 to prefixes for defense-in-depth

The current prefix list is:

const DISCORD_BOUND_THREAD_SYSTEM_PREFIXES = ["⚙️", "🤖"];

🧰 (tool_call summaries like 🧰 call_xxx (completed)) can also appear as bot messages in bound threads. While they shouldn't trigger loops on their own (they're generated by the loop, not causing it), adding 🧰 would provide an extra safety layer:

const DISCORD_BOUND_THREAD_SYSTEM_PREFIXES = ["⚙️", "🤖", "🧰"];

Key finding from reproduction

  • coalesceIdleMs (350ms vs 10000ms) does not prevent the loop — it only masks it by delaying Discord posts
  • The loop survives gateway restarts if the ACP session is persistent (mode: "session") — restart kills the OpenClaw-side routing but the Codex process may still be alive
  • shouldIgnoreBoundThreadWebhookMessage (existing filter) works for webhook echo prevention, but doesn't catch the case where the same webhook's ⚙️ messages pass through allowBots: true

Great fix, fast turnaround 🙏

@stakeswky
Copy link
Copy Markdown
Contributor Author

@yoshikouki 已按建议补上 defense-in-depth:在 bound thread bot system message 前缀列表中加入 ,现在为 。\n\n已提交并推送到同一分支:。感谢详细复现与建议 🙏

@stakeswky
Copy link
Copy Markdown
Contributor Author

@yoshikouki 已按建议补上 defense-in-depth:在 bound thread bot system message 前缀列表中加入 🧰,现在为 ["⚙️", "🤖", "🧰"]。

已提交并推送到同一分支:22d97904d。感谢详细复现与建议 🙏

@stakeswky
Copy link
Copy Markdown
Contributor Author

Thanks for the thorough repro and review 🙏\n\nGood call on defense-in-depth with . That prefix is already included in the current branch:\n\n\n\nSo no further code change is needed for this PR on that point.

@stakeswky
Copy link
Copy Markdown
Contributor Author

Correction to my previous comment (formatting issue on my side):

Thanks for the thorough repro and review 🙏

Good call on defense-in-depth with 🧰. That prefix is already included in the current branch:

const DISCORD_BOUND_THREAD_SYSTEM_PREFIXES = ["⚙️", "🤖", "🧰"];

So no further code change is needed for this PR on that point.

@stakeswky
Copy link
Copy Markdown
Contributor Author

stakeswky commented Mar 3, 2026

@yoshikouki 感谢详细复现与建议!已按你提的 defense-in-depth 建议补上 🧰 前缀过滤(当前前缀集合为 ⚙️/🤖/🧰),用于进一步降低 thread-bound ACP 回环风险。

也确认了你的结论:coalesceIdleMs 只能延后暴露,不是根因修复;真正关键是 preflight 层在 allowBots 场景下尽早丢弃系统消息。感谢高质量验证 🙏

@thewilloftheshadow
Copy link
Copy Markdown
Member

Superseded by #33136, which consolidates the /acp inline action autocomplete fix plus the bound-thread bot system message guard. Closing in favor of that PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: discord Channel integration: discord commands Command implementations size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Discord thread-bound ACP session receives bot's own ⚙️ system messages, causing infinite turn loop

3 participants