[Bug]: Native Codex subagents show the parent's reasoning effort instead of the one passed to spawn_agent#24435
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Start a Codex thread on
gpt-6.1-solwith reasoning effort set to Low. - Have the agent start a native subagent with Codex's
spawn_agentand an explicit effort, for example{"model":"gpt-6.1-sol","reasoning_effort":"xhigh","fork_turns":"none","message":"..."}. - Open the subagent's thread in T3. The subagent bar shows Low.
t3_thread_configurationfor the child thread also returnsreasoningEffort: "low". - Open the child's Codex rollout in
~/.codex/sessions/. Itsturn_contexthaseffort: "xhigh", and itsthread_settings_appliedevent hasreasoning_effort: "xhigh".
Expected behavior
The subagent shows the effort it runs at (Extra High here), or no effort until T3 knows it, as #15214 decided.
Actual behavior
The child thread shows the effort its parent had when it spawned the child, and ignores the reasoning_effort passed to spawn_agent. I checked three runs on the same day. All used gpt-6.1-sol for parent and children, and every child was spawned with reasoning_effort: "xhigh":
| Parent effort at spawn | T3 label on the child | Child rollout turn_context.effort |
|---|---|---|
| Low | Low | xhigh |
| Extra High | Extra High | xhigh |
| Low | Low (3 children) | xhigh |
Agents that check a child with t3_thread_configuration get the same wrong value. In my case the parent agent first told me the children ran at Low.
A read-only check of statev2.sqlite for the three children of the last run shows:
orchestration_v2_projection_threads: the child'smodelSelectionis the parent's,{"instanceId":"codex","model":"gpt-6.1-sol","options":[{"id":"reasoningEffort","value":"low"},{"id":"serviceTier","value":"default"}]}.orchestration_v2_projection_subagents:model: null,modelSelection: null.orchestration_v2_projection_provider_threads:nativeMetadata: null.
Likely cause
Code on main @ d53873b6a4. The same code is in v0.1.2.
registerSubagentThreadcreates the child thread with{ ...input.context.input.modelSelection, model: ... }(CodexAdapterV2.ts#L2894-L2897). This copies the parent'sreasoningEffortandserviceTieroptions into the child. Only the model is replaced.- An effort learned later, from
thread/settings/updatedor thethread/readrecovery, goes throughupdateSubagentSelectionandsubagent.updated. That updates only the subagent record (ProjectionStore.ts#L872). The child thread'smodelSelectionstays unchanged. - The subagent bar takes its label from
formatModelSelectionEffort(activeThread.modelSelection, ..., reportedModelSelection)(ChatView.tsx#L1694-L1701).getProviderOptionStatedValuereturns the thread's explicit option before any reported value (model.ts#L230-L239). So the copied parent effort wins, even when a reported value exists.
In this run the subagent records also got no selection at all. Their stored model is null, so the thread/read recovery at CodexAdapterV2.ts#L3031 should have run, but nothing was stored. The data I have doesn't show why.
A possible fix: don't copy the parent's effort options into a native child's selection. Use the spawn item's reasoningEffort when present, otherwise leave the effort unset, and update the child thread's selection when Codex reports the effort.
Related
- #17694 reported the same copy for a native Codex child with a different model and effort. It was closed as the same root cause as #15896.
- #15214 was closed after display support was verified on a delegated Codex child. Native Codex children weren't tested there.
- The open PRs #21493 and #17420 don't change this case. #21493 only adds the recovery when the model is known and the effort isn't, and it writes to the subagent record. #17420 reads the subagent record for subagent list rows, not for the child thread's bar.
- #24143 is the same kind of problem for Claude subagents.
Impact
Minor bug or occasional failure
Version or commit
T3 Code v0.1.2 (desktop). The same code is on main @ d53873b6a4.
Environment
Windows 11 Pro, T3 Code desktop v0.1.2, Codex CLI 0.164.0, gpt-6.1-sol
Logs or stack traces
| 1 | # Parent rollout, spawn call (excerpt, prompt shortened) |
| 2 | spawn_agent {"task_name":"..._a0001","fork_turns":"none","model":"gpt-6.1-sol","reasoning_effort":"xhigh","message":"..."} |
| 3 | |
| 4 | # Child rollout (excerpt) |
| 5 | {"type":"turn_context","payload":{"model":"gpt-6.1-sol","effort":"xhigh","collaboration_mode":{"settings":{"model":"gpt-6.1-sol","reasoning_effort":"xhigh"}}, ...}} |
| 6 | {"type":"event_msg","payload":{"type":"thread_settings_applied","thread_settings":{"model":"gpt-6.1-sol","reasoning_effort":"xhigh", ...}}} |
| 7 | |
| 8 | # t3_thread_configuration for the same child |
| 9 | {"modelSelection":{"instanceId":"codex","model":"gpt-6.1-sol","options":[{"id":"reasoningEffort","value":"low"},{"id":"serviceTier","value":"default"}]}} |
Screenshots, recordings, or supporting files
No response
Workaround
Before spawning, set the parent thread to the effort the children use. The child rollouts in ~/.codex/sessions/ show the effort the children actually ran at.