MultiAgentV2 plaintext support in 0.147.0-alpha.1 does not complete cross-provider task delivery

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

Summary

#35845, included in 0.147.0-alpha.1, added support for processing plaintext collaboration tool messages.

However, that change covers the receiving path only when plaintext has already been selected upstream. It does not provide an end-to-end way for an OpenAI parent to select plaintext delivery when spawning a child backed by a third-party provider.

As a result, the cross-provider failure reported in #34833 remains reproducible on a source baseline of 0.147.0-alpha.4: the child is created with the intended role, provider, and model, but cannot consume its initial task because the assignment is still delivered as provider-specific encrypted content.

Environment

  • Windows
  • Codex Desktop
  • Source baseline: codex-cli 0.147.0-alpha.4
  • Parent: OpenAI provider
  • Child: third-party provider using an OpenAI-compatible API
  • Multi-agent implementation: V2
  • Direct requests to the third-party provider succeed

Provider names, endpoints, credentials, account information, and third-party model identifiers have been intentionally omitted.

Observed behavior

  1. Enable MultiAgentV2.
  2. Configure a registered child role backed by a third-party provider.
  3. Start an OpenAI-backed parent.
  4. Invoke spawn_agent for that child role.
  5. Codex resolves the intended child role, provider, and model and creates the child.
  6. The child cannot read the initial assignment and therefore cannot begin the task.

The same third-party provider succeeds when invoked directly, which isolates the failure to the MultiAgentV2 provider boundary rather than authentication, networking, or model availability.

Why the 0.147.0-alpha.1 fix is incomplete

The implementation added by #35845 preserves encrypted_function_args and introduces ToolCallSource::DirectPlaintextMessage. A collaboration call is classified as plaintext only when all of the following are true:

  • the namespace is exactly collaboration;
  • the tool is spawn_agent, send_message, or followup_task;
  • encrypted_function_args == Some([]).

When that marker is present, the handlers construct a structured plaintext agent message. Otherwise, they retain the existing encrypted path.

The remaining gap is that the MultiAgentV2 tool schemas still unconditionally apply .with_encrypted() to the message fields for spawn_agent, send_message, and followup_task. An OpenAI parent therefore normally produces actual encrypted arguments rather than the empty marker required by DirectPlaintextMessage. The call is classified as Direct, and the handler still uses:

InterAgentCommunication::new_encrypted(...)

The third-party child then receives content it cannot decrypt or interpret.

The alpha.1 implementation also has the following limitations for this topology:

  • plaintext classification is hard-coded to the collaboration namespace;
  • a configured custom namespace cannot enter the plaintext branch;
  • providers without namespace-tool support cannot match that condition;
  • there is no provider-aware delivery selection;
  • there is no explicit configuration to request plaintext delivery;
  • encrypted delivery to a third-party child is not rejected before the unusable child is created.

The relevant schema, classification, and message-construction behavior remains materially unchanged between 0.147.0-alpha.1 and 0.147.0-alpha.4.

Simply removing .with_encrypted() is also insufficient. A modified plaintext schema under the reserved collaboration namespace is rejected by the OpenAI API because reserved collaboration functions must match the configured schema exactly. A complete fix therefore also needs a supported non-reserved namespace or an upstream-compatible schema mechanism.

Local source-level fix path

I implemented and validated an opt-in, backwards-compatible delivery policy across the following source paths.

Configuration and schema

  • codex-rs/features/src/feature_configs.rs
  • codex-rs/features/src/lib.rs
  • codex-rs/core/src/config/mod.rs
  • codex-rs/core/config.schema.json

The local configuration shape is:

[features.multi_agent_v2]
enabled = true
message_delivery = "plaintext"
tool_namespace = "agents"

encrypted remains the default.

Tool schemas

  • codex-rs/core/src/tools/handlers/multi_agents_spec.rs

The encrypted marker is applied conditionally to the message fields for spawn_agent, send_message, and followup_task.

