Skip to content

fix(subagent): resolve runtime model from subagent default instead of parent primary#72984

Open
joeykrug wants to merge 32 commits into
openclaw:mainfrom
joeykrug:fix/subagent-model-resolution
Open

fix(subagent): resolve runtime model from subagent default instead of parent primary#72984
joeykrug wants to merge 32 commits into
openclaw:mainfrom
joeykrug:fix/subagent-model-resolution

Conversation

@joeykrug

@joeykrug joeykrug commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Final upstream refresh

Exact head 29208668a6efa455ac9b407f5de4736c22b6b571 is a true merge containing the shared upstream cutoff 262baedcf7fa3d66dc35cce7d0253e0a31f0cc0e. The preceding focused head was fully green across CI, CodeQL, CodeQL Critical Quality, OpenGrep, Workflow Sanity, and iOS Periphery; fresh exact-head Actions are running after this merge-only synchronization.

Summary

Two-part fix for subagent model resolution:

  • Commit 1 — read-side fallback (defense in depth, fbbd3c2d5f): resolveSessionModelRef had no subagent awareness. When entry.model was empty (race between the spawn-side write and the gateway-side read at run-start), it fell through to resolveDefaultModelForAgent, returning the parent agent's primary model instead of the configured subagent default. Also reorders the ?? chain in resolveSubagentConfiguredModelSelection so global agents.defaults.subagents.model takes precedence over the spawning agent's own model field.
  • Commit 2 — Pi-harness write-side fix (production path, this commit): getReplyFromConfig resolved the run model via resolveDefaultModel (which goes through resolveDefaultModelForAgent and is not subagent-aware), and post-run persistence in updateSessionStoreAfterAgentRun then wrote that model back to entry.model, silently flipping every subagent run onto the parent agent's primary. The new resolveSubagentSessionDefaultModel helper performs a one-time override after sessionEntry is loaded so the Pi runtime boots on the configured subagent default and the post-run write preserves it.

Failure mode (before)

Config:

agents.list[main].model.primary = anthropic/claude-opus-4-7
agents.defaults.subagents.model.primary = openai-codex/gpt-5.5
agents.list[main].subagents.model.primary = openai-codex/gpt-5.5

Spawn flow:

  1. Parent calls sessions_spawn(task=..., agentId=main) with no explicit model:.
  2. Spawn-side computes the right ref (gpt-5.5) and writes entry.model / entry.modelProvider via persistInitialChildSessionRuntimeModel.
  3. The Pi runtime starts the run via getReplyFromConfig, which resolves defaultProvider/defaultModel via resolveDefaultModelForAgent — returning Opus (parent primary) — and uses that as the run's provider/model.
  4. Subagent runs on Opus instead of gpt-5.5.
  5. Post-run, updateSessionStoreAfterAgentRun → setSessionRuntimeModel writes Opus back to entry.model, clobbering the spawn-time gpt-5.5.

Result on disk: ~/.openclaw/agents/<agent>/sessions/sessions.json shows model: "claude-opus-4-7" for entries with subagentRole: "orchestrator", spawnDepth: 1, even though ~/.openclaw/subagents/runs.json correctly recorded gpt-5.5. The read-side fallback in commit 1 only kicks in while entry.model is empty — once the post-run write fires, entry.model is non-empty and the fallback is skipped.

Fix

  • Commit 1 — resolveSessionModelRef: when entry.spawnDepth >= 1 or entry.subagentRole is set, fall back to the configured subagent default for this agent before falling through to the agent's primary.
  • Commit 1 — resolveSubagentConfiguredModelSelection: reorder ?? chain to agentConfig.subagents.modelagents.defaults.subagents.modelagentConfig.model.
  • Commit 2 — resolveSubagentSessionDefaultModel: new helper in directive-handling.defaults.ts that, given the loaded sessionEntry, checks the same subagent shape (subagentRole set or spawnDepth >= 1) and resolves the configured subagent default. getReplyFromConfig invokes it once after sessionEntry is loaded and overrides defaultProvider/defaultModel/provider/model so the Pi runtime boots and post-run-persists on the right model.

Tests

  • Read-side fallback tests in src/gateway/session-utils.test.ts cover the runtime subagent fallback (with and without entry.spawnDepth).
  • Spawn-side chain-order tests cover the case where agentConfig.subagents.model is unset, agents.defaults.subagents.model is set, and agentConfig.model is set — we now return the global default instead of the agent's own primary.
  • New tests in src/auto-reply/reply/directive-handling.defaults.subagent.test.ts cover the Pi-harness write-side helper: subagent sessions resolve to the configured subagent default; non-subagent sessions return null so the parent's primary is preserved.
  • Existing get-reply test mocks updated to expose the new export.

Scope

Commit 1: src/gateway/session-utils.ts, src/agents/model-selection.ts, and their tests.
Commit 2: src/auto-reply/reply/directive-handling.defaults.ts, src/auto-reply/reply/get-reply.ts, and one new test plus two existing test-mock updates.
No drive-by changes.

Real behavior proof

  • Behavior or issue addressed: Spawned subagent runs persisted the parent agent's primary model (e.g. anthropic/claude-opus-4-7) into ~/.openclaw/agents/<agent>/sessions/sessions.json even though the configured subagent default was openai-codex/gpt-5.5 and the spawn-side resolver had already written the correct ref. Subsequent turns then ran on the wrong model.
  • Real environment tested: Local OpenClaw install on macOS, Node 22, single-agent config with agents.list[main].model.primary = anthropic/claude-opus-4-7, agents.defaults.subagents.model.primary = openai-codex/gpt-5.5, and agents.list[main].subagents.model.primary = openai-codex/gpt-5.5. Subagent spawned via sessions_spawn(task=..., agentId=main) from a parent Telegram chat with no explicit model: argument.
  • Exact steps or command run after this patch:
    1. pnpm openclaw doctor to confirm config parses cleanly.
    2. Start gateway: pnpm openclaw gateway start.
    3. From the active chat, ask the agent to spawn a subagent with no model override.
    4. While the subagent is running and again after it completes, inspect ~/.openclaw/agents/main/sessions/sessions.json and ~/.openclaw/subagents/runs.json.
  • Evidence after fix: Inspected ~/.openclaw/agents/main/sessions/sessions.json directly with jq — entries with subagentRole: "orchestrator" and spawnDepth: 1 now persist model: "gpt-5.5" and modelProvider: "openai-codex" instead of claude-opus-4-7. ~/.openclaw/subagents/runs.json continues to record gpt-5.5 as before, and the gateway run trace prints the openai-codex/gpt-5.5 provider/model pair when the run starts. Before the fix the same inspection printed model: "claude-opus-4-7" for those subagent entries even though the runs file recorded gpt-5.5.
  • Observed result after fix: Subagent runs boot on openai-codex/gpt-5.5 (visible in CLI run output and provider request logs), and the post-run write preserves that model in sessions.json, so subsequent turns of the same subagent session keep using gpt-5.5. Parent (non-subagent) sessions still resolve to anthropic/claude-opus-4-7 as expected.
  • What was not tested: Cross-agent configurations where the agent has no subagents.model and only agents.defaults.subagents.model is set were exercised only via the new unit tests, not on a live install. None of the alias-resolution paths were exercised against a real OpenRouter alias index live.

Post-rebase verification (2026-05-12)

Rebase merged upstream/main (e7e3e903bf) into the branch and addressed the clawsweeper P2 finding on src/auto-reply/reply/get-reply.ts:404-416. Specifically: a spawned subagent child entry with no own providerOverride/modelOverride could still inherit the parent session's persisted /model override via resolveStoredModelOverride (parent-inheritance branch), silently flipping the run back to the parent's model. resolveStoredModelOverride now skips the parent-inheritance branch when the child entry is a subagent session (subagentRole set or spawnDepth >= 1). Direct child overrides and non-subagent (topic/thread) child sessions are unaffected. New regression coverage in src/auto-reply/reply/stored-model-override.test.ts.

Commands run:

  • pnpm tsgo (core typecheck) -> exit 0, no diagnostics
  • pnpm test src/auto-reply/reply/stored-model-override.test.ts src/auto-reply/reply/directive-handling.defaults.subagent.test.ts src/agents/model-selection.test.ts src/gateway/session-utils.test.ts src/cron/isolated-agent.model-formatting.test.ts -> 4 vitest shards passed (236 tests)
  • pnpm test src/auto-reply/reply.block-streaming.test.ts -> passed (1 test)
  • pnpm format:check on touched files -> all clean after one auto-fix on stored-model-override.ts
  • node scripts/run-oxlint.mjs on touched files -> 0 warnings, 0 errors

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime agents Agent runtime and tooling size: S labels Apr 27, 2026
@greptile-apps

greptile-apps Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes a real spawn-time race condition: when the gateway reads a subagent's session entry before the model write has flushed, resolveSessionModelRef now correctly falls back to the configured subagent default instead of silently using the parent's primary model. The ?? chain reorder in resolveSubagentConfiguredModelSelection is intentional and aligns the runtime with documented semantics (agents.defaults.subagents.model as global subagent default), but it is a silent breaking change for any deployment that had agents.defaults.subagents.model configured while relying on per-agent primaries winning over it.

Confidence Score: 4/5

Safe to merge; the race-condition fix is correct and well-tested, with one intentional behavioral change worth calling out in release notes.

No logic errors or security issues found. The only concern is the precedence reorder in resolveSubagentConfiguredModelSelection which silently inverts the winner between agents.defaults.subagents.model and agentConfig.model for existing users — a P2 behavioral change that is documented as intentional but could surprise users on upgrade.

src/agents/model-selection.ts — the ?? chain reorder is the change most likely to affect existing deployments.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/model-selection.ts
Line: 244-248

Comment:
**Breaking precedence change for `agentConfig.model`**

After the reorder, any agent whose subagents relied on inheriting the agent's own primary model (no explicit `subagents.model` set on the agent, but a global `agents.defaults.subagents.model` does exist) will silently switch to the global default. Before this change `agentConfig.model` won over the global default; now it's the last resort. The behavior is documented as intentional, but it is a silent regression for that configuration pattern — users won't get a warning, and the previously-used model changes without any explicit action on their part.

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

Reviews (1): Last reviewed commit: "fix(subagent): resolve runtime model fro..." | Re-trigger Greptile

Comment thread src/agents/model-selection.ts Outdated
Comment on lines 244 to 248
return (
normalizeModelSelection(agentConfig?.subagents?.model) ??
normalizeModelSelection(agentConfig?.model) ??
normalizeModelSelection(params.cfg.agents?.defaults?.subagents?.model)
normalizeModelSelection(params.cfg.agents?.defaults?.subagents?.model) ??
normalizeModelSelection(agentConfig?.model)
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Breaking precedence change for agentConfig.model

After the reorder, any agent whose subagents relied on inheriting the agent's own primary model (no explicit subagents.model set on the agent, but a global agents.defaults.subagents.model does exist) will silently switch to the global default. Before this change agentConfig.model won over the global default; now it's the last resort. The behavior is documented as intentional, but it is a silent regression for that configuration pattern — users won't get a warning, and the previously-used model changes without any explicit action on their part.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/model-selection.ts
Line: 244-248

Comment:
**Breaking precedence change for `agentConfig.model`**

After the reorder, any agent whose subagents relied on inheriting the agent's own primary model (no explicit `subagents.model` set on the agent, but a global `agents.defaults.subagents.model` does exist) will silently switch to the global default. Before this change `agentConfig.model` won over the global default; now it's the last resort. The behavior is documented as intentional, but it is a silent regression for that configuration pattern — users won't get a warning, and the previously-used model changes without any explicit action on their part.

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

@joeykrug
joeykrug force-pushed the fix/subagent-model-resolution branch 2 times, most recently from 46612ec to 9d60b36 Compare April 27, 2026 20:22
@clawsweeper

clawsweeper Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 12, 2026, 12:13 AM ET / 04:13 UTC.

Summary
The PR makes spawned-subagent reply execution and session projections use configured subagent model policy, prevents inherited parent session model overrides from retargeting spawned children, and adds focused regression coverage.

PR surface: Source +113, Tests +202. Total +315 across 9 files.

Reproducibility: yes. at source level. Current main has separate spawn-selection, reply-default, parent-override, persistence, and projection paths, and the supplied real run demonstrates the resulting executed-versus-persisted model mismatch and its correction.

Review metrics: 1 noteworthy metric.

  • Model routing rules: 2 changed. The patch changes configured subagent fallback selection and parent-session override inheritance, both of which are upgrade-visible.

Stored data model
Persistent data-model change detected: serialized state: src/agents/session-model-ref.test.ts, serialized state: src/agents/session-model-ref.ts, unknown-data-model-change: src/agents/session-model-ref.test.ts, unknown-data-model-change: src/agents/session-model-ref.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #58822
Summary: This PR is the broader runtime and session-state candidate fix for the canonical subagent-default precedence issue; related PRs cover only subsets of the behavior.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] Existing spawned subagents that currently inherit a parent session’s interactive model override will instead follow configured subagent model policy after merge.
  • [P1] The precedence change can update persisted child session model state and route subsequent turns to a different provider, auth profile, pricing tier, or capability set.
  • [P1] The branch adds defensive policy resolution in reply and projection paths alongside the canonical spawn plan; future changes must keep those paths aligned to avoid another split source of truth.

Maintainer options:

  1. Confirm isolated subagent policy (recommended)
    A feature owner confirms that parent interactive overrides must not flow into spawned subagents, then exact-head CI can gate landing.
  2. Retain parent inheritance
    Remove the parent-inheritance guard and keep only the runtime clobber and incomplete-state fallback portions of the fix.

Next step before merge

  • [P2] A feature owner should decide the upgrade-visible parent-override inheritance contract; no remaining contributor-facing code repair is established.

Maintainer decision needed

  • Question: Should spawned subagents ignore the parent session’s interactive model override unless the child has its own direct override?
  • Rationale: Both precedence choices are technically coherent, but this choice changes existing user routing, persisted session behavior, and provider credentials after upgrade, so code review cannot safely infer product intent.
  • Likely owner: steipete — The broadest and most recent ownership trail spans the exact spawn, reply, and session-selection surfaces affected by this contract.
  • Options:
    • Isolate spawned subagents (recommended): Configured subagent policy wins, while only a direct child override may retarget the spawned child.
    • Preserve parent inheritance: A spawned child without its own direct override continues inheriting the parent session’s interactive model selection.

Security
Cleared: The focused TypeScript and test-only diff adds no dependency, workflow, permission, secret, artifact-download, or new supply-chain execution surface.

Review details

Best possible solution:

Treat the spawn plan’s persisted direct child selection as canonical across execution, persistence, and projections; retain the PR’s bounded fallback for incomplete child state, and encode the owner-approved parent-override rule in focused regression tests.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level. Current main has separate spawn-selection, reply-default, parent-override, persistence, and projection paths, and the supplied real run demonstrates the resulting executed-versus-persisted model mismatch and its correction.

Is this the best way to solve the issue?

Yes for the observable bug. The patch preserves higher-priority locks and direct overrides, but the ideal long-term shape is one canonical persisted spawn selection with recomputation limited to incomplete-state recovery.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 86b10ffb8e93.

Label changes

Label justifications:

  • P2: This is a bounded but user-visible correction to subagent model routing and persisted state with limited blast radius.
  • merge-risk: 🚨 compatibility: Existing spawned children may stop inheriting a parent-selected model after merge.
  • merge-risk: 🚨 session-state: The patch changes model values selected from and persisted into child session state.
  • merge-risk: 🚨 auth-provider: The precedence change can route child runs to a different provider and credential set.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR supplies after-fix real behavior evidence from a macOS install: a Telegram-triggered spawn, provider/model startup logs, and persisted child session and run-state inspection showing the configured subagent model executes and remains selected.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR supplies after-fix real behavior evidence from a macOS install: a Telegram-triggered spawn, provider/model startup logs, and persisted child session and run-state inspection showing the configured subagent model executes and remains selected.
Evidence reviewed

PR surface:

Source +113, Tests +202. Total +315 across 9 files.

View PR surface stats
Area Files Added Removed Net
Source 5 118 5 +113
Tests 4 202 0 +202
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 9 320 5 +315

What I checked:

  • Current-main spawn selection: Current main resolves a subagent model before launch and writes the selection plus override provenance into the child session patch, establishing the spawn plan as the intended selection source. (src/agents/subagent-spawn-plan.ts:53, 86b10ffb8e93)
  • Current-main runtime identity write: The spawn executor separately persists the selected provider/model as child runtime identity, but current reply startup still begins from the target agent default and can later consume a parent stored override. (src/agents/subagent-spawn.ts:361, 86b10ffb8e93)
  • PR reply-path ordering: The PR applies the subagent default only when the session is unlocked and heartbeat routing is absent, then preserves existing channel and direct stored override handling; direct child overrides therefore remain higher priority. (src/auto-reply/reply/get-reply.ts:547, e91c37f91b8c)
  • PR parent-inheritance boundary: The changed stored override resolver keeps a direct child override first, then prevents only spawned subagents from falling through to a parent session override. (src/auto-reply/reply/stored-model-override.ts:44, e91c37f91b8c)
  • Merged related fix is partial: Commit 2b04ced merged the spawn-planning precedence fix from Fix subagent default model precedence #81783, but its changed surface does not include the reply startup, parent override, or session projection paths changed here. (src/agents/model-selection.ts:1, 2b04cedfb131)
  • Re-review continuity: The only source change since the prior reviewed head is unrelated current-main synchronization in get-reply session initialization and reset-hook arguments; the previously cleared subagent changes are unchanged. (src/auto-reply/reply/get-reply.ts:493, e91c37f91b8c)

Likely related people:

  • steipete: Has the broadest and most recent history across the exact spawn, reply, session-state, and model-selection surfaces, including the spawn-plan extraction and active-session preservation work. (role: recent area contributor; confidence: high; commits: 7b36fa76726a, 9f09001014f8; files: src/agents/subagent-spawn-plan.ts, src/agents/subagent-spawn.ts, src/auto-reply/reply/get-reply.ts)
  • joshavant: Authored the merged change that made the global configured subagent default win during spawn planning and preserved model-scoped runtime selection. (role: introduced current precedence behavior; confidence: high; commits: 2b04cedfb131; files: src/agents/model-selection.ts, src/agents/model-selection.test.ts)
  • gumadeiras: Reviewed the earlier merged subagent model-display and selection work that shaped the current model-selection path. (role: reviewer and adjacent owner; confidence: medium; commits: 5c69e625f58d; files: src/agents/model-selection.ts, src/agents/subagent-spawn.ts)
  • vincentkoc: Has sustained contribution history in the central reply and session-selection files and is a plausible secondary reviewer for state precedence behavior. (role: recent session and reply contributor; confidence: medium; files: src/auto-reply/reply/get-reply.ts, src/auto-reply/reply/stored-model-override.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (2 earlier review cycles)
  • reviewed 2026-07-03T09:53:59.965Z sha d681e69 :: needs changes before merge. :: [P2] Keep subagent alias resolution on the static path | [P2] Preserve static alias policy after switching defaults | [P2] Forward gateway normalization options into the fallback
  • reviewed 2026-07-11T20:38:41.981Z sha 2920866 :: needs maintainer review before merge. :: none

joeykrug added 6 commits May 10, 2026 00:42
… parent primary

`resolveSessionModelRef` had no subagent awareness — when `entry.model` was
empty (race between spawn-side write and gateway read), it fell through to
`resolveDefaultModelForAgent`, returning the parent agent's primary model
instead of the configured subagent default.

Also reorder the `??` chain in `resolveSubagentConfiguredModelSelection`:
global `agents.defaults.subagents.model` now takes precedence over the
spawning agent's own `model` field, matching the documented behavior.

Tests cover both the runtime fallback and the spawn-time chain order.
The Pi runtime harness initialization writes the parent agent's
primary model into the child session entry, overwriting the value
that `resolveSubagentSpawnModelSelection` correctly resolved during
spawn. This was the production failure mode covered up by the
read-side fallback in fbbd3c2d5f.

When `entry.subagentRole` is set or `entry.spawnDepth >= 1`, prefer
`agents.list[<id>].subagents.model.primary` (with the standard chain
fallbacks via `resolveSubagentConfiguredModelSelection`) over the
parent agent's primary `model.primary`.

`getReplyFromConfig` resolved the run model via `resolveDefaultModel`
(which goes through `resolveDefaultModelForAgent` and is not
subagent-aware), and then post-run persistence in
`updateSessionStoreAfterAgentRun` wrote that model back to
`entry.model`, silently flipping every subagent run onto the parent
agent's primary. The new `resolveSubagentSessionDefaultModel` helper
performs a one-time override after `sessionEntry` is loaded so the Pi
runtime boots on the configured subagent default and the post-run
write preserves it.

Tests cover the subagent path and a sanity assertion that
non-subagent sessions still inherit the parent's primary.
Main re-introduced the inline 'type Command' export after the prior fix
extracted it to a separate 'export type { Command }' line; the merge kept
both, causing TS2300 'Duplicate identifier' under the extension package
boundary tsc compile. Keep only the inline form (consistent with main).
The reply-time fallback (resolveSubagentSessionDefaultModel) and the
gateway-side fallback (resolveSessionModelRef) both fed the configured
subagent selection straight into parseModelRef, so a configured alias
such as 'gpt' was parsed as a bare model under the default provider
instead of being resolved through agents.defaults.models. That made the
race fallback disagree with resolveSubagentSpawnModelSelection, which
already runs alias resolution.

Switch both helpers to resolveModelRefFromString with a buildModelAliasIndex
alias index built from the same default provider, matching the spawn-side
contract. Adds regression tests in both files (configured subagent alias
'gpt' resolves to openai/gpt-5.4) and a CHANGELOG entry.
@joeykrug
joeykrug force-pushed the fix/subagent-model-resolution branch from 63c26bd to b45a2f4 Compare May 10, 2026 04:47
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed extensions: memory-core Extension: memory-core labels May 10, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 22, 2026
joeykrug and others added 2 commits June 3, 2026 00:59
…icts

Resolve 5 conflicts preserving the subagent-model-resolution feature while
adopting upstream's refactors:
- get-reply.ts: keep the subagent-default boot block on upstream's
  timing-wrapped resolver; defaultProvider/defaultModel/aliasIndex become
  let-bound so the subagent block can reassign them.
- model-selection.ts / model-selection-resolve.ts / cron run-model-selection
  aggregator: adopt upstream's canonical resolveSubagentConfiguredModelSelection
  (same subagents.model -> defaults.subagents.model -> agent primary precedence
  the PR introduced, plus upstream's includeAgentPrimary knob); drop the now-stale
  resolve-file import/re-exports.
- transport-stream.ts, preaction.test.ts, embedded-agent-runner/runs.test.ts:
  take upstream's unrelated churn (Gemini signature payload helper, programLocal
  rename, file rename + new imports).

Finding: ClawSweeper's image-model one-turn override precedence defect is moot
after this merge -- upstream commit 55a0c9b removed the image-model override
plumbing (opts.modelOverride / hasAppliedImageModelOverride) from get-reply.ts
entirely. The surviving one-turn override is the heartbeat override, which the
subagent-default block already gates on (!hasResolvedHeartbeatModelOverride).
Added a focused regression in directive-handling.defaults.subagent.test.ts
pinning that gating: a resolved one-turn override wins and the subagent default
does not clobber it, while an ordinary subagent turn applies the subagent default.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. label Jun 3, 2026
joeykrug and others added 4 commits June 3, 2026 01:42
The branch's prior main-merges caused git merge to silently revert unrelated
upstream files (import-sort churn) in two files the PR never intended to touch:
- extensions/memory-wiki/src/tool.test.ts
- src/flows/doctor-lint-flow.ts

Restore both to upstream/main so check-dependencies / build-artifacts pass,
leaving only the PR's real subagent-model-resolution changes in the net diff.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
# Conflicts:
#	src/auto-reply/reply/stored-model-override.ts

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

Copy link
Copy Markdown
Contributor Author

Final shared-upstream synchronization is on exact head 29208668a6efa455ac9b407f5de4736c22b6b571, a true merge containing cutoff 262baedcf7fa3d66dc35cce7d0253e0a31f0cc0e and all three static-normalization repairs.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant