Skip to content

fix(agents): resolve model aliases in sessions_spawn#59681

Merged
vincentkoc merged 3 commits into
openclaw:mainfrom
HowdyDooToYou:fix/subagent-spawn-alias-resolution
Apr 27, 2026
Merged

fix(agents): resolve model aliases in sessions_spawn#59681
vincentkoc merged 3 commits into
openclaw:mainfrom
HowdyDooToYou:fix/subagent-spawn-alias-resolution

Conversation

@HowdyDooToYou

Copy link
Copy Markdown
Contributor

Summary:

resolveSubagentSpawnModelSelection() uses normalizeModelSelection() to process the model override — but that function only trims the string. It never checks the configured model alias index. When a user passes an alias like "opus" or "gpt" to sessions_spawn, the child session gets patched with the raw alias string, which the gateway cannot resolve to any provider. The child session dies immediately.

Changes:

Added resolveModelThroughAliases() helper in src/agents/model-selection.ts that checks bare strings against buildModelAliasIndex. Already-qualified provider/model refs and unknown strings pass through unchanged.
Modified resolveSubagentSpawnModelSelection() to pass its result through resolveModelThroughAliases() before returning.

Test plan:
4 new tests in model-selection.test.ts:
Alias override resolves to full provider/model ref
Configured subagent model alias resolves
Already-qualified refs pass through unchanged
Falls back to runtime default when no override
All 9 existing spawn model tests pass
pnpm tsgo — clean
Pre-commit hooks pass (lint, typecheck, conflict markers)

Fixes #57532
Refs #50736

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

greptile-apps Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a real bug where passing a user-defined model alias (e.g. "opus" or "gpt") to sessions_spawn produced a raw, unresolved string that the gateway couldn't route, causing the child session to die immediately. The fix is straightforward and well-scoped: a private resolveModelThroughAliases() helper is inserted at the end of resolveSubagentSpawnModelSelection(), consulting buildModelAliasIndex (the same mechanism already used by resolveConfiguredModelRef and resolveAllowedModelRef) to expand bare alias strings into fully-qualified provider/model references.

Key observations:

  • The logic is correct — the helper correctly short-circuits for already-qualified refs (value.includes("/")), resolves known aliases, and passes unknown bare strings through unchanged, matching the behaviour described in the PR description.
  • Four new test cases provide good coverage of the happy path (alias override, configured subagent alias, qualified pass-through, and runtime-default fallback).
  • Two minor style/performance concerns: the ?? raw fallback at the call site is unreachable (since raw is always a non-empty string), and buildModelAliasIndex is now built twice per spawn call. Neither is a correctness issue.

Confidence Score: 4/5

  • Safe to merge — the fix is isolated, the logic is correct, and all existing tests continue to pass.
  • The change is small and well-tested. The only concerns are two non-critical style issues: a dead ?? raw fallback and a redundant buildModelAliasIndex call. No correctness, security, or runtime-breaking issues were found.
  • No files require special attention beyond the minor style notes on src/agents/model-selection.ts.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/model-selection.ts
Line: 522

Comment:
**Dead fallback `?? raw` is unreachable**

`raw` is produced by a `??`-chain whose final branch is the always-non-empty string `\`${runtimeDefault.provider}/${runtimeDefault.model}\``. Because `raw` can never be falsy, `resolveModelThroughAliases` will never hit its `if (!value) return undefined` guard, so the `?? raw` at the end of the return statement can never be evaluated.

This is harmless today, but it creates a misleading implication that the function could return `undefined` for a non-empty `raw`, which may confuse future maintainers. Consider adjusting the helper's return type to `string` when `value` is guaranteed non-empty — or, at minimum, add a comment documenting why the fallback exists (purely as a type-safety net, not reachable at runtime).

```suggestion
  return resolveModelThroughAliases(raw, params.cfg) ?? /* unreachable; raw is always non-empty */ raw;
```

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/model-selection.ts
Line: 493-496

Comment:
**Alias index rebuilt on every call**

`buildModelAliasIndex` iterates over `cfg.agents?.defaults?.models` each time it is called. `resolveSubagentSpawnModelSelection` already calls `resolveDefaultModelForAgent``resolveConfiguredModelRef``buildModelAliasIndex`, so the index is built at least twice per spawn call (once in `resolveDefaultModelForAgent`, once here).

For a hot spawn path this is wasted work. Consider accepting a pre-built `ModelAliasIndex` as an optional parameter (matching the pattern already used in `resolveModelRefFromString` and `resolveAllowedModelRef`), or building the index once in `resolveSubagentSpawnModelSelection` and passing it down.

```ts
// Example signature change
function resolveModelThroughAliases(
  value: string | undefined,
  cfg: OpenClawConfig,
  aliasIndex?: ModelAliasIndex,   // accept pre-built index
): string | undefined {
  // ...
  const index = aliasIndex ?? buildModelAliasIndex({ cfg, defaultProvider: DEFAULT_PROVIDER });
  // ...
}
```

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

Reviews (1): Last reviewed commit: "fix(agents): resolve model aliases in se..." | Re-trigger Greptile

Comment thread src/agents/model-selection.ts Outdated
Comment thread src/agents/model-selection.ts Outdated

@martingarramon martingarramon left a comment

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.

Clean fix — the alias resolution logic is straightforward and the tests cover the main paths well.

One question: what's the expected behavior when modelOverride is a bare string that isn't a configured alias? Currently resolveModelThroughAliases returns it unchanged, so the gateway would get something like "typo-model" and presumably fail. Is that the right failure mode, or should this surface an error earlier (e.g., during spawn validation)?

@HowdyDooToYou

Copy link
Copy Markdown
Contributor Author

@martingarramon

Clean fix — the alias resolution logic is straightforward and the tests cover the main paths well.

One question: what's the expected behavior when modelOverride is a bare string that isn't a configured alias? Currently resolveModelThroughAliases returns it unchanged, so the gateway would get something like "typo-model" and presumably fail. Is that the right failure mode, or should this surface an error earlier (e.g., during spawn validation)?

Passing unknown strings through unchanged is intentional — it matches how resolveConfiguredModelRef and resolveAllowedModelRef already handle unrecognized values elsewhere in the codebase. The gateway's model routing layer is the right place to surface "unknown model" errors because it has the full provider catalog context to produce a useful diagnostic (e.g., "did you mean X?"). Adding validation at the spawn layer would duplicate that logic and create a second error surface to maintain.

TL;DR: fail late at the routing layer where the error message seems better, not early at spawn where we'd just say "unknown model."

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

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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 054243d0e9

ℹ️ 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/model-selection.ts Outdated
Comment thread src/agents/model-selection.ts Outdated
@martingarramon

Copy link
Copy Markdown
Contributor

Makes sense — matches the pattern. LGTM.

@HowdyDooToYou

HowdyDooToYou commented Apr 19, 2026

Copy link
Copy Markdown
Contributor Author

Makes sense — matches the pattern. LGTM.

@martingarramon - Thanks! I've addressed the Codex P1/P2 feedback in a follow-up PR:

Seems ready to merge.

HowdyDooToYou and others added 3 commits April 27, 2026 22:34
normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes #57532
Refs #50736
- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]
@vincentkoc
vincentkoc force-pushed the fix/subagent-spawn-alias-resolution branch from 054243d to da9c613 Compare April 27, 2026 22:40
@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish pushed a narrow repair to this branch so the original contributor path can stay canonical.

Source PR: #59681
Validation: pnpm -s vitest run src/agents/model-selection.test.ts; pnpm check:changed
Contributor credit is preserved in the branch history and PR context.

@vincentkoc
vincentkoc merged commit 3230305 into openclaw:main Apr 27, 2026
66 checks passed
@vincentkoc vincentkoc added the clawsweeper Tracked by ClawSweeper automation label Apr 27, 2026
@HowdyDooToYou
HowdyDooToYou deleted the fix/subagent-spawn-alias-resolution branch April 29, 2026 16:55
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes openclaw#57532
Refs openclaw#50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <[email protected]>
Co-authored-by: vincentkoc <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes openclaw#57532
Refs openclaw#50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <[email protected]>
Co-authored-by: vincentkoc <[email protected]>
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes openclaw#57532
Refs openclaw#50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <[email protected]>
Co-authored-by: vincentkoc <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes openclaw#57532
Refs openclaw#50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <[email protected]>
Co-authored-by: vincentkoc <[email protected]>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes openclaw#57532
Refs openclaw#50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <[email protected]>
Co-authored-by: vincentkoc <[email protected]>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes openclaw#57532
Refs openclaw#50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <[email protected]>
Co-authored-by: vincentkoc <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling clawsweeper Tracked by ClawSweeper automation size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sessions_spawn model param does not resolve aliases

3 participants