app-server: dynamicTools are not inherited by subagents spawned with fork_turns: "none"
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From “About Codex” dialog)?
26.831.21537
What subscription do you have?
Pro
What platform is your computer?
Darwin 25.5.0 arm64 arm
What issue are you seeing?
When a Codex app-server thread is started with custom dynamicTools, the main agent can use those tools, but subagents spawned with fork_turns: "none" do not receive them.
The child still receives the normal Codex tools and configured MCP servers, but the parent thread's dynamicTools are absent from the child’s callable tool inventory and from the child model request.
The same subagent receives the dynamic tools when spawned with fork_turns: "all".
This makes conversation-history isolation also act as tool-capability isolation. As a result, applications cannot create a clean, context-efficient subagent that has the same tools as its parent.
What steps can reproduce the bug?
-
Start Codex app-server.
-
Create a thread with at least one custom dynamic tool in
thread/start, for example:{ "dynamicTools": [ { "name": "test_dynamic_tool", "description": "A test tool provided by the app-server client.", "inputSchema": { "type": "object", "properties": {} } } ] } -
Start a parent-agent turn and ask it to call test_dynamic_tool. The parent can see and call the tool successfully.
-
Ask the parent to spawn a bounded subagent with:
{ "fork_turns": "none" }
Give the child a task that requires calling test_dynamic_tool.
- Observe that the child cannot see or call the tool. If the child model request or callable-tool registry is inspected, test_dynamic_tool is absent.
- Repeat the same test with:
{ "fork_turns": "all" } - Observe that the dynamic tool is now present in the child model request and can be called by the child.
In our integration, this reproduces consistently:
- fork_turns: "none": parent dynamicTools are absent.
- fork_turns: "all": parent dynamicTools are present.
- Configured MCP servers are inherited in both cases, so the behavior appears specific to dynamicTools.
What is the expected behavior?
A spawned subagent should inherit the parent thread's callable dynamicTools regardless of whether conversation turns are copied.
fork_turns should control conversation-history inheritance, not silently change the child’s tool registry.
Ideally:
fork_turns: "none"creates a clean child with the same allowed tools as the parent.- The inherited authorization is equal to or narrower than the parent’s authorization.
fork_turns: "all"additionally copies the parent conversation, but does not provide a different tool set.
If automatic inheritance is not intended, app-server should expose an explicit option for inheriting or supplying the parent’s dynamic tools when spawning a subagent.
Additional information
Reproduced with Codex app-server 0.153.0 on macOS.
Our application supplies server-handled tools through dynamicTools on thread/start.
The issue appears limited to dynamically supplied tools:
- Core Codex tools remain available to the child.
- Configured MCP servers are inherited with both
fork_turns: "none"andfork_turns: "all". dynamicToolsare inherited only withfork_turns: "all".
Using fork_turns: "all" is not an equivalent workaround because it copies the complete parent conversation, uses substantially more context, and inherits the parent model and reasoning configuration. Full-history forks also do not allow the same child model/reasoning overrides available to clean forks.
Prompts, skills, and AGENTS.md instructions cannot solve this because the missing tools are not included in the child’s callable tool definitions.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the app-server thread/start handling and the subagent fork path, comparing how dynamicTools are carried into children for fork_turns "none" versus "all". Reproduce the request with a custom dynamic tool and inspect the child callable-tool registry and model request; done means clean forks inherit the parent dynamicTools without inheriting conversation history.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100