Skip to content

feat(plugin-sdk): add extensible channel identity hook context#91903

Merged
vincentkoc merged 6 commits into
openclaw:mainfrom
lanzhi-lee:feature/hook-agent-context-sender
Jun 23, 2026
Merged

feat(plugin-sdk): add extensible channel identity hook context#91903
vincentkoc merged 6 commits into
openclaw:mainfrom
lanzhi-lee:feature/hook-agent-context-sender

Conversation

@lanzhi-lee

@lanzhi-lee lanzhi-lee commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

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.senderId and ctx.chatId keep the existing flat compatibility fields.
  • ctx.channel.sender.id mirrors ctx.senderId when sender identity is available.
  • ctx.channel.chat.id mirrors ctx.chatId when chat identity is available.
  • Channel plugins can extend ctx.channel.sender / ctx.channel.chat through TypeScript module augmentation.

Purpose

Some channel integrations need native sender/chat identifiers in plugin hooks and subprocess tools. Flat fields like senderId do 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 exec integrations need to consume.

Design considerations

  • Keep core plugin-agnostic: core only knows sender.id and chat.id; richer fields are owned by the channel plugin.
  • Preserve existing compatibility: senderId / chatId remain available where they already make sense.
  • Avoid model/tool schema pollution: exec receives the serialized context through environment, not through model-generated tool arguments.
  • Keep the PR scoped: MCP propagation is intentionally not included because SSE/streamable HTTP MCP needs a separate hook/transport design.
  • Avoid non-user leakage: identity fields are omitted for non-user triggers where sender/chat identity is not meaningful.

Implementation

  • Adds PluginHookChannelContext, PluginHookChannelSenderContext, and PluginHookChannelChatContext as extensible SDK-facing types.
  • Adds channelContext to the channel inbound builder and threads it through auto-reply, queued followups, embedded runs, CLI-backed runs, direct command execution, and hook context builders.
  • Ensures inbound conversation.id is available as ChatId, so common channel-origin runs populate ctx.chatId / ctx.channel.chat.id without requiring every channel to set a separate native field.
  • Passes channelContext into coding tools and exec defaults.
  • Exposes the context to resolve_exec_env as ctx.channel.
  • Adds OPENCLAW_CHANNEL_CONTEXT to the final exec environment as serialized JSON.
  • Covers gateway/node/sandbox exec env propagation and approval metadata with focused tests.

Follow-up work

  • MCP propagation is intentionally deferred. Supporting stdio is straightforward, but SSE / streamable HTTP MCP needs a proper hook or transport-level parameter design.
  • Channel plugins can adopt richer channelContext fields incrementally through module augmentation.
  • Feishu/Lark production fields should be added in a separate channel-plugin PR after this core SDK/exec contract lands.

Verification

  • git diff --check upstream/main...HEAD
  • node 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.ts
  • node 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/main

Real behavior proof

Behavior addressed: channel-originated plugin hooks and exec can 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 channelContext and logged hook/exec visibility.

Exact steps or command run after this patch: sent a Feishu DM that asked the agent to run uname -a via exec, then inspected gateway logs for before_agent_start, resolve_exec_env, and final exec environment 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_start received ctx.channel, resolve_exec_env received the same ctx.channel, and the final gateway exec environment contained both OPENCLAW_CHANNEL_CONTEXT and a proof env returned by resolve_exec_env with the same serialized channel context.

What was not tested: MCP propagation is not part of this PR and was not validated here.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation agents Agent runtime and tooling size: M triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 10, 2026
@clawsweeper

clawsweeper Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed June 22, 2026, 2:13 PM ET / 18:13 UTC.

Summary
The PR adds public Plugin SDK channel sender/chat context types, threads channel context through hook/run/follow-up paths, and exposes serialized channel context to exec environments.

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 channelContextEnv into subprocess environments, and the CLI prepare hook context omits the new identity helper despite the new RunCliAgentParams.channelContext field.

Review metrics: 2 noteworthy metrics.

  • Plugin SDK Context Surface: 3 types added, 1 hook field added. Public plugin API additions need explicit compatibility review even when they are additive.
  • Exec Environment Surface: 1 ambient env var added. Every channel-originated exec subprocess can receive channel identity JSON, which green CI does not settle.

Stored data model
Persistent data-model change detected: serialized state: src/agents/bash-tools.exec.resolve-env-hook.test.ts, serialized state: src/agents/bash-tools.exec.ts, serialized state: src/auto-reply/reply/queue/drain.ts, vector/embedding metadata: docs/plugins/sdk-channel-inbound.md, vector/embedding metadata: docs/tools/exec.md. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🦞 diamond lobster
Patch quality: 🧂 unranked krab
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Define and implement the exec metadata opt-in, allowlist, or redaction contract before exporting channel context to subprocesses.
  • [P2] Thread channelContext through prepareCliRunContext prompt-build hooks and add focused coverage for CLI-backed before_prompt_build or legacy before_agent_start.

Risk before merge

  • [P1] Automatic OPENCLAW_CHANNEL_CONTEXT export can expose sender/chat identifiers to arbitrary exec subprocesses unless maintainers define an allowlist, redaction rule, or opt-in contract.
  • [P1] Queued follow-up propagation now carries channel context through delivery and authorization keys, so stale or over-broad metadata association needs owner review with session-state proof.
  • [P1] GitHub reports the branch as dirty/unknown against current main, so any land-ready decision needs a refreshed merge result after the review blockers are addressed.

Maintainer options:

  1. Gate The Exec Boundary (recommended)
    Keep hook channelContext, but require explicit opt-in, allowlisting, or redaction before putting channel metadata into subprocess environments and document that contract.
  2. Accept Ambient Identity Export
    Maintainers can intentionally decide channel-owned sender/chat identifiers are non-secret exec context, but that needs to be stated as a public Plugin SDK and exec contract before merge.
  3. Split Exec From Hook Context
    Land only the hook/SDK context in this branch and handle exec propagation in a follow-up once the security model is chosen.

Next step before merge

  • [P2] The P2 hook propagation gap is mechanical, but the P1 exec metadata boundary is a maintainer security/API decision, so this is not a safe automation-only repair.

Security
Needs attention: The PR expands subprocess access to channel identity metadata, so the allowed exec data boundary needs maintainer approval before merge.

Review findings

  • [P1] Gate channel context before exporting it to exec — src/agents/bash-tools.exec.ts:1586-1592
  • [P2] Thread channel context through CLI prompt hooks — src/agents/cli-runner/types.ts:116
Review details

Best possible solution:

Keep ctx.channelContext as explicit hook metadata, add a maintainer-approved exec opt-in/allowlist/redaction contract before exporting it, and thread the same identity helper through CLI prompt-build hooks.

Do we have a high-confidence way to reproduce the issue?

Yes for the review findings by source inspection: the exec path merges channelContextEnv into subprocess environments, and the CLI prepare hook context omits the new identity helper despite the new RunCliAgentParams.channelContext field.

Is this the best way to solve the issue?

No. ctx.channelContext is the right field direction, but automatic full-context export to exec is not the best boundary without maintainer-approved opt-in/redaction, and CLI prompt-build hooks still miss the new context.

Full review comments:

  • [P1] Gate channel context before exporting it to exec — src/agents/bash-tools.exec.ts:1586-1592
    This serializes full plugin-provided channel metadata into OPENCLAW_CHANNEL_CONTEXT and places it in the spawned environment. The PR body’s Feishu example includes sender/chat identifiers such as open id, union id, and chat id; subprocesses and descendants can read env vars, so this needs an allowlist, redaction rule, or explicit opt-in contract before merge.
    Confidence: 0.9
  • [P2] Thread channel context through CLI prompt hooks — src/agents/cli-runner/types.ts:116
    Adding channelContext to RunCliAgentParams is not enough for CLI-backed prompt hooks: prepareCliRunContext still passes only buildAgentHookContextChannelFields(params) into resolvePromptBuildHookResult, so before_prompt_build and legacy before_agent_start miss ctx.channelContext while later hooks receive it. Thread buildAgentHookContextIdentityFields through that prepare path and add focused coverage.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 25090056dc22.

Label changes

Label justifications:

  • P2: This is a useful but compatibility-sensitive Plugin SDK feature with bounded blast radius once the API and exec boundary are corrected.
  • merge-risk: 🚨 compatibility: The PR adds a public Plugin SDK hook context contract and deprecates an identity field, so third-party plugin compatibility needs maintainer review.
  • merge-risk: 🚨 session-state: The diff carries channel context and native chat ids through queued follow-up and agent-run contexts where stale metadata could be associated with a later run.
  • merge-risk: 🚨 security-boundary: The diff exposes channel-owned sender/chat metadata to exec subprocess environments through a new ambient variable.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🦞 diamond lobster and patch quality is 🧂 unranked krab.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (logs): The PR body includes after-fix Feishu gateway log proof showing redacted channel context reaching hooks, resolve_exec_env, and the final exec environment.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix Feishu gateway log proof showing redacted channel context reaching hooks, resolve_exec_env, and the final exec environment.
Evidence reviewed

PR surface:

Source +220, Tests +209, Docs +51, Generated 0. Total +480 across 39 files.

View PR surface stats
Area Files Added Removed Net
Source 26 236 16 +220
Tests 9 217 8 +209
Docs 3 56 5 +51
Config 0 0 0 0
Generated 1 2 2 0
Other 0 0 0 0
Total 39 511 31 +480

Security concerns:

  • [medium] Review automatic exec identity export — src/agents/bash-tools.exec.ts:1586
    Serializing full channel context into OPENCLAW_CHANNEL_CONTEXT makes channel-owned sender/chat identifiers available to exec subprocesses and descendants without an allowlist, redaction rule, opt-in, or documented non-secret-data contract.
    Confidence: 0.9

What I checked:

  • Repository policy applied: Root and scoped AGENTS.md guidance treats Plugin SDK surfaces, channel boundaries, agent hook contexts, and exec/security data boundaries as compatibility-sensitive review areas. (AGENTS.md:23, 25090056dc22)
  • Current main hook contract: Current main exposes ctx.channel as a string channel/plugin id with flat chatId and senderId fields, so the branch's choice to keep channel string-compatible is the right direction. (src/plugins/hook-types.ts:248, 25090056dc22)
  • PR head public SDK shape: The PR head adds PluginHookChannelSenderContext, PluginHookChannelChatContext, PluginHookChannelContext, and PluginHookAgentContext.channelContext while preserving channel?: string. (src/plugins/hook-types.ts:237, be5b8434cd24)
  • Exec environment exposure: The PR serializes defaults.channelContext into OPENCLAW_CHANNEL_CONTEXT, merges it into requested env, and then assigns it into the spawned env, making full channel metadata ambient to subprocesses. (src/agents/bash-tools.exec.ts:1586, be5b8434cd24)
  • CLI prompt hook propagation gap: The PR adds RunCliAgentParams.channelContext, but the CLI prepare path still builds prompt-build and legacy before_agent_start hook context with only buildAgentHookContextChannelFields(params). (src/agents/cli-runner/prepare.ts:741, be5b8434cd24)
  • Contributor proof and prior discussion: The PR body supplies redacted Feishu gateway log proof showing channel context reaching hooks, resolve_exec_env, and final exec environment; the previous ClawSweeper comment raised the same exec-boundary concern before the latest force-push. (be5b8434cd24)

Likely related people:

  • vincentkoc: Assigned on the PR timeline and authored recent merged work forwarding channel identity to CLI hooks plus earlier hook contract splitting in the same surface. (role: recent hook context contributor and assigned reviewer; confidence: high; commits: 60e818f563d8, 7f5a5a34dbf8; files: src/plugins/hook-types.ts, src/plugins/hook-agent-context.ts, src/agents/cli-runner.ts)
  • lanzhi-lee: Authored the merged resolve_exec_env hook that this PR extends, so they are connected to the exec hook contract beyond authoring this proposal. (role: adjacent feature owner; confidence: high; commits: 10d10faa257d; files: src/agents/bash-tools.exec.ts, src/plugins/hooks.ts, src/plugins/hook-types.ts)
  • joshavant: Authored the host exec environment hardening path that this PR expands with a new ambient environment variable. (role: exec security contributor; confidence: medium; commits: 7abfff756d6c; files: src/agents/bash-tools.exec.ts, src/infra/host-env-security.ts)
  • jesse-merhi: Recent merged exec authorization work touched the same exec request pipeline and approval/security surface. (role: recent exec-area contributor; confidence: medium; commits: c9707ab635b9; files: src/agents/bash-tools.exec.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 10, 2026
@lanzhi-lee
lanzhi-lee force-pushed the feature/hook-agent-context-sender branch from 1de5d3b to d4f23ea Compare June 10, 2026 11:38
@openclaw-barnacle openclaw-barnacle Bot added the channel: feishu Channel integration: feishu label Jun 10, 2026
@lanzhi-lee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 10, 2026
@lanzhi-lee
lanzhi-lee force-pushed the feature/hook-agent-context-sender branch from d4f23ea to 9921908 Compare June 11, 2026 07:32
@openclaw-barnacle openclaw-barnacle Bot removed the channel: feishu Channel integration: feishu label Jun 11, 2026
@lanzhi-lee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 11, 2026
@lanzhi-lee
lanzhi-lee force-pushed the feature/hook-agent-context-sender branch from 9921908 to 1691d7e Compare June 11, 2026 07:39
@lanzhi-lee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@vincentkoc vincentkoc self-assigned this Jun 11, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 15, 2026
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Dependency graph guard cleared

This PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh /allow-dependencies-change comment after the guard blocks that new head SHA.

  • Current SHA: 90f51eafd5e7ee019b082ce64bc8dfb6834e2d0f

@vincentkoc

Copy link
Copy Markdown
Member

Merged via squash.

Thanks @lanzhi-lee!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: L status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants