Skip to content

feat(slack): track thread participation for auto-reply without @mention#29165

Merged
Takhoffman merged 4 commits intoopenclaw:mainfrom
luijoc:feat/slack-thread-participation-cache
Mar 1, 2026
Merged

feat(slack): track thread participation for auto-reply without @mention#29165
Takhoffman merged 4 commits intoopenclaw:mainfrom
luijoc:feat/slack-thread-participation-cache

Conversation

@luijoc
Copy link
Contributor

@luijoc luijoc commented Feb 27, 2026

Summary

  • Adds an in-memory Slack thread participation cache so the bot auto-responds in threads it has already participated in, without requiring @mention
  • Records participation when the bot sends messages via agent tool (sendMessage) and monitor reply dispatch
  • Checks participation in the message prepare phase to extend implicitMention detection

Changes

  • New: src/slack/sent-thread-cache.ts — TTL-based (24h) in-memory cache with 5000 soft-cap, following the pattern from MS Teams and Telegram caches
  • New: src/slack/sent-thread-cache.test.ts — 6 tests covering record/check, isolation, empty inputs, clearing, and TTL expiry
  • Modified: src/agents/tools/slack-actions.ts — records participation after sendMessage when threadTs and channelId are present
  • Modified: src/slack/monitor/message-handler/dispatch.ts — records participation after reply delivery
  • Modified: src/slack/monitor/message-handler/prepare.ts — extends implicitMention to include threads where the bot has participated (not just where it's the parent)

Review

Verdict: APPROVE WITH SUGGESTIONS | Risk: 18/100

Review details
Category Critical High Medium Low
Validation & Patterns 0 0 0 3
Impact & Blast Radius 0 0 1 1
Correctness & Logic 0 0 0 0
Security & Data Safety 0 0 0 0
Architecture & Quality 0 0 0 0
  • Medium: dispatch.ts recordSlackThreadParticipation call lacks dedicated unit test
  • Low: MAX_ENTRIES is a soft cap (consistent with MS Teams/Telegram caches)
  • Low: Comment wording "mirrors" is slightly imprecise vs actual structure
  • Low: Top-level agent messages not tracked as thread seeds (by design)

Testing

  • Unit tests pass (6/6 in sent-thread-cache.test.ts)
  • Type check passes
  • Lint passes (oxlint + oxfmt)
  • Manual testing in Slack workspace

Breaking Changes

None

🤖 Generated with Claude Code

@openclaw-barnacle openclaw-barnacle bot added channel: slack Channel integration: slack agents Agent runtime and tooling size: S labels Feb 27, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

Adds in-memory cache to track Slack thread participation so the bot auto-responds in threads it has joined without requiring @mention after the first reply. Implementation follows similar TTL-based caching patterns used elsewhere in the codebase.

Key Changes:

  • New sent-thread-cache.ts implements 24h TTL cache with 5000-entry soft cap
  • Records participation after bot sends messages (via agent tool and monitor dispatch)
  • Extends implicitMention detection to include threads where bot has participated
  • 6 unit tests cover core cache functionality (record/check, isolation, TTL, clearing)

Notes:

  • Cache structure differs from MS Teams/Telegram (flat vs nested), though both use TTL-based eviction
  • Integration points lack dedicated unit tests (mentioned in PR as medium-risk item)
  • MAX_ENTRIES triggers full cache scan on eviction (acceptable for 5000 entries)

Confidence Score: 4/5

  • This PR is safe to merge with low risk - adds well-isolated thread participation tracking without modifying core message handling logic
  • Score reflects clean implementation with good test coverage for the cache itself, though integration points (recordSlackThreadParticipation calls in dispatch.ts and slack-actions.ts) lack dedicated unit tests. The cache logic is straightforward with proper TTL handling and edge case coverage. No breaking changes or security concerns identified.
  • No files require special attention - all changes are straightforward and well-structured

Last reviewed commit: 4acee55

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: 4acee557ef

ℹ️ 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".

Comment on lines +417 to +418
if (anyReplyDelivered && statusThreadTs) {
recordSlackThreadParticipation(message.channel, statusThreadTs);

Choose a reason for hiding this comment

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

P1 Badge Record participation from actual reply thread in first mode

This only records participation when statusThreadTs is set, but for top-level messages in replyToMode: "first", resolveSlackThreadTargets leaves statusThreadTs undefined while the first reply is still sent into a thread via replyPlan.nextThreadTs() (see src/slack/threading.ts and src/slack/monitor/replies.ts). As a result, successful first threaded auto-replies are never cached, so later messages in that same thread still fail mention-gating unless users @mention the bot, which breaks the feature for first-mode configurations.

Useful? React with 👍 / 👎.

Comment on lines +12 to +13
function makeKey(channelId: string, threadTs: string): string {
return `${channelId}:${threadTs}`;

Choose a reason for hiding this comment

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

P2 Badge Scope thread participation cache by bot/account identity

The cache key is only channelId:threadTs, so participation state is shared across all configured Slack bots/accounts in the same process. In multi-bot setups where two Slack accounts monitor the same workspace/channel, one bot replying in a thread will make hasSlackThreadParticipation(...) true for the other bot as well, causing unsolicited implicit-mention replies from bots that never participated in that thread.

Useful? React with 👍 / 👎.

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: 0e9c47a2ca

ℹ️ 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".

Comment on lines +185 to +188
const replyThreadTs = forcedThreadTs ?? replyPlan.nextThreadTs();
if (replyThreadTs) {
usedReplyThreadTs ??= replyThreadTs;
}

Choose a reason for hiding this comment

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

P1 Badge Capture thread ID for streamed/thread-edited first replies

In replyToMode: "first", thread participation is only latched when usedReplyThreadTs is set here, but successful native-streaming starts (startSlackStream) and preview-final-edit paths can send the first threaded reply without calling deliverNormally. For top-level messages those paths also have no statusThreadTs, so the participation cache never records the thread and subsequent user replies in that thread still fail implicit-mention gating unless they @mention the bot. Fresh evidence: this commit’s new usedReplyThreadTs assignment exists only inside deliverNormally, while streaming-start and preview-edit paths bypass it.

Useful? React with 👍 / 👎.

Comment on lines +421 to +423
const participationThreadTs = usedReplyThreadTs ?? statusThreadTs;
if (anyReplyDelivered && participationThreadTs) {
recordSlackThreadParticipation(account.accountId, message.channel, participationThreadTs);

Choose a reason for hiding this comment

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

P2 Badge Update participation cache only after confirmed send success

This marks a thread as participated based on anyReplyDelivered, but that signal is derived from queued reply counts rather than successful Slack deliveries, so transient chat.postMessage/stream API failures can still populate the participation cache. In that failure mode, later messages in the thread may bypass mention-gating even though the bot never actually posted in the thread.

Useful? React with 👍 / 👎.

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: 6d811d5712

ℹ️ 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".

@@ -208,7 +212,8 @@ export async function prepareSlackMessage(params: {
!isDirectMessage &&
ctx.botUserId &&

Choose a reason for hiding this comment

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

P2 Badge Allow participation cache when bot user ID is unavailable

The new implicit-mention logic still short-circuits on ctx.botUserId, so the participation cache is never consulted when Slack auth.test fails at startup (which src/slack/monitor/provider.ts treats as non-fatal by leaving botUserId empty). In that degraded-auth scenario, threads where the bot already replied (and were recorded via recordSlackThreadParticipation) still require explicit @mentions, so this feature silently stops working precisely when mention detection is already in fallback mode.

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.

The ctx.botUserId && guard is pre-existing — it was there before this PR for the parent_user_id === ctx.botUserId check. Removing it to enable the participation cache in degraded-auth mode would change unrelated behavior and is out of scope for this change. If degraded-auth implicit mentions need fixing, that should be a separate PR.

@luijoc
Copy link
Contributor Author

luijoc commented Feb 28, 2026

Noting that all Codex-identified issues tied to his PR have been resolved. I did run CodeScene on the files I updated with this update, and found that there's high cyclomatic complexity in the handleSlackAction method in the src/agents/tools/slack-actions.ts file with the following code smells: Complex Method (cc=77), Large Method (253 LOC), Bumpy Road (11 bumps), Deep Nested Complexity (4 levels). I can tackle those in a separate PR.

@Takhoffman Takhoffman force-pushed the feat/slack-thread-participation-cache branch from 6d811d5 to 5079d0c Compare March 1, 2026 16:42
@Takhoffman Takhoffman merged commit bd78a74 into openclaw:main Mar 1, 2026
9 checks passed
@Takhoffman
Copy link
Contributor

Merged via salvage path.

Merge commit: bd78a74
Head commit pinned: 5079d0c

What changed before merge:

  • rebased onto latest main and resolved overlap with recent Slack threading changes
  • preserved per-message replyToMode routing while adding thread-participation implicit-mention support
  • added missing changelog entry for the user-facing threading behavior

Verification run on the rebased branch:

  • CI=true pnpm install --frozen-lockfile
  • pnpm build
  • pnpm check
  • pnpm test:macmini

All checks passed.

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: 5079d0c4c3

ℹ️ 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".

Comment on lines +208 to +210
// Record the thread ts only after confirmed delivery success.
if (replyThreadTs) {
usedReplyThreadTs ??= replyThreadTs;

Choose a reason for hiding this comment

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

P2 Badge Capture thread participation when chunked send partially succeeds

usedReplyThreadTs is only assigned after deliverReplies(...) resolves, but deliverReplies can send multiple Slack messages for one payload (media fan-out and chunked text) and will throw if a later API call fails after earlier messages were already posted. In that partial-success path the bot has participated in the thread, yet the cache is never updated, so subsequent thread messages can still be mention-gated unexpectedly.

Useful? React with 👍 / 👎.

Comment on lines 205 to +209
blocks,
});

if (threadTs && result.channelId && account.accountId) {
recordSlackThreadParticipation(account.accountId, result.channelId, threadTs);

Choose a reason for hiding this comment

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

P2 Badge Record participation even when tool send fails after first chunk

This records participation only after sendSlackMessage(...) returns, but that helper sends chunked/media replies as multiple Slack API calls and may throw on a later call after at least one message was already posted. When that happens, the tool action fails while the bot has still replied in-thread, and the participation cache remains empty, so follow-up thread messages keep requiring explicit @mentions.

Useful? React with 👍 / 👎.

zooqueen added a commit to hanzoai/bot that referenced this pull request Mar 1, 2026
ansh pushed a commit to vibecode/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
safzanpirani pushed a commit to safzanpirani/clawdbot that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
amitmiran137 pushed a commit to amitmiran137/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
delight-ai-agent pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 2, 2026
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 pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 2, 2026
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)
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
delight-ai-agent pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 2, 2026
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)
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
hanqizheng pushed a commit to hanqizheng/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
dorgonman pushed a commit to kanohorizonia/openclaw that referenced this pull request Mar 3, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
delight-ai-agent pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 3, 2026
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 pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 3, 2026
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)
carrotRakko added a commit to delight-co/openclaw-public that referenced this pull request Mar 3, 2026
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 pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 4, 2026
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 pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 5, 2026
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 pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 5, 2026
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 pushed a commit to delight-co/openclaw-public that referenced this pull request Mar 6, 2026
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)
sachinkundu pushed a commit to sachinkundu/openclaw that referenced this pull request Mar 6, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…on (openclaw#29165)

* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen added a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: slack Channel integration: slack size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants