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.
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_agentwith bothagent_typeand an explicitmodel, 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:
And
~/.codex/agents/potter_worker.tomlcontains role instructions but nomodelfield.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:
Actual behavior
The spawned subagent runs with the configured default model, for example:
The parent rollout records the
spawn_agentfunction call with"model":"gpt-5.2", but the child rolloutturn_contextrecords"model":"gpt-5.4".Root cause
The v1
spawn_agenthandler applies requested model overrides before applying the role:However,
apply_role_to_configrebuilds the config using the config layer stack:The
reload_overrideshelper preserves some runtime fields such as cwd and model provider, but it does not preserveconfig.modelorconfig.model_reasoning_effort. During config loading, the final model is resolved from: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
modelargument onspawn_agentunreliable 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_contextto know what really ran.Suggested fix
When applying a role that does not explicitly set
modelormodel_reasoning_effort, preserve the already-applied requested spawn overrides through the role config reload.Concretely,
reload_overridesor the role application path should carry forward the current in-memoryconfig.modelandconfig.model_reasoning_effortunless the role layer explicitly owns those fields.Existing behavior where a role config explicitly declares
modelshould continue to override the requested model.