openclaw - 💡(How to fix) Fix feat(hooks): expose senderId and sender metadata in agent turn hook contexts (before_prompt_build, agent_turn_prepare, etc.)

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…

We are building a turn-context plugin that injects entity identity and semantic memories via before_prompt_build. Without senderId on the hook context, we resort to a fragile message_received → cache → before_prompt_build reads cache pattern. The data is already on params — it just needs to be forwarded to the hook context.

Root Cause

We are building a turn-context plugin that injects entity identity and semantic memories via before_prompt_build. Without senderId on the hook context, we resort to a fragile message_received → cache → before_prompt_build reads cache pattern. The data is already on params — it just needs to be forwarded to the hook context.

Fix Action

Fix / Workaround

This is a significant gap. These hooks receive event.prompt (the user message) and event.messages (the full session history), but there is no attribution of who sent the message. A plugin building context-aware prompt injection (entity resolution, per-user preferences, semantic recall scoped to a sender) cannot identify the sender without a workaround.

senderId and related fields do exist on the internal dispatch params object (verified in compiled source at dist/selection-BeP8qtCb.js lines 6859-6862):

Workaround and Its Limitations

Code Example

senderId: params.senderId,
senderName: params.senderName,
senderUsername: params.senderUsername,
senderE164: params.senderE164,

---

const hookCtx = {
  runId: params.runId,
  trace: freezeDiagnosticTraceContext(diagnosticTrace),
  agentId: hookAgentId,
  sessionKey: params.sessionKey,
  sessionId: params.sessionId,
  workspaceDir: params.workspaceDir,
  modelProviderId: params.model.provider,
  modelId: params.model.id,
  trigger: params.trigger,
  ...buildAgentHookContextChannelFields(params),
  // NEW: sender attribution
  senderId: params.senderId,
  senderName: params.senderName,
  senderUsername: params.senderUsername,
  senderE164: params.senderE164,
};
RAW_BUFFERClick to expand / collapse

Problem

Agent turn hooks (before_prompt_build, agent_turn_prepare, before_agent_start, before_agent_finalize, agent_end) receive a ctx (hook context) that includes agentId, sessionKey, messageProvider, channelId, and runId — but not senderId, senderName, senderUsername, or senderE164.

This is a significant gap. These hooks receive event.prompt (the user message) and event.messages (the full session history), but there is no attribution of who sent the message. A plugin building context-aware prompt injection (entity resolution, per-user preferences, semantic recall scoped to a sender) cannot identify the sender without a workaround.

Current State

senderId and related fields do exist on the internal dispatch params object (verified in compiled source at dist/selection-BeP8qtCb.js lines 6859-6862):

senderId: params.senderId,
senderName: params.senderName,
senderUsername: params.senderUsername,
senderE164: params.senderE164,

But they are not spread into hookCtx when it is constructed (lines 7924-7935). Only messageProvider and channelId are added via buildAgentHookContextChannelFields(params).

Meanwhile, message-level hook contexts (message_received, message_sending, message_sent) do expose ctx.senderId — as documented under "Message hook contexts" in the plugin hooks docs.

Workaround and Its Limitations

For DM sessions, the sender can sometimes be extracted from ctx.sessionKey since DM session keys encode the sender:

  • discord:user:330189773371080716
  • signal:+15551234567

But for group/channel sessions, the session key identifies the channel, not the sender:

  • discord:channel:1492386247862390824

Multiple users share the same group session, so the session key provides no sender attribution.

The only current workaround for group chats is a two-hook pattern: cache sender info from message_received (fire-and-forget observation hook), then read that cache in before_prompt_build. This works but is fragile — it depends on the cache write being synchronous and completing before the agent turn hooks fire.

Proposed Change

Add sender fields to agent turn hook contexts:

const hookCtx = {
  runId: params.runId,
  trace: freezeDiagnosticTraceContext(diagnosticTrace),
  agentId: hookAgentId,
  sessionKey: params.sessionKey,
  sessionId: params.sessionId,
  workspaceDir: params.workspaceDir,
  modelProviderId: params.model.provider,
  modelId: params.model.id,
  trigger: params.trigger,
  ...buildAgentHookContextChannelFields(params),
  // NEW: sender attribution
  senderId: params.senderId,
  senderName: params.senderName,
  senderUsername: params.senderUsername,
  senderE164: params.senderE164,
};

These fields should be optional (undefined for cron-triggered or headless runs where there is no inbound message sender).

Affected Hooks

All hooks that receive the agent turn hookCtx:

  • before_model_resolve
  • agent_turn_prepare
  • before_prompt_build
  • before_agent_start
  • before_agent_finalize
  • agent_end

Use Cases

  • Entity resolution plugins — identify who is speaking to load their profile/preferences
  • Per-user context injection — scope semantic recall or memory search to the current sender
  • Access control plugins — make tool policy or prompt decisions based on sender identity
  • Analytics/logging plugins — attribute turns to specific users in agent_end

Context

We are building a turn-context plugin that injects entity identity and semantic memories via before_prompt_build. Without senderId on the hook context, we resort to a fragile message_received → cache → before_prompt_build reads cache pattern. The data is already on params — it just needs to be forwarded to the hook context.

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

openclaw - 💡(How to fix) Fix feat(hooks): expose senderId and sender metadata in agent turn hook contexts (before_prompt_build, agent_turn_prepare, etc.)