openclaw - 💡(How to fix) Fix Slack interactive button clicks should reliably reach the target session and thread [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#61502Fetched 2026-04-08 02:57:52
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

Fix Action

Fix / Workaround

No external credentials or third-party services are needed beyond the existing Slack integration, but there is a significant internal architecture risk: the current wake/runner path appears to rely on module-local mutable state that may split across runtime chunks after build. That means a narrow Slack-only patch can look correct locally yet still fail or regress in other wake paths.

  • A fix that only patches Slack ingress can still fail later if the wake scheduler and runner do not share the same state instance after bundling.

  • A fix that globalizes all wake state too aggressively may affect cron, email-batch, or other wake sources and create cross-session timing bugs.

  • Thread routing is easy to get subtly wrong; if threadTs is dropped even once, replies can end up in the channel root or the wrong session.

  • Retry logic can create storms (timer fired while already running) if scheduler state is not coherently owned.

  • #56142 — Slack block_actions not dispatched as inbound messages — buttons never wake session

  • #28047 — Slack interaction system events should auto-trigger a session turn

  • #21221 — Slack block_actions interactions should dispatch as inbound messages (like Telegram callback_query)

Code Example

Slack block_action
      |
      v
extensions/slack/.../interactions.block-actions.ts
      |
      | resolve sessionKey + deliveryContext (must include threadTs)
      v
src/infra/system-events.ts
      |
      | enqueueSystemEvent(..., wake)
      v
src/infra/heartbeat-wake.ts
      |
      | requestHeartbeatNow(reason="hook:slack-interaction")
      v
src/infra/heartbeat-runner.ts
      |
      | consume pending system events for hook wake
      | build prompt with interaction payload
      v
agent turn
      |
      v
outbound delivery
      |
      v
Slack thread reply (same channel + same threadTs)
RAW_BUFFERClick to expand / collapse

Original Request

这些修改会break其他东西吧,暂时不要改了,把刚才学到的东西记录下来,作为一个issue,首先feature reques是让slack可以接收到button。然后在feature reequest description写上我们尝试过的方法和对架构可能提出的影响。现在先去提issue吧。

English Translation: These changes may break other things, so don't keep changing code for now. Please record what we learned as an issue. First, the feature request is that Slack should be able to receive button clicks. Then, in the feature request description, write down the approaches we tried and the possible architectural implications. File the issue now.

Agent's Two Cents (could be wrong)

Everything below is the AI agent's best guess based on the current codebase. Take with a grain of salt — the original request above is the only thing that came from a human.

Suggested priority: p1

Problem / Motivation

Slack interactive buttons can render and be clicked, but the callback does not reliably turn into an assistant turn that replies in the originating Slack thread. In practice, this makes Slack buttons feel fake: the UI invites the user to click, but the agent often never sees or processes the action end-to-end.

Proposed Solution

Treat Slack button clicks as a first-class inbound event path with a durable, thread-aware handoff from Slack interaction ingestion to session wake, pending-system-event prompt generation, heartbeat execution, and outbound thread reply. The design should guarantee that a Slack block_action reaches the correct session/thread and produces exactly one agent turn (or a clear failure signal), rather than depending on loosely coupled module-local wake state.

Dependencies & Potential Blockers

No external credentials or third-party services are needed beyond the existing Slack integration, but there is a significant internal architecture risk: the current wake/runner path appears to rely on module-local mutable state that may split across runtime chunks after build. That means a narrow Slack-only patch can look correct locally yet still fail or regress in other wake paths.

How to Validate

  • Send a Slack message with interactive buttons in a thread.
  • Click a button once.
  • Verify the click produces exactly one wake for the correct session key, including the thread session key derived from threadTs.
  • Verify the agent receives the interaction payload in its prompt, not just a generic heartbeat prompt.
  • Verify the assistant replies back into the same Slack thread, not the channel root and not a different session.
  • Verify duplicate clicks, retry timing, and concurrent in-flight turns do not drop, fan out, or endlessly reschedule the wake.
  • Add automated coverage for the ingress path, wake scheduler, heartbeat runner, and outbound delivery path.

Scope Estimate

large

Key Files/Modules Likely Involved

  • extensions/slack/src/monitor/events/interactions.block-actions.ts
  • extensions/slack/src/monitor/context.ts
  • src/infra/system-events.ts
  • src/infra/heartbeat-wake.ts
  • src/infra/heartbeat-runner.ts

Architecture Diagram

Slack block_action
      |
      v
extensions/slack/.../interactions.block-actions.ts
      |
      | resolve sessionKey + deliveryContext (must include threadTs)
      v
src/infra/system-events.ts
      |
      | enqueueSystemEvent(..., wake)
      v
src/infra/heartbeat-wake.ts
      |
      | requestHeartbeatNow(reason="hook:slack-interaction")
      v
src/infra/heartbeat-runner.ts
      |
      | consume pending system events for hook wake
      | build prompt with interaction payload
      v
agent turn
      |
      v
outbound delivery
      |
      v
Slack thread reply (same channel + same threadTs)

Rough Implementation Sketch

  • Make Slack interaction handling explicitly thread-aware by carrying threadTs through session resolution and delivery context.
  • Define one canonical path for hook-originated system events so hook:slack-interaction gets the same prompt-generation guarantees as other actionable system events.
  • Revisit heartbeat-wake.ts state ownership so wake handler registration, queued wakes, timers, and running/scheduled flags cannot silently diverge across runtime chunks.
  • Add a dedicated integration test that simulates a Slack button click and asserts wake -> runner -> outbound thread reply.
  • Keep temporary debug logging out of the final design except for a minimal trace that is useful in production debugging.

Open Questions

  • Should Slack interactions continue to piggyback on the generic heartbeat wake path, or should they have a dedicated inbound-turn path closer to normal channel messages?
  • What is the right boundary for shared wake state: module-local, process-global, or encapsulated in a dedicated scheduler service?
  • How should retries behave when a session already has requests in flight, so that button clicks are not dropped or replayed excessively?
  • Should the system guarantee exactly-once handling for a Slack interaction action ID, and if so where should dedupe live?

Potential Risks or Gotchas

  • A fix that only patches Slack ingress can still fail later if the wake scheduler and runner do not share the same state instance after bundling.
  • A fix that globalizes all wake state too aggressively may affect cron, email-batch, or other wake sources and create cross-session timing bugs.
  • Thread routing is easy to get subtly wrong; if threadTs is dropped even once, replies can end up in the channel root or the wrong session.
  • Retry logic can create storms (timer fired while already running) if scheduler state is not coherently owned.

Related Issues

  • #56142 — Slack block_actions not dispatched as inbound messages — buttons never wake session
  • #28047 — Slack interaction system events should auto-trigger a session turn
  • #21221 — Slack block_actions interactions should dispatch as inbound messages (like Telegram callback_query)

What We Tried So Far

  • Added wake-on-enqueue for Slack block actions.
  • Fixed Slack system-event session resolution to include threadTs and generate thread session keys.
  • Taught the heartbeat runner to treat hook:slack-interaction as a real hook event rather than generic heartbeat noise.
  • Carried deliveryContext so interaction wakes can reply to the original Slack thread.
  • Added temporary debug logs around interaction enqueue, wake scheduling, wake dispatch, and runner delivery.
  • Live debugging showed two important architecture findings:
    • first failure mode: timer fired without active handler
    • second failure mode after partial state-sharing: timer fired while already running
  • That strongly suggests the current heartbeat-wake.ts mutable state is not owned robustly enough for built/runtime-split execution.

extent analysis

TL;DR

To fix the issue with Slack interactive buttons not reliably triggering an assistant turn, treat Slack button clicks as a first-class inbound event path with a durable, thread-aware handoff from Slack interaction ingestion to session wake.

Guidance

  • Review the current wake/runner path and identify potential issues with module-local mutable state that may cause failures or regressions.
  • Implement a dedicated inbound-turn path for Slack interactions, ensuring that threadTs is carried through session resolution and delivery context.
  • Define a canonical path for hook-originated system events to guarantee prompt-generation for hook:slack-interaction events.
  • Add automated coverage for the ingress path, wake scheduler, heartbeat runner, and outbound delivery path to validate the fix.

Example

No code snippet is provided as the issue does not contain specific code that needs to be modified.

Notes

The provided information suggests that the issue is related to the architecture of the Slack integration and the handling of interactive buttons. The proposed solution involves treating Slack button clicks as a first-class inbound event path, which may require significant changes to the existing codebase.

Recommendation

Apply the proposed workaround by treating Slack button clicks as a first-class inbound event path, as this approach addresses the root cause of the issue and provides a durable, thread-aware handoff from Slack interaction ingestion to session wake.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING