Subagent task payload invisible to custom non-OpenAI providers (DeepSeek): encrypted_content block dropped with multi_agent_version v2

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

Summary

When using a custom non-OpenAI provider (DeepSeek) with Codex multi-agent (subagents), tasks
dispatched via spawn_agent / followup_task are never seen by the subagent. The subagent
initializes, reads the workspace, and then replies that it has no task input ("no new task
input"), so every subagent run is a no-op.

Environment

  • Codex CLI 0.145.0 on Windows
  • Custom provider in config.toml: [model_providers.deepseek] with

base_url = "https://api.deepseek.com/" and wire_api = "responses"

  • model = "deepseek-v4-flash", model_catalog_json = "~/.codex/models.json" (written by the

official DeepSeek one-command setup, which sets "multi_agent_version": "v2" in both entries)

  • Multi-agent tools: collaboration__spawn_agent / followup_task (MultiAgentV2 tool surface)

Reproduction

  1. Start a session with deepseek-v4-flash (models.json entry has

"multi_agent_version": "v2").

  1. Spawn a subagent with a simple task, e.g. "reply exactly: PONG".
  2. The subagent replies with a workspace status summary and asks what to work on; it never

executes the dispatched task. followup_task with the same prompt also yields
"no new task input".

Same setup with a native catalog model (e.g. gpt-5.6-sol) executes subagent tasks correctly.

Root cause

For MultiAgentV2, the task payload is always delivered through an
InterAgentCommunication::new_encrypted(..) record whose content is a
[input_text header, encrypted_content] pair:

  • codex-rs/core/src/tools/handlers/multi_agents_v2.rscommunication_from_tool_message

uses new_encrypted(author, recipient, vec![], message, trigger_turn) for every
non-DirectPlaintextMessage source, so the task text lives in the encrypted_content
content block.

  • codex-rs/core/src/client.rs — in build_responses_request, the !is_openai branch only

clears FunctionCall.encrypted_function_args; it does not handle
ResponseItem::AgentMessage content, so the encrypted_content block is sent to the
provider API unchanged.

  • codex-rs/core/src/client_common.rsget_formatted_input_for_request passes the items

through as-is.

For OpenAI endpoints the agent-message payload is decrypted/rendered server-side, which is why
native models work. The DeepSeek Responses API does not understand the encrypted_content
content block type and drops it, so the model only receives
Message Type: NEW_TASK\nTask name: ...\nSender: ...\nPayload: with an empty payload.

Workaround (validated)

Set "multi_agent_version": "v1" for the custom model entries in ~/.codex/models.json
(instead of "v2"). With V1 the spawn initial input is delivered as a plain user message
(SpawnInitialInput::UserInput) instead of an inter-agent communication, and DeepSeek
subagents execute tasks correctly (verified with a codex exec spawn test returning the
expected output). Restart the session after editing models.json.

Note: this means custom non-OpenAI models cannot currently use the MultiAgentV2 tool surface
at all.

Suggested fix

In build_responses_request (codex-rs/core/src/client.rs), extend the !is_openai branch
to transform ResponseItem::AgentMessage content: fold the encrypted_content block into a
single InputText (header text + payload), mirroring the plaintext rendering already used by
communication_from_tool_message's DirectPlaintextMessage path. This lets custom
wire_api = "responses" providers receive subagent task payloads while keeping V2 behavior.

Related

  • #36382 — MCP tools silently unavailable with DeepSeek official setup (same family:

custom models.json + non-OpenAI provider gaps in tool/content handling)

View original on GitHub ↗

8 Comments

github-actions[bot] contributor · 26 days ago

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

  • #36493
  • #36387
  • #36376

Powered by Codex Action

CCanxue · 25 days ago

Additional reproduction and a working local patch (codex-cli 0.146.0 source, deepseek-v4-flash, wire_api = "responses", multi_agent_version = "v2").

Wire-level finding: even when the agent_message content is rewritten so the payload is plaintext input_text (no encrypted_content), DeepSeek still ignores the agent_message item in most runs and the child replies that it has no task. The task is only consumed reliably when it is delivered as a plain user message.

Working local patch: for non-OpenAI providers, deliver V2 spawn / followup_task / send_message payloads as plain user input (UserInput), mirroring the V1 SpawnInitialInput::UserInput path. The OpenAI path keeps encrypted InterAgentCommunication unchanged. Verified end-to-end with the real provider: spawn_agent -> PONG, followup_task -> PONG2.

The multi_agent_version: "v1" workaround does not work with deepseek-v4-flash: with DeepSeek's catalog (supports_search_tool: true), the V1 tool family is registered as Deferred behind tool_search. The tool_search tool is present in the request tools array, but deepseek-v4-flash does not recognize or call it (same family as #36382), so the V1 tools are unreachable and v1 stays broken for this model.

Full patch, build/install steps, QA evidence and config templates (sanitized) are published here: https://github.com/CCanxue/codex-deepseek-subagent-fix

liushiyao110 · 24 days ago

Reproducing on Codex Desktop (macOS), app version 26.727.51351, with deepseek-v4-flash via the official one-command DeepSeek setup (wire_api = "responses", multi_agent_version: "v2" in models.json).

Both spawn_agent (initial task) and followup_task fail the same way: the child initializes, reads the workspace, then replies "I don't see a task in this message yet" / "Ready when you are — just send over the task."

Log evidence (rollout JSONL): the delivered agent_message contains an input_text envelope with an empty Payload: plus an encrypted_content block holding the actual task. The HTTP request POSTed to https://api.deepseek.com/responses carries that encrypted_content block untouched, so DeepSeek only sees the empty envelope. Normal user messages are plain input_text and work fine in the same session.

This confirms the issue is not CLI-only — it also affects the Desktop app with a non-OpenAI model as the root agent. Happy to provide full rollout logs or test a proposed fix.

trillox9 · 23 days ago

Same issue on codex-cli 0.146.0 with the official DeepSeek setup

Environment:

  • codex-cli 0.146.0 on Windows 11 (PowerShell)
  • model: deepseek-v4-flash
  • Provider configured exactly as in the official DeepSeek guide:

wire_api = "responses", base_url = "https://api.deepseek.com/",
model_catalog_json with multi_agent_version = "v2"

Reproduction:

  1. The main agent calls collaboration__spawn_agent with a concrete task

(e.g. "run Get-Date and return the output").

  1. The child agent starts, but instead of executing the task it replies

with a generic greeting: "I'm ready to help. What would you like me to
work on?"

  1. followup_task has the same behavior: the child keeps greeting and never

receives/executes the follow-up.

  1. With fork_turns="all", the child receives no task at all and instead

replays the parent's spawn calls from the inherited context, creating
recursive spawn chains (I had to interrupt them manually).

What I found in the logs:

input item of type "agent_message", with the real payload inside
"encrypted_content". The visible content stops at "Payload:" with an
empty text.

  • DeepSeek's Responses API compatibility table only supports these input

item types: message, function_call, function_call_output, reasoning,
web_search_call. It explicitly says other types are ignored.

  • As a result, the model never sees the task and just greets the user.

Expected behavior:

  • For non-OpenAI providers, subagent tasks should be delivered as a plain

user message (like the community patch does), or Codex should fail fast
with a clear "provider does not support agent_message input items"
error instead of silently dropping the task.

Happy to provide redacted request/response logs or test a patched build.

CCanxue · 22 days ago

Thanks for the additional reproductions. trillox9's point about DeepSeek's Responses compatibility table (only message, function_call, function_call_output, reasoning, and web_search_call are accepted; other input item types are ignored) explains why folding encrypted_content into plaintext input_text inside the agent_message item is not enough: the whole item type is dropped, not just the encrypted block.

For anyone who wants to test a fix now: we published a local patch for 0.146.0 that delivers V2 spawn / followup_task / send_message tasks as plain user messages for non-OpenAI providers (OpenAI path unchanged), verified on CLI and applicable to the Desktop bundled CLI. liushiyao110, the build/install steps in the repo cover the Desktop case as well. We also saw the same recursive spawn chains with fork_turns: all that trillox9 described, when the parent prompt leaks into the child context.

Repo: https://github.com/CCanxue/codex-deepseek-subagent-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.

CCanxue · 14 days ago

Thanks for confirming the root cause and for the refined v1 workaround. We can confirm the mechanism: with supports_search_tool = false, V1 tools are registered with direct exposure instead of being deferred behind tool_search, which addresses the discoverability problem we hit earlier with deepseek-v4-flash. This is a config-only change, so it also works on the official unpatched binary (no rebuild needed). The tradeoff is losing the V2 tool family (followup_task, send_message, list_agents, interrupt_agent); if you need those, a local patch that keeps V2 and delivers payloads as plain user messages for non-OpenAI providers is verified end-to-end: https://github.com/CCanxue/codex-deepseek-subagent-fix

HaoYue1027 · 5 days ago

Additional reproduction: Codex Desktop (Windows) + DeepSeek official setup, CLI 0.149.0 / app 26.818.5229.0 — confirms the same encrypted_content drop; workaround (multi_agent_version v1) matches your analysis.

Environment

  • OS: Windows 11 (Build 26200), desktop Codex app 26.818.5229.0; embedded runtime codex-cli 0.149.0 (internal kernel string 0.149.0-alpha.4 from app\resources\codex.exe; UI version string differs — checked the binary, not the UI, per codex-desktop-diagnostics).
  • Model: deepseek-v4-flash-vision-exp; model_provider = "deepseek"; base_url = "https://api.deepseek.com/"; wire_api = "responses".
  • ~/.codex/models.json written by the official DeepSeek one-command setup: all three entries (deepseek-v4-flash, deepseek-v4-pro, deepseek-v4-flash-vision-exp) have "multi_agent_version": "v2".

Reproduction (stable)

  1. In a Desktop session with the model above, call spawn_agent(task_name="acceptance", message="...", fork_turns="none") and wait_agent.
  2. list_agents shows the sub-agent completing with: “I only received session context; I don't see the concrete task content.”
  3. The stored agent_message in the session rollout (~/.codex/sessions/**/*.jsonl) is exactly:

``
Message Type: NEW_TASK
Task name: /root/acceptance
Sender: /root
Payload:
`
— length **82 chars,
Payload: is empty**. Reproduced 3+ times across spawn_agent/followup_task/send_message`, both before and after a full Desktop restart.

Causal isolation

  • Same spawn works after editing models.json: setting "multi_agent_version": "v1" for the three DeepSeek entries delivers the task as plaintext user input and the sub-agent executes correctly (verified once, then rolled back).
  • Control: with model_provider="deepseek" unchanged, fork_turns=1 partially masks the issue (child receives forked history but still not the per-agent spawn message), while fork_turns="none" yields a fully empty agent — consistent with encrypted_content being dropped by the third-party endpoint.
  • No error is surfaced anywhere; spawn_agent returns success and followup_task returns silently empty.

Boundary

  • Verified on Windows Desktop only; not tested on macOS/CLI in this report.
  • The workaround v1 is usable but loses the v2 tool surface (per your note) — I reverted it to keep the default v2 baseline while upstream decides.

Request

This repo already tracks it in #37237/#37822; adding my Windows Desktop + 0.149.0 data point. Expected: task body reaches the sub-agent (plaintext expansion before serialization, or a loud error for third-party providers). Actual: empty Payload: header, zero diagnostics. Please confirm and prioritize the suggested fix in build_responses_request (fold encrypted_content into InputText for non-OpenAI providers).