Skip to content

Feature: Slack gateway should expose conversations.history as an agent tool #6345

@mecampbellsoup

Description

@mecampbellsoup

Problem

When Hermes is running as a Slack bot, the agent refuses to read channel or thread history beyond the current message it's responding to. Users ask the bot to reference prior conversations, find old messages, or search for context in the channel — and the bot reports that it can't, even though the underlying capability exists.

This has two parts:

  1. The Slack platform note in gateway/session.py:283-290 hardcodes a refusal into the system prompt:

    **Platform notes:** You are running inside Slack. You do NOT have access
    to Slack-specific APIs — you cannot search channel history, pin/unpin
    messages, manage channels, or list users. Do not promise to perform
    these actions. If the user asks, explain that you can only read messages
    sent directly to you and respond.
    

    This tells the model to refuse regardless of what tools are actually available at runtime. See feat: make platform notes configurable instead of hardcoded limitations #2020 (filed by another user who proved the agent CAN do Discord channel management via terminal + curl + bot token) and [Bug]: Slack gateway platform note becomes incorrect when Slack MCP tools are available #6533 (filed by a user with working Slack MCP tools who hits the contradictory-signal bug — tools present, hardcoded note still says "no access").

  2. No first-class tool wraps conversations.history/conversations.replies. The Slack gateway holds a WebClient with scopes channels:history, groups:history, im:history already — but nothing exposes it to the agent. Users without MCP tools configured have no convenient path to Slack history beyond shelling out via terminal + curl (once the hardcoded note is removed).

What OpenClaw did

OpenClaw's Slack extension dispatched via handleSlackAction(action: "readMessages", ...) which called client.conversations.history(...) or client.conversations.replies(...) depending on whether a threadId was supplied. Bot token was sufficient — no user token needed. It also had thread.historyScope config to pre-load thread context when starting new sessions, which OpenClaw injected into the prompt as ThreadHistoryBody.

The Hermes Slack adapter at gateway/platforms/slack.py already has the same AsyncWebClient available — it just doesn't register any read-history tool.

Expected behavior

The agent should be able to:

  1. Read channel history — paginate recent messages in the channel where it was invoked (conversations.history)
  2. Read thread history — fetch the full thread when joining a thread mid-conversation (conversations.replies)
  3. Optionally pre-load thread context — when a new session starts in a thread, automatically fetch prior messages (like OpenClaw's threadHistoryScope)

All via the existing bot token and existing scopes. No user token, no additional OAuth.

Relationship to #2020, #6533, and #13309

These issues are layered:

Issue Layer Fix
#2020 Hardcoded platform note lies about capabilities in general (Slack and Discord) Make platform notes configurable; stop asserting "no API access" when the agent has terminal + bot token
#13309 Adapter-level platform context notes Let adapters provide platform-specific context notes for the system prompt
#6533 Platform note doesn't account for runtime-available MCP tools Make the note capability-aware — different text when scoped Slack tools are registered
#6345 (this issue) No native first-class Slack read tools even for users without MCP Wrap conversations.history/conversations.replies as registered agent tools

#2020 or #6533 is the quickest unblock for users whose bot already has API access. #6345 is the "correct" shape — a dedicated tool with proper argument handling, pagination, and formatting, rather than expecting every user to configure MCP or shell out via curl.

Suggested approach

Add a Slack tool (or small toolset) registered when the Slack gateway is active:

  • slack_read_history(channel_id=None, limit=50, before=None, after=None, thread_ts=None) — dispatches to conversations.replies if thread_ts is set, otherwise conversations.history. Defaults channel_id to the current inbound channel. Returns formatted messages with author, ts, and content. Cursor pagination under the hood.
  • Optionally, a thread.historyScope session-seed feature matching OpenClaw's behavior (pre-load thread context on new sessions).

Reuse the existing AsyncWebClient held by the Slack adapter — no new auth, no new scopes.

Affected files

  • gateway/platforms/slack.py — adapter has the WebClient; needs to expose a read function
  • gateway/session.py:283-290 — hardcoded platform note; needs to become capability-aware (or get removed/softened) to unblock the agent from refusing
  • New tool module, e.g. tools/slack_tool.py — registers the slack_read_history tool when Slack is the active platform
  • platform_toolsets.slack in config — register the new toolset

Why this matters

"Search my Slack history" is the single most natural thing users ask a Slack bot to do. Today the bot actively refuses even though the underlying capability is one API call away.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havecomp/gatewayGateway runner, session dispatch, deliveryplatform/slackSlack app adaptertype/featureNew feature or request

    Type

    No type
    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