When Sub-Agent Prompts Go Dark: Encrypted MultiAgentV2 in Codex
A confusing moment in the rollout UI
Picture this: a Codex session spawns a sub-agent to do some delegated work. You watch the rollout timeline like you’ve done a hundred times—until you scroll back far enough to review what was actually delegated.
Instead of readable text like “Build a worker that audits X” or “Send this message to the child agent,” the entry is suddenly full of ciphertext (encrypted, unreadable text). There’s still a spawn_agent event, still a child thread, still a follow-up—but the human-readable task/message text is gone.
What happens to an audit trail when the prompts are ciphertext?
That’s the core complaint behind the “Codex starts encrypting sub-agent prompts” regression: the delivery to the recipient model can be encrypted (a privacy win), but the parent-side history and trace become much harder to interpret and debug.
The moving pieces: MultiAgentV2, inter-agent messaging, and the Responses API
Codex’s MultiAgentV2 feature introduces tools that let one model (the parent) coordinate other models (the child agents). Three tool calls matter here:
spawn_agent: asks Codex to create a new child agent/thread.send_message: queues a message to an already-running child agent without triggering a new “turn” immediately.followup_task: schedules the next work item for a child agent.
In MultiAgentV2, each of these tools accepts a message argument. In classic setups, that message is treated like normal tool arguments—meaning it’s readable plaintext that Codex can store and display in rollouts, trace metadata, and other debugging surfaces.
Now introduce a key architectural term: ciphertext. Ciphertext is what you get after encryption; it looks like random characters and can’t be read without the corresponding decryption step.
Codex also tracks inter-agent communication with an internal structure (let’s name it conceptually as InterAgentCommunication). That structure has two relevant fields:
content: the plaintext task/message text.encrypted_content: an encrypted payload intended for the recipient model.
Finally, Codex uses the Responses API (the server-side model interface) to run model turns. In this design, Codex constructs an input item for the child request—often described as an agent_message item—so the recipient model receives the right message content.
What changed: encrypted delivery for MultiAgentV2 message payloads
The regression comes from a deliberate change: MultiAgentV2’s message payloads for spawn_agent, send_message, and followup_task are marked as encrypted.
Concretely, the behavior shifts toward this pattern:
- The parent model emits a
messageargument, but the value is now treated as ciphertext. - Codex stores the result in inter-agent communication as
encrypted_content. - Codex leaves
contentempty (so there’s no plaintext task/message to show in parent-side history). - When Codex builds the child request, it forwards the ciphertext using a Responses input item (an
agent_message-style item whose content includesencrypted_content).
Here’s the shape conceptually (simplified):
// What the parent model calls (conceptual)
{
"name": "spawn_agent",
"arguments": {
"task_name": "worker",
"message": "<ciphertext>"
}
}
// What Codex stores internally for the parent-side audit/trace record
{
"author": "/root",
"recipient": "/root/worker",
"content": "",
"encrypted_content": "<ciphertext>",
"trigger_turn": true
}
// What the child request receives (conceptual)
{
"type": "agent_message",
"author": "/root",
"recipient": "/root/worker",
"content": [
{
"type": "encrypted_content",
"encrypted_content": "<ciphertext>"
}
]
}
This is privacy hardening in the simplest possible sense: the parent model’s delegated instruction text doesn’t remain as readable plaintext on the parent side.
The tradeoff: confidentiality improved, human auditability reduced
Encryption is not the villain. The villain is what happens next: once content is empty, most “readable audit” surfaces have nothing to show.
Those surfaces typically include:
- Rollout/history UI: a timeline of actions and delegated work.
- Trace reduction: a way to keep long agent runs interpretable by summarizing or compacting context.
- Parent-side audit/debug surfaces: views used after the fact to answer “what did we delegate and why?”
In the regression report, the consequences are spelled out as questions users naturally ask during debugging:
- What task did the
spawn_agentcall give the child? - What message was sent to the subagent?
- Why did a child thread exist when reviewing a rollout later?
When the record contains only ciphertext, those questions can’t be answered without decryption—and decryption isn’t part of the normal local debugging workflow.
This is a deeper systems tension: observability (how much you can inspect and understand what happened) and confidentiality (how much you can prevent disclosure of sensitive content) are often treated as separate features, then collide when you “turn on encryption.”
A better design pattern: encrypt delivery, keep an audit copy with separate controls
The fix suggested by the issue is a classic pattern in secure system design: separate the data used for delivery from the data used for auditing.
You can keep the message payload encrypted for the recipient model while also persisting a human-readable “audit copy” on the parent side.
The key is that the audit copy doesn’t need to be the exact same blob that the model receives.
Here are three design options that preserve debugging without throwing away the privacy goal.
Option 1: Dual-channel records (plaintext audit field, encrypted delivery field)
Store:
- Delivery data: encrypted
message→ goes toencrypted_content. - Audit data: a separate, non-encrypted (or separately protected) audit field that contains a structured preview of the delegated task/message.
A conceptual record could look like:
{
"recipient": "/root/worker",
"encrypted_content": "<ciphertext>",
"content": "",
"audit": {
"task_name": "worker",
"task_preview": "Audit repository dependencies for licensing constraints",
"message_type": "spawn_agent"
}
}
Even if task_preview is redacted, it can still answer the “what did we delegate?” question.
Option 2: Hash-based commitments (prove what was sent without storing it)
Sometimes you don’t want plaintext anywhere. In that case:
- Store a hash (a one-way fingerprint) of the plaintext message.
- Optionally store metadata like length, message type, or a summary generated earlier.
A reviewer can confirm integrity (“Was this the same message as in the child?”) without ever reading the content.
Option 3: Access-controlled plaintext audit (plaintext only where allowed)
“Plaintext audit copy” doesn’t have to mean “plaintext everywhere.”
You can encrypt the audit field at rest with a different key and only allow decryption in privileged debug contexts (like enterprise compliance tooling, or an operator mode).
This keeps the local rollout readable when permitted, while preventing casual disclosure.
Why this matters: audit trails aren’t cosmetic
A rollout trace isn’t just for curiosity—it’s how people answer safety and reliability questions after the fact.
In agent systems, logs and telemetry are the difference between:
- “Something changed and nobody can explain why,” and
- “We can inspect intent, delegation, and tool outcomes.”
OpenAI’s own Codex safety discussion emphasizes agent-native telemetry and audit trails as part of governed execution, pointing toward structured logging (including OpenTelemetry-style exports) as the mechanism that supports auditing beyond raw process logs.
So an audit trail should not be accidentally degraded when you improve message confidentiality.
Practical takeaway: expect ciphertext in the trace, but design for meaning
If a system encrypts delegated prompts, the trace will naturally trend toward opacity unless it also preserves meaningful, human-oriented metadata.
A good mental model is this:
- Encrypted delivery protects the model-facing prompt.
- Readable audit protects the human-facing question: “What did the agent choose to delegate?”
The strongest systems treat the audit layer as first-class data with its own privacy controls—rather than assuming that “if delivery is encrypted, then audit is optional.”
Closing thought
Encrypting MultiAgentV2 message payloads is a reasonable privacy hardening. But removing plaintext from the parent-side history turns debugging into guesswork and shifts burden to decryption workflows most humans never want to touch.
The best outcome is straightforward: keep the recipient protected, but preserve enough structured, permissioned audit context that the rollout timeline still tells a coherent story.
Comments (0)
No comments yet. Be the first to respond!
Leave a Comment
Your comment will be visible after review.