Skip to content

MultiAgentV2 spawn_agent defaults to full-history fork, rejecting agent_type/model overrides #20077

Open

Description

@iharc-jordan

What variant of Codex are you using?

Codex Desktop with MultiAgentV2 enabled.

What happened?

With MultiAgentV2 enabled, spawn_agent defaults to a full-history fork when fork_turns is omitted. Full-history forks reject agent_type, model, and reasoning_effort overrides.

That makes the natural/default call shape for a specialized subagent fail:

{
  "agent_type": "domain_expert",
  "task_name": "domain_expert_default_fork_probe",
  "message": "Probe task: reply with exactly one sentence saying whether you started successfully."
}

Observed error:

Full-history forked agents inherit the parent agent type, model, and reasoning effort; omit agent_type, model, and reasoning_effort, or spawn without a full-history fork.

The same failure occurs for built-in roles such as explorer and worker when fork_turns is omitted. This is not specific to domain_expert; it is the MultiAgentV2 default fork behavior interacting with role/model/reasoning overrides.

Expected behavior

One of these should be true:

  1. spawn_agent(agent_type=...) should default to a fork mode compatible with role/model/reasoning overrides.
  2. The tool schema/docs should explicitly state that agent_type, model, or reasoning_effort require fork_turns: "none" or another non-full-history mode.
  3. MultiAgentV2 should support full-history context plus a different child role/model/reasoning configuration, since "same context, specialized child" is a common multi-agent workflow.

Actual behavior

fork_turns is optional, but omission means "all", which maps to SpawnAgentForkMode::FullHistory. In that mode, MultiAgentV2 rejects overrides.

Current implementation appears to do this in codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs:

  • fork_turns.unwrap_or("all")
  • "all" maps to SpawnAgentForkMode::FullHistory
  • full-history mode calls reject_full_fork_spawn_overrides(role_name, model, reasoning_effort)

So a model following the visible spawn_agent schema can easily produce a rejected tool call by combining the default fork mode with an explicit agent_type.

Reproduction steps

  1. Start a Codex Desktop/CLI session with MultiAgentV2 enabled.
  2. Ask Codex to spawn a specialized subagent, or directly call:
{
  "agent_type": "explorer",
  "task_name": "explorer_default_fork_probe",
  "message": "Reply with exactly: STARTED"
}
  1. Observe the full-history fork rejection.
  2. Retry with:
{
  "agent_type": "explorer",
  "task_name": "explorer_no_fork_probe",
  "message": "Reply with exactly: STARTED",
  "fork_turns": "none"
}
  1. Observe that the specialized role can spawn.

Why this seems like a bug / DX issue

The official subagents docs describe specialized/custom agents with different model configurations and instructions. The tool schema also exposes agent_type, model, and reasoning_effort as ordinary spawn_agent arguments.

But with MultiAgentV2 enabled, the default fork_turns value makes those ordinary-looking arguments fail unless the caller knows to add fork_turns: "none".

This creates a sharp edge for users and orchestrating agents:

  • specialized subagent requests fail by default
  • the workaround is not discoverable until after a rejected tool call
  • users expecting "spawn a domain expert / explorer / worker" get a spawn failure instead of a specialized child

Suggested fix

Best option:

  • If agent_type, model, or reasoning_effort is present and fork_turns is omitted, default to a compatible fork mode instead of full-history.

Alternative:

  • Keep the current behavior, but update the tool schema/docs to explicitly state that role/model/reasoning overrides require fork_turns: "none" or another non-full-history mode.

Longer-term option:

  • Support full-history context with a different child role/model/reasoning configuration, since "same context, specialized child" is a common MultiAgentV2 workflow.

Related issue

Possibly related, but broader and Windows/named-agent focused:

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    subagentIssues involving subagents or multi-agent features
    on Apr 28, 2026
  2. github-actions commented on Apr 28, 2026

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

  3. iharc-jordan commented on Apr 28, 2026

    @iharc-jordan
    Author

    I can create a fix for this if it is acceptable. I have never contributed before but I'm happy to if the team is busy elsewhere.

  4. removed
    appIssues related to the Codex desktop app
    on Apr 28, 2026
  5. joeykrug commented on Apr 29, 2026

    @joeykrug

    +1 reproducing on Codex CLI v0.125.0 (Linux) with multi_agent_v2 = true.

    We have both reviewer and explorer roles configured in ~/.codex/agents/ with role-specific model = "gpt-5.5" / model_reasoning_effort overrides — the exact "specialized child with same context" workflow described in this issue. Every multi-agent spawn the lead thread attempts in our coding-agent automation gets rejected with the verbatim error string at the codex_core::tools::router ERROR level, and the lead thread then falls back to serial single-thread execution.

    Two examples from our logs in the past hour:

    2026-04-29T03:30:35.696218Z ERROR codex_core::tools::router: error=Full-history forked agents inherit the parent agent type, model, and reasoning effort; omit agent_type, model, and reasoning_effort, or spawn without a full-history fork.
    2026-04-29T03:30:35.720510Z ERROR codex_core::tools::router: error=Full-history forked agents inherit the parent agent type, model, and reasoning effort; ...
    2026-04-29T03:30:35.876210Z ERROR codex_core::tools::router: ...
    2026-04-29T04:13:56.729037Z ERROR codex_core::tools::router: error=Full-history forked agents inherit the parent agent type, model, and reasoning effort; ...
    

    The lead thread's own narration of the failure:

    The first spawn attempt hit a tooling constraint about full-history forks with explicit roles. I'm retrying with fresh role-specific threads and the relevant instructions embedded.

    So in practice, multi-agent-v2 with role overrides currently degrades to single-thread + role-discipline-via-prompt for us. Functional, but parallelism is lost.

    Strong agreement with the suggested fix:

    If agent_type, model, or reasoning_effort is present and fork_turns is omitted, default to a compatible fork mode instead of full-history.

    That seems like the least-surprise option — caller intent ("specialized child") wins over the silent default ("inherit everything"). The longer-term option ("same context + different role/model/reasoning") would be ideal because that's the actual workflow we want, but I assume that requires deeper API/runtime changes.

    Happy to test a fix on a release candidate if useful.

  6. jakvbs commented on May 6, 2026

    @jakvbs

    I can reproduce a related failure on codex-cli 0.128.0.

    A/B result:

    • --disable multi_agent_v2: subagent completes, writes a dynamic nonce file, and wait returns the child final response.
    • --enable multi_agent_v2 with default spawn behavior: wait times out, nonce file is missing, child final response is missing.
    • --enable multi_agent_v2 with explicit fork_turns: "none": subagent completes and returns the expected dynamic nonce.

    This suggests the V2 default full-history fork can make a child inherit parent orchestration context strongly enough that even a simple isolated worker task may not execute. Explicit fork_turns: "none" is a working workaround for task-worker style subagents.

    Observed local smoke summaries:

    V1 disabled:
    WAIT_STATUS=completed
    FILE_NONCE=<value>
    CHILD_FINAL=CHILD_NONCE <same value>
    
    V2 default:
    WAIT_STATUS=timeout
    FILE_NONCE=missing
    CHILD_FINAL=missing
    
    V2 fork_turns none:
    WAIT_STATUS=completed
    FILE_NONCE=<value>
    CHILD_FINAL=CHILD_NONCE <same value>
    
  7. fightZy commented on May 9, 2026

    @fightZy
    • 1 There is a possibility of a call error and a second attempt is needed
    Image
  8. netbrah commented on Jun 9, 2026

    @netbrah

    We hit this on our side too. The combination is especially painful when an agent prompt also instructs "always pass agent_type to bind subagents to a role config" — every first dispatch is guaranteed to fail. Captured in a rollout: the parent burns a turn on the rejection, reasons about it, then re-dispatches with fork_turns: "none".

    A small fix that resolves it cleanly: when fork_turns is omitted and the caller supplied any of agent_type / model / reasoning_effort, default the fork mode to "none" instead of "all". An explicit fork_turns="all" paired with overrides should still be rejected — that's a genuine contradiction, and the rejection now means what it says. The rejection error is also worth rewriting to tell the caller the actual fix (set fork_turns="none", or omit it entirely) rather than "omit your role."

    Diff is small — roughly:

    • SpawnAgentArgs::fork_mode() in multi_agents_v2/spawn.rs takes a has_child_overrides flag and picks the default accordingly.
    • Tool schema description for fork_turns documents the override-aware default.
    • Two tests: one locks in the new ergonomic (overrides + implicit fork_turns ⇒ no-fork spawn with role applied), the other locks in the still-strict behavior for explicit fork_turns="all" + overrides.

    Happy to send a PR if it would help — let me know if there's a preferred shape (behind a feature flag vs. unconditional, exact error wording, etc.).

  9. runfence commented on Jul 12, 2026

    @runfence

    I made a hook to require passing fork_turns to fix this for myself.

  10. usernameup commented on Jul 15, 2026

    @usernameup

    Additional macOS Codex Desktop reproduction (July 2026):

    Before restoring our custom agent setup, we defined 11 named TOML roles with explicit model and model_reasoning_effort values, including lightweight scan roles and high-effort implementation/review roles.

    Across a fresh-parent test set (5 parent threads and 4 spawned children), every observed spawned runtime reported the same effective context:

    • multi_agent_version = v2
    • multi_agent_mode = explicitRequestOnly
    • agent_role = null
    • model = gpt-5.6-sol
    • model_reasoning_effort = high

    That was true even where the requested custom role had a different configured model/effort. The child often completed the task, so this can be a silent routing failure rather than an obvious spawn error.

    This is consistent with the full-history inheritance/override conflict described here, and makes it impossible to trust custom model routing or cost controls without inspecting child runtime metadata. We also reproduced the behavior after restarting the Desktop app.

  11. swansonlimited commented on Jul 16, 2026

    @swansonlimited

    Reproduced on Codex Desktop / CLI 0.144.5 on macOS after explicitly registering the custom agents in ~/.codex/config.toml and restarting Codex.

    Parent thread: 019f6981-9265-7742-bf90-a3eef6f0ea07
    Child thread: 019f6982-472d-7020-84b0-3f144dab1736

    The parent called spawn_agent with:

    • task_name: levelup_builder
    • fork_turns: all

    The exposed MultiAgentV2 tool surface did not provide an agent_type field for selecting the registered custom agent. The child metadata recorded:

    • agent_path: /root/levelup_builder
    • agent_role: null
    • model: gpt-5.6-sol
    • effort: low

    The registered levelup_builder TOML specifies:

    • model: gpt-5.3-codex-spark
    • model_reasoning_effort: xhigh

    The role-specific developer_instructions were also absent from the child. Explicit [agents.levelup_builder] registration and a full Codex restart did not change the result.

    This suggests MultiAgentV2 treats task_name as a thread label and creates a full-history child without resolving the registered custom-agent configuration. This overlaps the named custom-agent/tool-surface gap reported in #15250. A durable fix appears to require exposing/resolving agent_type for registered agents, or automatically selecting a non-full-history spawn mode when a custom role is requested.

  12. parkjs101 commented on Aug 20, 2026

    @parkjs101

    This looks resolved in the handler, but the prompt still describes the old behavior.

    Code. #37252 ("Allow agent roles on full-history forks") removed the reject_full_fork_agent_type_override call from multi_agents_v2/spawn.rs and renamed the test multi_agent_v2_spawn_fork_turns_all_rejects_agent_type_override to ..._applies_agent_type_override. On current main, is_full_history_fork gates only the role branch:

    let is_full_history_fork = matches!(fork_mode, Some(SpawnAgentForkMode::FullHistory));
    apply_requested_spawn_agent_model_overrides(
        &session, turn.as_ref(), &mut config,
        args.model.as_deref(), args.reasoning_effort.clone(),
    ).await?;
    if !is_full_history_fork || role_name.is_some() {
        apply_spawn_agent_role(&session, &mut config, role_name).await?;

    apply_requested_spawn_agent_model_overrides runs unconditionally and takes no fork-mode parameter, so option 3 from the original report -- "full-history context plus a different child role/model/reasoning" -- appears to be implemented. The v1 handler still has an agent_type rejection, but its message no longer mentions model or reasoning effort.

    Prompt. The default usage hint added in #32749 still asserts the old constraint:

    Full-history forks (fork_turns omitted or "all") inherit the parent model and reasoning effort and do not accept overrides.

    It is injected whenever features.multi_agent_v2.expose_spawn_agent_model_overrides is true (the default), so agents still avoid a call shape the runtime now supports. The wording has also propagated outward: third-party documentation quotes "rejects model or effort overrides" as an enforced constraint.

    Two questions:

    1. Is the remaining hint intentional policy (discouraging overrides on full forks), or leftover text describing the removed rejection? If it is policy, would wording like "should not carry overrides" be preferable to "do not accept overrides"?
    2. Can this issue be closed as fixed by Allow agent roles on full-history forks #37252, or retitled to track only the stale prompt text?

    Checked against main on 2026-08-21.

  13. diogovalada commented on Aug 25, 2026

    @diogovalada

    Following up with a concrete minimal patch against current main:

    • change the MultiAgentV2 hint from saying full-history forks "do not accept overrides" to stating that they accept explicit model and reasoning_effort overrides;
    • preserve the guard that agents should only set overrides when explicitly requested by the user or applicable instructions;
    • align the generic model/effort omission guidance with configured subagent defaults and selected roles;
    • extend the existing usage-hint test and explicitly reject the obsolete prohibition.

    Commit: diogovalada@cc70fee6

    Focused tests pass:

    just test -p codex-core multi_agent_v2_exposes_model_overrides_by_default
    just test -p codex-core spawn_agent_tool_v2_requires_task_name_and_lists_visible_models
    

    This intentionally changes only stale guidance and its regression assertions. The runtime support already added by #37252 is left untouched. Since the repository restricts PR creation to collaborators and its contribution guide does not accept external PRs, I am linking the ready-to-cherry-pick commit here instead.

  14. jakobboss1010-source commented on Sep 1, 2026

    @jakobboss1010-source

    Additional current-main evidence and a ready-to-cherry-pick patch:

    On upstream main f4e6cb7, omitted fork_turns still maps to all and the tool schema still documents all as the default. The runtime override conflict discussed above has evolved, but the implicit full-history transport remains: every ordinary bounded worker receives the complete parent history unless the caller remembers to opt out.

    This patch makes history inheritance deliberate: omission defaults to none, while explicit all and positive-N modes remain available. It updates the schema and usage hint and adds a regression test covering omitted, none, all, and last-N behavior.

    Commit: jakobboss1010-source@a919ce1

    Focused verification against f4e6cb7:

    • just test -p codex-core fork_mode_requires_explicit_history_inheritance
    • 1 passed; 3,619 skipped
    • cargo fmt check clean

    The intended effect is to avoid duplicating full parent context into small or independently briefed workers while preserving explicit inheritance when it is actually needed.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsubagentIssues involving subagents or multi-agent features

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions