Codex starts encrypting sub-agent prompts
What version of Codex CLI is running?
Upstream main after #26210 (Encrypt multi-agent v2 message payloads, merged 2026-06-05). This appears to affect versions that include that change and enable MultiAgentV2 (post-0.137.0).
What subscription do you have?
Not subscription-specific.
Which model were you using?
Not model-specific. This concerns MultiAgentV2 spawn_agent, send_message, and followup_task message handling.
What platform is your computer?
Not platform-specific.
What terminal emulator and version are you using (if applicable)?
Not terminal-specific.
Codex doctor report
Not applicable. The regression is visible from the merged code behavior in #26210 rather than from local environment state.
What issue are you seeing?
#26210 makes MultiAgentV2 agent task/message payloads opaque to Codex by marking the model-facing message parameter as encrypted, storing only InterAgentCommunication.encrypted_content, and leaving InterAgentCommunication.content empty.
The encrypted delivery path is understandable as privacy hardening, but it also removes the human-readable task/message text from local rollout history, trace reduction, and parent-side audit/debug surfaces. That makes it difficult to answer basic questions such as:
- What task did this
spawn_agentcall give the child agent? - What message was sent to a subagent?
- Why did a child thread exist when reviewing a rollout after the fact?
This is different from #26753, which reports request validation failures for encrypted tool schemas. This issue is about auditability and debuggability after the encrypted schema is accepted.
What steps can reproduce the bug?
- Use a build containing Encrypt multi-agent v2 message payloads #26210 with MultiAgentV2 enabled. (aka post-0.137.0)
- Have the model call
spawn_agent,send_message, orfollowup_task. - Inspect the parent rollout/history/trace for the subagent task.
- The task/message content is hidden behind ciphertext rather than being available as human-readable audit text.
What is the expected behavior?
Codex should preserve a human-readable, structured audit copy of the subagent task/message while still allowing encrypted delivery to the recipient model.
A possible shape is to keep the encrypted message field for model delivery, but add a separate non-encrypted audit field for the readable task text. The audit field should be persisted in rollout/history/trace metadata so users and maintainers can inspect what was delegated without needing to decrypt model-delivery ciphertext.
Additional information
Related PR/issues:
- Encryption change: Encrypt multi-agent v2 message payloads #26210
- Related but distinct schema-validation issue: MultiAgentV2 encrypted spawn_agent schema returns 400: model not configured for encrypted tool use #26753
The goal is not necessarily to revert encrypted delivery. The concern is that encrypted delivery should not fully remove local human auditability for subagent delegation.
Source analysis
Upstream InterAgentCommunication::new_encrypted() deliberately initializes content as an empty string and stores the payload only in encrypted_content:
codex/codex-rs/protocol/src/protocol.rs
Lines 735 to 791 in fde21ba
The conversion used for recipient history then emits only the encrypted payload whenever encrypted_content is present. Merely populating the runtime content field would therefore not create a readable persisted ResponseItem; the fix also needs an explicit local audit persistence path:
codex/codex-rs/protocol/src/protocol.rs
Lines 813 to 845 in fde21ba
The current v2 message helper constructs encrypted communication with empty plaintext content:
codex/codex-rs/core/src/tools/handlers/multi_agents_v2.rs
Lines 54 to 65 in fde21ba
send_message and followup_task still deserialize only target plus the encrypted message, then pass that ciphertext directly through the shared helper. There is no plaintext companion available to persist:
codex/codex-rs/core/src/tools/handlers/multi_agents_v2/message_tool.rs
Lines 99 to 114 in fde21ba
The receiver records the model-facing ResponseItem produced by to_model_input_item(). For encrypted communication that item contains the encrypted delivery payload, not readable audit text:
codex/codex-rs/core/src/session/mod.rs
Lines 2929 to 2957 in fde21ba
The structured communication log has the same fallback: when content is empty, it records encrypted_content as the event content:
codex/codex-rs/core/src/agent_communication.rs
Lines 44 to 66 in fde21ba
Implementation / fix spec
A concrete implementation can preserve encrypted delivery and restore a local audit trail:
- Keep the existing encrypted
messagefield as the delivery payload. - Add a required, non-encrypted plaintext companion to each v2 communication tool:
spawn_agent:task_messagesend_messageandfollowup_task: a consistently named plaintext audit field, such astask_messageormessage_text
- Reject empty plaintext audit values at the handler boundary.
- Construct
InterAgentCommunicationwith both:encrypted_contentset to the encryptedmessagecontentset to the plaintext audit copy
- Keep
to_model_input_item()behavior unchanged so the recipient model still receives ciphertext, not the local audit copy. - Persist the plaintext companion in the parent tool invocation/rollout and retain it in structured trace edges and local communication logs.
- Match tool calls to delivered child items using ciphertext/IDs, not plaintext equality. The plaintext field is audit metadata and should not replace the encrypted delivery identity.
- Bound the plaintext audit field with the same hard size limit as the corresponding delegated message so the new rollout/context item cannot grow without limit.
The spawn_agent half of this shape is implemented in the following snapshot commit:
That prototype makes task_message required in the v2 spawn schema:
v2 spawn_agent schema and required task_message field
It validates the field and places it in InterAgentCommunication.content while leaving the encrypted delivery payload in encrypted_content:
dual plaintext audit and encrypted delivery construction
It also teaches rollout-trace reduction to keep readable audit content while using the encrypted value only to correlate the tool invocation with delivery:
separate audit content from delivery-match content
correlate delivery while applying readable audit content
The remaining implementation work is to apply the same dual-content contract to send_message and followup_task, and to ensure every user-facing history/replay/debug surface reads the audit copy rather than falling back to provider ciphertext.
Acceptance criteria
- Parent rollout/history shows the readable text for v2
spawn_agent,send_message, andfollowup_task. - The child model still receives only the encrypted delivery payload when encryption is enabled.
- Structured rollout-trace interaction edges carry bounded plaintext
message_content. - Communication logs use plaintext audit content when present and never substitute ciphertext into a field presented as readable message text.
- Resume/replay preserves the audit copy without injecting it into the child model context.
- Existing plaintext v1 communication behavior is unchanged.
- Regression tests cover all three v2 tools and assert both sides of the contract: readable local audit data and encrypted recipient-model input.
Source: hackernews