Repository navigation
MultiAgentV2 cross-provider subagent cannot consume encrypted task assignment #34833
Description
Summary
With an OpenAI parent and a correctly selected non-OpenAI custom-provider child, MultiAgentV2 delivers the child assignment only as encrypted content that the custom-provider model cannot consume.
The spawned child metadata shows the intended custom role, provider, model, and MultiAgentV2 implementation, but the child sees an empty visible Payload: and reports that it has no assignment.
A same-provider OpenAI child consumes an otherwise equivalent encrypted assignment successfully.
Environment
- Codex CLI: 0.145.0
- Surface: Codex desktop connected to a remote Codex app-server over SSH
- Multi-agent version: v2
- Parent provider: OpenAI
- Child role: registered custom agent
- Child provider: non-OpenAI, OpenAI-compatible Chat Completions provider
- Child model: Kimi K3
Reproduction
- Enable
multi_agent_v2. - Configure a registered custom child agent using a non-OpenAI provider and an OpenAI-compatible Chat Completions model.
- Start an OpenAI-backed parent.
- Spawn the custom child with a unique harmless marker and an explicit instruction to run
pwd. - Inspect the spawned session metadata and child handoff.
The session metadata confirms:
agent_roleis the registered custom role.multi_agent_versionisv2.model_provideris the intended custom provider.modelis the intended custom model.
The stored handoff displays an empty Payload: and contains an encrypted-content block. The child reports that it received no assignment and does not execute the marker or pwd.
In a related continuation path, the parent can terminate with:
Encrypted function output content could not be decrypted or decoded.
Control: same-provider child
Repeat the test with an OpenAI child.
Its stored handoff also displays an empty visible Payload: plus encrypted content, but the OpenAI child successfully consumes the assignment, reproduces the marker, runs pwd, and returns the expected path.
This indicates that general v2 dispatch works and that the problem is specific to the provider boundary.
Control: provider-neutral delivery
As a diagnostic only, provide the same assignment to the custom child through a single-use, permission-restricted, nonce-bound local file referenced by the custom agent's developer instructions.
The custom child then executes the marker and pwd successfully.
This confirms that:
- The custom provider and model are operational.
- Child provider/model selection works.
- The task itself is valid.
- Failure occurs when the assignment is carried only through the encrypted MultiAgentV2 field.
A fixed file inbox is not a safe permanent workaround because of stale-task, concurrency, cleanup, attribution, and local instruction-injection risks.
Expected behavior
Codex should make the assignment available to the selected child in a representation that its configured provider can consume.
Possible implementations include decrypting/translating the assignment within Codex before invoking a provider that does not support OpenAI encrypted tool parameters, or explicitly rejecting unsupported cross-provider delegation before spawning the child.
Actual behavior
The custom child is spawned with the correct role, provider, and model, but cannot consume the encrypted assignment and behaves as though no task was supplied.
Related issues
codex exec: multi_agent_v2 subagent results unusable — parent turn fails with "Encrypted function output content could not be decrypted or decoded" #33267 - exact decryption error when consuming MultiAgentV2 child results- Model switch mid-conversation fails: "encrypted content could not be decrypted" #17541 - provider-specific encrypted content retained across a provider/model boundary
- MultiAgentV2 encrypted spawn_agent schema returns 400: model not configured for encrypted tool use #26753 - MultiAgentV2 agent tools use encrypted parameters
- Invalid Value: 'tools'. Function 'functions.followup_task' declares encrypted parameters but is not configured for encrypted tool use by this model. #27205 - model not configured for encrypted tool use
- Native subagent orchestration does not work correctly with non-OpenAI custom providers #17598 - native subagent orchestration with non-OpenAI custom providers
- Multi-agent V2 regression: subagent instructions are no longer observable #32753 - encrypted MultiAgentV2 assignments are no longer observable
Additional notes
This is not a request to support a CPA-backed parent. The failing topology is specifically:
OpenAI parent -> registered non-OpenAI custom-provider child
Please let me know which narrowly scoped logs or sanitized session records would help. I have intentionally omitted authorization data, internal network details, complete encrypted blobs, and unrelated prompts.
Activity
github-actions commentedon Jul 22, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
qqq-jump commentedon Jul 22, 2026
Thanks — I reviewed #33551. It is closely related, but I do not think it is an exact duplicate.
#33551 focuses on external Responses providers receiving the OpenAI-specific
agent_messageitem type, which may be rejected even when the item is plaintext.This report reproduces with a custom provider using the OpenAI-compatible Chat Completions protocol. The child session is created with the correct custom role, provider, and model, but the assignment is available only through the encrypted MultiAgentV2 handoff and the child behaves as though no task was supplied. The same encrypted handoff is consumed successfully by an OpenAI child, while the same custom-provider child executes the task when it is delivered through a provider-neutral plaintext diagnostic.
So the reports may share the same broader need for provider-aware inter-agent transport, but they exercise different provider protocols and failure points. I am leaving this open for maintainer triage and am happy for it to be consolidated if the fix for #33551 is intended to cover Chat Completions providers as well.
ignatremizov commentedon Jul 23, 2026
You can change model catalogue to force v1. Anyways duplicate of #28058
ysxk commentedon Jul 23, 2026
Corroboration from Codex desktop multi-role session
Confirmed the same MultiAgentV2 cross-provider failure on Codex desktop / CLI 0.145.0-alpha.30, macOS
Darwin 25.5.0 arm64, with project-local agents under.codex/agents/.Topology
gpt-5.6-sol(MultiAgentV2)frontendrole →kimi-k3(custom/non-OpenAI)backendrole →gpt-5.6-sol(OpenAI control)skills_openapirole →grok-4.5via external Responses gateway (separate wire-format failure; see also Multi-Agent V2 sends OpenAI-specific agent_message items to external Responses providers #33551)Observed behavior (Kimi K3 child)
spawn_agent(agent_type=frontend, ...)succeeds; child thread starts with correct role/model.encrypted_contentonly (visiblePayload:empty).followup_taskto the same child produces the same empty-payload handoff; child reasons "The parent agent hasn't sent a task yet" and stands by again.backendchild ongpt-5.6-solconsumes the assignment and executes immediately.developer_instructionsmakes the K3 child start working (reads repo). Same model channel is therefore operational; only the encrypted MultiAgentV2 assignment path fails.Follow-up
Parent eventually completed the work by temporarily spawning the same frontend role on
gpt-5.6-sol. Persistent project config remained on K3.Expected
If Codex allows selecting a non-OpenAI provider for a registered child role, MultiAgentV2 should deliver spawn/followup/send_message assignments in a representation that provider can consume (decrypt/translate at the boundary to a standard plaintext
messageitem), or fail fast with an explicit unsupported-cross-provider error before the child stands by forever.Related
agent_messageitems (matches our Grok path)codex exec: multi_agent_v2 subagent results unusable — parent turn fails with "Encrypted function output content could not be decrypted or decoded" #33267 — encrypted multi-agent function output decrypt failuresHappy to provide redacted rollout excerpts (parent + child) if useful; avoiding full ciphertext and internal network details here.
qqq-jump commentedon Jul 24, 2026
Thanks — V1 can indeed be forced and works as a workaround, but it gives up quite a bit of V2 functionality.
My understanding is that #28058 is related but slightly different: it concerns the loss of a readable audit trail, whereas this issue concerns the encrypted handoff preventing a non-OpenAI sub-agent from receiving the task at all. The underlying mechanism may be the same, but the user-facing problems are different.
CCanxue commentedon Aug 3, 2026
Additional data from codex-cli 0.146.0 source with a real DeepSeek child (wire-captured).
For the non-OpenAI -> non-OpenAI direction, the task text only ever reaches the child inside
encrypted_content; DeepSeek drops that block and the child sees an emptyPayload:. Even after rewriting theagent_messagecontent so the payload is plaintextinput_text, DeepSeek still ignores theagent_messageitem in most runs. The task is only consumed reliably when delivered as a plainusermessage.For the OpenAI -> non-OpenAI direction,
messageis real ciphertext withencrypted_function_args: null, so a local request transform cannot decrypt it (see also #36376).We published a local patch that delivers V2 spawn / followup_task / send_message payloads as plain user input for non-OpenAI providers (OpenAI path unchanged), verified end-to-end: https://github.com/CCanxue/codex-deepseek-subagent-fix
YukiagoTpf commentedon Aug 6, 2026
Follow-up after validating the plaintext collaboration changes shipped in
0.147.0-alpha.1via #35845:The cross-provider failure described here remains reproducible on a
0.147.0-alpha.4source baseline.The alpha.1 change added a valid plaintext receiving path, but that path is entered only when
encrypted_function_args == Some([])and the tool namespace is exactlycollaboration. The MultiAgentV2 schemas still unconditionally mark the message fields forspawn_agent,send_message, andfollowup_taskwith.with_encrypted(). An OpenAI parent therefore normally supplies actual encrypted arguments, the call remainsDirect, and the child assignment is still constructed withInterAgentCommunication::new_encrypted(...).This leaves the original third-party-provider topology unresolved. It also does not cover custom or absent tool namespaces, does not expose an explicit delivery policy, and does not fail before creating a child that cannot consume the encrypted task.
I implemented and tested a local source-level path with an opt-in plaintext delivery policy, a non-reserved tool namespace, end-to-end call classification, and a fail-closed guard. Targeted feature tests passed 34/34, targeted MultiAgentV2 tests passed 74/74, the release build succeeded, and a restarted Codex Desktop session successfully completed an OpenAI-parent to third-party-provider-child smoke test.
The full analysis, affected source paths, sanitized configuration shape, and validation results are documented in #37197.
CCanxue commentedon Aug 6, 2026
Thanks for the detailed analysis. It matches what we observed on the non-OpenAI parent side: the #35845 plaintext marker is only entered with
encrypted_function_args == Some([]), which third-party parents do not emit, and even a plaintextagent_messageitem is dropped by DeepSeek (its Responses compatibility table only acceptsmessage,function_call,function_call_output,reasoning, andweb_search_callitem types).Our local patch takes a simpler route for the non-OpenAI parent case: V2 spawn / followup_task / send_message payloads are delivered as plain
UserInput(V1-style standard user messages), verified end-to-end with deepseek-v4-flash. It intentionally does not cover the OpenAI-parent -> third-party-child case, which still needs an opt-in plaintext delivery policy like the one you described; the fail-closed guard and end-to-end call classification sound like the right direction. Patch, wire evidence, and write-up: https://github.com/CCanxue/codex-deepseek-subagent-fixsnoyiatk commentedon Aug 11, 2026
+1 we need to merge/fix this issue so codex is really usable with open-weighted models
NOirBRight commentedon Aug 13, 2026
CodexHub Beta4.1 follow-up (sanitized; no credentials or raw ciphertext included).
This issue remains an upstream producer/delivery limitation for the OpenAI-parent -> non-OpenAI-child direction. We reproduced that the child can be created correctly while the V2 assignment is available only through an
agent_message/encrypted_contenthandoff containing ciphertext. A Gateway downstream of the parent cannot decrypt that value; simply converting the item shape to a normal function/message or removing an Official schema flag does not restore the task body.CodexHub Beta4.1 has completed the separate Gateway adaptation work: V2 namespace declarations are presented to third-party models as ordinary function tools, aliases are deterministic and reversible, streamed/non-streamed calls and history are adapted, and Official OpenAI traffic remains passthrough. This is an adapter for ordinary tool-calling models, not a claim that they natively understand Codex V2.
The missing piece is provider-aware delivery on the upstream producer side: retain encrypted transport for OpenAI targets, but use a provider-neutral plaintext user/message path for non-OpenAI targets across spawn/follow-up/send-message, with a fail-closed error when unsupported. We are keeping the full external-V2 lifecycle gate open rather than marking it passed based only on tool declarations or a model catalog flag.
ta9to commentedon Aug 15, 2026
Reproduced on stable 0.147.0 with Vercel AI Gateway + DeepSeek
I reproduced the OpenAI-parent -> non-OpenAI-child failure on the current stable CLI, with a Responses-compatible hosted gateway rather than a local provider.
Environment
codex-cli 0.147.0gpt-5.6-sol/ MultiAgentV2deepseek_flash_0731wire_api = "responses"deepseek/deepseek-v4-flash-0731fork_turns = "none"Observed
model_provider = "vercel_ai_gateway"; the child turn used the intended DeepSeek model.spawn_agent.messagewas stored as encrypted content.This matches the empty/missing assignment behavior described here: provider/model selection succeeds, but the dynamic V2 handoff is not consumable across the provider boundary.
Controls
/v1/responsesendpoint with the exact model returned the expected canary.codex execsubprocess. DeepSeek then successfully created a minimal PythonHello, World!program, executed it, and verified exact stdout.That last control confirms that Vercel authentication, the DeepSeek model, Responses transport, tool execution, and file writes are all operational. The failure remains isolated to native MultiAgentV2 cross-provider task delivery.
joenoon commentedon Sep 22, 2026
Additional reproduction with Codex CLI 0.155.1 and Vercel AI Gateway, using an OpenAI model for both parent and child.
Configuration
gpt-6-astra, low reasoning effortwire_api = "responses"https://ai-gateway.vercel.sh/codex/v1codex exec, outside our application and App Server integrationV2 reproduction
We asked the parent to spawn exactly one child, have it read a harmless marker file, and return its contents.
The child started, but its transcript contained an
agent_messagewith a task header andencrypted_content. It replied, “What would you like me to work on?” without reading the file. The parent continued waiting until our test harness interrupted it at 180 seconds.Successful V1 control
Using the same CLI, model, and endpoint, we supplied a temporary copy of the bundled model catalogue through
model_catalog_json, changing:multi_agent_versionto"v1"supports_search_tooltofalseThe child then received the assignment as plain user input, read the marker file, and returned the correct result. The parent received it through native wait and completed normally.
We did not modify Codex or rewrite network traffic. This was an isolated test; we have not adopted the catalogue override in our product.
Related: #36586 documents the V1/tool-discovery workaround, which also succeeded in our test.
Our case does not switch to a non-OpenAI model: both agents use an OpenAI model through Gateway. We have not isolated whether the failure occurs in Codex, Gateway translation, or the upstream endpoint.
Is V2 task delivery expected to work in this configuration? Is there a supported fix or configuration we should test before relying on the V1 catalogue override?
We can provide sanitized transcript excerpts and a minimal reproduction.
cgasgarth commentedon Oct 5, 2026
Verified a small producer-side plaintext V2 prototype on official Codex
0.160.0(October 4, 2026). Using an ordinaryagentsnamespace plus a two-file opt-in patch, real GPT → Fable/Opus/GPT tasks, Claude Opus → GPT tasks, follow-ups, proactive messages, and an app-server GPT → Opus → GPT chain all completed with independently verified files.This does not decrypt ciphertext or merely reclassify sealed bytes. The patch changes both message schemas and delivery selection so the generated tasks are readable from the start. All nine saved sessions recorded V2 and the requested models; their 34 inter-agent input records had no encrypted parts.
Full evidence and limits: #46939 (comment)
Source patch and reproducible probes: https://github.com/cgasgarth/skills/tree/e5b3134/patches/v2-plaintext
This is isolated CLI/app-server backend proof, not desktop UI acceptance or an upstream-supported configuration. Existing encrypted history and other providers remain outside the tested scope.
cgasgarth commentedon Oct 5, 2026
Update: verified both GPT Sol → Claude Opus and Claude Opus → GPT Sol in actual desktop-app chats with the official signed Codex 0.160.0 backend. Initial tasks, explicit parent-directed messages, and same-child follow-ups all passed.
VibeProxy's installed CLIProxyAPI 8.0.4 already supports
codex.optimize-multi-agent-v2: true. Codex also needs V2 enabled and V2 model catalog entries for the children's collaboration tools. No custom Codex build or app patch is needed for this setup.The previous local-build approach broke native app tools because of macOS peer code-signature checks (#34583). It has been removed.
Configuration, source links, results, and scope: #46939 (comment)
Deliver plaintext collaboration tasks as a standard user message
Add tools/mode8verify to check mode-8 capabilities
jesus-rwp commentedon Oct 17, 2026
Cross-referencing the non-OpenAI parent → OpenAI-compatible child direction, which fails differently from the empty-payload case above: the child rejects the handoff with
400 {"code":"thinking_signature_invalid","message":"Encrypted function output content could not be decrypted or decoded."}.The gate added in #35845 is still
encrypted_function_args.as_ref().is_some_and(Vec::is_empty)inToolCall::direct_source()(codex-rs/core/src/tools/router.rs). Third-party parents that omit the field entirely (None) never enter the plaintext path, soagent_message_from_toolwraps the parsed plaintext message asAgentMessage::Encrypted. TreatingNonelike[](is_none_or(Vec::is_empty)) fixes that direction without a config switch; code-mode nested calls hit the same path because they build the call withencrypted_function_args: None.Repro, the two-line patch and test results are in #36586: #36586 (comment)
Scope note: this only fixes the content-type/signature failure for children that accept
agent_message. The separate DeepSeek behavior of dropping the wholeagent_messageitem (#33551) still needs a user-message delivery path.