Tool planning and call classification

  • codex-rs/core/src/tools/spec_plan.rs
  • codex-rs/core/src/tools/router.rs
  • codex-rs/core/src/tools/parallel.rs

Plaintext mode classifies the relevant calls as DirectPlaintextMessage using the configured tool namespace rather than only the hard-coded collaboration namespace.

MultiAgentV2 message handling

  • codex-rs/core/src/tools/handlers/multi_agents_v2.rs
  • codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
  • codex-rs/core/src/tools/handlers/multi_agents_v2/send_message.rs
  • codex-rs/core/src/tools/handlers/multi_agents_v2/followup_task.rs
  • codex-rs/core/src/stream_events_utils.rs

Plaintext mode reuses the structured input_text path. If an encrypted task is about to be delivered to a non-OpenAI child, the spawn fails before child creation with an actionable configuration error.

Validation results

  • Feature configuration tests: 34/34 passed.
  • Targeted MultiAgentV2 tests: 74/74 passed.
  • Plaintext tool-schema tests passed.
  • Custom and unnamespaced collaboration-tool tests passed.
  • Structured parent-to-child input_text delivery tests passed.
  • Fail-closed tests for encrypted delivery to a third-party child passed.
  • Release build succeeded.
  • After fully restarting Codex Desktop with the local build, an OpenAI parent successfully spawned a third-party-provider child.
  • The child received the assignment, executed it, and returned the expected fixed marker.
  • The default encrypted behavior remains unchanged.

Expected upstream behavior

A complete upstream solution should:

  1. Keep encrypted delivery as the default.
  2. Provide an explicit plaintext delivery policy for providers that cannot consume OpenAI encrypted tool parameters.
  3. Apply the policy consistently across tool schemas, planning, routing, and message construction.
  4. Support a non-reserved tool namespace for plaintext collaboration schemas.
  5. Fail before spawning when encrypted delivery is incompatible with the selected child provider.
  6. Add an end-to-end integration test for an OpenAI parent spawning a third-party-provider child.

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 22 days ago

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

  • #36376
  • #36387
  • #36586
  • #36321
  • #35932

Powered by Codex Action

NOirBRight · 14 days ago

CodexHub Beta4.1 status update (sanitized; no credentials or raw ciphertext included).

We independently confirmed that the plaintext receiving path alone does not complete cross-provider delivery. In the OpenAI-parent -> non-OpenAI-child case, the parent-side V2 handoff can still carry a real Fernet-like ciphertext in encrypted_content; a downstream Gateway cannot decrypt it, so envelope rewrites or removal of the encrypted JSON-schema marker cannot recover the task text.

Implemented in CodexHub Beta4.1 at the Gateway boundary:

  • Adapt the V2 collaboration namespace into ordinary third-party function tools.
  • Use deterministic/collision-safe aliases and reverse-map normal and streamed function calls/results.
  • Strip Official-only encrypted schema annotations from the external tool declarations.
  • Preserve Official OpenAI passthrough unchanged.
  • Keep history/replay transformations bounded and covered by regression tests.

This proves the protocol/tool-surface adapter direction, not full OpenAI-parent -> external-child delivery. The external model is not being treated as natively V2-capable; the Gateway is adapting ordinary tool-calling behavior into the Codex V2 lifecycle surface.

Requested upstream resolution:

  1. Add an explicit provider-aware delivery policy selected from the actual target provider.
  2. Keep OpenAI -> OpenAI opaque/encrypted behavior unchanged.
  3. For non-OpenAI targets, emit a provider-neutral plaintext user/message representation (or decrypt/re-encode at an upstream boundary) for spawn, follow-up, and send-message.
  4. Fail closed with a clear unsupported-cross-provider error when the target cannot consume the selected representation.
  5. Add an end-to-end OpenAI-parent -> third-party-child regression test, including follow-up/send-message.

Until that producer-side change exists, CodexHub can ship the tool-surface adapter separately but cannot honestly claim complete cross-provider V2 lifecycle support.