feat(slack): add thread.autoReplyOnParticipation config option#31741
feat(slack): add thread.autoReplyOnParticipation config option#31741carrotRakko wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryAdded Key Changes:
Minor Issues Found:
Confidence Score: 4/5
Last reviewed commit: 10edd92 |
src/config/schema.help.ts
Outdated
| "channels.slack.thread.initialHistoryLimit": | ||
| "Maximum number of existing Slack thread messages to fetch when starting a new thread session (default: 20, set to 0 to disable).", | ||
| "channels.slack.thread.autoReplyOnParticipation": | ||
| "If true, the bot auto-replies in threads it has previously participated in, even without @mention (default: true). Set to false to require explicit @mention for every thread reply.", |
There was a problem hiding this comment.
help text says "for every thread reply" but bot will still auto-reply in threads it started (parent_user_id === botUserId) even when this is false. consider clarifying: "Set to false to require explicit @mention in threads where the bot participated but did not start the thread."
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/config/schema.help.ts
Line: 695
Comment:
help text says "for every thread reply" but bot will still auto-reply in threads it started (`parent_user_id === botUserId`) even when this is `false`. consider clarifying: "Set to false to require explicit `@mention` in threads where the bot participated but did not start the thread."
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Good catch — updated the help text to clarify that false only affects threads where the bot participated but did not start the conversation (parent_user_id === botUserId still triggers auto-reply).
| @@ -72,6 +72,7 @@ describe("slack prepareSlackMessage inbound contract", () => { | |||
| replyToMode: params.replyToMode ?? "off", | |||
| threadHistoryScope: "thread", | |||
| threadInheritParent: false, | |||
There was a problem hiding this comment.
no test coverage for threadAutoReplyOnParticipation: false - all tests use the default true value. consider adding a test that verifies the bot doesn't auto-reply in threads it participated in (but didn't start) when this config is disabled.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/slack/monitor/message-handler/prepare.test.ts
Line: 74
Comment:
no test coverage for `threadAutoReplyOnParticipation: false` - all tests use the default `true` value. consider adding a test that verifies the bot doesn't auto-reply in threads it participated in (but didn't start) when this config is disabled.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Added a test case that mocks hasSlackThreadParticipation returning true with threadAutoReplyOnParticipation: false and verifies the message is skipped (mention gating not bypassed).
10edd92 to
dc5c543
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc5c543b3e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| replyToMode, | ||
| threadHistoryScope, | ||
| threadInheritParent, | ||
| threadAutoReplyOnParticipation: slackCfg.thread?.autoReplyOnParticipation ?? true, |
There was a problem hiding this comment.
Honor top-level thread auto-reply setting for account overrides
threadAutoReplyOnParticipation is derived only from slackCfg.thread?.autoReplyOnParticipation ?? true, but resolveSlackAccount() shallow-merges top-level and per-account config ({ ...base, ...account } in src/slack/accounts.ts), so an account that sets any thread subfield (for example historyScope) drops the top-level channels.slack.thread.autoReplyOnParticipation: false and silently falls back to true. In multi-account setups this makes the new opt-out ineffective unless every account repeats the flag explicitly.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good observation about shallow merge, but this is a pre-existing characteristic of mergeSlackAccountConfig() in accounts.ts:51 ({ ...base, ...account }), not something introduced by this PR. The thread object already has three other properties (historyScope, inheritParent, initialHistoryLimit) that are all subject to the same shallow merge behavior. For example, setting historyScope at the top level and overriding inheritParent per-account would similarly drop historyScope. Addressing the shallow-to-deep merge upgrade is out of scope for this change.
dc5c543 to
99b276c
Compare
99b276c to
f9421ad
Compare
f9421ad to
1871ea4
Compare
1871ea4 to
82a5f40
Compare
fb259e9 to
d0a7ce8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0a7ce8f4e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| replyToMode, | ||
| threadHistoryScope, | ||
| threadInheritParent, | ||
| threadAutoReplyOnParticipation: slackCfg.thread?.autoReplyOnParticipation ?? true, |
There was a problem hiding this comment.
Honor top-level thread auto-reply opt-out for account overrides
resolveSlackAccount() still does a shallow merge ({ ...base, ...account } in src/slack/accounts.ts), so when an account defines any thread subfield (for example historyScope) but omits autoReplyOnParticipation, slackCfg.thread loses the top-level value and this fallback ?? true turns auto-reply back on. That makes channels.slack.thread.autoReplyOnParticipation: false ineffective in multi-account setups unless every account repeats the new flag explicitly.
Useful? React with 👍 / 👎.
d0a7ce8 to
6c2bad6
Compare
6c2bad6 to
1da462a
Compare
1da462a to
105422e
Compare
105422e to
b251082
Compare
PR openclaw#29165 added always-on thread participation auto-reply that bypasses requireMention gating with no opt-out. Add a config option under channels.slack.thread to disable this behavior: channels.slack.thread.autoReplyOnParticipation: false When false, hasSlackThreadParticipation() is skipped and implicitMention only fires for parent_user_id === botUserId (the pre-openclaw#29165 behavior). Default: true (preserves current behavior). Closes openclaw#31728 ✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
329edec to
dab688f
Compare
Summary
requireMentiongating with no opt-out. The in-memory cache (24h TTL, 5000-entry soft cap, no persistence) makes the behavior non-deterministic across process restarts.requireMention(defaulttrue) get unexpected bot responses in threads. The volatile cache means the same thread can behave differently before and after a restart.channels.slack.thread.autoReplyOnParticipationconfig option (default:true). Whenfalse,hasSlackThreadParticipation()is skipped andimplicitMentiononly fires forparent_user_id === botUserId.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
New config option:
channels.slack.thread.autoReplyOnParticipation(boolean, default:true).When set to
false, the bot no longer auto-replies in threads it has participated in unless explicitly@mentioned. This restores the pre-#29165 behavior for that thread.Security Impact (required)
Repro + Verification
Environment
Steps
channels.slack.thread.autoReplyOnParticipation: falsein config@mentionthe bot in a channel → bot replies in thread@mentionExpected
Bot does not respond (respects
requireMentiongating).Actual
Bot does not respond (correct with the new config).
Evidence
Existing tests pass. The change is a single boolean gate wrapping the
hasSlackThreadParticipation()call inprepare.ts.Human Verification (required)
pnpm checkpasses (format, typecheck, lint). Slack thread cache tests (8/8 pass).truepreserves existing behavior.falsecorrectly skips only the participation check while preserving theparent_user_id === botUserIdpath.prepare.test.tssuite has a pre-existingstrip-ansiimport failure unrelated to this change.Compatibility / Migration
Failure Recovery (if this breaks)
autoReplyOnParticipation: falsefrom config (or set totrue). Default behavior is unchanged.channels.slack.thread.autoReplyOnParticipationkeyRisks and Mitigations
true(no change). Documentation added via schema labels and help text.✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)