Skip to content

fix(agents): backfill missing sessionKey in embedded PI runner — prevents undefined key in model selection and live-switch#60555

Merged
jalehman merged 12 commits intoopenclaw:mainfrom
electricsheephq:fix/backfill-sessionkey-in-embedded-runner
Apr 6, 2026
Merged

fix(agents): backfill missing sessionKey in embedded PI runner — prevents undefined key in model selection and live-switch#60555
jalehman merged 12 commits intoopenclaw:mainfrom
electricsheephq:fix/backfill-sessionkey-in-embedded-runner

Conversation

@100yenadmin
Copy link
Copy Markdown
Contributor

@100yenadmin 100yenadmin commented Apr 3, 2026

What this fixes (plain English)

When a chat session was started with only a session ID (no session key), downstream features like hooks, live-model switching, and error formatting would break because they expected a session key. This fix resolves the session key from the store at startup, so all downstream paths work correctly.

Technical details

Root cause: The embedded runner could receive a sessionId without a corresponding sessionKey. Downstream paths (hooks, live-model switch, error formatting, pending-clear) all require sessionKey but received undefined.

Fix: Added resolveSessionKeyForRequest() backfill at the start of the embedded runner when only sessionId is provided. The resolved key is used consistently throughout the run lifecycle. Logs a warning if backfill resolution fails (instead of silently swallowing).

Files changed:

  • src/agents/pi-embedded-runner/run.ts — backfill sessionKey from sessionId via resolver
  • src/agents/command/session.ts — updated docstring
  • src/agents/pi-embedded-runner.e2e.test.ts — e2e regression test for sessionKey backfill
  • src/gateway/sessions-history-http.test.ts — SSE seq validation: verifies NO_REPLY messages are excluded from streamed history and seq numbering is correct
  • CHANGELOG.md — release note for the sessionKey backfill fix

Related

Test plan

  • 60/60 tests pass (model + tool-result-context-guard suites)
  • Regression test: successful sessionId -> sessionKey backfill
  • Regression test: warning log emission when backfill resolution throws
  • SSE seq validation test for NO_REPLY message filtering in session history

Copilot AI review requested due to automatic review settings April 3, 2026 21:58
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Apr 3, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 3, 2026

Greptile Summary

This PR adds a backfillSessionKey() helper that resolves a sessionKey from the session store by sessionId at the top of runEmbeddedPiAgent(), ensuring hooks, LCM, and compaction receive a non-null key when callers omit it. The fix is narrow, correctly guarded, and has no behavior change for callers that already supply sessionKey.

Confidence Score: 5/5

Safe to merge — the fix is a well-scoped read-only lookup with a no-op fallback; no behavioral regression for existing callers.

All remaining findings are P2 style suggestions (silent catch, redundant fallback operand). No correctness or data-integrity issues were found.

No files require special attention.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/run.ts
Line: 121-123

Comment:
**Silent error swallowing without any log**

If `resolveSessionKeyForRequest` throws unexpectedly (corrupt session store, permission error, etc.) the failure is invisible — the function returns `undefined` and the caller never knows the backfill was skipped. At minimum a `debug`/`warn` log would make future incidents diagnosable.

```suggestion
  } catch (err) {
    log.warn(
      `[backfillSessionKey] Failed to resolve sessionKey for sessionId=${params.sessionId}: ${describeUnknownError(err)}`,
    );
    return params.sessionKey;
  }
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/run.ts
Line: 120

Comment:
**Redundant fallback operand**

`params.sessionKey` is guaranteed to be `undefined` or an empty string at this point (the early-return guard on line 112 already handles any truthy value). The `?? params.sessionKey` tail is therefore a no-op and adds a small amount of confusion — `resolved.sessionKey` alone is clearer.

```suggestion
    return resolved.sessionKey;
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(agents): backfill sessionKey in runE..." | Re-trigger Greptile

Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses missing sessionKey propagation at the embedded runner boundary by backfilling sessionKey from sessionId via the existing store-backed resolver, avoiding null/undefined session keys reaching hooks/LCM/compaction.

Changes:

  • Import and use resolveSessionKeyForRequest() to backfill sessionKey when callers omit it.
  • Add a backfillSessionKey() helper and apply it at the start of runEmbeddedPiAgent().

Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Comment thread src/agents/pi-embedded-runner/run.ts
Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Comment thread src/agents/pi-embedded-runner/run.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 312b18bfc2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/pi-embedded-runner/run.ts Outdated
@100yenadmin
Copy link
Copy Markdown
Contributor Author

Pushed fixes for all review feedback:

P1 (agentId binding): Removed agentId from the resolveSessionKeyForRequest() call entirely. The resolver now looks up purely by sessionId, avoiding resolveExplicitAgentSessionKey() which would bind one-off callers (model probes, etc.) to the agent's main session. Good catch — this was a real correctness issue.

P2 (silent catch): Replaced bare catch with log.warn() using sanitizeForLog() and describeUnknownError() (both already imported in this file).

P2 (redundant fallback): Removed the ?? params.sessionKey tail — it was unreachable after the early-return guard.

P2 (whitespace normalization): Now normalizes with .trim() || undefined at entry and on the resolved value, so downstream consumers never see whitespace-only keys.

Docstring: Updated to reflect best-effort semantics.

On the test coverage request: happy to add a regression test if you can point me at the right mock setup for resolveSessionKeyForRequest() / session store in the embedded runner test suite. I'll submit a follow-up commit.

@100yenadmin
Copy link
Copy Markdown
Contributor Author

CI note: the checks-fast-extensions failure is unrelated to this PR — it's Mattermost reconnect test timeouts (extensions/mattermost/src/mattermost/reconnect.test.ts). There's already an upstream commit (1322aa2, test(ci): make mattermost reconnect deterministic) addressing that flaky suite.

This PR only modifies src/agents/pi-embedded-runner/run.ts.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread src/agents/pi-embedded-runner/run.ts
@100yenadmin
Copy link
Copy Markdown
Contributor Author

@jalehman can you merge in. This quick fix enable LCM's to get the correct session key again - upstream fix of LCM patch already- need upstream to give LCM the data now to filter out subs and junk:
https://github.com/Martian-Engineering/lossless-claw/releases/tag/v0.6.0

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: M and removed size: XS labels Apr 5, 2026
@100yenadmin
Copy link
Copy Markdown
Contributor Author

Review feedback addressed in commit 8374c2ef:

Greptile P2: silent error swallowing → Fixed. Added log.warn in catch block so resolution failures are visible.

Greptile P2: redundant fallback operand → Fixed. Simplified to use resolved/trimmed key flow.

Copilot: whitespace-only sessionKey propagation → Fixed. Now returns trimmed/resolved value, not original.

Copilot: misleading docstring → Fixed. Updated to accurately describe resolver behavior.

Codex P1: avoid forcing agent main key during backfill → Fixed. Resolver now uses sessionId alone, not agentId, so it does not bias toward agent:<agent>:explicit:... when lookup misses.

Copilot: no regression test → Fixed. Added tests for:

  • successful sessionIdsessionKey backfill
  • warning log emission when backfill resolution throws

All 8 review items addressed.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8374c2ef8f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Comment thread src/agents/pi-embedded-runner/run.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Comment thread src/agents/pi-embedded-runner/run.ts
Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Comment thread src/agents/pi-embedded-runner/run.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75ee14e23e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/pi-embedded-runner.e2e.test.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread src/agents/pi-embedded-runner/run.ts
Comment thread src/agents/pi-embedded-runner/run.ts
Comment thread src/agents/pi-embedded-runner.e2e.test.ts Outdated
Comment thread src/gateway/sessions-history-http.test.ts Outdated
@100yenadmin 100yenadmin force-pushed the fix/backfill-sessionkey-in-embedded-runner branch from 75ee14e to 77f56fd Compare April 5, 2026 21:05
@jalehman jalehman force-pushed the fix/backfill-sessionkey-in-embedded-runner branch from 77f56fd to e5ceffa Compare April 5, 2026 21:05
@jalehman jalehman force-pushed the fix/backfill-sessionkey-in-embedded-runner branch from 1354cda to 25fb6a4 Compare April 6, 2026 16:36
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25fb6a4d34

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +129 to +133
const resolved = params.agentId?.trim()
? resolveStoredSessionKeyForSessionId({
cfg: params.config,
sessionId: params.sessionId,
agentId: params.agentId,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fall back to explicit key when agent-store lookup misses

When agentId is present, backfillSessionKey only calls resolveStoredSessionKeyForSessionId, which returns undefined if the sessionId is not already in that store. For fresh agent-scoped runs (for example probe runs that create a new probe-<uuid> session ID), this leaves sessionKey unset and the downstream hooks/live-switch/error-context paths still see the same missing-key state this patch is trying to eliminate. Add a fallback (for example an explicit session key derived from sessionId) when the scoped lookup misses.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The backfill is intentionally best-effort — when the session store lookup misses (new probe session, fresh sessionId not yet persisted), returning undefined is the correct behavior. Synthesizing a fake session key from the sessionId would create a key that doesn't map to any real session in the store, which is worse than undefined — downstream consumers would attempt operations against a non-existent session. The undefined case is already handled gracefully: hooks skip the sessionKey field, model selection falls back to defaults, and error formatting omits the field. The fix ensures that sessions which DO exist in the store get their key resolved, which is the primary gap this PR addresses.

@jalehman jalehman force-pushed the fix/backfill-sessionkey-in-embedded-runner branch from 25fb6a4 to 078247b Compare April 6, 2026 16:43
@jalehman jalehman force-pushed the fix/backfill-sessionkey-in-embedded-runner branch from 078247b to 1720b53 Compare April 6, 2026 16:46
100yenadmin and others added 12 commits April 6, 2026 09:49
…mit it

When callers of runEmbeddedPiAgent() don't provide params.sessionKey,
the null value propagates to all downstream consumers: hooks, LCM
afterTurn(), and compaction flows.

This causes session_key = NULL in the LCM database, which breaks:
- ignoreSessionPatterns glob matching (Martian-Engineering/lossless-claw#176)
- Session-scoped compaction routing
- Any extension using sessionKey for session identification

Fix: resolve sessionKey from sessionId via resolveSessionKeyForRequest()
at the top of runEmbeddedPiAgent(), before any downstream consumer sees
it. Explicit sessionKey takes precedence (no behavior change for callers
that already provide it). Resolution failure is silently swallowed.

Fixes openclaw#60552
…whitespace

Review feedback from Greptile + Codex:

P1: Remove agentId from resolveSessionKeyForRequest() call to avoid
    resolveExplicitAgentSessionKey() binding one-off callers (model probes,
    etc.) to the agent main session. Now resolves purely by sessionId lookup.

P2: Replace silent catch with log.warn() using sanitizeForLog() so failed
    backfill attempts are diagnosable in production.

P2: Remove redundant ?? params.sessionKey fallback (unreachable after the
    early-return guard). Return undefined directly on failure.

P2: Normalize whitespace-only sessionKey values to undefined so downstream
    consumers never see '   ' as a valid key.
… path

- Revert shouldSwitchToLiveModel/clearLiveModelSwitchPending back to the
  original consumeLiveSessionModelSwitch API (cherry-pick artifact)
- Remove duplicate inner backfill block — outer backfillSessionKey() already
  sets params.sessionKey before this point, so the inner path was dead code
…w#60552

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply redactRunIdentifier to the sessionId in the backfillSessionKey
catch block to match the redaction pattern used elsewhere in the file.
Update the CHANGELOG entry for openclaw#60552 to describe both the sessionKey
backfill from sessionId and the whitespace normalization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jalehman jalehman force-pushed the fix/backfill-sessionkey-in-embedded-runner branch from 1720b53 to 8081345 Compare April 6, 2026 16:50
@jalehman jalehman merged commit 594ea6e into openclaw:main Apr 6, 2026
8 checks passed
@jalehman
Copy link
Copy Markdown
Contributor

jalehman commented Apr 6, 2026

Merged via squash.

Thanks @100yenadmin!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8081345f1c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +118 to +119
const selection = resolveSessionIdMatchSelection(
Object.entries(sessionStore).filter(([, entry]) => entry?.sessionId === sessionId),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Filter agent-scoped backfill matches by agent id

The new resolveStoredSessionKeyForSessionId() path only filters by sessionId, so when runEmbeddedPiAgent backfills with an agentId and session.store is configured as a shared file (no {agentId} segment), a duplicate sessionId from another agent can be selected as the winner. That binds the current run to the wrong session key, which can leak/pollute hook, live-switch, and compaction state across agents. Fresh evidence in this commit is that the new helper introduced for scoped backfill does not constrain candidate keys to the requested agent prefix before resolveSessionIdMatchSelection.

Useful? React with 👍 / 👎.

lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…ents undefined key in model selection and live-switch (openclaw#60555)

Merged via squash.

Prepared head SHA: 8081345
Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…ents undefined key in model selection and live-switch (openclaw#60555)

Merged via squash.

Prepared head SHA: 8081345
Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…ents undefined key in model selection and live-switch (openclaw#60555)

Merged via squash.

Prepared head SHA: 8081345
Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling gateway Gateway runtime size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(agents): runEmbeddedPiAgent/runEmbeddedAttempt blindly forward params.sessionKey — no backfill when omitted

3 participants