Regression: Responses Lite makes deferred MultiAgentV1 tools unreachable because tool_search is hidden in AdditionalTools

Open 💬 4 comments Opened Jul 10, 2026 by ignatremizov
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

v0.144.0

This is visible from the planner and Responses request serialization code path rather than from a local environment-specific crash.

What subscription do you have?

Not subscription-specific. Pro 20x.

Which model were you using?

Any model/runtime configuration with all of:

  • use_responses_lite = true
  • supports_search_tool = true
  • multi_agent_version = None
  • [features] multi_agent = true
  • [features] multi_agent_v2 = false

The current known practical case is GPT-5.6-style Responses Lite metadata where multi_agent_version = null in a custom models.json lets feature flags select V1.

What platform is your computer?

Not platform-specific.

What terminal emulator and version are you using (if applicable)?

Not terminal-specific.

Codex doctor report

Not applicable. This is a request-framing / tool-surface bug.

What issue are you seeing?

Responses Lite can make the V1 multi-agent tools unreachable when tool_search is enabled.

The configuration below correctly resolves to MultiAgentVersion::V1:

use_responses_lite = true
supports_search_tool = true
multi_agent_version = None
features.multi_agent = true
features.multi_agent_v2 = false

The planner then correctly defers the V1 collaboration tools because tool search is available:

  • spawn_agent
  • send_input
  • resume_agent
  • wait_agent
  • close_agent

However, the serialized Responses Lite request currently moves the entire tool list into a developer input item of type additional_tools and omits top-level tools. That means the special hosted/client-executed tool_search entrypoint is also hidden inside additional_tools instead of being sent as a top-level Responses tool.

In the live Responses Lite path, that leaves the model with neither:

  • directly visible V1 tools, nor
  • a usable top-level tool_search tool to discover them.

So V1 agent tools are deferred but unreachable.

This is distinct from the workaround of setting supports_search_tool = false, which exposes the V1 tools directly. That workaround avoids the unreachable state, but it disables deferred tool discovery globally for the model and is not the right fix.

What steps can reproduce the bug?

  1. Use model metadata / config that resolves to:

``text
use_responses_lite = true
supports_search_tool = true
multi_agent_version = None
features.multi_agent = true
features.multi_agent_v2 = false
``

  1. Start a Codex turn with V1 multi-agent selected by feature fallback.
  2. Inspect the final serialized Responses request, not just the planner registry.
  3. Observe that:
  • the request uses Responses Lite framing,
  • top-level tools is absent,
  • a developer additional_tools input item is present,
  • V1 agent tools are not directly exposed because they were deferred,
  • tool_search is not available as a usable top-level tool.
  1. Ask for a subagent/delegation action requiring spawn_agent.
  2. The model has no reachable way to discover or call the V1 agent tools.

What is the expected behavior?

Responses Lite should still expose a usable tool_search entrypoint when deferred tool discovery is enabled.

For the V1 multi-agent case:

  1. The first Responses Lite request should keep ordinary Lite tools in the developer additional_tools item.
  2. The same request should expose hosted/client-executed tool_search as a top-level Responses tool, with type = "tool_search" and execution = "client".
  3. V1 multi-agent tools should remain deferred and should not be directly exposed in either top-level tools or additional_tools.
  4. A tool_search call for spawn agent should return the multi_agent_v1 namespace containing spawn_agent.
  5. A subsequent model call to multi_agent_v1.spawn_agent should route to the registered V1 handler.
  6. Responses Lite should continue to set parallel_tool_calls = false.

Additional information

Relevant source areas:

  • V1 tools become deferred when search is available:
  • codex-rs/core/src/tools/spec_plan.rs
  • tool_search is appended when deferred runtimes have search metadata:
  • codex-rs/core/src/tools/spec_plan.rs
  • Responses Lite request framing moves tools into AdditionalTools and omits top-level tools:
  • codex-rs/core/src/client.rs
  • Multi-agent version fallback from model metadata to feature flags:
  • codex-rs/core/src/session/mod.rs

Related but not identical issue:

  • #31894 reports code-mode/exec tools not being exposed under Responses Lite. This issue is narrower: tool_search itself is the hosted/client-executed discovery entrypoint for deferred V1 collaboration tools, so hiding it inside additional_tools makes the deferred V1 tools unreachable.

Short implementation plan based on local verification:

  1. In ModelClient::build_responses_request, split Lite tool specs before JSON serialization by ToolSpec variant, not by serialized JSON strings.
  2. For Responses Lite:
  • keep non-ToolSearch specs in the developer ResponseItem::AdditionalTools item,
  • keep ToolSpec::ToolSearch { .. } in top-level tools,
  • omit top-level tools only when there is no ToolSearch spec,
  • leave non-Lite behavior unchanged.
  1. Preserve parallel_tool_calls: prompt.parallel_tool_calls && !model_info.use_responses_lite.
  2. (test coverage) Add a combined integration regression under the Responses Lite suite that:
  • configures use_responses_lite = true, supports_search_tool = true, model multi_agent_version = None, V1 selected by feature fallback,
  • uses the remote-aware integration builder (build_with_auto_env),
  • asserts the first request omits top-level instructions, has parallel_tool_calls = false, and has exactly one top-level hosted tool: type = "tool_search", execution = "client",
  • asserts V1 agent tools do not leak directly in top-level tools or additional_tools, including post-search parent requests,
  • simulates a tool_search_call for spawn agent,
  • asserts the next request contains a completed client tool_search_output with multi_agent_v1.spawn_agent,
  • simulates calling multi_agent_v1.spawn_agent,
  • asserts the child prompt is routed to the child turn and the parent follow-up contains a function_call_output with an agent_id.

This should allow GPT-5.6-style Responses Lite models to keep supports_search_tool = true without making every deferred V1 collaboration tool direct.

Reference implementation

A tested reference patch is available in a durable fork snapshot:

It implements the split Responses Lite serialization described above and covers deferred V1 tool discovery, spawn_agent routing, child request delivery, and the parent function_call_output.

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 1 month ago

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

  • #31894

Powered by Codex Action

Mushst · 1 month ago

I can reproduce this with a model-catalog-selected V1 route, rather than only
the feature-fallback configuration described in the original report.

Environment

  • macOS 26.5.2, Darwin 25.5.0, Apple Silicon
  • Codex Desktop bundled CLI: 0.144.5
  • features.multi_agent = true
  • features.multi_agent_v2.enabled = true
  • Custom agent: luna_explorer

Observed behavior

After fully quitting and restarting Codex, a fresh Desktop task using
gpt-5.6-sol with High reasoning recorded:

model: gpt-5.6-sol
effort: high
multi_agent_version: v1

The task had no reachable spawn_agent, wait_agent, or close_agent
capability.

A fresh isolated codex exec task using Sol produced the same result:

Spawning failed: no custom-agent spawning capability is available in this
session. Requested agent type: luna_explorer.

A/B control

Using the same Codex installation, global configuration, and custom agent
definition:

| Root model | Recorded route | Result |
| --- | --- | --- |
| gpt-5.6-sol | V1 | No reachable spawning capability |
| gpt-5.6-terra | V2 | Successfully spawned luna_explorer |

The Terra control returned:

Spawning succeeded. Agent type used: luna_explorer.

The diagnostic prompts explicitly prohibited project-file inspection and file
modification.

Expected behavior

If model metadata routes Sol through stable MultiAgent V1, the V1 collaboration
tools should be reachable. Alternatively, Sol should not be routed through V1
while that discovery path is unavailable.

This suggests #32086 also affects explicit model-catalog V1 routing, not only
configurations where multi_agent_version = None falls back to V1.

nerdchanii · 1 month ago

Cross-linking a newly isolated upstream cause from #33559: #33593.

#33593 demonstrates that two app-server processes using the exact same Codex
binary, provider, auth mode, ChatGPT account, client version, and CODEX_HOME
can receive different model catalogs when only originator changes:

  • Desktop / CLI originators: Sol multi_agent_version = v1,

tool_mode = direct

  • Chrome sidepanel originator: Sol multi_agent_version = v2,

tool_mode = code_mode_only

Both catalogs are persisted to the same models_cache.json, and the
three-minute app-server refresh workers cause the file to oscillate. This can
explain why a fresh session unexpectedly enters the V1 route.

This does not make #32086 a duplicate. The issues are complementary:

  • #33593 is the upstream catalog identity and cross-process cache-isolation

problem.

  • #32086 is the downstream Responses Lite serialization problem that makes

deferred V1 tools unreachable after V1 has been selected.

Fixing cache isolation should make the selected route stable, but a surface
intentionally served V1/Responses Lite would still require the #32086 fix.

Woudart · 1 month ago

Independent Windows/MCP confirmation of the Responses Lite tool_search failure

I can reproduce the downstream failure described here with a deferred MCP namespace, rather than only MultiAgent V1 collaboration tools. The results strongly support the same Responses Lite tool-exposure boundary.

Environment

  • Codex Desktop: 26.707.91948 (released 16 Jul 2026)
  • Bundled Codex CLI/app-server: 0.144.5
  • Platform: Windows
  • Subscription: ChatGPT Pro
  • Model: gpt-5.6-sol
  • Native OpenAI provider with ChatGPT authentication
  • Sol catalog metadata:
  • tool_mode: direct
  • use_responses_lite: true
  • supports_search_tool: true
  • multi_agent_version: v1
  • Independent, read-only stdio MCP canary exposing one uniquely named echo tool

The original user-facing symptom involved Browser/Computer Use becoming unavailable after selecting Sol even though the Windows helper and MCP backend were healthy. Controlled fresh runs reproduce the failure, so an in-task model switch or stale thread state is not required.

Controlled live results

| Route | Only catalog change | tools/list | Successful MCP call |
|---|---|---:|---:|
| GPT-5.5, normal Responses | none | 1/1 | 1/1 |
| Sol, Responses Lite + deferred tool_search | none | 3/3 | 0/3 |
| Sol, normal Responses + deferred tool_search | use_responses_lite: true → false | 3/3 | 3/3 |
| Sol, Responses Lite + direct MCP namespace | supports_search_tool: true → false | 2/2 | 2/2 |

Every failing Sol/Lite run:

  • initialized the MCP server successfully;
  • received a valid one-tool tools/list result;
  • logged the discovered tool in Codex’s MCP inventory;
  • made no tools/call; and
  • returned the prompt’s exact TOOL_SEARCH_UNAVAILABLE fallback.

All five matched Sol controls invoked the canary successfully with the expected token.

This rules out:

  • MCP process startup;
  • stdio transport;
  • the tool schema;
  • the Windows helper;
  • Codex’s MCP invocation router;
  • a generic Sol tool-calling limitation;
  • a generic Responses Lite inability to call MCP tools; and
  • random model tool choice.

Sanitized final outbound request trace

I captured the final request using the real 0.144.5 executable pointed only at a loopback endpoint. Nothing was forwarded externally, and no raw request body, authentication data, prompts, instructions, or tool schemas were retained.

For the failing Sol/Responses Lite route, the request:

  • targets POST /v1/responses;
  • carries the Responses Lite header;
  • has no top-level tools field;
  • begins with a developer-role additional_tools item; and
  • includes:
{
  "type": "tool_search",
  "execution": "client"
}

The initial request does not contain the deferred mcp__node_repl namespace. That absence is expected: the namespace remains in Codex’s client-side search index and should be returned only after a successful tool_search call.

The matched controls further narrow the boundary:

  • With only use_responses_lite=false, the same client-executed tool_search is serialized as a top-level tool, and Sol succeeds 3/3.
  • With Responses Lite retained but only supports_search_tool=false, the direct MCP namespace is placed in additional_tools, and Sol successfully calls the equivalent MCP canary 2/2.

Therefore, Responses Lite can expose and invoke direct MCP namespaces. The failing sub-path is specifically the model-visible, client-executed tool_search entrypoint under Responses Lite.

Source and regression-test check

The installed source-equivalent revision and current upstream source both intentionally move Lite tools into a leading AdditionalTools input item.

I added a local Responses Lite variant of the existing stdio MCP integration test covering:

tool_search → deferred MCP namespace → MCP call

Both tests pass:

responses_lite_stdio_server_round_trip ... ok
stdio_server_round_trip ... ok

This does not invalidate the live failure. The mocked test supplies the expected tool_search_call, proving that the public client-side search index, response routing, and MCP invocation path can complete the exchange once that call exists. It does not test the internal service/model transformation that decides whether the accepted additional_tools declaration becomes model-visible.

Relationship to this issue

These results indicate that the mechanism in #32086 is not limited to deferred MultiAgent V1 tools. It also affects deferred MCP namespaces, including the namespace required by Browser Use. This explains why local Browser/Computer Use helpers can be healthy while the model has no callable route to them.

The reference implementation proposed here—keeping ToolSearch top-level while retaining ordinary Lite tools in AdditionalTools—is directionally consistent with the live A/B results.

A useful additional regression would cover:

Responses Lite
→ top-level client tool_search
→ deferred MCP namespace
→ MCP tool invocation

Related local route variability

Two simultaneously running, byte-identical Codex executables are present locally:

  • the Codex Desktop runtime; and
  • the plugin app-server runtime.

They share the same models_cache.json. The current cached Sol route is the affected V1 + direct + Responses Lite + search enabled combination. The cache was rewritten during observation, although those Sol fields remained stable.

That establishes the local precondition described in #33593 and may explain why users or client surfaces receive different Sol routes. It is not required to reproduce the downstream bug, however: the matched catalog controls above independently isolate the Responses Lite/deferred-search path.

The complete sanitized RCA, detailed request comparisons, source review, and regression-test findings are available here:

https://github.com/openai/codex/issues/19425#issuecomment-4992900637

Could a maintainer confirm from a sanitized post-ingestion trace whether tool_search remains registered in the model-visible tool list after the developer-role additional_tools item is accepted, and whether keeping the client-executed ToolSearch declaration top-level is the intended fix?