Skip to content

fix(slack): resolve replyToMode per-message using chat type#24717

Merged
Takhoffman merged 2 commits intoopenclaw:mainfrom
dbachelder:fix/slack-dm-reply-to-mode-per-chat-type
Mar 1, 2026
Merged

fix(slack): resolve replyToMode per-message using chat type#24717
Takhoffman merged 2 commits intoopenclaw:mainfrom
dbachelder:fix/slack-dm-reply-to-mode-per-chat-type

Conversation

@dbachelder
Copy link
Contributor

@dbachelder dbachelder commented Feb 23, 2026

Summary

  • Problem: replyToModeByChatType.direct: "off" is ignored on the inbound path — DM replies are always threaded when the top-level replyToMode is "all".
  • Why it matters: Users configuring flat DM replies still get threaded responses, making DMs harder to read and breaking expected behavior.
  • What changed: The inbound message handler (prepare.ts) now calls resolveSlackReplyToMode(account, chatType) per-message instead of using the static ctx.replyToMode resolved once at startup. dispatch.ts reads the resolved value from prepared.replyToMode.
  • What did NOT change: The outbound dock and tool threading context already used resolveSlackReplyToMode correctly — those paths are untouched. The SlackMonitorContext.replyToMode field remains for backward compatibility but is no longer used in the message handler hot path.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

N/A

User-visible / Behavior Changes

  • replyToModeByChatType.direct and dm.replyToMode config overrides now take effect on the inbound Slack path. Previously these were silently ignored for inbound message threading.
  • No change for users who don't use replyToModeByChatTyperesolveSlackReplyToMode falls through to the top-level replyToMode.

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: macOS (Darwin 25.2.0)
  • Runtime/container: Docker linux/amd64, OpenCLAW v2026.2.22
  • Model/provider: AWS Bedrock (Claude)
  • Integration/channel: Slack (Socket Mode)
  • Relevant config:
    {
      "channels": {
        "slack": {
          "replyToMode": "all",
          "replyToModeByChatType": {
            "direct": "off"
          }
        }
      }
    }

Steps

  1. Configure replyToMode: "all" with replyToModeByChatType.direct: "off"
  2. Send an unthreaded DM to the bot
  3. Observe the bot's reply

Expected

  • Bot replies as a flat message in the DM (no thread_ts)

Actual (before fix)

  • Bot replies inside a thread on the user's message

Evidence

  • Verified in production Slack workspace: DM replies are now flat when replyToModeByChatType.direct: "off"
  • Channel messages still thread correctly with replyToMode: "all"

Human Verification (required)

  • Verified scenarios: Unthreaded DM with direct: "off" → flat reply. Channel message with top-level "all" → threaded reply.
  • Edge cases checked: Existing threads in DMs still reply within the thread (isThreadReply path unchanged). Group DMs respect their own override if configured.
  • What I did not verify: replyToMode: "first" with per-chat-type override (same code path, should work identically).

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert: Remove replyToModeByChatType from config — behavior falls back to top-level replyToMode as before.
  • Files/config to restore: src/slack/monitor/message-handler/prepare.ts, dispatch.ts, types.ts
  • Known bad symptoms: If regression, DM replies would ignore replyToModeByChatType overrides again (same as current behavior, not worse).

Risks and Mitigations

  • Risk: resolveSlackReplyToMode is called per-message instead of once at startup — negligible perf impact (pure in-memory config lookup, no I/O).
    • Mitigation: The outbound dock and tool context already call this per-message without issue.

Greptile Summary

Fixed replyToModeByChatType.direct config being ignored on the inbound Slack path. Previously, the message handler used a static ctx.replyToMode value resolved once at startup, which prevented per-chat-type overrides from taking effect. Now calls resolveSlackReplyToMode(account, chatType) per-message in prepare.ts:202-203 and passes the resolved value through PreparedSlackMessage.replyToMode, which dispatch.ts consumes in place of the static ctx.replyToMode.

Key changes:

  • prepare.ts:202-203: resolve replyToMode per-message based on chat type
  • dispatch.ts:93,104,170,192: read prepared.replyToMode instead of ctx.replyToMode
  • types.ts:16: added replyToMode field to PreparedSlackMessage
  • prepare.ts:679: include resolved replyToMode in returned object

Incidental changes in this PR:

  • resolve-channels.ts:54: changed exclude_archived: false to true (now excludes archived channels from startup resolution)
  • Dockerfile: multi-stage build reduces image size by ~3GB
  • docker-image-digests.test.ts: updated test to handle multi-stage Dockerfile with AS clauses

Confidence Score: 5/5

  • Safe to merge with no risk
  • The fix is surgical and correct: moves reply-to-mode resolution from startup to per-message, enabling chat-type-specific config. The change is well-contained (3 core files), type-safe, backward compatible (falls back to top-level config), and verified in production. Incidental changes (Docker multi-stage, archived channel exclusion) are improvements with no breaking impact.
  • No files require special attention

Last reviewed commit: 469d49b

@openclaw-barnacle openclaw-barnacle bot added channel: slack Channel integration: slack docker Docker and sandbox tooling size: S labels Feb 23, 2026
@dbachelder dbachelder force-pushed the fix/slack-dm-reply-to-mode-per-chat-type branch from 469d49b to 87847be Compare February 23, 2026 18:50
@openclaw-barnacle openclaw-barnacle bot added size: XS and removed docker Docker and sandbox tooling size: S labels Feb 23, 2026
@dbachelder dbachelder force-pushed the fix/slack-dm-reply-to-mode-per-chat-type branch from 87847be to 823c36a Compare February 23, 2026 18:58
@openclaw-barnacle openclaw-barnacle bot added docker Docker and sandbox tooling size: S and removed size: XS labels Feb 23, 2026
@dbachelder dbachelder force-pushed the fix/slack-dm-reply-to-mode-per-chat-type branch from 823c36a to 27ca5cb Compare February 23, 2026 19:05
@openclaw-barnacle openclaw-barnacle bot added size: XS and removed docker Docker and sandbox tooling size: S labels Feb 23, 2026
@dbachelder dbachelder force-pushed the fix/slack-dm-reply-to-mode-per-chat-type branch from 27ca5cb to 99647ea Compare February 23, 2026 19:07
@dbachelder dbachelder force-pushed the fix/slack-dm-reply-to-mode-per-chat-type branch from 99647ea to 90762fb Compare February 23, 2026 19:17
@openclaw-barnacle
Copy link

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 1, 2026
dbachelder and others added 2 commits March 1, 2026 09:28
The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Takhoffman Takhoffman force-pushed the fix/slack-dm-reply-to-mode-per-chat-type branch from 90762fb to bc912a1 Compare March 1, 2026 16:20
@Takhoffman Takhoffman merged commit 9ae9439 into openclaw:main Mar 1, 2026
6 checks passed
@Takhoffman
Copy link
Contributor

Merged via salvage path.

Merge commit: 9ae9439
Head commit pinned: bc912a1

What changed before merge:

Verification run on the rebased branch:

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

All checks passed.

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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
sachinkundu pushed a commit to sachinkundu/openclaw that referenced this pull request Mar 6, 2026
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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
…#24717)

* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.


* Slack: add changelog for per-message replyToMode resolution

---------

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

channel: slack Channel integration: slack size: S stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants