feat(plugin-sdk): add extensible channel identity hook context#91903
Conversation
|
Codex review: found issues before merge. Reviewed June 22, 2026, 2:13 PM ET / 18:13 UTC. Summary PR surface: Source +220, Tests +209, Docs +51, Generated 0. Total +480 across 39 files. Reproducibility: yes. for the review findings by source inspection: the exec path merges Review metrics: 2 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Keep Do we have a high-confidence way to reproduce the issue? Yes for the review findings by source inspection: the exec path merges Is this the best way to solve the issue? No. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 25090056dc22. Label changesLabel justifications:
Evidence reviewedPR surface: Source +220, Tests +209, Docs +51, Generated 0. Total +480 across 39 files. View PR surface stats
Security concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
1de5d3b to
d4f23ea
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
d4f23ea to
9921908
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
9921908 to
1691d7e
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Dependency graph guard clearedThis PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh
|
|
Merged via squash.
Thanks @lanzhi-lee! |
Summary
This PR adds an extensible channel sender/chat context to plugin hook contexts and exposes the same context to
exec.It lets a channel plugin pass channel-owned identity metadata, such as Feishu/Lark sender and chat identifiers, without adding more core-specific flat fields. Core defines only the stable base shape:
ctx.senderIdandctx.chatIdkeep the existing flat compatibility fields.ctx.channel.sender.idmirrorsctx.senderIdwhen sender identity is available.ctx.channel.chat.idmirrorsctx.chatIdwhen chat identity is available.ctx.channel.sender/ctx.channel.chatthrough TypeScript module augmentation.Purpose
Some channel integrations need native sender/chat identifiers in plugin hooks and subprocess tools. Flat fields like
senderIddo not scale well because each channel may have different native identifiers. This PR adds a generic channel-owned object so plugins can carry their own metadata while keeping core channel-agnostic.The immediate use case is Feishu/Lark-style identity metadata that downstream plugin hooks and
execintegrations need to consume.Design considerations
sender.idandchat.id; richer fields are owned by the channel plugin.senderId/chatIdremain available where they already make sense.execreceives the serialized context through environment, not through model-generated tool arguments.Implementation
PluginHookChannelContext,PluginHookChannelSenderContext, andPluginHookChannelChatContextas extensible SDK-facing types.channelContextto the channel inbound builder and threads it through auto-reply, queued followups, embedded runs, CLI-backed runs, direct command execution, and hook context builders.conversation.idis available asChatId, so common channel-origin runs populatectx.chatId/ctx.channel.chat.idwithout requiring every channel to set a separate native field.channelContextinto coding tools andexecdefaults.resolve_exec_envasctx.channel.OPENCLAW_CHANNEL_CONTEXTto the finalexecenvironment as serialized JSON.Follow-up work
channelContextfields incrementally through module augmentation.Verification
git diff --check upstream/main...HEADnode scripts/run-vitest.mjs src/channels/inbound-event/context.test.ts src/agents/cli-runner.reliability.test.ts src/agents/bash-tools.exec.resolve-env-hook.test.ts src/agents/bash-tools.exec-host-node.test.ts src/auto-reply/reply/agent-runner-utils.test.tsnode scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/channel-context-pr-update.tsbuildinfo --noUnusedLocals false.agents/skills/autoreview/scripts/autoreview --mode branch --base upstream/mainReal behavior proof
Behavior addressed: channel-originated plugin hooks and
execcan receive channel-owned sender/chat metadata through a structured context.Real environment tested: local OpenClaw gateway with Feishu enabled, using a temporary uncommitted Feishu proof patch on top of this PR. The proof patch injected redacted test fields into Feishu
channelContextand logged hook/exec visibility.Exact steps or command run after this patch: sent a Feishu DM that asked the agent to run
uname -aviaexec, then inspected gateway logs forbefore_agent_start,resolve_exec_env, and finalexecenvironment proof lines.Evidence after fix: the same redacted context shape appeared in all three stages:
{ "sender": { "id": "<feishu-open-id>", "testCode1": 1, "unionId": "<feishu-union-id>" }, "chat": { "id": "<feishu-chat-id>", "testCode2": 2 } }Observed result after fix:
before_agent_startreceivedctx.channel,resolve_exec_envreceived the samectx.channel, and the final gatewayexecenvironment contained bothOPENCLAW_CHANNEL_CONTEXTand a proof env returned byresolve_exec_envwith the same serialized channel context.What was not tested: MCP propagation is not part of this PR and was not validated here.