fix: prefer queued.run.agentId over session key parsing for model fallback resolution#24137
Closed
derricksy wants to merge 1 commit intoopenclaw:mainfrom
Closed
fix: prefer queued.run.agentId over session key parsing for model fallback resolution#24137derricksy wants to merge 1 commit intoopenclaw:mainfrom
derricksy wants to merge 1 commit intoopenclaw:mainfrom
Conversation
| @@ -133,7 +133,7 @@ export function createFollowupRunner(params: { | |||
| agentDir: queued.run.agentDir, | |||
| fallbacksOverride: resolveAgentModelFallbacksOverride( | |||
| queued.run.config, | |||
| resolveAgentIdFromSessionKey(queued.run.sessionKey), | |||
| queued.run.agentId ?? resolveAgentIdFromSessionKey(queued.run.sessionKey), | |||
Contributor
There was a problem hiding this comment.
Incomplete fix - same pattern exists in agent-runner-utils.ts. The resolveModelFallbackOptions function at src/auto-reply/reply/agent-runner-utils.ts:140-151 still uses resolveAgentIdFromSessionKey(run.sessionKey) without preferring run.agentId. This function is called by agent-runner-execution.ts:173 and agent-runner-memory.ts:100, so those code paths will still have the fallback issue.
Apply the same fix there:
export function resolveModelFallbackOptions(run: FollowupRun["run"]) {
return {
cfg: run.config,
provider: run.provider,
model: run.model,
agentDir: run.agentDir,
fallbacksOverride: resolveAgentModelFallbacksOverride(
run.config,
run.agentId ?? resolveAgentIdFromSessionKey(run.sessionKey),
),
};
}Prompt To Fix With AI
This is a comment left during a code review.
Path: src/auto-reply/reply/followup-runner.ts
Line: 136
Comment:
Incomplete fix - same pattern exists in `agent-runner-utils.ts`. The `resolveModelFallbackOptions` function at `src/auto-reply/reply/agent-runner-utils.ts:140-151` still uses `resolveAgentIdFromSessionKey(run.sessionKey)` without preferring `run.agentId`. This function is called by `agent-runner-execution.ts:173` and `agent-runner-memory.ts:100`, so those code paths will still have the fallback issue.
Apply the same fix there:
```typescript
export function resolveModelFallbackOptions(run: FollowupRun["run"]) {
return {
cfg: run.config,
provider: run.provider,
model: run.model,
agentDir: run.agentDir,
fallbacksOverride: resolveAgentModelFallbacksOverride(
run.config,
run.agentId ?? resolveAgentIdFromSessionKey(run.sessionKey),
),
};
}
```
How can I resolve this? If you propose a fix, please make it concise.b0d7cac to
eb6888f
Compare
…lback resolution When a subagent spawned via sessions_spawn hits a rate limit, the model fallback chain fails to trigger because the fallbacksOverride is resolved using resolveAgentIdFromSessionKey(queued.run.sessionKey), which requires the session key to be in 'agent:<agentId>:<rest>' format. If the session key is absent, undefined, or in an unexpected format, resolveAgentIdFromSessionKey falls back to DEFAULT_AGENT_ID (main agent), which typically has no fallbacks configured — resulting in a single-candidate array and no model fallback. queued.run.agentId is already explicitly set on the run object (it is passed directly to runEmbeddedPiAgent three lines below this call), making the session key string-parsing approach redundant and fragile. Fix: prefer queued.run.agentId directly, falling back to session key parsing only when agentId is absent. Fixes: resolves the symptom reported in openclaw#24102 Related: openclaw#11972, openclaw#19249, openclaw#5744
eb6888f to
46102a7
Compare
Contributor
|
Closing this one as not needed in current flow. Reasoning:
If we still want defensive hardening, we can do a tiny clean follow-up with only:
for readability/safety, no behavior change intended in normal paths. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a subagent spawned via `sessions_spawn` hits a rate limit or quota error, the configured `model.fallbacks` chain does not trigger. The agent retries the same primary model repeatedly and fails permanently instead of falling back to the next model.
Root Cause
In two places, the queue/followup runner resolves the agent ID for fallback lookup by parsing it from the session key string:
```ts
// src/auto-reply/reply/followup-runner.ts
fallbacksOverride: resolveAgentModelFallbacksOverride(
queued.run.config,
resolveAgentIdFromSessionKey(queued.run.sessionKey), // ← brittle
)
// src/auto-reply/reply/agent-runner-utils.ts
fallbacksOverride: resolveAgentModelFallbacksOverride(
run.config,
resolveAgentIdFromSessionKey(run.sessionKey), // ← same issue
)
```
`resolveAgentIdFromSessionKey` calls `parseAgentSessionKey`, which requires the format `agent::`. If `sessionKey` is absent, undefined, or in an unexpected format, it falls back to `DEFAULT_AGENT_ID` (the main agent). The main agent typically has no fallbacks configured, so `resolveFallbackCandidates` builds a single-entry candidates array — and the fallback chain never fires.
Both `queued.run.agentId` and `run.agentId` are already explicitly set on the run object (passed directly to `runEmbeddedPiAgent` in the same call site), making the string-parsing approach redundant and fragile.
Fix
Prefer the explicit `agentId` field directly, falling back to session key parsing only when it's absent:
```ts
// followup-runner.ts
fallbacksOverride: resolveAgentModelFallbacksOverride(
queued.run.config,
queued.run.agentId ?? resolveAgentIdFromSessionKey(queued.run.sessionKey),
)
// agent-runner-utils.ts
fallbacksOverride: resolveAgentModelFallbacksOverride(
run.config,
run.agentId ?? resolveAgentIdFromSessionKey(run.sessionKey),
)
```
Verification
Reproduction
Related Issues
Possibly related to #11972, #19249, #5744. Addresses symptom reported in #24102.
OpenClaw version tested
2026.2.17 (macOS 14.x, npm global install)