Skip to content

Force forked agents to inherit parent model settings#16055

Closed
friel-openai wants to merge 11 commits into
mainfrom
dev/friel/fork-context-inherits-parent-model
Closed

Force forked agents to inherit parent model settings#16055
friel-openai wants to merge 11 commits into
mainfrom
dev/friel/fork-context-inherits-parent-model

Conversation

@friel-openai

@friel-openai friel-openai commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make explicit forked spawns (fork_context = true / fork_turns) ignore child model and reasoning_effort overrides
  • keep forked agents on the spawning thread's effective model, provider, reasoning, service tier, verbosity, context-window, auto-compact, and profile settings
  • preserve forked-child prompt-cache behavior by reusing the parent prompt cache key
  • preserve MCP tool-surface parity for forked children by inheriting the parent MCP connection manager instead of starting a fresh manager
  • add v1/v2 regression tests for model inheritance, cache-key inheritance, and MCP inheritance

Test

  • cargo +1.93.1 test -p codex-core spawn_agent_fork_context_ignores_child_model_overrides --lib
  • cargo +1.93.1 test -p codex-core multi_agent_v2_spawn_fork_turns_ignores_child_model_overrides --lib
  • cargo +1.93.1 test -p codex-core spawn_agent_can_fork_parent_thread_history_with_sanitized_items --lib

@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: 9b0bc4b161

ℹ️ 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 codex-rs/core/src/tools/handlers/multi_agents/spawn.rs
Comment thread codex-rs/core/src/tools/handlers/multi_agents_tests.rs
@friel-openai friel-openai force-pushed the dev/friel/fork-context-inherits-parent-model branch 4 times, most recently from 8bbc644 to 3379d41 Compare April 1, 2026 00:07
@friel-openai friel-openai force-pushed the dev/friel/fork-context-inherits-parent-model branch from 3379d41 to fc08138 Compare April 1, 2026 23:46
@friel-openai friel-openai force-pushed the dev/friel/fork-context-inherits-parent-model branch 3 times, most recently from 7d0d474 to 01c2cff Compare April 7, 2026 17:33
@friel-openai friel-openai force-pushed the dev/friel/fork-context-inherits-parent-model branch from 6b62601 to e351cad Compare April 7, 2026 22:31

@jif-oai jif-oai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is way too large. Forked agent should just inherit the full config of the parent agent. We shouldn't need to touch any other components

Btw profiles will disappear so feel free to ignore them all

@friel-openai

Copy link
Copy Markdown
Contributor Author

@jif-oai there are a few issues fixed in this PR:

  • configuration that affects forked agent behavior, such as model, reasoning effort, context window
  • MCP servers refreshing and generating distinct tool calls, not relying on the parent's MCP
  • Prompt cache keys

I think your comment is primarily about the first, is that right?

@jif-oai jif-oai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this would be good to share more cache here but I don't think this PR fits at the right level.
I would suggest 3 different small PRs:

  1. Fully re-use the parent config in case of a fork + return a warning or error to the agent if it tries to set anything else
  2. Shared cache key, do a proper wiring that let us "override" the cache key for a given thread. That we fix at the creation of the thread and gets set directly into the API client
  3. Make the MCP tools listing stable. Either by definition or using a snapshot

mcp_connection_manager: Arc::new(RwLock::new(McpConnectionManager::new_uninitialized(
&config.permissions.approval_policy,
))),
mcp_connection_manager: session_configuration

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't do this. MCP manager get replaced/modified if we have sandbox updates, elicitation, ...
In general, we can't share the manager without re-designing it
If I get it correctly, the only reason we do this is because we want a stability over built_tools. First, this shouldn't drift most of the time. Second, we should use a snapshot around it to fix the issue then

let inherited_exec_policy = self
.inherited_exec_policy_for_source(&state, Some(&session_source), &config)
.await;
let inherited_prompt_cache_key = self

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This resume path should not opportunistically inherit parent cache/MCP state from a live parent. SubAgentSource::ThreadSpawn does not persist whether this child was originally forked, so the same resumed agent will get parent-shared cache/MCP only when the parent is currently loaded, and isolated state otherwise... we can't have such non-determinism

inherited_shell_snapshot: None,
user_shell_override: None,
inherited_exec_policy: Some(Arc::clone(&parent_session.services.exec_policy)),
inherited_prompt_cache_key: Some(parent_session.prompt_cache_key()),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are not fork

@@ -770,6 +773,8 @@ impl ThreadManagerState {
metrics_service_name: Option<String>,
inherited_shell_snapshot: Option<Arc<ShellSnapshot>>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a lot of optional inherited things. We should have a small builder pattern for the inherited things

@@ -225,7 +225,11 @@ fn build_agent_shared_config(turn: &TurnContext) -> Result<Config, FunctionCallE
let mut config = (*base_config).clone();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this should be cleared IMO
We should just re-use the full same config... otherwise this will become brittle over time

config.model = Some(turn.model_info.slug.clone());
config.model_provider = turn.provider.clone();
config.model_reasoning_effort = turn.reasoning_effort;
// Forked children must preserve the spawning turn's effective model settings, including a

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code path is not only for forked agents

pub(crate) inherited_shell_snapshot: Option<Arc<ShellSnapshot>>,
pub(crate) inherited_exec_policy: Option<Arc<ExecPolicyManager>>,
pub(crate) inherited_prompt_cache_key: Option<ThreadId>,
pub(crate) inherited_mcp_connection_manager: Option<Arc<RwLock<McpConnectionManager>>>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up Option of an Arc of RwLock looks like a code smell in Rust... there are better alternatives for hot swap shared references

}

#[tokio::test]
async fn spawn_agent_fork_context_ignores_child_model_overrides() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is kind of pointless IMO
A better test would be an integration test that makes sure the full context is the same at the API level


let mut config = (*turn.config).clone();
let mut role_provider =
built_in_model_providers(/* openai_base_url */ /*openai_base_url*/ None)["openai"].clone();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dup in the comment

args.reasoning_effort,
)
.await?;
if !args.fork_context {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably error to the model if it specify fork with a model and reasoning effort. Or at least emit a warning

friel-openai added a commit that referenced this pull request Apr 13, 2026
## Summary

When a `spawn_agent` call does a full-history fork, keep the parent's
effective agent type and model configuration instead of applying child
role/model overrides.

This is the minimal config-inheritance slice of #16055. Prompt-cache key
inheritance and MCP tool-surface stability are split into follow-up PRs.

## Design

- Reject `agent_type`, `model`, and `reasoning_effort` for v1
`fork_context` spawns.
- Reject `agent_type`, `model`, and `reasoning_effort` for v2
`fork_turns = "all"` spawns.
- Keep v2 partial-history forks (`fork_turns = "N"`) configurable;
requested model/reasoning overrides and role config still apply there.
- Keep non-forked spawn behavior unchanged.

## Tests

- `cargo +1.93.1 test -p codex-core spawn_agent_fork_context --lib`
- `cargo +1.93.1 test -p codex-core multi_agent_v2_spawn_fork_turns
--lib`
- `cargo +1.93.1 test -p codex-core
multi_agent_v2_spawn_partial_fork_turns_allows_agent_type_override
--lib`
AIALRA-0 pushed a commit to AIALRA-0/codex-turn-engine that referenced this pull request Jun 10, 2026
## Summary

When a `spawn_agent` call does a full-history fork, keep the parent's
effective agent type and model configuration instead of applying child
role/model overrides.

This is the minimal config-inheritance slice of openai#16055. Prompt-cache key
inheritance and MCP tool-surface stability are split into follow-up PRs.

## Design

- Reject `agent_type`, `model`, and `reasoning_effort` for v1
`fork_context` spawns.
- Reject `agent_type`, `model`, and `reasoning_effort` for v2
`fork_turns = "all"` spawns.
- Keep v2 partial-history forks (`fork_turns = "N"`) configurable;
requested model/reasoning overrides and role config still apply there.
- Keep non-forked spawn behavior unchanged.

## Tests

- `cargo +1.93.1 test -p codex-core spawn_agent_fork_context --lib`
- `cargo +1.93.1 test -p codex-core multi_agent_v2_spawn_fork_turns
--lib`
- `cargo +1.93.1 test -p codex-core
multi_agent_v2_spawn_partial_fork_turns_allows_agent_type_override
--lib`
AIALRA-0 pushed a commit to AIALRA-0/codex-turn-engine that referenced this pull request Jun 10, 2026
## Summary

When a `spawn_agent` call does a full-history fork, keep the parent's
effective agent type and model configuration instead of applying child
role/model overrides.

This is the minimal config-inheritance slice of openai#16055. Prompt-cache key
inheritance and MCP tool-surface stability are split into follow-up PRs.

## Design

- Reject `agent_type`, `model`, and `reasoning_effort` for v1
`fork_context` spawns.
- Reject `agent_type`, `model`, and `reasoning_effort` for v2
`fork_turns = "all"` spawns.
- Keep v2 partial-history forks (`fork_turns = "N"`) configurable;
requested model/reasoning overrides and role config still apply there.
- Keep non-forked spawn behavior unchanged.

## Tests

- `cargo +1.93.1 test -p codex-core spawn_agent_fork_context --lib`
- `cargo +1.93.1 test -p codex-core multi_agent_v2_spawn_fork_turns
--lib`
- `cargo +1.93.1 test -p codex-core
multi_agent_v2_spawn_partial_fork_turns_allows_agent_type_override
--lib`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants