openclaw - 💡(How to fix) Fix [Feature]: Expose agent id in ChannelOutboundContext [1 comments, 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#70905Fetched 2026-04-24 10:38:01
View on GitHub
Comments
1
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
commented ×1labeled ×1

Add an optional agentId field to ChannelOutboundContext so channel plugins can attribute outbound sends to a specific agent.

Root Cause

Add an optional agentId field to ChannelOutboundContext so channel plugins can attribute outbound sends to a specific agent.

RAW_BUFFERClick to expand / collapse

Summary

Add an optional agentId field to ChannelOutboundContext so channel plugins can attribute outbound sends to a specific agent.

Problem to solve

Channel plugins that model each agent as a distinct remote identity (one agent per user/member row on the remote side, rather than a single shared bot with per-message display costumes) need to know which agent is producing a message when OpenClaw
invokes sendText / sendMedia / sendPayload.

Today the adapter context exposes display-layer fields (identity.name, identity.avatarUrl, identity.emoji, identity.theme) but no stable agent id, even though that id is already in scope throughout the upstream outbound pipeline (OutboundSessionContext, OutboundSendServiceParams, MessageActionRunnerContext, OutboundMirrorRoute, SessionContext, MessageActionThreading). Inbound-driven replies can recover the id from the originating route; non-inbound paths (heartbeats, sessions_send tool calls, cron-triggered turns, any autonomous agent action) cannot.

Affected plugins are forced to either resolve by display name (fragile: names collide, change, and aren't globally unique) or
smuggle the id through a display field (abuses render semantics and breaks plugins that use those fields as intended).

Proposed solution

Add an optional agentId to ChannelOutboundContext:

export type ChannelOutboundContext = { cfg: OpenClawConfig; to: string; text: string; // ... accountId?: string | null;

  • /**
    • Stable runtime id of the agent producing this outbound. Populated for
    • agent-driven sends (inbound replies, heartbeats, sessions_send, cron
    • jobs). Absent for human-initiated or system sends where no agent is in
    • scope. Intended for channels that model each agent as a first-class
    • remote identity rather than a shared bot with display costumes.
  • */
  • agentId?: string; identity?: OutboundIdentity; // ... };

Populate at the call sites that already carry agentId. This would be primarily deliverOutboundPayloads in infra/outbound/deliver.ts and any other spot where the adapter ctx is assembled from a context that holds agentId (5–10 locations, all with the local already in scope).

Alternatives considered

  1. Add agentId to OutboundIdentity. Rejected: OutboundIdentity is display-facing (name, avatar, emoji, theme); mixing addressing with rendering muddles both and creates ambiguity about what identity?: undefined means.

  2. Look up the agent by identity.name. Fragile: display names can collide, change mid-lifetime, and aren't guaranteed unique per channel.

  3. Smuggle the id through identity.emoji / identity.theme. Pollutes display semantics and breaks plugins that actually use
    those fields for rendering.

  4. Pass via the deps bag. deps is a per-channel function registry, not per-send metadata; also racy under concurrent sends on a single channel.

  5. Singleton "currently running agent" inside the plugin. Races under concurrent turns (heartbeat overlapping with inbound,
    concurrent sessions_send calls, etc.).

Impact

  • Affected: plugin authors building channels where each agent corresponds to a distinct user/member on the remote side. Also
    useful for analytics/audit plugins that want per-agent attribution of outbound traffic.
    • Severity: blocks non-inbound send paths for this class of plugin — remotes that require per-agent authentication will reject sends; remotes that accept anonymous writes will drop attribution or silently drop attachments.
    • Frequency: every non-inbound send. For deployments with scheduled or autonomous agent workloads, daily to hourly.
    • Consequence: affected plugins either fail sends outright, drop attachments silently, or fall back to fragile name-based
      resolution that breaks on rename.

Evidence/examples

  • Affected: plugin authors building channels where each agent corresponds to a distinct user/member on the remote side. Also
    useful for analytics/audit plugins that want per-agent attribution of outbound traffic.
  • Severity: blocks non-inbound send paths for this class of plugin — remotes that require per-agent authentication will reject sends; remotes that accept anonymous writes will drop attribution or silently drop attachments.
  • Frequency: every non-inbound send. For deployments with scheduled or autonomous agent workloads, daily to hourly.
  • Consequence: affected plugins either fail sends outright, drop attachments silently, or fall back to fragile name-based
    resolution that breaks on rename.

Additional information

  • Backward compatibility: field is optional; existing plugins that don't destructure agentId are unaffected.
  • Non-goals: no new hooks (resolveSenderAgent, etc.) and no changes to OutboundIdentity. Channels that need full agent config
    can call resolveAgent(cfg, ctx.agentId) themselves with what they already have.
  • Propagation surface: roughly 5–10 call sites in infra/outbound/, all of which already have agentId as a local variable.
  • Happy to contribute the PR if there's agreement on the shape.

extent analysis

TL;DR

Add an optional agentId field to ChannelOutboundContext to enable channel plugins to attribute outbound sends to a specific agent.

Guidance

  • Review the proposed solution to add an optional agentId to ChannelOutboundContext and assess its feasibility for your use case.
  • Identify the call sites in infra/outbound/ where agentId is already available as a local variable and can be populated in the ChannelOutboundContext.
  • Consider the backward compatibility of the proposed solution, as the agentId field is optional and existing plugins that don't use it will be unaffected.
  • Evaluate the potential impact on your plugins, particularly those that model each agent as a distinct remote identity, and determine if this solution addresses their needs.

Example

No code snippet is provided as the issue is focused on proposing a solution rather than providing a specific implementation.

Notes

The proposed solution aims to address the issue of channel plugins needing to attribute outbound sends to a specific agent, but its implementation details and potential edge cases should be carefully reviewed.

Recommendation

Apply the proposed workaround by adding an optional agentId field to ChannelOutboundContext, as it provides a straightforward solution to the problem and maintains backward compatibility with existing plugins.

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