`spawn_agent` silently creates empty sub-agents for any non-OpenAI Responses provider — task body sent as `encrypted_content` and dropped, with zero diagnostics

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

Summary

The ChatGPT desktop app's embedded Codex runtime (cli 0.147.0-alpha.1.2, app 26.730.61639) creates sub-agents via spawn_agent / followup_task, but when model_provider points at a non-OpenAI Responses-compatible endpoint (wire_api="responses" -> e.g. https://api.deepseek.com), the task body never reaches the sub-agent. The sub-agent spawns, sees only an empty "Message Type: NEW_TASK ... Payload:" header, and replies "I don't see a specific task." Switching model_provider to the OpenAI backend makes it work. No error is surfaced anywhere. This silently breaks the multi-agent feature for every third-party provider.

Repro

config.toml:

model = "deepseek-v4-flash"
model_provider = "deepseek"

[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com"
wire_api = "responses"

In a session:

  1. spawn_agent(task_name="test", message="Reply with DELIVERY_OK only", fork_turns="none")
  2. wait_agent
  3. list_agents

Observed: spawn_agent returns {"task_name": "/root/test"} (success). But list_agents shows the sub-agent completed with "Hi! It looks like your message may not have come through yet — I don't see a specific request to work on."

Root cause — captured from the wire

The HTTP request the app sends to the third-party endpoint serializes the task as:

{"type":"agent_message","author":"/root","recipient":"/root/test","content":[
  {"type":"input_text","text":"Message Type: NEW_TASK\nTask name: /root/test\nSender: /root\nPayload:\n"},
  {"type":"encrypted_content","encrypted_content":"Reply with DELIVERY_OK only"}
]}

The encrypted_content content item is forwarded verbatim. A third-party Responses endpoint has no way to render that type, so the body is dropped and the model only sees the empty Payload: header. The same spawn under model_provider="openai" resolves correctly.

Notes:

  • This is not a tool-contract problem: spawn_agent's task_name / message / fork_turns arguments are exactly as documented, and the handler returns a valid task path.
  • followup_task (target + message) fails the same way; its output is silently empty.
  • fork_turns="all" partially masks it: the child gets the parent's forked history, but still not the per-agent spawn message. fork_turns="none" yields a fully empty agent.

Suspected area: the multi-agent v2 delivery path (core/src/tools/handlers/multi_agents_v2/spawn_agent.rs, followup_task.rs) and core/src/agent_communication.rs, where inter-agent messages are stored/transported as encrypted_content items and only expanded on the OpenAI backend.

Expected behavior

  • encrypted_content in agent-message payloads must be decrypted/expanded to plaintext input_text before the request is serialized to any provider; or
  • if that expansion is intentionally OpenAI-only, spawn_agent / followup_task must fail loudly with a clear error instead of silently spawning an empty agent.

Silently creating a sub-agent with no task — and silently returning empty results for followup_task / send_message — is the worst possible failure mode: no exception, no log, just empty agents doing nothing.

Environment

  • macOS (Darwin 25.5.0)
  • ChatGPT desktop app 26.730.61639 (build 6234), embedded Codex runtime cli 0.147.0-alpha.1.2
  • model=deepseek-v4-flash, model_provider=deepseek, base_url=https://api.deepseek.com, wire_api=responses

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 22 days ago

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

  • #36586
  • #36493
  • #36321
  • #37197
  • #36376

Powered by Codex Action

TOV1C · 16 days ago

Root cause
MultiAgentV2 delivers tasks through InterAgentCommunication: the plaintext content is empty, and the entire task text is placed in the encrypted_content content block. OpenAI endpoints decrypt and render this block server-side, which is why native models work; DeepSeek's Responses implementation does not recognize encrypted_content (community packet captures show that sending a request containing this content item directly returns a 400 / it gets dropped), so the sub-agent only sees an empty Payload:. This is the same family of issues as openai/codex #36493, #36321, #36586, #37237, and #37822.
Verified workaround (currently in effect on this machine)
Modify both entries in ~/.codex/models.json:

  • "multi_agent_version": "v2"
  • "multi_agent_version": "v1"
  • "supports_search_tool": true
  • "supports_search_tool": false

Rationale: supports_search_tool=false makes search_tool_enabled=false, so deferred tools are no longer hidden behind tool_search but are exposed directly to the model (the same mechanism as the workaround in #36382). The v1 tool family then becomes directly visible, and v1 delivers tasks as plain user messages (UserInput), which DeepSeek consumes reliably.

wo6909096 · 15 days ago

Confirming this with additional reproduction data on the desktop app.

Environment

  • macOS (Darwin, arm64), ChatGPT desktop app, embedded Codex runtime (multi-agent v2)
  • Custom sub-agent deepseek_v4_pro pointing at a non-OpenAI provider (wire_api="responses")

Controlled fork_turns comparison (same parent turn, same message)

| fork_turns | result |
|---|---|
| "none" | child completes with "only system/collaboration metadata, no assignment content" — message body fully dropped |
| "1" | child appears to work, but only because it inherits forked parent history; the spawn message itself still never arrives, so in a complex thread the child follows the old topic instead of the new task |

This matches the encrypted_content root cause exactly: fork_turns="1"/"all" merely masks the bug via inherited history; "none" yields a fully empty agent.

Additional data point worth triage: an OpenAI-backend built-in role (explorer) spawned with fork_turns="none" also returned "I don't see a task yet" for a one-token message. This suggests the loss may not be limited to non-OpenAI providers — worth confirming whether the encrypted_content expansion is actually provider-gated or also skipped for certain built-in role spawns.

Requested behavior (same as OP): fail loudly with a clear error rather than silently spawning an empty agent, so orchestrating agents don't produce garbage "I see no task" replies with zero diagnostics.