fix(cron): reuse existing sessionId for webhook/cron sessions#18031
fix(cron): reuse existing sessionId for webhook/cron sessions#18031steipete merged 2 commits intoopenclaw:mainfrom
Conversation
When a webhook or cron job provides a stable sessionKey, the session should maintain conversation history across invocations. Previously, resolveCronSession always generated a new sessionId and hardcoded isNewSession: true, preventing any conversation continuity. Changes: - Check if existing entry has a valid sessionId - Evaluate freshness using configured reset policy - Reuse sessionId and set isNewSession: false when fresh - Add forceNew parameter to override reuse behavior - Spread existing entry to preserve conversation context This enables persistent, stateful conversations for webhook-driven agent endpoints when allowRequestSessionKey is configured. Fixes openclaw#18027
| @@ -34,5 +79,5 @@ export function resolveCronSession(params: { | |||
| displayName: entry?.displayName, | |||
| skillsSnapshot: entry?.skillsSnapshot, | |||
| }; | |||
There was a problem hiding this comment.
redundant field assignments overwrite spread values
When isNewSession is false, line 63 spreads all fields from entry, but lines 68-80 then re-assign many of those same fields using entry?.field. This is redundant and could cause confusion - the spread already copied all fields.
| const sessionEntry: SessionEntry = { | |
| // Spread existing entry to preserve conversation context when reusing | |
| ...(isNewSession ? undefined : entry), | |
| // Always update these core fields | |
| sessionId, | |
| updatedAt: params.nowMs, | |
| systemSent, | |
| }; |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cron/isolated-agent/session.ts
Line: 61:81
Comment:
redundant field assignments overwrite spread values
When `isNewSession` is `false`, line 63 spreads all fields from `entry`, but lines 68-80 then re-assign many of those same fields using `entry?.field`. This is redundant and could cause confusion - the spread already copied all fields.
```suggestion
const sessionEntry: SessionEntry = {
// Spread existing entry to preserve conversation context when reusing
...(isNewSession ? undefined : entry),
// Always update these core fields
sessionId,
updatedAt: params.nowMs,
systemSent,
};
```
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Good catch! You're right — the spread already copies those fields when reusing an existing session. Pushed a fix that removes the redundant assignments. Thanks for the review!
Addresses Greptile review comment: when !isNewSession, the spread already copies all entry fields. The explicit entry?.field assignments were redundant and could cause confusion. Simplified to only override the core fields (sessionId, updatedAt, systemSent).
|
forceNew parameter is completely dead - not configurable anywhere. Now, every cron session is forced to use a shared session, which burns tokens...changing the default behavior and even without any configurability is not very smart. check #20092 |
) Adds a `sessionFreshness` field to `CronJob` with two values: - `"reuse-if-fresh"` (default, existing behavior) - `"always-new"` (forces a new session UUID on every run) When set to `"always-new"`, each isolated cron run gets a fresh session with no accumulated context from prior runs, fixing the contradiction between docs and PR openclaw#18031 behavior.
) Adds a `sessionFreshness` field to `CronJob` with two values: - `"reuse-if-fresh"` (default, existing behavior) - `"always-new"` (forces a new session UUID on every run) When set to `"always-new"`, each isolated cron run gets a fresh session with no accumulated context from prior runs, fixing the contradiction between docs and PR openclaw#18031 behavior.
Summary
allowRequestSessionKeyis configured. Conversation history is never preserved.resolveCronSessionnow checks for existing session entries, evaluates freshness, and reusessessionIdwhen appropriateChange Type
Scope
Linked Issue/PR
User-visible / Behavior Changes
Webhook and cron job sessions now properly maintain conversation history when:
hooks.allowRequestSessionKey: trueis configuredsessionKeyis provided across invocationsPrevious behavior: Every invocation started fresh (isNewSession: true)
New behavior: Reuses existing session when fresh (isNewSession: false)
Security Impact
Repro + Verification
Environment
Steps
hooks.allowRequestSessionKey: true/hooks/agenttwice with samesessionKeyExpected
Webhook sessions preserve conversation history across calls
Actual
Implemented as expected. Session freshness evaluated per reset policy.
Evidence
session.test.tsHuman Verification
Verified scenarios:
Root cause analysis:
resolveCronSessionhardcodedconst sessionId = crypto.randomUUID()unconditionallyisNewSession: trueCompatibility / Migration
allowRequestSessionKeyconfigRisks and Mitigations
evaluateSessionFreshnessas other channels, respects configuredidleMinutes/dailyresetGreptile Summary
Fixed webhook/cron sessions to properly reuse existing
sessionIdwhenallowRequestSessionKeyis configured and the session is still fresh, enabling stateful conversations across webhook invocations.Key changes:
evaluateSessionFreshnessandresolveSessionResetPolicyresolveCronSessionnow checks for existing sessions and reusessessionIdwhen appropriate (not stale, not forced new)forceNewoverride, and missingsessionIdhandlingisNewSession: falsewhen reusing, allowing conversation history to persistThe implementation correctly addresses the root cause where
sessionIdwas previously hardcoded to always generate a new UUID. The fix uses the same session reset policy evaluation ("direct"type) that other channels use, ensuring consistent behavior across the platform.Confidence Score: 4/5
Last reviewed commit: 7d54a1a