Skip to content

[Enhancement]: Slack provider lacks per-inbound INFO log for app_mention events — asymmetry with Telegram blocks silent-failure forensics #94691

Description

@BryceMurray

Environment

  • OpenClaw: 2026.6.8 (gateway + CLI)
  • Channel provider: bundled Slack provider (@openclaw/slack external as of 2026.5.x)
  • Channel surface: socket-mode bot in a workspace, registered to a single channel
  • Host: single-VPS Linux deployment, no container

TL;DR

The OpenClaw Slack provider does not emit an INFO-level log line on receipt of an app_mention event. The Telegram provider does:

[telegram] Inbound message telegram:group:<chat>:topic:<id> -> @<bot> (group, 42 chars)

The Slack equivalent log line does not exist. The only journal evidence that a Slack app_mention arrived is downstream side-effects:

  • [plugins] [<plugin>] usage surface=tool_mention sender=llm ... — fires only when a plugin tool actually executes.
  • [agent/cli-backend] cli exec ... trigger=user reuse=invalidated:auth-profile — fires when the LLM router is invoked. Closest proxy, but indirect.

When the LLM router consumes a mention but produces no tool call (e.g., a systemPrompt routing gap silently drops the request), there is zero journal evidence that the inbound ever arrived. The bot's response to the user is missing, but journalctl ... | grep '\[slack\]' returns empty between socket-connect time and now.

The reaction lifecycle in Slack (👀 → 🧠 → ⏳ via the channel-feedback controller in dist/channel-feedback-2_QV4FKD.js) is the only diagnostic signal — and it's only visible in the Slack UI itself, not in the server journal.

Why this matters (concrete failure I just triaged)

A user typed @<bot> refresh in a target channel. The reactions cycled 👀 → 🧠 → ⏳ but no text response landed. My initial triage:

  1. grep '\[slack\]' journal --since "1 hour ago" → zero matches.
  2. I concluded "Slack socket-mode silently disconnected" because the bundled provider also doesn't log heartbeat / disconnect events at INFO level.
  3. The user pushed back: "if it never reached the gateway, where did the eye-reaction come from?"
  4. I re-read the source (dist/channel-feedback-2_QV4FKD.js DEFAULT_EMOJIS), recognized that 👀/🧠/⏳ is the gateway's status-reaction lifecycle, then traced the cli-session metadata at the right timestamp and found cli exec promptChars=13495 trigger=user reuse=invalidated:auth-profile — which IS the Slack inbound, just unlabelled.
  5. Root cause turned out to be a systemPrompt routing gap (orthogonal to the observability problem). But the observability gap delayed root cause by ~15 minutes and two wrong-turn hypotheses.

A single [slack] app_mention received log line at INFO would have made step 1 the conclusive answer.

Proposed change

Add an INFO-level log emit in the Slack provider on inbound app_mention (and ideally message events that pass the channel filter), mirroring the Telegram pattern:

[slack] Inbound app_mention slack:<workspace>:channel:<channel-id> -> @<bot> (channel, 42 chars)

Optional finer-grained variants:

[slack] Inbound app_mention channel=<channel-id> user=<user-id> body_chars=<N> bot=@<bot> ts=<message-ts> thread_ts=<thread-ts-or-none>

The Telegram provider's log emits at info from the [telegram] log category (matches op[<pid>]: ... [telegram] Inbound message ...). Mirroring that level + category for [slack] keeps existing journal-grep workflows uniform across channels.

Why INFO (not DEBUG)

  • Telegram inbound is INFO. Channel-level parity matters for cross-channel triage — operators learn one pattern, not two.
  • INFO is the lowest level that survives the default systemd journal capture in a single-VPS deployment. DEBUG-level entries are routinely filtered out at the host level.
  • Volume is small: one log line per app_mention. A busy bot processing 200 mentions/hour adds ~200 INFO lines/hour — negligible.

Suggested log message format

To match the Telegram format already in use, propose:

log.info(
  "[slack] Inbound app_mention slack:%s:channel:%s -> @%s (channel, %d chars)",
  workspaceId,
  channelId,
  botUsername,
  bodyChars,
);

If the provider already constructs a from/to semantic pair (as the Telegram provider does — search for Inbound message ${params.from} -> ${params.to} in dist/bot-<hash>.js:7302), the obvious symmetric API is:

log.info(
  "[slack] Inbound app_mention %s -> @%s (channel, %d chars)",
  `slack:${workspaceId}:channel:${channelId}`,
  botUsername,
  bodyChars,
);

Adjacent observability gap (could fix here or separately)

The same Slack provider also does not log:

  • Socket-mode connect / disconnect / reconnect events at INFO. There IS an emit on initial connect ([slack] socket mode connected) but no corresponding disconnect/reconnect emit. A silent socket-mode WebSocket disconnect — which I have seen mentioned in other forum posts — would be undetectable without enabling DEBUG.
  • slack-sdk disconnected event passthrough. Wiring this into a re-connect attempt + log emit would make the bundled provider self-healing and visible.

If maintainers prefer, these are scope-separable into their own issues; I can file a follow-up.

Acceptance criteria suggestions

  1. Every Slack app_mention event received by the provider produces a single INFO-level log line with channel, sender, body length, and bot identity.
  2. The log category is [slack] to align with the Telegram convention.
  3. The line is emitted before the event is dispatched to inbound_claim / LLM router, so it survives downstream silent failures.
  4. (Optional) Same for message events that pass the channel filter, behind a config knob if volume becomes a concern.

Sanitization notes

This draft replaces deployment-specific values with placeholders:

  • <channel-id> for the target channel
  • <workspace> for the Slack workspace id
  • <chat> / <id> / <user> for Telegram analogues
  • @<bot> for the bot username
  • <plugin> for the relevant plugin id
  • Specific tool names, business names, and PII redacted entirely

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low-priority cleanup, docs, polish, ergonomics, or speculative work.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.no-staleExclude from stale automation

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions