Skip to content

fix(hooks): propagate ephemeral sessionId through embedded tool contexts#32273

Merged
vincentkoc merged 6 commits intomainfrom
vincentkoc-code/sessionid-hook-context-followup
Mar 2, 2026
Merged

fix(hooks): propagate ephemeral sessionId through embedded tool contexts#32273
vincentkoc merged 6 commits intomainfrom
vincentkoc-code/sessionid-hook-context-followup

Conversation

@vincentkoc
Copy link
Member

Summary

Describe the problem and fix in 2–5 bullets:

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Plugin tool context now includes ephemeral sessionId in embedded run + compaction paths where tool context is constructed.
  • Embedded after_tool_call hook context now includes sessionId in addition to sessionKey and agentId.
  • Client-tool before_tool_call hook context now includes sessionId.

Security Impact (required)

  • New permissions/capabilities? (Yes/No): No
  • Secrets/tokens handling changed? (Yes/No): No
  • New/changed network calls? (Yes/No): No
  • Command/tool execution surface changed? (Yes/No): No
  • Data access scope changed? (Yes/No): No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 22 + pnpm
  • Model/provider: N/A (unit/e2e hook wiring)
  • Integration/channel (if any): embedded tool hooks
  • Relevant config (redacted): default test config

Steps

  1. Run embedded hook path tests and plugin context tests.
  2. Verify hook context payload includes sessionId on after_tool_call and before_tool_call path updates.
  3. Verify compaction and attempt path pass sessionId through tool-construction options.

Expected

  • sessionId is available in embedded plugin tool/hook contexts on the updated paths.
  • Existing sessionKey + single-fire after_tool_call behavior remains intact.

Actual

  • Matches expected.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Executed:

  • pnpm exec vitest run src/agents/openclaw-tools.plugin-context.test.ts
  • pnpm exec vitest run src/agents/pi-embedded-subscribe.handlers.tools.test.ts
  • pnpm exec vitest run --config vitest.e2e.config.ts src/plugins/wired-hooks-after-tool-call.e2e.test.ts src/agents/pi-tools.before-tool-call.integration.e2e.test.ts
  • pnpm format

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: embedded after_tool_call context includes sessionId; before_tool_call context propagation includes sessionId; compaction/attempt paths pass sessionId into tool construction.
  • Edge cases checked: hook dispatch still once-per-tool path (regression suite unchanged), and cross-suite toolCallId collision fixed in e2e test fixture.
  • What you did not verify: end-to-end behavior in external mem0 plugin runtime repository.

Compatibility / Migration

  • Backward compatible? (Yes/No): Yes
  • Config/env changes? (Yes/No): No
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this PR or temporarily ignore ctx.sessionId in plugin hooks.
  • Files/config to restore: touched files in src/agents/*, src/plugins/*, and CHANGELOG.md.
  • Known bad symptoms reviewers should watch for: missing sessionId in hook ctx payloads; mismatched hook test expectations.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: Optional context-field additions can be missed in one execution path.
    • Mitigation: Added embedded runtime + e2e hook tests and patched compaction + client-tool paths explicitly.

SidQin-cyber and others added 5 commits March 2, 2026 14:56
…versation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes #31253

Made-with: Cursor
@vincentkoc vincentkoc merged commit 0954b6b into main Mar 2, 2026
22 of 23 checks passed
@vincentkoc vincentkoc deleted the vincentkoc-code/sessionid-hook-context-followup branch March 2, 2026 23:11
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

This PR completes the ephemeral sessionId propagation across embedded plugin tool/hook contexts. After the prior sessionKey/agentId baseline from #32201, this change threads sessionId through the after_tool_call embedded dispatch, before_tool_call hook context, createOpenClawCodingTools in both the attempt and compaction paths, and the downstream createOpenClawTools plugin context — enabling plugins to isolate per-conversation state across /new and /reset events. It also corrects a pre-existing inconsistency in attempt.ts where toClientToolDefinitions was receiving the raw params.sessionKey instead of the already-resolved sandboxSessionKey, which could result in an undefined session key being passed to client tools while all other tools in the same run received the resolved value.

Key changes:

  • sessionId?: string added to OpenClawPluginToolContext, PluginHookToolContext, SubscribeEmbeddedPiSessionParams, ToolHandlerParams, HookContext, and createOpenClawCodingTools / createOpenClawTools options — all optional and backward-compatible.
  • after_tool_call and before_tool_call hook dispatch contexts now include sessionId.
  • toClientToolDefinitions call in attempt.ts corrected to use sandboxSessionKey (consistent with every other tool-construction call in the same file).
  • toolCallId values in wired-hooks-after-tool-call.e2e.test.ts renamed from the generic "call-1" to "wired-hook-call-1" to avoid collisions with IDs used by other test suites running in parallel.

Confidence Score: 5/5

  • This PR is safe to merge; all changes are backward-compatible optional-field additions with no behavior change to existing callers that omit sessionId.
  • The scope is tightly bounded: only optional context fields are added, the propagation chain is complete and consistent across all relevant call sites, the sandboxSessionKey fix in attempt.ts aligns client-tool handling with every other tool in the same file, and test coverage directly exercises the new sessionId field in both before_tool_call and after_tool_call paths. No logic is restructured, no hook contracts are changed, and the deduplication guarantees from fix(hooks): consolidate after_tool_call context + single-fire behavior #32201 are preserved.
  • No files require special attention.

Last reviewed commit: 5c652d1

planfit-alan pushed a commit to planfit/openclaw that referenced this pull request Mar 3, 2026
…xts (openclaw#32273)

* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes openclaw#31253

Made-with: Cursor

* fix(agents): propagate embedded sessionId through tool hook context

* test(hooks): cover sessionId in embedded tool hook contexts

* docs(changelog): add sessionId hook context follow-up note

* test(hooks): avoid toolCallId collision in after_tool_call e2e

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
(cherry picked from commit 0954b6b)
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
…xts (openclaw#32273)

* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes openclaw#31253

Made-with: Cursor

* fix(agents): propagate embedded sessionId through tool hook context

* test(hooks): cover sessionId in embedded tool hook contexts

* docs(changelog): add sessionId hook context follow-up note

* test(hooks): avoid toolCallId collision in after_tool_call e2e

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
…xts (openclaw#32273)

* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes openclaw#31253

Made-with: Cursor

* fix(agents): propagate embedded sessionId through tool hook context

* test(hooks): cover sessionId in embedded tool hook contexts

* docs(changelog): add sessionId hook context follow-up note

* test(hooks): avoid toolCallId collision in after_tool_call e2e

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…xts (openclaw#32273)

* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes openclaw#31253

Made-with: Cursor

* fix(agents): propagate embedded sessionId through tool hook context

* test(hooks): cover sessionId in embedded tool hook contexts

* docs(changelog): add sessionId hook context follow-up note

* test(hooks): avoid toolCallId collision in after_tool_call e2e

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants