Skip to content

Cannot overwrite subagent's model when spawning via LLM #22250

@breezewish

Description

@breezewish

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.506.31421 (2620)

What subscription do you have?

Pro 20x

What platform is your computer?

Linux 6.17.0-1010-aws aarch64 aarch64 (Codex App + Connection)

What issue are you seeing?

(issue is summarized via codex)

When calling spawn_agent with both agent_type and an explicit model, the spawned subagent run with the parent/default configured model instead of the requested model.

What steps can reproduce the bug?

Given a global config like:

model = "gpt-5.4"

[agents.potter_worker]
description = "Worker role"
config_file = "./agents/potter_worker.toml"

And ~/.codex/agents/potter_worker.toml contains role instructions but no model field.

Then spawn an agent with:

{
  "agent_type": "potter_worker",
  "message": "Work according to this handoff file: ...",
  "model": "gpt-5.2",
  "reasoning_effort": "xhigh"
}

Expected behavior

The spawned subagent should run with:

model: gpt-5.2
reasoning effort: xhigh

Actual behavior

The spawned subagent runs with the configured default model, for example:

model: gpt-5.4
reasoning effort: xhigh

The parent rollout records the spawn_agent function call with "model":"gpt-5.2", but the child rollout turn_context records "model":"gpt-5.4".

Root cause

The v1 spawn_agent handler applies requested model overrides before applying the role:

apply_requested_spawn_agent_model_overrides(...);
apply_role_to_config(&mut config, role_name).await?;

However, apply_role_to_config rebuilds the config using the config layer stack:

Config::load_config_with_layer_stack(
    ...,
    reload_overrides(config, preserve_current_provider),
    ...
)

The reload_overrides helper preserves some runtime fields such as cwd and model provider, but it does not preserve config.model or config.model_reasoning_effort. During config loading, the final model is resolved from:

model override -> active profile model -> config.toml model

Because the requested spawn model is not passed as a config override, it is lost unless the role TOML itself explicitly sets model.

Impact

This makes the model argument on spawn_agent unreliable for role-based agents. Callers can believe they started a subagent with one model while the actual thread runs with another. This is especially confusing for orchestrators that intentionally alternate models across rounds.

It also makes the spawn result misleading: the request contains the desired model, but the actual child thread must be inspected through turn_context to know what really ran.

Suggested fix

When applying a role that does not explicitly set model or model_reasoning_effort, preserve the already-applied requested spawn overrides through the role config reload.

Concretely, reload_overrides or the role application path should carry forward the current in-memory config.model and config.model_reasoning_effort unless the role layer explicitly owns those fields.

Existing behavior where a role config explicitly declares model should continue to override the requested model.

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingconfigIssues involving config.toml, config keys, config merging, or config updatessubagentIssues involving subagents or multi-agent features

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions