Regression: encrypted MultiAgentV2 messages remove readable task audit trail #28058
Description
What version of Codex CLI is running?
Originally reported after #26210 (Encrypt multi-agent v2 message payloads, merged 2026-06-05; post-0.137.0). Source review refreshed on 2026-10-26 against upstream main at 245691b2dc66. References to my fork below are from the maintained 0.164.0 integration.
What subscription do you have?
Not subscription-specific.
Which model were you using?
This concerns the default encrypted delivery used by MultiAgentV2 spawn_agent, send_message, and followup_task.
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 to this source-level report.
What issue are you seeing?
This issue remains unresolved in upstream's default MultiAgentV2 workflow. Encrypted message delivery is still the default. Users still cannot inspect the exact tasks delegated by the parent, follow-up instructions, or intermediate child-to-parent messages when those payloads are encrypted.
#35845 added conditional plaintext-response handling and provider compatibility, but did not change that default or add a user-configurable plaintext delivery policy. The response flag and non-OpenAI provider handling are described below. Even when that separate plaintext path is used, normal parent/child transcript surfaces still omit readable messages.
This concerns messages explicitly sent between agents. The requested audit trail does not require exposing private reasoning.
What steps can reproduce the bug?
- Use the default OpenAI MultiAgentV2 workflow and delegate a task with
spawn_agent; optionally send follow-ups withsend_messageorfollowup_task. - Inspect the parent activity rows, switch to the child, and inspect its normal transcript/history.
- The encrypted task/message payload is unavailable locally as readable text.
- Resume the session and check the same surfaces. Knowing that a child ran or seeing its terminal answer does not establish what assignment or intermediate handoff it received.
What is the expected behavior?
Users should be able to choose readable inter-agent delivery and inspect a structured operational transcript with sender/recipient attribution. If encrypted delivery is retained, an explicit readable audit-copy mode is also useful.
The chosen representation should survive live display, history, resume, pagination, and agent switching. Ciphertext should never be presented as readable message text.
Current upstream status (2026-10-26)
Encrypted delivery remains the upstream default. All three bundled V2 schemas still mark message encrypted, and ordinary direct calls without an explicit plaintext response marker follow the encrypted path. Users have no upstream equivalent of my fork's delivery-policy setting.
#35845 added a conditional plaintext path and related provider compatibility. A direct collaboration response must explicitly carry encrypted_function_args: [] to be classified as plaintext; an absent marker does not select plaintext. For non-OpenAI provider requests, the client removes this OpenAI-specific metadata when serializing history: provider handling. This is provider-response metadata, not a user flag that disables encryption in the default OpenAI workflow.
The V2 helper also has a separate Code Mode plaintext path. Neither exception changes the default encrypted schema or restores a readable audit copy for encrypted calls.
The unresolved delivery and transcript gaps, with references pinned to the reviewed upstream commit:
| Area | Current behavior | Source |
|---|---|---|
| Delivery selection | Encrypted delivery remains the default. Plaintext direct calls require an explicit response marker; there is no equivalent of my fork's user-configurable three-mode delivery policy. | Direct-call classification, plaintext/encrypted helper, send/follow-up schemas, spawn schema |
| Parent activity | SubAgentActivityEvent and the public activity payload still have no task/prompt field. The TUI renders the activity title with an empty detail list. |
Core event, API payload, TUI rendering |
| Child history | The normal history builder ignores InterAgentCommunication; its response-item handler accepts hook-prompt user messages, not ResponseItem::AgentMessage. A readable canonical agent message therefore does not itself establish a readable typed transcript. |
Rollout handling, response-item handling |
| Diagnostics | Plaintext direct-call arguments are logged as [plaintext arguments]. The communication stream logs ciphertext when present and otherwise [plaintext], rather than the readable message. |
Tool log, communication log |
Encrypted recipient input still deliberately selects the ciphertext representation: current conversion. A local audit copy needs its own persistence/presentation path; populating a runtime string alone does not make it visible.
Current implementation in my fork
The maintained implementation covers all three V2 communication tools:
[features.multi_agent_v2]
message_delivery = "plaintext" # encrypted | encrypted_with_audit | plaintextplaintextemits one readablemessage, persists it, and delivers it with the contextual agent-message wrapper. No second audit payload is required.encrypted_with_auditis the default in my fork. It requires encryptedmessageplus nonempty readabletask_message. The sender's tool record and parent activity retain the audit copy; the recipient model still receives ciphertext.encryptedretains opaque delivery without a readable assignment copy.
The audit copy in encrypted_with_audit is sender-supplied metadata, not decrypted ciphertext or cryptographic proof that both payloads match. The receiving child's encrypted message remains an opaque placeholder; my fork does not substitute the parent's audit copy into child model input or claim it recovered the exact plaintext.
The implementation also:
- validates mode, required fields, and one combined 8 KiB UTF-8 payload limit before recipient resolution, restoration, or spawn;
- preserves stored plaintext/encrypted provenance across resume rather than reinterpreting old messages under the current configuration;
- carries full readable spawn/follow-up prompts through parent activity, applying configurable preview limits only when displaying them;
- projects incoming agent messages into normal typed app-server/TUI history with sender/recipient provenance, canonical identities, encrypted placeholders, and live/resume/pagination handling;
- retains readable audit content in communication diagnostics and rollout-trace interaction edges while keeping transport correlation separate;
- exposes the latest accepted readable assignment through V2
list_agentsas volatile registry metadata, not a durable delivery receipt.
Updated implementation commits:
- Configurable V2 delivery policy —
ace034da81e5 - All three V2 tools, audit/delivery separation, validation, and assignment inspection —
2f255f284ddc - Readable rollout-trace interaction content —
56797e38007d - Source-preserving task/response previews —
c5183cb4e6b1 - Readable task prompts in parent activity —
e34d72512020 - Durable inter-agent transcripts with typed provenance —
a6960826521a
Delivery and transcript contract.
Separately, my fork extends plaintext V1 send_input with attributed parent/child/sibling messages, distinct queued turns, receiver-selected durable mail, and optional commentary/final-response observation. This covers related coordination needs through one input operation; the V1 contract is documented separately.
Acceptance criteria
- The selected delivery policy makes readable assignments available in parent tool history/activity without duplicating plaintext payloads unnecessarily.
- Plaintext incoming messages appear in child transcripts with attribution. Encrypted incoming messages use a fixed opaque placeholder, never ciphertext presented as readable text.
- Encrypted-with-audit delivery keeps audit metadata separate from recipient-model input and does not imply the audit text was decrypted or verified.
- Live notifications, normal thread history, resume, pagination, and agent switching retain message identity, ordering, and duplicate suppression.
- Communication diagnostics and rollout-trace edges distinguish readable content from encrypted transport identity.
- Regression coverage exercises
spawn_agent,send_message, andfollowup_task, delivery validation, parent/child presentation, and persisted history.
Related: #26210 introduced encryption; #35845 added conditional plaintext-response and provider compatibility handling while retaining encrypted delivery by default; #26753 concerns encrypted-schema validation failures; #33885 covers direct user corrections to V2 children.
Activity
ignatremizov commentedon Jun 13, 2026
Guys, we don’t want to build Skynet and then be unable to audit what it’s doing.
septrcode commentedon Jun 14, 2026
I too would like to be able to audit my agents… if we can’t audit agents… only providers can… it’s clear we are on a path to enterprise only has access to these tools, why restrict otherwise
Alek2077 commentedon Jul 4, 2026
The auditability concern is no longer meaningfully opt-in for GPT-5.5 users on Codex 0.142.5.
[now applies to Sol and Terra, while 5.5 has been reverted to using v1 again]
The current GPT-5.5 model catalog sets
multi_agent_version: v2, and the 0.142.5 runtime gives that value precedence overfeatures.multi_agent_v2=false. In a fresh GPT-5.5 thread,features listsays V2 is disabled, butspawn_agentstill exposes the V2 task-path schema. A fresh GPT-5.4 thread with the same configuration uses V1 normally.Because GPT-5.5 forces the encrypted V2 path, users selecting the current frontier model cannot choose the readable V1 delegation trail through the documented feature setting. That turns the loss of locally readable delegated-task content from an experimental opt-in tradeoff into mandatory behavior for that model.
The same forced surface also prevents selection of documented custom-agent profiles because it hides the agent type, model, and reasoning controls. This compounds the auditability problem: GPT-5.5 users cannot select the configured reviewer profile and also cannot inspect the plaintext task that a generic replacement received.
I have filed the configuration-precedence reproduction separately: #31097
ignatremizov commentedon Jul 7, 2026
Upd: #30867, and #30872 by @bolinfest and @rka-oai are directionally related, but they don’t address this issue yet.
The PRs add/prepare structured lifecycle logging for multi-agent communication, which is useful for operational observability. The gap here is specifically local auditability of the actual task/message text in rollout/history/replay/debug surfaces.
For encrypted MultiAgentV2 messages, the new logging path still falls back to
encrypted_contentwhen plaintextcontentis empty, so it will record an opaque encrypted payload rather than the human-readable task the model delegated.A reminder that the desired behavior here is narrow: keep encrypted delivery if needed for some reason, and also persist a human-readable structured audit copy of
spawn_agent/send_message/followup_tasktask text in the parent rollout history so users can later answer "what did this agent get asked to do?" without relying on provider-side visibility or opt-in trace logging.runfence commentedon Jul 14, 2026
Please revert this! I need to be able to inspect those messages to debug my multi-agent workflows.
Who thought this is a good idea???
embedding-shapes commentedon Jul 14, 2026
I'm also being hit by this, playing around with GPT 5.6 Sol Ultra (which spawns sub-agents) and there is no way to introspect exactly what the main model sent the sub-agents, what on earth?! We have to be able to introspect exactly what inputs inference use, otherwise how are we supposed to be able to understand what went wrong, when things go wrong?
This seems like a completely bananas thing to implement, encrypt local content not to protect end-users, but to protect OpenAI from other providers extracting how the multi-agent stuff works? This basically makes the whole flashy new "Ultra" stuff unusable, as we have 0 introspection into what instructions they actually received when they started.
I came across the encrypted stuff some weeks or months ago even, thought it was just experimental things or things for enterprise users who sometimes want encrypted-at-rest stuff. Imagine my surprise when I now tried to integrate with the new stuff via app-server and y'all are trying to hide the actual prompts from us paying users?!
Please carefully consider resolving this as otherwise it becomes really hard to justify continuing to use codex as you're moving towards hiding stuff from us users rather than making it easier to work with codex.
Aquaticat commentedon Jul 14, 2026
My current workaround: Not using subagents at all.
ZenulAbidin commentedon Jul 14, 2026
Sorry to shamelessly plug my project in, but I just created stringbean to solve this problem.
You can use it to run your own agents in Codex, even non-OpenAI models.
cooluser69 commentedon Jul 14, 2026
This is bad!
runfence commentedon Jul 14, 2026
Moreover it doesn't really protect you from competition.
ignatremizov commentedon Jul 15, 2026
Update: #33030 removed
last_task_messagefromlist_agentsand stopped tracking the most recent instruction in agent metadata. This makes the auditability problem described here even more significant: users can see that an agent exists and what status it has, but not what it was asked to do anymore at all.Switching to the child thread does not fully replace this information because as mentioned, encrypted v2 task delivery is stored as opaque
encrypted_content; the original readable delegation is not available in the local rollout for agent switching.The #33030 description explains what was removed, but not why. Was this motivated by privacy, context size, correctness, or another constraint? Some attempt at building a moat? Anti-distillation? It's strange.
Agent inspection is operationally important for the average user. It should remain possible to answer:
One possible design is a configurable delivery policy:
This would preserve encrypted behavior while allowing users who prioritize local auditability or token efficiency to choose the appropriate tradeoff. At minimum, I think a readable task description should remain available somewhere in history, trace metadata, and/or
list_agents.feat(anatomy,ai-agents): add agent-run simulator slides with vendor t…
19 remaining items
wuyak commentedon Aug 9, 2026
A current Codex App reproduction shows an output-side consequence of this issue, not just missing delegated input.
send_message.Evidence capsule delivered to /root: ....AgentMessageand the separate shortFINAL_ANSWER.The expanded inspector should show an ordered operational transcript: initial assignment, parent-to-child follow-ups, child-to-parent messages/evidence capsules, and the terminal result, with sender, recipient, timestamp, operation type, and delivery state. A collapsed row could summarize something like
Completed · 57s · Handoff sent · 2 blockers · 10 findings.This does not require chain-of-thought exposure. It is about user-visible messages that agents explicitly send to each other. The same representation should survive live view, history, resume, and replay. Users should not have to duplicate a full capsule into the terminal result solely to make it visible in the App.
Related UI reports: #32125 covers missing orchestrator/subagent communications, and #36266 proposes a richer expandable Subagents panel.
fwf-ben commentedon Aug 18, 2026
Just got bitten by this: can't run evals against the subagent rollouts, without their prompt can't re-run them or improve them. Why was this done in the first place? Seems a crazy regression.
arthurlapertosa commentedon Aug 28, 2026
This is ridiculous, we have to be able to view and inspect our subagents too. I mean, it's part of the machine that will build your solution, so you gotta be able to view it. That's so crazy that they encrypted it.
embedding-shapes commentedon Aug 28, 2026
Yeah, I'm not sure what they were thinking.
I want to use
ultra, but since it starts spawning sub-agents, and I can't inspect their prompts, I literally don't dare to use it. So I'm stuck atmax, because I want to be able to see what the agents are doing.They're literally hiding stuff we need for debugging, and leaving money on the table while doing so. Really strange decision overall.
VolkumDev commentedon Aug 30, 2026
OpenAI team will stop being so incompetent some day?? Holy fuck
jiahao-d commentedon Sep 1, 2026
Also reproduced on Codex desktop for Windows with bundled codex-cli 0.151.0-alpha.7.2. I used subagents for an independent evaluation and needed to confirm that two runs received exactly the same task, without leading language or a leaked expected answer. Codex stored only ciphertext in both the parent and child histories, so I could not compare the delegated tasks or determine whether different results came from model variance or different instructions. This makes the evaluation impossible to audit or reproduce.
future3OOO commentedon Sep 14, 2026
Additional observation on Codex CLI 0.154.0, Linux/WSL2, OpenAI provider,
gpt-5.6-sol, Multi-Agent V2 (2026-09-14 UTC).During a real repository task, the parent spawned three explorer agents with
fork_turns="all". We needed to verify whether the parent supplied the required task contract, scoped context summary, target files and GitNexus repository/status, because two delegates repeated a graph query and one printed a large truncated response.Read-only inspection of the parent rollout, all three child rollouts, native log database and thread-history projection found:
spawn_agent.messagevalues are ciphertext.NEW_TASKcontains a readable sender/recipient header followed byencrypted_content.InterAgentCommunicationlogs show empty plaintextcontentand populatedencrypted_content.subAgentActivityhistory entries contain lifecycle/identity metadata, without the assignment text. No readable assignment was recovered from these inspected surfaces.Consequently, we could confirm their actions but could not establish whether the exact dispatch omitted constraints or whether the delegates disregarded adequate instructions. A model-authored retrospective summary would not resolve that distinction.
Please provide or identify a supported, authorized way to inspect the exact dispatched assignments and follow-ups, correlated to sender/recipient and execution. For a fix, compare real initial/follow-up dispatch on unchanged and candidate runtimes: the exact input must become auditable while recipient behavior and existing permission boundaries remain preserved. No new workflow stages or duplicate model-authored message logs are needed.
This corroborates this issue; it does not establish compromise, unauthorized background activity, or malicious intent. No credentials, ciphertext payloads, or private task contents are included here.
pedroyan commentedon Sep 17, 2026
+1 on this issue. If I cannot inspect the prompt that the parent agent is passing to its sub-agents, I can't be certain that the correct task is being executed.
For all I know, they could be secretly cooking Skynet on my machine without me even knowing
nleononline commentedon Sep 20, 2026
Two and a half months later, this still hasn't been fixed...
xlionjuan commentedon Oct 13, 2026
Still NOTHING
embedding-shapes commentedon Oct 13, 2026
@tibo-openai how on earth are we supposed to be able to use "ultra" or sub-agents even, when we're not able to troubleshoot when things invariably go wrong? It's impossible to figure out why a sub-agent messed up because we're unable to see the prompts the "root" session sent, so what really is the point of even having sub-agents or "ultra", when any serious programmer would be unable to use it?
You have this "super" feature that consumes a ton more usage, yet you're not caring enough about the feature to actually allow us to us it, what's the point?
ignatremizov commentedon Oct 26, 2026
Update (2026-10-27): This issue is still unresolved in upstream's default MultiAgentV2 workflow. Encrypted message delivery remains the default. The bundled
spawn_agent,send_message, andfollowup_taskschemas still request encryptedmessagepayloads, and upstream exposes no user-configurable plaintext delivery policy.#35845 added conditional plaintext-response handling and related non-OpenAI provider compatibility. A direct
collaborationcall is treated as plaintext only when its response explicitly carriesencrypted_function_args: []; without that marker, it follows the encrypted path. The client also removes this OpenAI-specific metadata from requests to non-OpenAI providers. That response marker is not a user setting for disabling encryption. This did not fix the default OpenAI workflow's unreadable assignments.At the reviewed upstream revision
245691b2dc66, the tool schemas still request encryption, parent activity still has no prompt, and normal history reconstruction still skips incoming agent messages. Those transcript gaps also affect the conditional plaintext path and the separate Code Mode plaintext path.My fork now provides explicit
plaintext,encrypted_with_audit, andencryptedmodes for all three V2 tools, plus readable parent prompts and attributed live/resumed child transcripts. Plaintext mode emits one readable payload. Audit mode keeps the sender's readable copy separate from encrypted recipient input; the receiving child's encrypted message remains opaque. That audit copy is sender-supplied, not a claim that Codex decrypted or verified the ciphertext.Current implementation: delivery, parent prompt propagation, and typed transcripts. The body links the remaining implementation commits and current upstream paths.
My fork also extends plaintext V1
send_inputwith attributed same-tree messaging, queued turns, receiver-selected mail, and optional reply observation. Its detailed contract is linked separately; the V2 delivery and audit gap remains the focus here.embedding-shapes commentedon Oct 27, 2026
@ignatremizov
This is the core of the issue, if it doesn't solve that, it's not a solution. Why are you again polluting the issue with LLM generated slop?
ignatremizov commentedon Oct 27, 2026
@embedding-shapes thanks for pointing that out, I was just updating the body text since it's been a few months since my last update. gpt-6.1-sol hedged it too much to sound like there was progress, when there wasn't really. corrected now
saidelike commentedon Oct 29, 2026
Confirmed with App Server 0.164.0.
For one recorded
followup_taskinteraction:thread/items/listreturned a complete turn item page (nextCursor: null).thread/items/read, queried for the exact item, returned the samesubAgentActivitymetadata without message text.encrypted_contentblock in the recipient’s persistedagent_message.The message is retained as ciphertext, but its readable content is unavailable through these native history endpoints. This confirms the audit gap independently of UI rendering.
@ignatremizov: a better name is probably
MultiAgentV2: delegated instructions and messages are unreadable in history