feat: add nested subagent session lineage for OpenClaw#210
feat: add nested subagent session lineage for OpenClaw#210mnajafian-nv wants to merge 3 commits into
Conversation
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
WalkthroughRefactors hook-replay to canonicalize sessions by internal ownerKey, defer session-root opening until parent lineage is available, thread microsecond timestamps through lifecycle emits and replay, add subagent lineage/promote logic, and update tests and docs to the new model. ChangesSession identity re-anchoring and lifecycle materialization
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
integrations/openclaw/src/hook-replay/llm.ts (1)
1191-1193:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse
ownerKeyfor internal replay bookkeeping fallback.
trajectoryRunKey()still falls back tosession.sessionId, which this PR otherwise treats as aliasable/mutable. If hooks arrive withoutrunIdbefore/after a session-id remap,trajectoryReplayedRuns,agentRunInputSnapshots, andhookLlmOutputReplayCountscan split across two keys and cause duplicate replay or missed cleanup. Use the stable internal identity here instead.Suggested fix
function trajectoryRunKey(session: SessionState, runId?: string): string { - return runId ?? session.sessionId; + return runId ?? session.ownerKey; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/openclaw/src/hook-replay/llm.ts` around lines 1191 - 1193, trajectoryRunKey currently falls back to session.sessionId which is mutable; change the fallback to the stable internal identity by returning runId ?? session.ownerKey (i.e., use SessionState.ownerKey) so replay bookkeeping like trajectoryReplayedRuns, agentRunInputSnapshots, and hookLlmOutputReplayCounts use the stable owner key instead of the sessionId.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@integrations/openclaw/src/hook-replay/tool.ts`:
- Around line 55-63: The session is being materialized with observedAtMicros,
which can be after the tool span start when the first event is after_tool_call;
change ensureSession(...) so its timestamp uses the derived tool start time
(compute startMicrosFromDuration(observedAtMicros, event.durationMs) or use an
existing derived variable) instead of observedAtMicros when event.type ===
'after_tool_call' (or when event.durationMs is present and start is earlier), so
materializeSessionRoot sees the correct backdated start; update the call site
around ensureSession in tool.ts to pass that computed start time and keep
observedAtMicros for other cases.
In `@integrations/openclaw/src/hooks-backend.ts`:
- Around line 86-87: The two maps pendingSubagentLineageByChildSessionKey and
pendingSubagentChildKeyByRunId can grow unbounded because entries are only
removed by forgetPendingSubagentLineage during closeSession; update the code to
evict or bound these maps: add TTL-based eviction or a max-size ring behavior
and remove expired/old entries from these maps inside evictExpiredReplayRecords
(and also call the remover from cleanupSession), and ensure subagent_spawned
handling records creation metadata (timestamp/runId) so
forgetPendingSubagentLineage, cleanupSession, or evictExpiredReplayRecords can
correlate and delete orphaned entries to prevent memory buildup.
---
Outside diff comments:
In `@integrations/openclaw/src/hook-replay/llm.ts`:
- Around line 1191-1193: trajectoryRunKey currently falls back to
session.sessionId which is mutable; change the fallback to the stable internal
identity by returning runId ?? session.ownerKey (i.e., use
SessionState.ownerKey) so replay bookkeeping like trajectoryReplayedRuns,
agentRunInputSnapshots, and hookLlmOutputReplayCounts use the stable owner key
instead of the sessionId.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 071b8d5d-ec90-427b-8982-ffe69035954b
📒 Files selected for processing (7)
docs/supported-integrations/openclaw-plugin.mdxintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hook-replay/session.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/test/llm-replay.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Node.js / Test (linux-arm64)
- GitHub Check: Node.js / Test (linux-amd64)
- GitHub Check: Node.js / Test (windows-arm64)
- GitHub Check: Node.js / Test (macos-arm64)
- GitHub Check: Node.js / Test (windows-amd64)
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (17)
{docs/**,README.md,CONTRIBUTING.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Usejust docsfor docs-site builds andjust docs-linkcheckwhen links changed
Run docs site build withjust docs
Files:
docs/supported-integrations/openclaw-plugin.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run docs link validation with
just docs-linkcheckwhen links change
Files:
docs/supported-integrations/openclaw-plugin.mdx
{docs/**,README.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Verify README and docs entry points still match current package names and paths for large or public-facing changes
Files:
docs/supported-integrations/openclaw-plugin.mdx
{docs/**,examples/**,README.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Verify examples still run with documented commands for large or public-facing changes
Files:
docs/supported-integrations/openclaw-plugin.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes
Files:
docs/supported-integrations/openclaw-plugin.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
Keep package names, repo references, and build commands current
Files:
docs/supported-integrations/openclaw-plugin.mdx
**/*.mdx
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.
MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)
Files:
docs/supported-integrations/openclaw-plugin.mdx
**/*.{html,md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in HTML and Markdown files using HTML comment syntax
Files:
docs/supported-integrations/openclaw-plugin.mdx
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed
Files:
docs/supported-integrations/openclaw-plugin.mdx
docs/**
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run
just docsor./scripts/build-docs.sh htmlto regenerate ignored Fern API reference pages before validation for documentation site changes
Files:
docs/supported-integrations/openclaw-plugin.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}
⚙️ CodeRabbit configuration file
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.
Files:
docs/supported-integrations/openclaw-plugin.mdx
**/*{test,spec,smoke}.{js,ts,py}
📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)
Relevant integration tests or smoke path must pass
Files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/test/hooks-backend.test.ts
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Maintain documented and tested validation and report behavior for adaptive surfaces
Files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/test/hooks-backend.test.ts
**/*.{wasm,js,ts}{,x}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption
Files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/session.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run Node.js formatting with
npm run format --workspace=nemo-relay-nodeInclude SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax
Files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.
Files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,go,js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/session.ts
🧠 Learnings (7)
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: Applies to docs/{about/concepts/subscribers,export-observability-data/about}.md : Update documentation under `docs/about/concepts/subscribers.md` and `docs/export-observability-data/about.md` to reflect lifecycle changes: create, register, run, deregister, flush, shutdown
Applied to files:
docs/supported-integrations/openclaw-plugin.mdx
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.
Applied to files:
integrations/openclaw/test/llm-replay.test.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/session.ts
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: For Node.js binding changes, use `test-node-binding`
Applied to files:
integrations/openclaw/test/hooks-backend.test.ts
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Applies to crates/node/**/*.{js,ts,tsx} : Node.js public entry points include the main runtime package plus `nemo-relay-node/typed`, `nemo-relay-node/plugin`, and `nemo-relay-node/adaptive`.
Applied to files:
integrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/session.ts
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add chain execution helpers to `NemoRelayContextState` following the pattern of existing methods like `tool_sanitize_request_chain` or `tool_request_intercepts_chain`
Applied to files:
integrations/openclaw/test/hooks-backend.test.ts
📚 Learning: 2026-05-26T21:03:12.012Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/review-doc-style/SKILL.md:0-0
Timestamp: 2026-05-26T21:03:12.012Z
Learning: Keep documentation aligned with current NeMo Relay behavior, repo layout, and entry points
Applied to files:
integrations/openclaw/test/hooks-backend.test.ts
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Scope stacks are hierarchical and always have a root scope. They establish parent-child event relationships, visibility for scope-local middleware and subscribers, cleanup boundaries, and concurrent request isolation.
Applied to files:
integrations/openclaw/test/hooks-backend.test.ts
🔇 Additional comments (7)
docs/supported-integrations/openclaw-plugin.mdx (1)
271-271: LGTM!integrations/openclaw/src/hook-replay/session.ts (3)
385-439: LGTM!
1-2: LGTM!Also applies to: 44-67, 70-131, 453-477
177-204: ⚡ Quick winRemove the requester-vs-child precedence collapse concern (call sites don’t pass both keys together)
resolveSessionOwnerKeyiterateslookupSessionKeyswithrequesterSessionKeybeforechildSessionKey, but the subagent handlers inintegrations/openclaw/src/hooks-backend.tscallensureSessionin two separate attempts: first withrequesterSessionKeyonly, then withchildSessionKeyonly (no single input object contains both). As a result, the claimed “child collapses into requester” andrememberSessionAliasesclobbering via the same input object won’t happen in the current flow; child nesting instead comes fromresolveSessionRootContextsettingparentHandleusingresolveTrackedSession({ requesterSessionKey: ... }).> Likely an incorrect or invalid review comment.integrations/openclaw/src/hook-replay/tool.ts (1)
25-32: LGTM!Also applies to: 83-83
integrations/openclaw/src/hooks-backend.ts (1)
108-337: LGTM!Also applies to: 345-357, 423-457, 492-631
integrations/openclaw/test/hooks-backend.test.ts (1)
391-684: LGTM!Also applies to: 729-832, 852-861
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
integrations/openclaw/src/hooks-backend.ts (1)
498-507:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftKeep deferred child roots deferred until the requester root exists.
Line 507 correctly computes
deferRootOpen: truewhen lineage is known but the requester root is still missing, but that defer state is broken a few frames later:onSubagentSpawned()still callspromoteDeferredSubagentSession(), andmaterializeDeferredSessionRoot()will open the child withparentHandle === undefined. In thesubagent_spawned-before-parent-session_startordering, the child becomes a top-level root and can never be nested under the requester afterward.This needs to stay deferred until the parent root is available, and there should be a promotion path when the requester session eventually opens.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/openclaw/src/hooks-backend.ts` around lines 498 - 507, The deferred child-root decision in resolvePendingSubagentLineage is correct but later broken by onSubagentSpawned/promoteDeferredSubagentSession and materializeDeferredSessionRoot which open a child as top-level when parentHandle is undefined; change onSubagentSpawned to respect deferRootOpen (do not call promoteDeferredSubagentSession if parentHandle is undefined), modify materializeDeferredSessionRoot to no-op (keep deferred) when parentHandle is undefined, and add logic in the session-start path (where resolveTrackedSession/resolvePendingSubagentLineage are used) to detect when a requester root becomes available and then call promoteDeferredSubagentSession to materialize and attach any pending child sessions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@integrations/openclaw/src/hooks-backend.ts`:
- Around line 498-507: The deferred child-root decision in
resolvePendingSubagentLineage is correct but later broken by
onSubagentSpawned/promoteDeferredSubagentSession and
materializeDeferredSessionRoot which open a child as top-level when parentHandle
is undefined; change onSubagentSpawned to respect deferRootOpen (do not call
promoteDeferredSubagentSession if parentHandle is undefined), modify
materializeDeferredSessionRoot to no-op (keep deferred) when parentHandle is
undefined, and add logic in the session-start path (where
resolveTrackedSession/resolvePendingSubagentLineage are used) to detect when a
requester root becomes available and then call promoteDeferredSubagentSession to
materialize and attach any pending child sessions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 7ade0fef-a945-444a-ac7a-7d7eeaec7840
📒 Files selected for processing (3)
integrations/openclaw/src/hook-replay/session.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Node.js / Test (macos-arm64)
- GitHub Check: Node.js / Test (windows-amd64)
- GitHub Check: Node.js / Test (linux-arm64)
- GitHub Check: Node.js / Test (windows-arm64)
- GitHub Check: Node.js / Test (linux-amd64)
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (6)
**/*{test,spec,smoke}.{js,ts,py}
📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)
Relevant integration tests or smoke path must pass
Files:
integrations/openclaw/test/hooks-backend.test.ts
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Maintain documented and tested validation and report behavior for adaptive surfaces
Files:
integrations/openclaw/test/hooks-backend.test.ts
**/*.{wasm,js,ts}{,x}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption
Files:
integrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/src/hook-replay/session.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run Node.js formatting with
npm run format --workspace=nemo-relay-nodeInclude SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax
Files:
integrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.
Files:
integrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,go,js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
integrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/src/hook-replay/session.ts
🧠 Learnings (2)
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: For Node.js binding changes, use `test-node-binding`
Applied to files:
integrations/openclaw/test/hooks-backend.test.ts
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.
Applied to files:
integrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/src/hook-replay/session.ts
🔇 Additional comments (1)
integrations/openclaw/src/hook-replay/session.ts (1)
164-180: LGTM!Also applies to: 245-245, 406-406
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
integrations/openclaw/src/hooks-backend.ts (1)
262-297:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftDon't promote the child root before the requester scope exists.
subagent_spawnedstill misparents spawn-first flows where no requester session has been seen yet.ensureSession({ requesterSessionKey })cannot seed a new parent on its own because owner-key fallback only usessessionId/sessionKey/childSessionKey/runId, so this path falls through to a deferred child session;promoteDeferredSubagentSession()then immediately materializes that child withparentHandle === undefined. If the requestersession_startarrives later, the child is already locked in as a top-level scope. Please keep the child deferred until a requester root is available, or create a lazy requester session fromrequesterSessionKeyfirst.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrations/openclaw/src/hooks-backend.ts` around lines 262 - 297, onSubagentSpawned currently can materialize a child as top-level because ensureSession({ requesterSessionKey }) doesn't create a requester root; change the flow so you do not call promoteDeferredSubagentSession(event.childSessionKey) until a requester session exists or you explicitly create a lazy requester session: first check for an existing requester session (via ensureSession with requesterSessionKey and verifying it returned a true requester/root), if none and ctx.requesterSessionKey is present then create a lazy requester root (call ensureSession in a mode that seeds a requester root) or otherwise keep the child deferred; only call promoteDeferredSubagentSession when the requester root is present. Ensure to reference onSubagentSpawned, ensureSession, and promoteDeferredSubagentSession when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@integrations/openclaw/src/hooks-backend.ts`:
- Around line 262-297: onSubagentSpawned currently can materialize a child as
top-level because ensureSession({ requesterSessionKey }) doesn't create a
requester root; change the flow so you do not call
promoteDeferredSubagentSession(event.childSessionKey) until a requester session
exists or you explicitly create a lazy requester session: first check for an
existing requester session (via ensureSession with requesterSessionKey and
verifying it returned a true requester/root), if none and
ctx.requesterSessionKey is present then create a lazy requester root (call
ensureSession in a mode that seeds a requester root) or otherwise keep the child
deferred; only call promoteDeferredSubagentSession when the requester root is
present. Ensure to reference onSubagentSpawned, ensureSession, and
promoteDeferredSubagentSession when making this change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: dd2eb2ce-6cb7-40a3-8fd3-cdf1e6977ce4
📒 Files selected for processing (4)
integrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/src/hooks-backend.tsintegrations/openclaw/test/hooks-backend.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{wasm,js,ts}{,x}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption
Files:
integrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run Node.js formatting with
npm run format --workspace=nemo-relay-nodeInclude SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax
Files:
integrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.
Files:
integrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.ts
**/*.{rs,py,go,js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
integrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.ts
**/*{test,spec,smoke}.{js,ts,py}
📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)
Relevant integration tests or smoke path must pass
Files:
integrations/openclaw/test/hooks-backend.test.ts
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}
📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)
Maintain documented and tested validation and report behavior for adaptive surfaces
Files:
integrations/openclaw/test/hooks-backend.test.ts
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.
Applied to files:
integrations/openclaw/src/hook-replay/tool.tsintegrations/openclaw/test/hooks-backend.test.tsintegrations/openclaw/src/hook-replay/llm.tsintegrations/openclaw/src/hooks-backend.ts
🔇 Additional comments (2)
integrations/openclaw/src/hook-replay/llm.ts (1)
1191-1193: LGTM!integrations/openclaw/src/hook-replay/tool.ts (1)
55-57: LGTM!Also applies to: 63-63, 84-84
Overview
This PR adds nested subagent session lineage for OpenClaw so child subagent activity can nest under the requester session when stable lineage is available, while keeping replay state and emitted metadata honest when hooks arrive out of order.
Details
subagent_spawnedprovides stable parent/child lineage.sessionIdvalues.subagent_endedpaths under the child session scope instead of dropping or misparenting the terminal mark.session_start.Where should the reviewer start?
Start in
integrations/openclaw/src/hooks-backend.ts, especially the subagent lineage tracking and deferred child-root materialization flow. Then look atintegrations/openclaw/src/hook-replay/session.tsfor the stable internal session ownership model andintegrations/openclaw/test/hooks-backend.test.tsfor the contract-level subagent ordering cases covered here.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
Documentation
New Features
Tests