You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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_agent call 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.
Have the model call spawn_agent, send_message, or followup_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.
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.
Current status (2026-07-22)
This remains unresolved on current upstream main:
spawn_agent, send_message, and followup_task still expose only an encrypted message field.
All three handlers still construct InterAgentCommunication::new_encrypted(), leaving readable content empty.
The structured communication log still substitutes encrypted_content into its content field when plaintext is absent.
Rollout-trace still uses encrypted delivery content as message_content.
list_agents no longer exposes the most recent task/message.
A complete fork implementation now covers all three tools and makes delivery policy explicit:
encrypted preserves the current upstream opaque behavior.
encrypted_with_audit keeps encrypted recipient delivery and requires a separate readable task_message.
plaintext emits and persists one readable message, avoiding duplicate model output.
The implementation:
validates the selected schema/arguments before agent lookup or spawn;
applies one combined 8 KiB hard limit to each communication payload;
keeps the audit copy out of encrypted recipient-model input;
persists readable content in parent tool arguments and InterAgentCommunication.content;
prevents ciphertext from being presented as readable communication-log or rollout-trace content;
restores last_task_message for live list_agents inspection and serializes mailbox delivery with metadata updates;
preserves encrypted/plaintext communication representation through rollout resume and fork handling;
carries readable V2 spawn/follow-up text through SubAgentActivity into the parent TUI instead of showing only Started /root/child;
projects child-side ResponseItem::AgentMessage records into typed app-server/TUI history with sender attribution, stable IDs, encrypted placeholders, resume/pagination support, and duplicate suppression;
covers spawn_agent, send_message, and followup_task, including encrypted-only, encrypted-with-audit, and plaintext modes.
Upstream InterAgentCommunication::new_encrypted() deliberately initializes content as an empty string and stores the payload only in encrypted_content:
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:
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:
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:
Why changing the V2 tool schema is necessary but not sufficient for the TUI
The tool-schema/handler change makes readable text exist locally again, but current upstream main still drops that text before the relevant parent and child transcript surfaces.
For the parent view, upstream's SubAgentActivityEvent carries only the event ID, child ID/path, and activity kind. It has no task/prompt field:
For the child view, readable plaintext can already be present canonically as ResponseItem::AgentMessage, but upstream thread-history reconstruction ignores InterAgentCommunication records and its generic response-item handler accepts only hook-prompt user messages:
let codex_protocol::models::ResponseItem::Message{
role, content, id, ..
} = item
else{
return;
};
if role != "user"{
return;
Live raw response items are emitted only through the separate rawResponseItem/* notification path; that is not the normal typed thread-item stream consumed by the TUI and app-server clients:
Make V2 communication readable under an explicit delivery policy and persist that representation.
Carry readable parent activity prompts and child AgentMessage records through protocol conversion, app-server history/live notifications, resume/pagination, and TUI rendering.
The fork implements the second layer in the final three commits linked above. Plaintext messages render with sender attribution; encrypted-only messages render a fixed Input message encrypted placeholder rather than ciphertext. The durable projection is fork-owned and rebuildable from canonical plain or compressed rollouts so the same SQLite cache remains compatible with upstream Codex.
Implementation / fix spec
A concrete implementation can preserve encrypted delivery and restore a local audit trail:
Keep the existing encrypted message field as the delivery payload.
Add a required, non-encrypted plaintext companion to each v2 communication tool:
spawn_agent: task_message
send_message and followup_task: a consistently named plaintext audit field, such as task_message or message_text
Reject empty plaintext audit values at the handler boundary.
Construct InterAgentCommunication with both:
encrypted_content set to the encrypted message
content set 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.
Add readable prompt content to V2 sub-agent activity items and render it with a bounded TUI preview.
Convert persisted and live ResponseItem::AgentMessage records into normal typed thread items with sender attribution, stable IDs, and explicit encrypted-content redaction.
Preserve ordering and suppress duplicates across thread read/resume, pagination, running-thread subscription handoff, and agent switching.
The fork implementation linked in the current-status section now applies this contract consistently to spawn_agent, send_message, and followup_task, including local inspection, communication logs, and rollout-trace reduction.
Acceptance criteria
Parent rollout/history shows the readable text for v2 spawn_agent, send_message, and followup_task.
Parent TUI activity rows show the readable task/follow-up text rather than only the child path.
Child app-server/TUI history shows the same readable instruction with sender attribution; encrypted-only delivery shows a non-sensitive placeholder, never ciphertext.
The child model still receives only the encrypted delivery payload when encryption is enabled.
Communication logs use plaintext audit content when present and never substitute ciphertext into a field presented as readable message text.
Live notifications, thread/read, resume, pagination, and agent switching preserve one ordered copy of each communication.
Resume/replay preserves the audit copy without injecting it into the child model context, and remains compatible with canonical plain and compressed rollouts.
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, plus parent/child TUI rendering and live/resumed app-server history.
What version of Codex CLI is running?
Upstream
mainafter #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, andfollowup_taskmessage 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
messageparameter as encrypted, storing onlyInterAgentCommunication.encrypted_content, and leavingInterAgentCommunication.contentempty.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:
spawn_agentcall give the child agent?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?
spawn_agent,send_message, orfollowup_task.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
messagefield 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:
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.
Current status (2026-07-22)
This remains unresolved on current upstream
main:spawn_agent,send_message, andfollowup_taskstill expose only an encryptedmessagefield.InterAgentCommunication::new_encrypted(), leaving readablecontentempty.encrypted_contentinto itscontentfield when plaintext is absent.message_content.list_agentsno longer exposes the most recent task/message.A complete fork implementation now covers all three tools and makes delivery policy explicit:
encryptedpreserves the current upstream opaque behavior.encrypted_with_auditkeeps encrypted recipient delivery and requires a separate readabletask_message.plaintextemits and persists one readable message, avoiding duplicate model output.The implementation:
InterAgentCommunication.content;last_task_messagefor livelist_agentsinspection and serializes mailbox delivery with metadata updates;SubAgentActivityinto the parent TUI instead of showing onlyStarted /root/child;ResponseItem::AgentMessagerecords into typed app-server/TUI history with sender attribution, stable IDs, encrypted placeholders, resume/pagination support, and duplicate suppression;spawn_agent,send_message, andfollowup_task, including encrypted-only, encrypted-with-audit, and plaintext modes.Current implementation commits:
ignatremizov@2ffe360
ignatremizov@3b523d7
ignatremizov@ebb53b6
ignatremizov@7fd1514
ignatremizov@f6ddcea
ignatremizov@b60e626
Source analysis
Upstream
InterAgentCommunication::new_encrypted()deliberately initializescontentas an empty string and stores the payload only inencrypted_content:codex/codex-rs/protocol/src/protocol.rs
Lines 735 to 791 in bdd3118
The conversion used for recipient history then emits only the encrypted payload whenever
encrypted_contentis present. Merely populating the runtimecontentfield would therefore not create a readable persistedResponseItem; the fix also needs an explicit local audit persistence path:codex/codex-rs/protocol/src/protocol.rs
Lines 814 to 846 in bdd3118
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 bdd3118
send_messageandfollowup_taskstill deserialize onlytargetplus the encryptedmessage, 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 34 to 66 in bdd3118
codex/codex-rs/core/src/tools/handlers/multi_agents_v2/message_tool.rs
Lines 99 to 114 in bdd3118
The receiver records the model-facing
ResponseItemproduced byto_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 2957 to 2978 in bdd3118
The structured communication log has the same fallback: when
contentis empty, it recordsencrypted_contentas the event content:codex/codex-rs/core/src/agent_communication.rs
Lines 44 to 66 in bdd3118
Why changing the V2 tool schema is necessary but not sufficient for the TUI
The tool-schema/handler change makes readable text exist locally again, but current upstream
mainstill drops that text before the relevant parent and child transcript surfaces.For the parent view, upstream's
SubAgentActivityEventcarries only the event ID, child ID/path, and activity kind. It has no task/prompt field:codex/codex-rs/protocol/src/protocol.rs
Lines 4340 to 4350 in bdd3118
The app-server
ThreadItem::SubAgentActivitylikewise exposes no prompt:codex/codex-rs/app-server-protocol/src/protocol/v2/item.rs
Lines 357 to 364 in bdd3118
The upstream TUI therefore renders only
Started,Interacted with, orInterruptedplus the agent path, with an empty detail list:codex/codex-rs/tui/src/multi_agents.rs
Lines 303 to 320 in bdd3118
For the child view, readable plaintext can already be present canonically as
ResponseItem::AgentMessage, but upstream thread-history reconstruction ignoresInterAgentCommunicationrecords and its generic response-item handler accepts only hook-prompt user messages:codex/codex-rs/app-server-protocol/src/protocol/thread_history.rs
Lines 395 to 407 in bdd3118
codex/codex-rs/app-server-protocol/src/protocol/thread_history.rs
Lines 446 to 455 in bdd3118
Live raw response items are emitted only through the separate
rawResponseItem/*notification path; that is not the normal typed thread-item stream consumed by the TUI and app-server clients:codex/codex-rs/app-server/src/bespoke_event_handling.rs
Lines 1045 to 1053 in bdd3118
codex/codex-rs/app-server/src/bespoke_event_handling.rs
Lines 1418 to 1431 in bdd3118
So a complete local fix has two layers:
AgentMessagerecords through protocol conversion, app-server history/live notifications, resume/pagination, and TUI rendering.The fork implements the second layer in the final three commits linked above. Plaintext messages render with sender attribution; encrypted-only messages render a fixed
Input message encryptedplaceholder rather than ciphertext. The durable projection is fork-owned and rebuildable from canonical plain or compressed rollouts so the same SQLite cache remains compatible with upstream Codex.Implementation / fix spec
A concrete implementation can preserve encrypted delivery and restore a local audit trail:
messagefield as the delivery payload.spawn_agent:task_messagesend_messageandfollowup_task: a consistently named plaintext audit field, such astask_messageormessage_textInterAgentCommunicationwith both:encrypted_contentset to the encryptedmessagecontentset to the plaintext audit copyto_model_input_item()behavior unchanged so the recipient model still receives ciphertext, not the local audit copy.ResponseItem::AgentMessagerecords into normal typed thread items with sender attribution, stable IDs, and explicit encrypted-content redaction.The fork implementation linked in the current-status section now applies this contract consistently to
spawn_agent,send_message, andfollowup_task, including local inspection, communication logs, and rollout-trace reduction.Acceptance criteria
spawn_agent,send_message, andfollowup_task.message_content.thread/read, resume, pagination, and agent switching preserve one ordered copy of each communication.