Skip to content

OpenClaw plugin: ctx.channelId returns provider name instead of channel ID for Discord sessions #854

@bradfreels

Description

@bradfreels

Bug: ctx.channelId returns provider name instead of actual channel ID for Discord sessions

Environment

  • OpenClaw version: 2026.4.1
  • Hindsight plugin: @vectorize-io/hindsight-openclaw@0.4.19
  • Channel: Discord
  • Config: dynamicBankGranularity: ["agent", "channel"]

Expected Behavior

With dynamicBankGranularity: ["agent", "channel"], Discord channel memories should be isolated per-channel. For a session key like agent:main:discord:channel:1472750640760623226, the bank ID should resolve to something like main::channel:1472750640760623226 (or ideally the channel name like main::morpheus).

Actual Behavior

All Discord memories go to a single bank main::discord regardless of which channel the conversation is in.

Root Cause

In deriveBankId(), the field map uses:

channel: ctx?.channelId || sessionParsed.channel || 'unknown'

The ctx.channelId value is "discord" (the provider/channel type name) rather than the actual Discord channel ID (e.g. 1472750640760623226). Since ctx.channelId has priority over the session key parser fallback, the bank always resolves to main::discord.

Debug output confirms:

[Hindsight] before_prompt_build - bank: main::discord, channel: undefined/undefined

(Note: ctx.messageProvider is also undefined in some hook contexts)

The parseSessionKey() fallback would correctly extract channel:1472750640760623226 from the session key, but it never gets used because ctx.channelId is truthy (it's "discord").

Workaround Attempted

None found within plugin config. The issue appears to be upstream — OpenClaw's hook context populates ctx.channelId with the provider name rather than the Discord channel snowflake ID.

Suggested Fix

  1. In OpenClaw core: Populate ctx.channelId with the actual channel/conversation identifier (e.g. the Discord channel snowflake) rather than the provider name.
  2. In the plugin (defensive): If ctx.channelId matches a known provider name (discord, telegram, slack, etc.), treat it as missing and fall through to the sessionParsed.channel fallback.

Impact

  • All Discord channel memories merge into one bank, defeating per-channel isolation
  • Users who configure dynamicBankGranularity with "channel" get no benefit on Discord
  • Likely affects other multi-channel providers too (Telegram groups, Slack channels)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions