[Bug] spawn_agent/followup_task/send_message: child agents receive empty task payload (multi-agent v2, 0.146.0-alpha.9.2)

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

What version of the Codex App are you using (From “About Codex” dialog)?

0.146.0-alpha.9.2 (CLI version from session logs; confirm in About Codex dialog)

What subscription do you have?

Plus

What platform is your computer?

Darwin 25.5.0 arm64 arm

What issue are you seeing?

When the root agent spawns a sub-agent or sends it a follow-up message, the child agent never sees the message text. The child's transcript records the delivered message with the real text stored in an encrypted_content field, while the plaintext envelope ends at Payload: with nothing after it. The child's model-visible conversation contains only system prompts and environment context, so every child agent replies that no task arrived (e.g. "no task has come through yet" / "I don't see a task or question yet").

This affects spawn_agent (initial task), followup_task, and send_message. Session id: 019fb7f8-9094-7513-a260-d53c55f1d6d6

What steps can reproduce the bug?

  1. From the root agent, call spawn_agent with task_name and a non-empty message (tested with both fork_turns="none" and the default full-history fork).
  2. Observe the child agent's replies: it says it received no task.
  3. Send followup_task or send_message with non-empty content: same behavior.
  4. With the default fork, the child inherits the parent conversation, infers intent from history, and may recursively spawn its own sub-agents; the deepest agent again receives an empty task. A simple weather query stalled for ~13 minutes.

Evidence from rollout logs (child's delivered message):

{"type":"agent_message","author":"/root","recipient":"/root/beijing_weather","content":[{"type":"input_text","text":"Message Type: NEW_TASK\nTask name: /root/beijing_weather\nSender: /root\nPayload:\n"},{"type":"encrypted_content","encrypted_content":"<actual task text>"}]}

The parent's function_call arguments contain the full message, but the child's model-visible messages (response_item entries with roles) contain only developer/system instructions and an environment_context user message — the task text never appears.

What is the expected behavior?

The message payload (including encrypted_content) should be decrypted and rendered into the child agent's conversation so it can act on the task.

Additional information

  • Codex Desktop, originator: Codex Desktop, source: vscode, thread source: user
  • CLI version 0.146.0-alpha.9.2, multi_agent_version v2
  • Model: deepseek-v4-flash (via model provider)
  • macOS, Darwin 25.5.0 arm64
  • inter_agent_communication_metadata entries contain only {"trigger_turn": true|false}; no message content
  • Rollout logs under ~/.codex/sessions/2026/07/31/ for the root session (019fb7f8-9094-7513-a260-d53c55f1d6d6) and its sub-agents (019fb802-9481-7993-934a-ff7daf5f9b49, 019fb806-818d-7073-b3cf-579bc70ab4a0, 019fb806-a2ce-7662-b47b-2fd04b01e262, 019fb806-cd7b-7563-8d76-b0fabafa7e90)

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 27 days ago

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

  • #35932

Powered by Codex Action

CCanxue · 25 days ago

Reproduced on stable 0.146.0 as well (DeepSeek, wire_api = "responses", multi_agent_version = "v2"), covering all three tools: spawn_agent, followup_task and send_message.

Wire-level detail: the request does contain the NEW_TASK envelope, but Payload: is empty because the task text sits in encrypted_content; DeepSeek drops that block. Even a plaintext input_text inside the agent_message item is ignored by DeepSeek in most runs. Delivering the same text as a plain user message works reliably.

Local patch + build/install guide: https://github.com/CCanxue/codex-deepseek-subagent-fix

yangwuan55 · 24 days ago

I hit a related MultiAgentV2 / spawn_agent failure today in Codex Desktop while trying to orchestrate a small multi-agent workflow.

This may not be the exact same encrypted-payload failure described in the issue body, but it looks adjacent because the root agent could not get a valid spawn_agent call through the tool boundary at all.

Environment observed from this machine:

  • PATH codex: codex-cli 0.146.0
  • ChatGPT/Codex Desktop embedded CLI: codex-cli 0.146.0-alpha.9.2
  • Provider: OpenAI / ChatGPT-auth Codex Desktop session
  • Native subagent tool exposed in the session as spawn_agent

What happened:

The model-visible tool shape exposed both message and items as callable fields, with guidance saying to use either message or items. In practice, attempted calls repeatedly failed with:

Provide either message or items, but not both

The failure happened because empty/default fields still counted as present. For example, calls shaped like this failed:

{
  "fork_context": true,
  "items": [],
  "message": "...task text...",
  "model": "gpt-5.6-terra",
  "reasoning_effort": "medium",
  "service_tier": "priority"
}

And the inverse shape with items: [...] plus message: "" also failed. From the public source, this lines up with parse_collab_input(message, items) treating (Some(_), Some(_)) as invalid, without normalizing empty items or an empty default message as absent.

Why this matters:

If the client/tool schema makes both branches appear present, or if the tool wrapper materializes the unused branch as an empty array/string, the root agent has no reliable schema-valid way to spawn a child agent. The delegation fails before we can even observe whether the child receives the payload. In my case, a harness agent that was supposed to delegate design, implementation, and QA subtasks degraded back to single-threaded local work.

Expected behavior:

One of these would make the tool much more robust:

  1. The model-visible schema should express message vs items as a real oneOf / mutually exclusive choice, where the unused branch can be omitted entirely.
  2. The tool binding should not auto-materialize the unused branch as items: [] or message: "".
  3. The parser could defensively treat an empty unused branch as absent when the other branch is non-empty, e.g. items: [] + non-empty message should behave as message-only.
  4. The error message could include the exact valid call shape, because the current schema/guidance makes it easy for the root agent to retry the same invalid shape.

Again, this is not necessarily the same child-side empty-payload bug, but it seems like the same broader MultiAgentV2 spawn_agent tool-surface problem: schema/default payload shape and runtime validation are not aligned, so subagent orchestration can fail even when the parent agent is explicitly trying to use the native tool correctly.

CCanxue · 22 days ago

This looks like a separate tool-surface bug from the empty-payload issue tracked here: the failure happens before delivery, in the message vs items validation (parse_collab_input rejecting both being present, including empty defaults). Worth filing as its own issue so maintainers can track the schema/validation mismatch separately. I agree that treating an empty unused branch as absent (option 3) is the smallest robust fix.

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.