Skip to content

fix(slack): include bot root message in new thread sessions (#79338)#80409

Merged
bek91 merged 5 commits into
openclaw:mainfrom
sxxtony:fix/slack-thread-include-root-79338
May 11, 2026
Merged

fix(slack): include bot root message in new thread sessions (#79338)#80409
bek91 merged 5 commits into
openclaw:mainfrom
sxxtony:fix/slack-thread-include-root-79338

Conversation

@sxxtony

@sxxtony sxxtony commented May 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: When a user replies in-thread to a bot's own message in a Slack DM, the new thread session was constructed without the parent/root message content. The agent received reply_to_id metadata but had no way to resolve it to the actual text — leading to confident-but-wrong follow-up actions (incident Images not passed to Claude CLI - only path reference in text #4 in Slack thread sessions do not include parent/root message content #79338: a correction email sent to the wrong person about the wrong meeting).
  • Why it matters: This is high-impact: silent failure mode, and the agent's tool access amplifies the damage.
  • What changed: resolveSlackThreadContextData no longer strips current-bot messages from new thread session history. The bot's own root/parent message is now retained and rendered with role=assistant under a Bot (this assistant) sender label, so the agent has the parent text it is replying to. Adds opt-out channels.slack.thread.includeRootMessage (default true).
  • What did NOT change (scope boundary): Existing-session thread reads still strip current-bot history (the assistant's own messages are already in the live transcript). Third-party bot behavior, allowlist rules for human users, and inheritParent semantics are untouched. ThreadStarterBody remains user-authored; the bot's root flows via ThreadHistoryBody so downstream "thread starter" UX is not retroactively populated by bot output.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

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

Linked Issue/PR

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Slack DM thread reply to a bot message constructs a new thread session that omits the parent message; the agent loses context of what it is replying to.

  • Real environment tested: OpenClaw 2026.5.10-beta.1 built from this branch on Ubuntu 24.04 (Linux 6.8.0-111-generic, x64), Node v22.22.0. Live gateway boot via node dist/entry.js gateway against a config that sets channels.slack.thread.includeRootMessage. Direct invocation of the built resolveSlackThreadContextData function with a synthetic Slack conversations.replies payload to capture the runtime ThreadHistoryBody string the agent receives.

  • Exact steps or command run after this patch:

    pnpm build
    # Live gateway boot with the new config field
    OPENCLAW_STATE_DIR=/tmp/openclaw-79338-e2e/.openclaw \
      OPENCLAW_CONFIG_PATH=/tmp/openclaw-79338-e2e/.openclaw/openclaw.json \
      node dist/entry.js gateway
    
    # Direct runtime exercise of the production code path
    node --import tsx /tmp/proof-79338.mjs            # default: includeRootMessage=true (fix)
    node --import tsx /tmp/proof-79338-optout.mjs     # explicit includeRootMessage=false

    Test config used:

    {
      "channels": {
        "slack": {
          "enabled": true,
          "botToken": "xoxb-fake-test-only",
          "appToken": "xapp-1-fake-test-only",
          "thread": {
            "historyScope": "thread",
            "initialHistoryLimit": 20,
            "includeRootMessage": true
          }
        }
      }
    }
  • Evidence after fix (live runtime output, redacted):

    (1) Live gateway boot — config schema accepts the new field, gateway reaches ready:

    2026-05-10T21:39:21.226+00:00 [gateway] loading configuration…
    2026-05-10T21:39:21.382+00:00 [gateway] auth mode=none explicitly configured; all gateway connections are unauthenticated.
    2026-05-10T21:39:21.384+00:00 [gateway] starting...
    2026-05-10T21:39:24.452+00:00 [gateway] auto-enabled plugins for this runtime without writing config:
    2026-05-10T21:39:29.853+00:00 [gateway] starting HTTP server...
    2026-05-10T21:39:31.050+00:00 [gateway] http server listening (9 plugins: acpx, browser, canvas, device-pair, file-transfer, memory-core, phone-control, slack, talk-voice; 9.7s)
    2026-05-10T21:39:31.420+00:00 [slack] [default] starting provider
    2026-05-10T21:39:33.431+00:00 [gateway] ready
    

    Compare to the same boot before the schema-wiring fixup commit, which rejected the field:

    Gateway failed to start: Invalid config at /tmp/openclaw-79338-e2e/.openclaw/openclaw.json.
    channels.slack.thread: invalid config: must NOT have additional properties
    Run "openclaw doctor --fix" to repair, then retry.
    

    (2) Direct runtime call into the built resolveSlackThreadContextData (default includeRootMessage=true, the fix):

    === resolveSlackThreadContextData live runtime output ===
    threadStarterBody: undefined
    threadLabel: "Slack thread DM (assistant root): Confirmed Saturday 12:30pm meeting with Alice"
    threadHistoryBody:
    [Slack Bot (this assistant) (assistant) Thu 1970-01-01 00:01 UTC] Confirmed Saturday 12:30pm meeting with Alice
    [slack message id: 100.000 channel: D123]
    

    (3) Same runtime call against main (before the fix):

    === resolveSlackThreadContextData live runtime output ===
    threadStarterBody: undefined
    threadLabel: "Slack thread DM"
    threadHistoryBody:
    undefined
    

    → On main, ThreadHistoryBody is undefined. The agent receives only the user's reply text plus reply_to_id metadata, exactly matching the failure mode in Slack thread sessions do not include parent/root message content #79338. With the fix on this branch, the bot's parent message is rendered with (assistant) role and shows up at the top of ThreadHistoryBody.

    (4) Opt-out path runtime call (includeRootMessage: false):

    === includeRootMessage: false (opt-out) ===
    threadStarterBody: undefined
    threadLabel: "Slack thread DM"
    threadHistoryBody: undefined
    

    → Operators who explicitly do not want the bot's own root message in new thread sessions get the prior behavior back.

  • Observed result after fix:

    • With default config: ThreadHistoryBody includes the bot's parent message labeled Bot (this assistant) (assistant). ThreadLabel becomes Slack thread <room> (assistant root): <snippet>.
    • With includeRootMessage: false: prior behavior preserved (parent omitted).
    • Live gateway boot accepts the new field instead of rejecting with must NOT have additional properties.
  • What was not tested: A multi-tenant production Slack workspace with real conversations.replies traffic (the test environment does not have a Slack app with valid xapp-1-… socket-mode credentials; the boot log above shows invalid_auth reaching Slack as expected for fake tokens, which is the only boundary not exercised). All in-process code paths (config validation, schema acceptance, thread context resolution, history filter policy, role labeling) are exercised live above.

  • Before evidence: see (3) above and the original schema-rejection log for the gateway boot.

Root Cause (if applicable)

  • Root cause: resolveSlackThreadContextData (extensions/slack/src/monitor/message-handler/prepare-thread-context.ts) filtered current-bot messages out of threadHistory (threadHistoryWithoutCurrentBot = threadHistory.filter(!isCurrentBotAuthor)) and also gated threadStarterBody/threadLabel on !starterIsCurrentBot. That prevented duplication during normal turns, where the bot's prior outputs already live in the assistant's transcript — but for thread-reply turns the new thread session has no prior transcript at all, so the bot's parent message vanished.
  • Missing detection / guardrail: No test asserted the contents of ThreadHistoryBody for a bot-rooted thread; the existing tests actively verified the (incorrect) "omits bot starter" behavior.
  • Contributing context: PR fix(agents): repair stale bootstrap completion #71230 fixed a related but distinct bootstrap pending issue. PR fix(slack): preserve mention source metadata #75356 added thread-reply mention metadata. Neither covered the root-message inclusion gap.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
  • Target test or file:
    • extensions/slack/src/monitor/message-handler/prepare-thread-context.test.ts (new test issue #79338: …)
    • extensions/slack/src/monitor/message-handler/prepare-thread-context-root.test.ts (26 new helper tests)
    • extensions/slack/src/monitor/message-handler/prepare.test.ts (existing integration test updated to assert bot reply now appears in ThreadHistoryBody)
  • Scenario the test should lock in: A new thread session whose root message is authored by the current bot must include that root in ThreadHistoryBody with role=assistant and a recognizable sender label, regardless of contextVisibilityMode.
  • Why this is the smallest reliable guardrail: prepare-thread-context.ts is the single function that constructs every thread session's pre-prompt context for Slack. Asserting its outputs at this seam is cheaper and more deterministic than a full inbound→agent E2E and exercises the exact branch that broke.

User-visible / Behavior Changes

  • New (default-on) config: channels.slack.thread.includeRootMessage (boolean, default true). Operators who explicitly do not want the bot's own root message replayed into a new thread session can set it to false and recover the prior behavior.
  • New thread sessions whose root is the current bot now show that root in ThreadHistoryBody labeled Bot (this assistant) (assistant) instead of being silently dropped.
  • ThreadLabel for bot-rooted thread sessions gains an (assistant root): <snippet> suffix so per-session telemetry/logs show which bot message anchored the thread.

Diagram (if applicable)

Before (#79338):
  user replies in-thread to bot ─▶ resolveSlackThreadContextData
                                    ├─ threadHistory.filter(!isCurrentBot)   ← drops bot root
                                    └─ threadStarterBody = undefined          (bot starter blocked)
  agent prompt: only user's reply + reply_to_id metadata
  agent output: confident wrong action

After:
  user replies in-thread to bot ─▶ resolveSlackThreadContextData
                                    ├─ historyFilterPolicy.retainCurrentBotMessages = true
                                    └─ threadLabel = "Slack thread … (assistant root): …"
  agent prompt: ThreadHistoryBody includes the bot's parent text as assistant role
  agent output: corrects the parent it actually said

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No — the same conversations.replies call is used; only the post-fetch filter changed.
  • Command/tool execution surface changed? No
  • Data access scope changed? Bounded yes. The bot's own prior output is now retained in new thread sessions where it was previously stripped. This is the bot's own content (not third-party data), but it is now visible to whichever model serves the new session. Operators concerned about the bot's prior text being re-sent to a different model (e.g. main session uses provider A, thread uses provider B) can opt out via channels.slack.thread.includeRootMessage: false.
  • The visibility-allowlist filter for third-party humans is unchanged; only current-bot authorship bypasses it (the bot's output is not third-party content).

Repro + Verification

Environment

  • OS: Linux 6.8.0-111-generic (x64)
  • Runtime: Node v22.22.0, pnpm 10.33.2
  • Model/provider: agnostic (any model that consumes ThreadHistoryBody)
  • Integration/channel: Slack (DM, default thread config)

Steps

  1. Bot posts a top-level message in a Slack DM (e.g. a confirmation or summary).
  2. User replies in-thread to that bot message with a follow-up that depends on the parent (e.g. "actually it's Sunday — apologize and correct").
  3. OpenClaw routes the reply into agent:<id>:slack:direct:<userId>:thread:<threadTs>, a fresh session.

Expected

The new thread session's ThreadHistoryBody contains the bot's parent text labeled Bot (this assistant) (assistant). The agent answers the corrective reply with full context.

Actual (this branch)

Matches expected. Live runtime captures above show ThreadHistoryBody contains the bot parent on this branch and is undefined on main.

Evidence

  • Failing test/log before + passing after — see "Real behavior proof" section above (live runtime output before/after).
  • Trace/log snippets — gateway boot log + redacted runtime output above.
  • Screenshot/recording
  • Perf numbers (if relevant) — N/A; same number of Slack API calls.

Human Verification (required)

  • Verified scenarios:
    • Live gateway boot accepts the new includeRootMessage field (was rejected before the schema-wiring commit).
    • Direct runtime call into built resolveSlackThreadContextData shows bot's parent in ThreadHistoryBody on this branch.
    • Same call on main shows ThreadHistoryBody: undefined — reproduces Slack thread sessions do not include parent/root message content #79338.
    • Opt-out (includeRootMessage: false) at runtime restores prior behavior.
    • Bot-rooted DM thread with user reply → parent now in history (new test).
    • Third-party bot starter → unchanged (existing test still green).
    • Allowlist mode with current-bot history → bot retained, non-allowlisted humans still filtered (existing test updated to lock in the new behavior).
    • User-authored starter → unchanged (existing test still green).
    • Existing thread session (already-known timestamp) → bot history still filtered (regression-tested via resolveSlackThreadHistoryFilterPolicy unit test).
  • Edge cases checked: Empty starter text (label falls back to base), all-whitespace starter (label trims to base), 120-char starter (label truncated to 80), bot identified by userId rather than botId, mixed third-party-bot + current-bot history.
  • What I did NOT verify: A multi-tenant production Slack workspace with real xapp-1-… socket-mode auth (the test environment does not have a real Slack app available). The Slack WebClient.conversations.replies boundary is exercised through a synthetic payload identical in shape to Slack's documented response. All other code paths are exercised in-process.

Compatibility / Migration

  • Backward compatible? Yes — new field defaults to the corrected (issue-fixing) behavior; operators on prior versions see no schema rejection because the field is optional.
  • Config/env changes? Yes — adds channels.slack.thread.includeRootMessage (optional, default true). Existing configs without the field get the fix automatically.
  • Migration needed? No.

Risks and Mitigations

  • Risk: Workspaces relying on the bot's own messages being absent from new thread sessions (e.g. to keep token cost down for long threads) will see slightly larger initial context.
    • Mitigation: Set channels.slack.thread.includeRootMessage: false to restore prior behavior; documented in docs/channels/slack.md.
  • Risk: A model running in the new thread session might re-act on its own prior message (e.g. interpret "Confirmed meeting" as a fresh user instruction).
    • Mitigation: History entries are formatted with explicit (assistant) role labels and untrusted-envelope wrapping (formatInboundEnvelope), matching how the rest of the thread history is rendered.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

…#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes openclaw#79338.
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: slack Channel integration: slack size: L triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels May 10, 2026
@clawsweeper

clawsweeper Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

Summary
Review failed before ClawSweeper could summarize the requested change.

Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path.

Real behavior proof
Not applicable: Real behavior proof was not assessed because the Codex review failed.

Next step before merge
Review did not complete, so no work-lane recommendation was made.

Review details

Best possible solution:

Retry the Codex review after fixing the execution failure.

Do we have a high-confidence way to reproduce the issue?

Unclear. The review failed before ClawSweeper could establish a reproduction path.

Is this the best way to solve the issue?

Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction.

What I checked:

  • failure reason: codex execution failed.
  • codex failure detail: Codex review failed for this PR with exit 1.

Likely related people:

  • unknown: Codex failed before it could trace repository history. (role: review did not complete; confidence: low)

Remaining risk / open question:

  • No close action taken because the review did not complete.

Codex review notes: model gpt-5.5, reasoning high; reviewed against cac585a29f7e.

…law#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels May 10, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 10, 2026
@bek91 bek91 self-assigned this May 11, 2026
@sxxtony

sxxtony commented May 11, 2026

Copy link
Copy Markdown
Contributor Author

@bek91 Thanks for review.
Could you tell me the direction to fix this pr?
This is my first contribution, I would like to have merged PR rather than a closed one.
Please help.

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring openclaw#79338 has parent/root context.
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 11, 2026
@bek91

bek91 commented May 11, 2026

Copy link
Copy Markdown
Contributor

@sxxtony Thanks for the contribution! I pushed a maintainer follow-up.

The original fix was pointing in the right direction: replies to a bot-authored Slack root message need the parent/root text in context, otherwise the agent only sees reply_to_id metadata and misses what the user is correcting or responding to.

changes i made:

  • Removed the new channels.slack.thread.includeRootMessage config option.
  • Kept the behavior focused on the bug: only include the current bot’s root/parent Slack message on the first
    turn of a new thread session.
  • Continued filtering other current-bot Slack history, so we don’t replay arbitrary prior assistant messages
    into prompts.
  • Added handling for the case where Slack history fetching/trimming does not return the root message: we
    synthesize/prepend the root from the fetched thread starter.
  • Added/updated tests for bot-authored roots, user-authored roots, current-bot non-root replies, existing
    sessions, and trimmed history.

The main reason for removing the config option is that new public config surface has a higher bar: it affects docs, schema, generated metadata, UX, long-term support, and usually needs more maintainer discussion. Since this PR can fix the reported bug without adding a new setting, the smaller behavior-only change is easier to review and safer to merge.

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 11, 2026
…ude-root-79338

# Conflicts:
#	CHANGELOG.md
#	docs/.generated/config-baseline.sha256
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 11, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 11, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 11, 2026
@bek91
bek91 merged commit b2dab30 into openclaw:main May 11, 2026
107 checks passed
steipete added a commit that referenced this pull request May 12, 2026
…80409)

* fix(slack): include bot root message in new thread sessions (#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes #79338.

* fix(slack): wire includeRootMessage into runtime config schema (#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring #79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
# Conflicts:
#	docs/.generated/config-baseline.sha256
steipete added a commit that referenced this pull request May 13, 2026
…80409)

* fix(slack): include bot root message in new thread sessions (#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes #79338.

* fix(slack): wire includeRootMessage into runtime config schema (#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring #79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
# Conflicts:
#	docs/.generated/config-baseline.sha256
steipete added a commit that referenced this pull request May 13, 2026
…80409)

* fix(slack): include bot root message in new thread sessions (#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes #79338.

* fix(slack): wire includeRootMessage into runtime config schema (#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring #79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
# Conflicts:
#	docs/.generated/config-baseline.sha256
steipete added a commit that referenced this pull request May 13, 2026
…80409)

* fix(slack): include bot root message in new thread sessions (#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes #79338.

* fix(slack): wire includeRootMessage into runtime config schema (#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring #79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
# Conflicts:
#	docs/.generated/config-baseline.sha256
steipete added a commit that referenced this pull request May 13, 2026
…80409)

* fix(slack): include bot root message in new thread sessions (#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes #79338.

* fix(slack): wire includeRootMessage into runtime config schema (#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring #79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
# Conflicts:
#	docs/.generated/config-baseline.sha256
steipete added a commit that referenced this pull request May 13, 2026
…80409)

* fix(slack): include bot root message in new thread sessions (#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes #79338.

* fix(slack): wire includeRootMessage into runtime config schema (#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring #79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…#79338) (openclaw#80409)

* fix(slack): include bot root message in new thread sessions (openclaw#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes openclaw#79338.

* fix(slack): wire includeRootMessage into runtime config schema (openclaw#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring openclaw#79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…#79338) (openclaw#80409)

* fix(slack): include bot root message in new thread sessions (openclaw#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes openclaw#79338.

* fix(slack): wire includeRootMessage into runtime config schema (openclaw#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring openclaw#79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…#79338) (openclaw#80409)

* fix(slack): include bot root message in new thread sessions (openclaw#79338)

When a user replies in-thread to a bot's own message in a Slack DM,
the new thread session was constructed without the parent/root message
content. The agent only saw `reply_to_id` metadata and could not
resolve what was being replied to, leading to confident-but-wrong
actions on follow-up corrections.

The thread-context resolver was filtering out every message authored
by the current bot before formatting thread history, including the
bot's own root message. For thread-replies starting a fresh session,
that left the agent without the parent context it needed.

This change retains current-bot messages in the thread history when
starting a new thread session, formats them with role=assistant under
a "Bot (this assistant)" sender label, and adds
`channels.slack.thread.includeRootMessage` (default `true`) to opt out.
Bot messages still bypass allowlist visibility filtering since the
bot's own output is not third-party content.

Fixes openclaw#79338.

* fix(slack): wire includeRootMessage into runtime config schema (openclaw#79338)

The first commit added `channels.slack.thread.includeRootMessage` to
the TypeScript type and zod schema, but the runtime AJV-style schema
generated from `extensions/slack/src/config-ui-hints.ts` rejected the
new field with `must NOT have additional properties` at gateway boot.

Adds the matching UI hint entry for `thread.includeRootMessage` and
regenerates the bundled channel config metadata so the live gateway
accepts the new field.

* Narrow Slack thread root context handling

Remove the public includeRootMessage config and keep the Slack thread fix focused on including only the current bot's root message on the first turn of a new thread session.

Preserve filtering of arbitrary current-bot Slack history while ensuring openclaw#79338 has parent/root context.

* Fix Slack thread root CI checks

---------

Co-authored-by: Bek <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack docs Improvements or additions to documentation proof: supplied External PR includes structured after-fix real behavior proof. size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack thread sessions do not include parent/root message content

2 participants