Skip to content

feat(slack): add thread.autoReplyOnParticipation config option#31741

Open
carrotRakko wants to merge 2 commits intoopenclaw:mainfrom
delight-co:feat/thread-participation-opt-out
Open

feat(slack): add thread.autoReplyOnParticipation config option#31741
carrotRakko wants to merge 2 commits intoopenclaw:mainfrom
delight-co:feat/thread-participation-opt-out

Conversation

@carrotRakko
Copy link
Contributor

Summary

  • Problem: PR feat(slack): track thread participation for auto-reply without @mention #29165 added always-on thread participation auto-reply that bypasses requireMention gating with no opt-out. The in-memory cache (24h TTL, 5000-entry soft cap, no persistence) makes the behavior non-deterministic across process restarts.
  • Why it matters: Operators who rely on requireMention (default true) get unexpected bot responses in threads. The volatile cache means the same thread can behave differently before and after a restart.
  • What changed: Added channels.slack.thread.autoReplyOnParticipation config option (default: true). When false, hasSlackThreadParticipation() is skipped and implicitMention only fires for parent_user_id === botUserId.
  • What did NOT change: Thread participation tracking (feat(slack): track thread participation for auto-reply without @mention #29165) remains intact. The cache, recording, and default behavior are unchanged. Only a single boolean gate is added.

Change Type (select all)

  • Feature

Scope (select all touched areas)

  • Integrations
  • API / contracts

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)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Ubuntu 24.04
  • Runtime/container: Built from source (main)
  • Integration/channel: Slack

Steps

  1. Set channels.slack.thread.autoReplyOnParticipation: false in config
  2. @mention the bot in a channel → bot replies in thread
  3. Send a message in the same thread without @mention

Expected

Bot does not respond (respects requireMention gating).

Actual

Bot does not respond (correct with the new config).

Evidence

  • Failing test/log before + passing after

Existing tests pass. The change is a single boolean gate wrapping the hasSlackThreadParticipation() call in prepare.ts.

Human Verification (required)

  • Verified scenarios: pnpm check passes (format, typecheck, lint). Slack thread cache tests (8/8 pass).
  • Edge cases checked: Default true preserves existing behavior. false correctly skips only the participation check while preserving the parent_user_id === botUserId path.
  • What you did not verify: Manual Slack testing (not available in CI environment). The prepare.test.ts suite has a pre-existing strip-ansi import failure unrelated to this change.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? New optional config key (default preserves existing behavior)
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Remove autoReplyOnParticipation: false from config (or set to true). Default behavior is unchanged.
  • Files/config to restore: channels.slack.thread.autoReplyOnParticipation key
  • Known bad symptoms: None expected. The change only adds an opt-out gate.

Risks and Mitigations

  • Risk: Operators unaware of this option continue to experience the non-deterministic cache behavior.
    • Mitigation: Default is true (no change). Documentation added via schema labels and help text.

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

Added channels.slack.thread.autoReplyOnParticipation config option (default: true) to control whether the bot auto-replies in Slack threads it has participated in without requiring @mention. When set to false, the bot respects requireMention gating for threads it didn't start.

Key Changes:

  • Clean implementation with a single boolean gate in prepare.ts:226-227 wrapping the hasSlackThreadParticipation() check
  • Proper type safety and schema validation throughout (types.slack.ts, zod-schema.providers-core.ts)
  • Config value correctly threaded through context with sensible default (provider.ts:333)
  • All existing tests updated to include the new field, preserving backward compatibility

Minor Issues Found:

  • Help text could be more precise about auto-reply behavior when bot started the thread
  • No automated test coverage for the false config case (only manual verification per PR description)

Confidence Score: 4/5

  • Safe to merge with minor documentation and test coverage improvements recommended
  • Score reflects solid implementation with proper type safety and backward compatibility, offset slightly by missing test coverage for the new config option when disabled. The core logic is correct and straightforward, with only minor documentation clarity issues.
  • No files require special attention - the implementation is minimal and focused with proper safeguards

Last reviewed commit: 10edd92

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

11 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

"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.",
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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,
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a test case that mocks hasSlackThreadParticipation returning true with threadAutoReplyOnParticipation: false and verifies the message is skipped (mention gating not bypassed).

@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from 10edd92 to dc5c543 Compare March 2, 2026 14:23
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 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,

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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.

@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from dc5c543 to 99b276c Compare March 3, 2026 04:56
@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from 99b276c to f9421ad Compare March 3, 2026 14:46
@carrotRakko carrotRakko force-pushed the feat/thread-participation-opt-out branch from f9421ad to 1871ea4 Compare March 3, 2026 15:23
@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from 1871ea4 to 82a5f40 Compare March 4, 2026 17:17
@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch 2 times, most recently from fb259e9 to d0a7ce8 Compare March 5, 2026 11:46
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 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,

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from d0a7ce8 to 6c2bad6 Compare March 6, 2026 03:37
@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from 6c2bad6 to 1da462a Compare March 8, 2026 16:59
@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from 1da462a to 105422e Compare March 9, 2026 05:51
@carrotRakko carrotRakko force-pushed the feat/thread-participation-opt-out branch from 105422e to b251082 Compare March 9, 2026 08:54
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)
@delight-ai-agent delight-ai-agent force-pushed the feat/thread-participation-opt-out branch from 329edec to dab688f Compare March 9, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add opt-out config for thread participation auto-reply (#29165)

2 participants