From 854ae7eec07abe883b56cf09f29ad60e20311184 Mon Sep 17 00:00:00 2001
From: jif-oai <jif@openai.com>
Date: Tue, 16 Jun 2026 19:39:45 +0200
Subject: [PATCH 1/6] Expose inter-agent communications as app-server items

---
 codex-rs/analytics/src/reducer.rs             |  2 +
 .../schema/json/ClientRequest.json            |  6 ++
 .../schema/json/ServerNotification.json       | 53 +++++++++++++++++
 .../codex_app_server_protocol.schemas.json    | 59 +++++++++++++++++++
 .../codex_app_server_protocol.v2.schemas.json | 59 +++++++++++++++++++
 .../json/v2/ItemCompletedNotification.json    | 53 +++++++++++++++++
 .../json/v2/ItemStartedNotification.json      | 53 +++++++++++++++++
 .../RawResponseItemCompletedNotification.json |  6 ++
 .../schema/json/v2/ReviewStartResponse.json   | 53 +++++++++++++++++
 .../schema/json/v2/ThreadForkResponse.json    | 53 +++++++++++++++++
 .../schema/json/v2/ThreadListResponse.json    | 53 +++++++++++++++++
 .../json/v2/ThreadMetadataUpdateResponse.json | 53 +++++++++++++++++
 .../schema/json/v2/ThreadReadResponse.json    | 53 +++++++++++++++++
 .../schema/json/v2/ThreadResumeParams.json    |  6 ++
 .../schema/json/v2/ThreadResumeResponse.json  | 53 +++++++++++++++++
 .../json/v2/ThreadRollbackResponse.json       | 53 +++++++++++++++++
 .../schema/json/v2/ThreadStartResponse.json   | 53 +++++++++++++++++
 .../json/v2/ThreadStartedNotification.json    | 53 +++++++++++++++++
 .../json/v2/ThreadUnarchiveResponse.json      | 53 +++++++++++++++++
 .../json/v2/TurnCompletedNotification.json    | 53 +++++++++++++++++
 .../schema/json/v2/TurnStartResponse.json     | 53 +++++++++++++++++
 .../json/v2/TurnStartedNotification.json      | 53 +++++++++++++++++
 .../schema/typescript/ResponseItemMetadata.ts |  2 +-
 .../schema/typescript/v2/ThreadItem.ts        |  2 +-
 .../src/protocol/thread_history.rs            |  7 +++
 .../src/protocol/v2/item.rs                   | 29 +++++++++
 .../src/protocol/v2/tests.rs                  | 31 ++++++++++
 codex-rs/core/src/compact_tests.rs            |  1 +
 .../core/src/context_manager/history_tests.rs |  1 +
 codex-rs/core/src/session/mod.rs              | 26 ++++++++
 codex-rs/core/src/session/tests.rs            |  1 +
 .../handlers/multi_agents_v2/message_tool.rs  |  7 ++-
 codex-rs/protocol/src/items.rs                | 21 +++++++
 codex-rs/protocol/src/models.rs               |  4 ++
 34 files changed, 1115 insertions(+), 3 deletions(-)

diff --git a/codex-rs/analytics/src/reducer.rs b/codex-rs/analytics/src/reducer.rs
index 89d6e57dc5c4..1123af7d67f6 100644
--- a/codex-rs/analytics/src/reducer.rs
+++ b/codex-rs/analytics/src/reducer.rs
@@ -381,6 +381,7 @@ impl TurnToolCounts {
             ThreadItem::UserMessage { .. }
             | ThreadItem::HookPrompt { .. }
             | ThreadItem::AgentMessage { .. }
+            | ThreadItem::InterAgentCommunication { .. }
             | ThreadItem::Plan { .. }
             | ThreadItem::Reasoning { .. }
             | ThreadItem::ImageView { .. }
@@ -1617,6 +1618,7 @@ fn tracked_tool_item_id(item: &ThreadItem) -> Option<&str> {
         ThreadItem::UserMessage { .. }
         | ThreadItem::HookPrompt { .. }
         | ThreadItem::AgentMessage { .. }
+        | ThreadItem::InterAgentCommunication { .. }
         | ThreadItem::Plan { .. }
         | ThreadItem::Reasoning { .. }
         | ThreadItem::SubAgentActivity { .. }
diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json
index 3ed2791c8551..eefa94ac4883 100644
--- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json
+++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json
@@ -2937,6 +2937,12 @@
     },
     "ResponseItemMetadata": {
       "properties": {
+        "source_call_id": {
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "turn_id": {
           "type": [
             "string",
diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json
index 1cf3d96c8172..59d753a8d589 100644
--- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json
@@ -3882,6 +3882,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
index eb659fda3be9..5f393eef5e17 100644
--- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
+++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
@@ -15424,6 +15424,12 @@
       },
       "ResponseItemMetadata": {
         "properties": {
+          "source_call_id": {
+            "type": [
+              "string",
+              "null"
+            ]
+          },
           "turn_id": {
             "type": [
               "string",
@@ -17310,6 +17316,59 @@
             "title": "AgentMessageThreadItem",
             "type": "object"
           },
+          {
+            "properties": {
+              "content": {
+                "type": "string"
+              },
+              "encrypted": {
+                "type": "boolean"
+              },
+              "id": {
+                "type": "string"
+              },
+              "otherReceivers": {
+                "items": {
+                  "type": "string"
+                },
+                "type": "array"
+              },
+              "receiver": {
+                "type": "string"
+              },
+              "sender": {
+                "type": "string"
+              },
+              "sourceCallId": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              },
+              "triggerTurn": {
+                "type": "boolean"
+              },
+              "type": {
+                "enum": [
+                  "interAgentCommunication"
+                ],
+                "title": "InterAgentCommunicationThreadItemType",
+                "type": "string"
+              }
+            },
+            "required": [
+              "content",
+              "encrypted",
+              "id",
+              "otherReceivers",
+              "receiver",
+              "sender",
+              "triggerTurn",
+              "type"
+            ],
+            "title": "InterAgentCommunicationThreadItem",
+            "type": "object"
+          },
           {
             "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
             "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
index e0562760f6b7..e88c353fc705 100644
--- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
+++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
@@ -11877,6 +11877,12 @@
     },
     "ResponseItemMetadata": {
       "properties": {
+        "source_call_id": {
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "turn_id": {
           "type": [
             "string",
@@ -15118,6 +15124,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json
index 233ff8dc98e2..abcd3dfea10e 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json
@@ -605,6 +605,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json
index a55d9e776649..c5b9c6d6cc69 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json
@@ -605,6 +605,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json
index fdd40dae6106..3efca032240f 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json
@@ -1035,6 +1035,12 @@
     },
     "ResponseItemMetadata": {
       "properties": {
+        "source_call_id": {
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "turn_id": {
           "type": [
             "string",
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json
index e27c911b3600..581faea94d79 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json
@@ -749,6 +749,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json
index 4a666672b66e..4c437356dc4d 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json
@@ -1233,6 +1233,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json
index c1d1b6759a80..e9182b6affa9 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json
@@ -1048,6 +1048,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json
index 801d1cf131be..d5315b32e8f7 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json
@@ -1048,6 +1048,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json
index 01b5ed907efc..feb6e6a17a95 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json
@@ -1048,6 +1048,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json
index 7ba2a0a64696..093c27044d26 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json
@@ -1106,6 +1106,12 @@
     },
     "ResponseItemMetadata": {
       "properties": {
+        "source_call_id": {
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "turn_id": {
           "type": [
             "string",
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json
index 032d1dd74ef2..b1b44ce098e4 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json
@@ -1233,6 +1233,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json
index c1ad534756fd..ba57cee7d375 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json
@@ -1048,6 +1048,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json
index 33373b9f7208..8166de5d36d5 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json
@@ -1233,6 +1233,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json
index 577df57e0501..8cd99a79f8dd 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json
@@ -1048,6 +1048,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json
index fcc42e6261c0..a16ffadc3af4 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json
@@ -1048,6 +1048,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json
index 24d1dccf475c..3fdf06f8f92e 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json
@@ -749,6 +749,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json
index da88eacd4874..bd8e18c7d176 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json
@@ -749,6 +749,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json
index edb3fa636a07..84e32c7d14b8 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json
@@ -749,6 +749,59 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
+        {
+          "properties": {
+            "content": {
+              "type": "string"
+            },
+            "encrypted": {
+              "type": "boolean"
+            },
+            "id": {
+              "type": "string"
+            },
+            "otherReceivers": {
+              "items": {
+                "type": "string"
+              },
+              "type": "array"
+            },
+            "receiver": {
+              "type": "string"
+            },
+            "sender": {
+              "type": "string"
+            },
+            "sourceCallId": {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "triggerTurn": {
+              "type": "boolean"
+            },
+            "type": {
+              "enum": [
+                "interAgentCommunication"
+              ],
+              "title": "InterAgentCommunicationThreadItemType",
+              "type": "string"
+            }
+          },
+          "required": [
+            "content",
+            "encrypted",
+            "id",
+            "otherReceivers",
+            "receiver",
+            "sender",
+            "triggerTurn",
+            "type"
+          ],
+          "title": "InterAgentCommunicationThreadItem",
+          "type": "object"
+        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/typescript/ResponseItemMetadata.ts b/codex-rs/app-server-protocol/schema/typescript/ResponseItemMetadata.ts
index f7b69a6dfe17..365c561fd15b 100644
--- a/codex-rs/app-server-protocol/schema/typescript/ResponseItemMetadata.ts
+++ b/codex-rs/app-server-protocol/schema/typescript/ResponseItemMetadata.ts
@@ -2,4 +2,4 @@
 
 // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
 
-export type ResponseItemMetadata = { turn_id?: string, };
+export type ResponseItemMetadata = { turn_id?: string, source_call_id?: string, };
diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts
index 4ccab77b32ad..933f6b632e2a 100644
--- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts
+++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts
@@ -24,7 +24,7 @@ import type { SubAgentActivityKind } from "./SubAgentActivityKind";
 import type { UserInput } from "./UserInput";
 import type { WebSearchAction } from "./WebSearchAction";
 
-export type ThreadItem = { "type": "userMessage", id: string, clientId: string | null, content: Array<UserInput>, } | { "type": "hookPrompt", id: string, fragments: Array<HookPromptFragment>, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, memoryCitation: MemoryCitation | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array<string>, content: Array<string>, } | { "type": "commandExecution", id: string,
+export type ThreadItem = { "type": "userMessage", id: string, clientId: string | null, content: Array<UserInput>, } | { "type": "hookPrompt", id: string, fragments: Array<HookPromptFragment>, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, memoryCitation: MemoryCitation | null, } | { "type": "interAgentCommunication", id: string, sourceCallId: string | null, sender: string, receiver: string, otherReceivers: Array<string>, content: string, encrypted: boolean, triggerTurn: boolean, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array<string>, content: Array<string>, } | { "type": "commandExecution", id: string,
 /**
  * The command to be executed.
  */
diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history.rs b/codex-rs/app-server-protocol/src/protocol/thread_history.rs
index 6ca038981fc1..4f942c1a9fe1 100644
--- a/codex-rs/app-server-protocol/src/protocol/thread_history.rs
+++ b/codex-rs/app-server-protocol/src/protocol/thread_history.rs
@@ -376,6 +376,7 @@ impl ThreadHistoryBuilder {
             codex_protocol::items::TurnItem::UserMessage(_)
             | codex_protocol::items::TurnItem::HookPrompt(_)
             | codex_protocol::items::TurnItem::AgentMessage(_)
+            | codex_protocol::items::TurnItem::InterAgentCommunication(_)
             | codex_protocol::items::TurnItem::Reasoning(_)
             | codex_protocol::items::TurnItem::WebSearch(_)
             | codex_protocol::items::TurnItem::ImageView(_)
@@ -403,6 +404,12 @@ impl ThreadHistoryBuilder {
                     ThreadItem::from(payload.item.clone()),
                 );
             }
+            codex_protocol::items::TurnItem::InterAgentCommunication(_) => {
+                self.upsert_item_in_turn_id(
+                    &payload.turn_id,
+                    ThreadItem::from(payload.item.clone()),
+                );
+            }
             codex_protocol::items::TurnItem::UserMessage(_)
             | codex_protocol::items::TurnItem::HookPrompt(_)
             | codex_protocol::items::TurnItem::AgentMessage(_)
diff --git a/codex-rs/app-server-protocol/src/protocol/v2/item.rs b/codex-rs/app-server-protocol/src/protocol/v2/item.rs
index 502eb62e103a..9e265f3e0fa1 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/item.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/item.rs
@@ -237,6 +237,18 @@ pub enum ThreadItem {
     },
     #[serde(rename_all = "camelCase")]
     #[ts(rename_all = "camelCase")]
+    InterAgentCommunication {
+        id: String,
+        source_call_id: Option<String>,
+        sender: String,
+        receiver: String,
+        other_receivers: Vec<String>,
+        content: String,
+        encrypted: bool,
+        trigger_turn: bool,
+    },
+    #[serde(rename_all = "camelCase")]
+    #[ts(rename_all = "camelCase")]
     /// EXPERIMENTAL - proposed plan item content. The completed plan item is
     /// authoritative and may not match the concatenation of `PlanDelta` text.
     Plan { id: String, text: String },
@@ -397,6 +409,7 @@ impl ThreadItem {
             ThreadItem::UserMessage { id, .. }
             | ThreadItem::HookPrompt { id, .. }
             | ThreadItem::AgentMessage { id, .. }
+            | ThreadItem::InterAgentCommunication { id, .. }
             | ThreadItem::Plan { id, .. }
             | ThreadItem::Reasoning { id, .. }
             | ThreadItem::CommandExecution { id, .. }
@@ -827,6 +840,22 @@ impl From<CoreTurnItem> for ThreadItem {
                     memory_citation: agent.memory_citation.map(Into::into),
                 }
             }
+            CoreTurnItem::InterAgentCommunication(communication) => {
+                ThreadItem::InterAgentCommunication {
+                    id: communication.id,
+                    source_call_id: communication.source_call_id,
+                    sender: communication.sender.to_string(),
+                    receiver: communication.receiver.to_string(),
+                    other_receivers: communication
+                        .other_receivers
+                        .into_iter()
+                        .map(String::from)
+                        .collect(),
+                    content: communication.content,
+                    encrypted: communication.encrypted,
+                    trigger_turn: communication.trigger_turn,
+                }
+            }
             CoreTurnItem::Plan(plan) => ThreadItem::Plan {
                 id: plan.id,
                 text: plan.text,
diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
index 2567e386c839..6a3ce66f975e 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
@@ -1,9 +1,11 @@
 use super::*;
+use codex_protocol::AgentPath;
 use codex_protocol::approvals::ElicitationRequest as CoreElicitationRequest;
 use codex_protocol::items::AgentMessageContent;
 use codex_protocol::items::AgentMessageItem;
 use codex_protocol::items::FileChangeItem;
 use codex_protocol::items::ImageViewItem;
+use codex_protocol::items::InterAgentCommunicationItem;
 use codex_protocol::items::McpToolCallItem;
 use codex_protocol::items::McpToolCallStatus as CoreMcpToolCallStatus;
 use codex_protocol::items::ReasoningItem;
@@ -2496,6 +2498,35 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
         }
     );
 
+    let communication_item = TurnItem::InterAgentCommunication(InterAgentCommunicationItem {
+        id: "communication-1".to_string(),
+        source_call_id: Some("call-1".to_string()),
+        sender: AgentPath::root(),
+        receiver: AgentPath::root().join("worker").expect("receiver path"),
+        other_receivers: vec![
+            AgentPath::root()
+                .join("reviewer")
+                .expect("other receiver path"),
+        ],
+        content: "please check this".to_string(),
+        encrypted: true,
+        trigger_turn: false,
+    });
+
+    assert_eq!(
+        ThreadItem::from(communication_item),
+        ThreadItem::InterAgentCommunication {
+            id: "communication-1".to_string(),
+            source_call_id: Some("call-1".to_string()),
+            sender: "/root".to_string(),
+            receiver: "/root/worker".to_string(),
+            other_receivers: vec!["/root/reviewer".to_string()],
+            content: "please check this".to_string(),
+            encrypted: true,
+            trigger_turn: false,
+        }
+    );
+
     let reasoning_item = TurnItem::Reasoning(ReasoningItem {
         id: "reasoning-1".to_string(),
         summary_text: vec!["line one".to_string(), "line two".to_string()],
diff --git a/codex-rs/core/src/compact_tests.rs b/codex-rs/core/src/compact_tests.rs
index a52e70a7ba1e..c1004004ade2 100644
--- a/codex-rs/core/src/compact_tests.rs
+++ b/codex-rs/core/src/compact_tests.rs
@@ -238,6 +238,7 @@ fn build_compacted_history_preserves_user_message_metadata() {
             message: "first user message".to_string(),
             metadata: Some(ResponseItemMetadata {
                 turn_id: Some("turn-1".to_string()),
+                ..Default::default()
             }),
         }],
         "summary text",
diff --git a/codex-rs/core/src/context_manager/history_tests.rs b/codex-rs/core/src/context_manager/history_tests.rs
index a98061b5b097..9a449653c294 100644
--- a/codex-rs/core/src/context_manager/history_tests.rs
+++ b/codex-rs/core/src/context_manager/history_tests.rs
@@ -1049,6 +1049,7 @@ fn record_items_truncates_function_call_output_content() {
         },
         metadata: Some(ResponseItemMetadata {
             turn_id: Some("turn-1".to_string()),
+            ..Default::default()
         }),
     };
 
diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs
index 242e35f37568..a7262cf48c92 100644
--- a/codex-rs/core/src/session/mod.rs
+++ b/codex-rs/core/src/session/mod.rs
@@ -93,6 +93,7 @@ use codex_protocol::config_types::Settings;
 use codex_protocol::config_types::WebSearchMode;
 use codex_protocol::dynamic_tools::DynamicToolResponse;
 use codex_protocol::dynamic_tools::DynamicToolSpec;
+use codex_protocol::items::InterAgentCommunicationItem;
 use codex_protocol::items::TurnItem;
 use codex_protocol::items::UserMessageItem;
 use codex_protocol::mcp::CallToolResult;
@@ -2674,6 +2675,26 @@ impl Session {
         communication: InterAgentCommunication,
     ) {
         let response_item = communication.to_model_input_item();
+        let source_call_id = communication
+            .metadata
+            .as_ref()
+            .and_then(|metadata| metadata.source_call_id.clone());
+        let (content, encrypted) = match &communication.encrypted_content {
+            Some(encrypted_content) => (encrypted_content.clone(), true),
+            None => (communication.content.clone(), false),
+        };
+        let communication_item = InterAgentCommunicationItem {
+            id: source_call_id
+                .clone()
+                .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
+            source_call_id,
+            sender: communication.author.clone(),
+            receiver: communication.recipient.clone(),
+            other_receivers: communication.other_recipients.clone(),
+            content,
+            encrypted,
+            trigger_turn: communication.trigger_turn,
+        };
         let items = self.prepare_conversation_items_for_history(
             turn_context,
             std::slice::from_ref(&response_item),
@@ -2686,6 +2707,11 @@ impl Session {
         self.persist_rollout_items(&[RolloutItem::InterAgentCommunication(communication)])
             .await;
         self.send_raw_response_items(turn_context, items).await;
+        self.emit_turn_item_completed(
+            turn_context,
+            TurnItem::InterAgentCommunication(communication_item),
+        )
+        .await;
     }
 
     async fn maybe_warn_on_server_model_mismatch(
diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs
index 5086fd63bd57..1cd39aec6590 100644
--- a/codex-rs/core/src/session/tests.rs
+++ b/codex-rs/core/src/session/tests.rs
@@ -1606,6 +1606,7 @@ async fn reconstruct_history_uses_replacement_history_verbatim() {
         phase: None,
         metadata: Some(ResponseItemMetadata {
             turn_id: Some("compact-turn".to_string()),
+            ..Default::default()
         }),
     };
     let replacement_history = vec![
diff --git a/codex-rs/core/src/tools/handlers/multi_agents_v2/message_tool.rs b/codex-rs/core/src/tools/handlers/multi_agents_v2/message_tool.rs
index 7fdb80e8bcb2..81eebed4a304 100644
--- a/codex-rs/core/src/tools/handlers/multi_agents_v2/message_tool.rs
+++ b/codex-rs/core/src/tools/handlers/multi_agents_v2/message_tool.rs
@@ -6,6 +6,7 @@
 use super::*;
 use crate::tools::context::FunctionToolOutput;
 use crate::turn_timing::now_unix_timestamp_ms;
+use codex_protocol::models::ResponseItemMetadata;
 use codex_protocol::protocol::InterAgentCommunication;
 
 #[derive(Clone, Copy, PartialEq, Eq)]
@@ -99,8 +100,12 @@ pub(crate) async fn handle_message_string_tool(
         .session_source
         .get_agent_path()
         .unwrap_or_else(AgentPath::root);
-    let communication =
+    let mut communication =
         communication_from_tool_message(author, receiver_agent_path.clone(), message);
+    communication
+        .metadata
+        .get_or_insert_with(ResponseItemMetadata::default)
+        .source_call_id = Some(call_id.clone());
     let result = session
         .services
         .agent_control
diff --git a/codex-rs/protocol/src/items.rs b/codex-rs/protocol/src/items.rs
index 01f44576ace3..d830ba300277 100644
--- a/codex-rs/protocol/src/items.rs
+++ b/codex-rs/protocol/src/items.rs
@@ -1,3 +1,4 @@
+use crate::AgentPath;
 use crate::mcp::CallToolResult;
 use crate::memory_citation::MemoryCitation;
 use crate::models::ContentItem;
@@ -43,6 +44,7 @@ pub enum TurnItem {
     UserMessage(UserMessageItem),
     HookPrompt(HookPromptItem),
     AgentMessage(AgentMessageItem),
+    InterAgentCommunication(InterAgentCommunicationItem),
     Plan(PlanItem),
     Reasoning(ReasoningItem),
     WebSearch(WebSearchItem),
@@ -114,6 +116,23 @@ pub struct AgentMessageItem {
     pub memory_citation: Option<MemoryCitation>,
 }
 
+#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq, Eq)]
+#[serde(rename_all = "camelCase")]
+#[ts(rename_all = "camelCase")]
+pub struct InterAgentCommunicationItem {
+    pub id: String,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    #[ts(optional)]
+    pub source_call_id: Option<String>,
+    pub sender: AgentPath,
+    pub receiver: AgentPath,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub other_receivers: Vec<AgentPath>,
+    pub content: String,
+    pub encrypted: bool,
+    pub trigger_turn: bool,
+}
+
 #[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
 pub struct PlanItem {
     pub id: String,
@@ -579,6 +598,7 @@ impl TurnItem {
             TurnItem::UserMessage(item) => item.id.clone(),
             TurnItem::HookPrompt(item) => item.id.clone(),
             TurnItem::AgentMessage(item) => item.id.clone(),
+            TurnItem::InterAgentCommunication(item) => item.id.clone(),
             TurnItem::Plan(item) => item.id.clone(),
             TurnItem::Reasoning(item) => item.id.clone(),
             TurnItem::WebSearch(item) => item.id.clone(),
@@ -596,6 +616,7 @@ impl TurnItem {
             TurnItem::UserMessage(item) => vec![item.as_legacy_event()],
             TurnItem::HookPrompt(_) => Vec::new(),
             TurnItem::AgentMessage(item) => item.as_legacy_events(),
+            TurnItem::InterAgentCommunication(_) => Vec::new(),
             TurnItem::Plan(_) => Vec::new(),
             TurnItem::WebSearch(item) => vec![item.as_legacy_event()],
             TurnItem::ImageView(item) => {
diff --git a/codex-rs/protocol/src/models.rs b/codex-rs/protocol/src/models.rs
index 0e7e9bb44655..9443866c6f0e 100644
--- a/codex-rs/protocol/src/models.rs
+++ b/codex-rs/protocol/src/models.rs
@@ -909,6 +909,9 @@ pub struct ResponseItemMetadata {
     #[serde(default, skip_serializing_if = "Option::is_none")]
     #[ts(optional)]
     pub turn_id: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    #[ts(optional)]
+    pub source_call_id: Option<String>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema, TS)]
@@ -2072,6 +2075,7 @@ mod tests {
     fn response_item_metadata(turn_id: &str) -> ResponseItemMetadata {
         ResponseItemMetadata {
             turn_id: Some(turn_id.to_string()),
+            ..Default::default()
         }
     }
 

From 0979d99c386c89d03ed9e1cf7e0a4bc7f25ed5b6 Mon Sep 17 00:00:00 2001
From: jif-oai <jif@openai.com>
Date: Tue, 16 Jun 2026 20:21:56 +0200
Subject: [PATCH 2/6] Handle inter-agent items in TUI consumers

---
 codex-rs/tui/src/app/agent_status_feed.rs     | 11 ++++
 .../tui/src/app/agent_status_feed_tests.rs    | 58 +++++++++++++++++++
 codex-rs/tui/src/chatwidget/replay.rs         |  1 +
 codex-rs/tui/src/thread_transcript.rs         |  1 +
 4 files changed, 71 insertions(+)

diff --git a/codex-rs/tui/src/app/agent_status_feed.rs b/codex-rs/tui/src/app/agent_status_feed.rs
index 544c0b7172d5..f9dd137020f6 100644
--- a/codex-rs/tui/src/app/agent_status_feed.rs
+++ b/codex-rs/tui/src/app/agent_status_feed.rs
@@ -135,6 +135,17 @@ impl AgentStatusThreadPreview {
 fn activity_summary(item: &ThreadItem) -> Option<String> {
     let summary = match item {
         ThreadItem::AgentMessage { text, .. } | ThreadItem::Plan { text, .. } => text,
+        ThreadItem::InterAgentCommunication {
+            sender,
+            content,
+            encrypted,
+            ..
+        } => {
+            if *encrypted {
+                return bounded_summary(&format!("Encrypted message from {sender}"));
+            }
+            return bounded_summary(&format!("Message from {sender}: {content}"));
+        }
         ThreadItem::Reasoning { summary, .. } => summary.last()?,
         ThreadItem::CommandExecution { command, .. } => {
             let command = truncate_text(
diff --git a/codex-rs/tui/src/app/agent_status_feed_tests.rs b/codex-rs/tui/src/app/agent_status_feed_tests.rs
index 5b8bc4b59b17..c4a671463777 100644
--- a/codex-rs/tui/src/app/agent_status_feed_tests.rs
+++ b/codex-rs/tui/src/app/agent_status_feed_tests.rs
@@ -60,6 +60,64 @@ fn agent_status_uses_bounded_buffered_activity() {
     assert!(!rendered.contains("unbounded output"));
 }
 
+#[test]
+fn agent_status_summarizes_inter_agent_communications() {
+    let mut store = ThreadEventStore::new(/*capacity*/ 8);
+    store.push_notification(ServerNotification::ItemCompleted(
+        ItemCompletedNotification {
+            item: ThreadItem::InterAgentCommunication {
+                id: "message-1".to_string(),
+                source_call_id: Some("call-1".to_string()),
+                sender: "/root".to_string(),
+                receiver: "/root/reviewer".to_string(),
+                other_receivers: Vec::new(),
+                content: "Please check the schema output.".to_string(),
+                encrypted: false,
+                trigger_turn: true,
+            },
+            thread_id: "thread-child".to_string(),
+            turn_id: "turn-1".to_string(),
+            completed_at_ms: 1,
+        },
+    ));
+    store.push_notification(ServerNotification::ItemCompleted(
+        ItemCompletedNotification {
+            item: ThreadItem::InterAgentCommunication {
+                id: "message-2".to_string(),
+                source_call_id: Some("call-2".to_string()),
+                sender: "/root/other".to_string(),
+                receiver: "/root/reviewer".to_string(),
+                other_receivers: Vec::new(),
+                content: "opaque-ciphertext".to_string(),
+                encrypted: true,
+                trigger_turn: false,
+            },
+            thread_id: "thread-child".to_string(),
+            turn_id: "turn-1".to_string(),
+            completed_at_ms: 2,
+        },
+    ));
+
+    let preview = AgentStatusThreadPreview::from_store("/root/reviewer".to_string(), &store);
+    let cell = AgentStatusHistoryCell::new(vec![preview]);
+    let rendered = cell
+        .display_lines(/*width*/ 80)
+        .iter()
+        .map(ToString::to_string)
+        .collect::<Vec<_>>()
+        .join("\n");
+
+    insta::assert_snapshot!(rendered, @r###"
+    /agent
+    Sub-agents running
+
+      • `/root/reviewer`
+        Message from /root: Please check the schema output.
+        Encrypted message from /root/other
+    "###);
+    assert!(!rendered.contains("opaque-ciphertext"));
+}
+
 #[test]
 fn agent_status_uses_reasoning_summaries_only() {
     let mut store = ThreadEventStore::new(/*capacity*/ 8);
diff --git a/codex-rs/tui/src/chatwidget/replay.rs b/codex-rs/tui/src/chatwidget/replay.rs
index a96ab614cac9..de60eec42993 100644
--- a/codex-rs/tui/src/chatwidget/replay.rs
+++ b/codex-rs/tui/src/chatwidget/replay.rs
@@ -192,6 +192,7 @@ impl ChatWidget {
                 agents_states,
             }),
             item @ ThreadItem::SubAgentActivity { .. } => self.on_sub_agent_activity(item),
+            ThreadItem::InterAgentCommunication { .. } => {}
             ThreadItem::DynamicToolCall { .. } => {}
             ThreadItem::Sleep { .. } => {}
         }
diff --git a/codex-rs/tui/src/thread_transcript.rs b/codex-rs/tui/src/thread_transcript.rs
index 13b2a3a3897e..f127c3985802 100644
--- a/codex-rs/tui/src/thread_transcript.rs
+++ b/codex-rs/tui/src/thread_transcript.rs
@@ -225,6 +225,7 @@ fn fallback_transcript_cell(item: &ThreadItem) -> Option<PlainHistoryCell> {
         }
         ThreadItem::UserMessage { .. }
         | ThreadItem::AgentMessage { .. }
+        | ThreadItem::InterAgentCommunication { .. }
         | ThreadItem::Plan { .. }
         | ThreadItem::Reasoning { .. }
         | ThreadItem::Sleep { .. } => return None,

From bf64dcab2cda3bc91a752cb7e634a73494e4e3a1 Mon Sep 17 00:00:00 2001
From: jif-oai <jif@openai.com>
Date: Tue, 16 Jun 2026 20:53:48 +0200
Subject: [PATCH 3/6] Simplify inter-agent communication joins

---
 codex-rs/analytics/src/reducer.rs             |  2 -
 .../schema/json/ServerNotification.json       | 53 -----------------
 .../codex_app_server_protocol.schemas.json    | 53 -----------------
 .../codex_app_server_protocol.v2.schemas.json | 53 -----------------
 .../json/v2/ItemCompletedNotification.json    | 53 -----------------
 .../json/v2/ItemStartedNotification.json      | 53 -----------------
 .../schema/json/v2/ReviewStartResponse.json   | 53 -----------------
 .../schema/json/v2/ThreadForkResponse.json    | 53 -----------------
 .../schema/json/v2/ThreadListResponse.json    | 53 -----------------
 .../json/v2/ThreadMetadataUpdateResponse.json | 53 -----------------
 .../schema/json/v2/ThreadReadResponse.json    | 53 -----------------
 .../schema/json/v2/ThreadResumeResponse.json  | 53 -----------------
 .../json/v2/ThreadRollbackResponse.json       | 53 -----------------
 .../schema/json/v2/ThreadStartResponse.json   | 53 -----------------
 .../json/v2/ThreadStartedNotification.json    | 53 -----------------
 .../json/v2/ThreadUnarchiveResponse.json      | 53 -----------------
 .../json/v2/TurnCompletedNotification.json    | 53 -----------------
 .../schema/json/v2/TurnStartResponse.json     | 53 -----------------
 .../json/v2/TurnStartedNotification.json      | 53 -----------------
 .../schema/typescript/v2/ThreadItem.ts        |  2 +-
 .../src/protocol/thread_history.rs            |  7 ---
 .../src/protocol/v2/item.rs                   | 29 ----------
 .../src/protocol/v2/tests.rs                  | 31 ----------
 codex-rs/core/src/session/mod.rs              | 26 ---------
 .../src/tools/handlers/multi_agents_tests.rs  | 27 +++++++++
 .../tools/handlers/multi_agents_v2/spawn.rs   |  7 ++-
 codex-rs/protocol/src/items.rs                | 21 -------
 codex-rs/tui/src/app/agent_status_feed.rs     | 11 ----
 .../tui/src/app/agent_status_feed_tests.rs    | 58 -------------------
 codex-rs/tui/src/chatwidget/replay.rs         |  1 -
 codex-rs/tui/src/thread_transcript.rs         |  1 -
 31 files changed, 34 insertions(+), 1143 deletions(-)

diff --git a/codex-rs/analytics/src/reducer.rs b/codex-rs/analytics/src/reducer.rs
index 1123af7d67f6..89d6e57dc5c4 100644
--- a/codex-rs/analytics/src/reducer.rs
+++ b/codex-rs/analytics/src/reducer.rs
@@ -381,7 +381,6 @@ impl TurnToolCounts {
             ThreadItem::UserMessage { .. }
             | ThreadItem::HookPrompt { .. }
             | ThreadItem::AgentMessage { .. }
-            | ThreadItem::InterAgentCommunication { .. }
             | ThreadItem::Plan { .. }
             | ThreadItem::Reasoning { .. }
             | ThreadItem::ImageView { .. }
@@ -1618,7 +1617,6 @@ fn tracked_tool_item_id(item: &ThreadItem) -> Option<&str> {
         ThreadItem::UserMessage { .. }
         | ThreadItem::HookPrompt { .. }
         | ThreadItem::AgentMessage { .. }
-        | ThreadItem::InterAgentCommunication { .. }
         | ThreadItem::Plan { .. }
         | ThreadItem::Reasoning { .. }
         | ThreadItem::SubAgentActivity { .. }
diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json
index 59d753a8d589..1cf3d96c8172 100644
--- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json
@@ -3882,59 +3882,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
index 5f393eef5e17..0656368ae08b 100644
--- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
+++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
@@ -17316,59 +17316,6 @@
             "title": "AgentMessageThreadItem",
             "type": "object"
           },
-          {
-            "properties": {
-              "content": {
-                "type": "string"
-              },
-              "encrypted": {
-                "type": "boolean"
-              },
-              "id": {
-                "type": "string"
-              },
-              "otherReceivers": {
-                "items": {
-                  "type": "string"
-                },
-                "type": "array"
-              },
-              "receiver": {
-                "type": "string"
-              },
-              "sender": {
-                "type": "string"
-              },
-              "sourceCallId": {
-                "type": [
-                  "string",
-                  "null"
-                ]
-              },
-              "triggerTurn": {
-                "type": "boolean"
-              },
-              "type": {
-                "enum": [
-                  "interAgentCommunication"
-                ],
-                "title": "InterAgentCommunicationThreadItemType",
-                "type": "string"
-              }
-            },
-            "required": [
-              "content",
-              "encrypted",
-              "id",
-              "otherReceivers",
-              "receiver",
-              "sender",
-              "triggerTurn",
-              "type"
-            ],
-            "title": "InterAgentCommunicationThreadItem",
-            "type": "object"
-          },
           {
             "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
             "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
index e88c353fc705..1b72355b6ab4 100644
--- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
+++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
@@ -15124,59 +15124,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json
index abcd3dfea10e..233ff8dc98e2 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json
@@ -605,59 +605,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json
index c5b9c6d6cc69..a55d9e776649 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json
@@ -605,59 +605,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json
index 581faea94d79..e27c911b3600 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json
@@ -749,59 +749,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json
index 4c437356dc4d..4a666672b66e 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json
@@ -1233,59 +1233,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json
index e9182b6affa9..c1d1b6759a80 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json
@@ -1048,59 +1048,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json
index d5315b32e8f7..801d1cf131be 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadMetadataUpdateResponse.json
@@ -1048,59 +1048,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json
index feb6e6a17a95..01b5ed907efc 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json
@@ -1048,59 +1048,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json
index b1b44ce098e4..032d1dd74ef2 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json
@@ -1233,59 +1233,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json
index ba57cee7d375..c1ad534756fd 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json
@@ -1048,59 +1048,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json
index 8166de5d36d5..33373b9f7208 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json
@@ -1233,59 +1233,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json
index 8cd99a79f8dd..577df57e0501 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json
@@ -1048,59 +1048,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json
index a16ffadc3af4..fcc42e6261c0 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json
@@ -1048,59 +1048,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json
index 3fdf06f8f92e..24d1dccf475c 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json
@@ -749,59 +749,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json
index bd8e18c7d176..da88eacd4874 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json
@@ -749,59 +749,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json
index 84e32c7d14b8..edb3fa636a07 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json
@@ -749,59 +749,6 @@
           "title": "AgentMessageThreadItem",
           "type": "object"
         },
-        {
-          "properties": {
-            "content": {
-              "type": "string"
-            },
-            "encrypted": {
-              "type": "boolean"
-            },
-            "id": {
-              "type": "string"
-            },
-            "otherReceivers": {
-              "items": {
-                "type": "string"
-              },
-              "type": "array"
-            },
-            "receiver": {
-              "type": "string"
-            },
-            "sender": {
-              "type": "string"
-            },
-            "sourceCallId": {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "triggerTurn": {
-              "type": "boolean"
-            },
-            "type": {
-              "enum": [
-                "interAgentCommunication"
-              ],
-              "title": "InterAgentCommunicationThreadItemType",
-              "type": "string"
-            }
-          },
-          "required": [
-            "content",
-            "encrypted",
-            "id",
-            "otherReceivers",
-            "receiver",
-            "sender",
-            "triggerTurn",
-            "type"
-          ],
-          "title": "InterAgentCommunicationThreadItem",
-          "type": "object"
-        },
         {
           "description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
           "properties": {
diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts
index 933f6b632e2a..4ccab77b32ad 100644
--- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts
+++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts
@@ -24,7 +24,7 @@ import type { SubAgentActivityKind } from "./SubAgentActivityKind";
 import type { UserInput } from "./UserInput";
 import type { WebSearchAction } from "./WebSearchAction";
 
-export type ThreadItem = { "type": "userMessage", id: string, clientId: string | null, content: Array<UserInput>, } | { "type": "hookPrompt", id: string, fragments: Array<HookPromptFragment>, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, memoryCitation: MemoryCitation | null, } | { "type": "interAgentCommunication", id: string, sourceCallId: string | null, sender: string, receiver: string, otherReceivers: Array<string>, content: string, encrypted: boolean, triggerTurn: boolean, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array<string>, content: Array<string>, } | { "type": "commandExecution", id: string,
+export type ThreadItem = { "type": "userMessage", id: string, clientId: string | null, content: Array<UserInput>, } | { "type": "hookPrompt", id: string, fragments: Array<HookPromptFragment>, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, memoryCitation: MemoryCitation | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array<string>, content: Array<string>, } | { "type": "commandExecution", id: string,
 /**
  * The command to be executed.
  */
diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history.rs b/codex-rs/app-server-protocol/src/protocol/thread_history.rs
index 4f942c1a9fe1..6ca038981fc1 100644
--- a/codex-rs/app-server-protocol/src/protocol/thread_history.rs
+++ b/codex-rs/app-server-protocol/src/protocol/thread_history.rs
@@ -376,7 +376,6 @@ impl ThreadHistoryBuilder {
             codex_protocol::items::TurnItem::UserMessage(_)
             | codex_protocol::items::TurnItem::HookPrompt(_)
             | codex_protocol::items::TurnItem::AgentMessage(_)
-            | codex_protocol::items::TurnItem::InterAgentCommunication(_)
             | codex_protocol::items::TurnItem::Reasoning(_)
             | codex_protocol::items::TurnItem::WebSearch(_)
             | codex_protocol::items::TurnItem::ImageView(_)
@@ -404,12 +403,6 @@ impl ThreadHistoryBuilder {
                     ThreadItem::from(payload.item.clone()),
                 );
             }
-            codex_protocol::items::TurnItem::InterAgentCommunication(_) => {
-                self.upsert_item_in_turn_id(
-                    &payload.turn_id,
-                    ThreadItem::from(payload.item.clone()),
-                );
-            }
             codex_protocol::items::TurnItem::UserMessage(_)
             | codex_protocol::items::TurnItem::HookPrompt(_)
             | codex_protocol::items::TurnItem::AgentMessage(_)
diff --git a/codex-rs/app-server-protocol/src/protocol/v2/item.rs b/codex-rs/app-server-protocol/src/protocol/v2/item.rs
index 9e265f3e0fa1..502eb62e103a 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/item.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/item.rs
@@ -237,18 +237,6 @@ pub enum ThreadItem {
     },
     #[serde(rename_all = "camelCase")]
     #[ts(rename_all = "camelCase")]
-    InterAgentCommunication {
-        id: String,
-        source_call_id: Option<String>,
-        sender: String,
-        receiver: String,
-        other_receivers: Vec<String>,
-        content: String,
-        encrypted: bool,
-        trigger_turn: bool,
-    },
-    #[serde(rename_all = "camelCase")]
-    #[ts(rename_all = "camelCase")]
     /// EXPERIMENTAL - proposed plan item content. The completed plan item is
     /// authoritative and may not match the concatenation of `PlanDelta` text.
     Plan { id: String, text: String },
@@ -409,7 +397,6 @@ impl ThreadItem {
             ThreadItem::UserMessage { id, .. }
             | ThreadItem::HookPrompt { id, .. }
             | ThreadItem::AgentMessage { id, .. }
-            | ThreadItem::InterAgentCommunication { id, .. }
             | ThreadItem::Plan { id, .. }
             | ThreadItem::Reasoning { id, .. }
             | ThreadItem::CommandExecution { id, .. }
@@ -840,22 +827,6 @@ impl From<CoreTurnItem> for ThreadItem {
                     memory_citation: agent.memory_citation.map(Into::into),
                 }
             }
-            CoreTurnItem::InterAgentCommunication(communication) => {
-                ThreadItem::InterAgentCommunication {
-                    id: communication.id,
-                    source_call_id: communication.source_call_id,
-                    sender: communication.sender.to_string(),
-                    receiver: communication.receiver.to_string(),
-                    other_receivers: communication
-                        .other_receivers
-                        .into_iter()
-                        .map(String::from)
-                        .collect(),
-                    content: communication.content,
-                    encrypted: communication.encrypted,
-                    trigger_turn: communication.trigger_turn,
-                }
-            }
             CoreTurnItem::Plan(plan) => ThreadItem::Plan {
                 id: plan.id,
                 text: plan.text,
diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
index 6a3ce66f975e..2567e386c839 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
@@ -1,11 +1,9 @@
 use super::*;
-use codex_protocol::AgentPath;
 use codex_protocol::approvals::ElicitationRequest as CoreElicitationRequest;
 use codex_protocol::items::AgentMessageContent;
 use codex_protocol::items::AgentMessageItem;
 use codex_protocol::items::FileChangeItem;
 use codex_protocol::items::ImageViewItem;
-use codex_protocol::items::InterAgentCommunicationItem;
 use codex_protocol::items::McpToolCallItem;
 use codex_protocol::items::McpToolCallStatus as CoreMcpToolCallStatus;
 use codex_protocol::items::ReasoningItem;
@@ -2498,35 +2496,6 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
         }
     );
 
-    let communication_item = TurnItem::InterAgentCommunication(InterAgentCommunicationItem {
-        id: "communication-1".to_string(),
-        source_call_id: Some("call-1".to_string()),
-        sender: AgentPath::root(),
-        receiver: AgentPath::root().join("worker").expect("receiver path"),
-        other_receivers: vec![
-            AgentPath::root()
-                .join("reviewer")
-                .expect("other receiver path"),
-        ],
-        content: "please check this".to_string(),
-        encrypted: true,
-        trigger_turn: false,
-    });
-
-    assert_eq!(
-        ThreadItem::from(communication_item),
-        ThreadItem::InterAgentCommunication {
-            id: "communication-1".to_string(),
-            source_call_id: Some("call-1".to_string()),
-            sender: "/root".to_string(),
-            receiver: "/root/worker".to_string(),
-            other_receivers: vec!["/root/reviewer".to_string()],
-            content: "please check this".to_string(),
-            encrypted: true,
-            trigger_turn: false,
-        }
-    );
-
     let reasoning_item = TurnItem::Reasoning(ReasoningItem {
         id: "reasoning-1".to_string(),
         summary_text: vec!["line one".to_string(), "line two".to_string()],
diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs
index a7262cf48c92..242e35f37568 100644
--- a/codex-rs/core/src/session/mod.rs
+++ b/codex-rs/core/src/session/mod.rs
@@ -93,7 +93,6 @@ use codex_protocol::config_types::Settings;
 use codex_protocol::config_types::WebSearchMode;
 use codex_protocol::dynamic_tools::DynamicToolResponse;
 use codex_protocol::dynamic_tools::DynamicToolSpec;
-use codex_protocol::items::InterAgentCommunicationItem;
 use codex_protocol::items::TurnItem;
 use codex_protocol::items::UserMessageItem;
 use codex_protocol::mcp::CallToolResult;
@@ -2675,26 +2674,6 @@ impl Session {
         communication: InterAgentCommunication,
     ) {
         let response_item = communication.to_model_input_item();
-        let source_call_id = communication
-            .metadata
-            .as_ref()
-            .and_then(|metadata| metadata.source_call_id.clone());
-        let (content, encrypted) = match &communication.encrypted_content {
-            Some(encrypted_content) => (encrypted_content.clone(), true),
-            None => (communication.content.clone(), false),
-        };
-        let communication_item = InterAgentCommunicationItem {
-            id: source_call_id
-                .clone()
-                .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
-            source_call_id,
-            sender: communication.author.clone(),
-            receiver: communication.recipient.clone(),
-            other_receivers: communication.other_recipients.clone(),
-            content,
-            encrypted,
-            trigger_turn: communication.trigger_turn,
-        };
         let items = self.prepare_conversation_items_for_history(
             turn_context,
             std::slice::from_ref(&response_item),
@@ -2707,11 +2686,6 @@ impl Session {
         self.persist_rollout_items(&[RolloutItem::InterAgentCommunication(communication)])
             .await;
         self.send_raw_response_items(turn_context, items).await;
-        self.emit_turn_item_completed(
-            turn_context,
-            TurnItem::InterAgentCommunication(communication_item),
-        )
-        .await;
     }
 
     async fn maybe_warn_on_server_model_mismatch(
diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
index ebb452c1de08..7b541b7cf9b0 100644
--- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
+++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
@@ -1195,6 +1195,11 @@ async fn multi_agent_v2_spawn_returns_path_and_send_message_accepts_relative_pat
                         && communication.other_recipients.is_empty()
                         && communication.content.is_empty()
                         && communication.encrypted_content.as_deref() == Some("encrypted-spawn-message")
+                        && communication
+                            .metadata
+                            .as_ref()
+                            .and_then(|metadata| metadata.source_call_id.as_deref())
+                            == Some("call-1")
                         && communication.trigger_turn
             )
     }));
@@ -1222,6 +1227,11 @@ async fn multi_agent_v2_spawn_returns_path_and_send_message_accepts_relative_pat
                         && communication.other_recipients.is_empty()
                         && communication.content.is_empty()
                         && communication.encrypted_content.as_deref() == Some("encrypted-send-message")
+                        && communication
+                            .metadata
+                            .as_ref()
+                            .and_then(|metadata| metadata.source_call_id.as_deref())
+                            == Some("call-1")
                         && !communication.trigger_turn
             )
     }));
@@ -2027,6 +2037,23 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
         .await
         .expect("followup_task should succeed");
 
+    assert!(manager.captured_ops().iter().any(|(id, op)| {
+        *id == agent_id
+            && matches!(
+                op,
+                Op::InterAgentCommunication { communication }
+                    if communication.author == AgentPath::root()
+                        && communication.recipient == worker_path
+                        && communication.encrypted_content.as_deref() == Some("continue")
+                        && communication
+                            .metadata
+                            .as_ref()
+                            .and_then(|metadata| metadata.source_call_id.as_deref())
+                            == Some("call-1")
+                        && communication.trigger_turn
+            )
+    }));
+
     let second_turn = thread.codex.session.new_default_turn().await;
     thread
         .codex
diff --git a/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs b/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
index 2186a4a6d605..51813c5c1991 100644
--- a/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
+++ b/codex-rs/core/src/tools/handlers/multi_agents_v2/spawn.rs
@@ -8,6 +8,7 @@ use crate::tools::handlers::multi_agents_spec::SpawnAgentToolOptions;
 use crate::tools::handlers::multi_agents_spec::create_spawn_agent_tool_v2;
 use crate::turn_timing::now_unix_timestamp_ms;
 use codex_protocol::AgentPath;
+use codex_protocol::models::ResponseItemMetadata;
 use codex_protocol::protocol::Op;
 use codex_tools::ToolSpec;
 
@@ -117,8 +118,12 @@ async fn handle_spawn_agent(
                         .session_source
                         .get_agent_path()
                         .unwrap_or_else(AgentPath::root);
-                    let communication =
+                    let mut communication =
                         communication_from_tool_message(author, new_agent_path.clone(), message);
+                    communication
+                        .metadata
+                        .get_or_insert_with(ResponseItemMetadata::default)
+                        .source_call_id = Some(call_id.clone());
                     Op::InterAgentCommunication { communication }
                 }
                 initial_operation => initial_operation,
diff --git a/codex-rs/protocol/src/items.rs b/codex-rs/protocol/src/items.rs
index d830ba300277..01f44576ace3 100644
--- a/codex-rs/protocol/src/items.rs
+++ b/codex-rs/protocol/src/items.rs
@@ -1,4 +1,3 @@
-use crate::AgentPath;
 use crate::mcp::CallToolResult;
 use crate::memory_citation::MemoryCitation;
 use crate::models::ContentItem;
@@ -44,7 +43,6 @@ pub enum TurnItem {
     UserMessage(UserMessageItem),
     HookPrompt(HookPromptItem),
     AgentMessage(AgentMessageItem),
-    InterAgentCommunication(InterAgentCommunicationItem),
     Plan(PlanItem),
     Reasoning(ReasoningItem),
     WebSearch(WebSearchItem),
@@ -116,23 +114,6 @@ pub struct AgentMessageItem {
     pub memory_citation: Option<MemoryCitation>,
 }
 
-#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq, Eq)]
-#[serde(rename_all = "camelCase")]
-#[ts(rename_all = "camelCase")]
-pub struct InterAgentCommunicationItem {
-    pub id: String,
-    #[serde(default, skip_serializing_if = "Option::is_none")]
-    #[ts(optional)]
-    pub source_call_id: Option<String>,
-    pub sender: AgentPath,
-    pub receiver: AgentPath,
-    #[serde(default, skip_serializing_if = "Vec::is_empty")]
-    pub other_receivers: Vec<AgentPath>,
-    pub content: String,
-    pub encrypted: bool,
-    pub trigger_turn: bool,
-}
-
 #[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
 pub struct PlanItem {
     pub id: String,
@@ -598,7 +579,6 @@ impl TurnItem {
             TurnItem::UserMessage(item) => item.id.clone(),
             TurnItem::HookPrompt(item) => item.id.clone(),
             TurnItem::AgentMessage(item) => item.id.clone(),
-            TurnItem::InterAgentCommunication(item) => item.id.clone(),
             TurnItem::Plan(item) => item.id.clone(),
             TurnItem::Reasoning(item) => item.id.clone(),
             TurnItem::WebSearch(item) => item.id.clone(),
@@ -616,7 +596,6 @@ impl TurnItem {
             TurnItem::UserMessage(item) => vec![item.as_legacy_event()],
             TurnItem::HookPrompt(_) => Vec::new(),
             TurnItem::AgentMessage(item) => item.as_legacy_events(),
-            TurnItem::InterAgentCommunication(_) => Vec::new(),
             TurnItem::Plan(_) => Vec::new(),
             TurnItem::WebSearch(item) => vec![item.as_legacy_event()],
             TurnItem::ImageView(item) => {
diff --git a/codex-rs/tui/src/app/agent_status_feed.rs b/codex-rs/tui/src/app/agent_status_feed.rs
index f9dd137020f6..544c0b7172d5 100644
--- a/codex-rs/tui/src/app/agent_status_feed.rs
+++ b/codex-rs/tui/src/app/agent_status_feed.rs
@@ -135,17 +135,6 @@ impl AgentStatusThreadPreview {
 fn activity_summary(item: &ThreadItem) -> Option<String> {
     let summary = match item {
         ThreadItem::AgentMessage { text, .. } | ThreadItem::Plan { text, .. } => text,
-        ThreadItem::InterAgentCommunication {
-            sender,
-            content,
-            encrypted,
-            ..
-        } => {
-            if *encrypted {
-                return bounded_summary(&format!("Encrypted message from {sender}"));
-            }
-            return bounded_summary(&format!("Message from {sender}: {content}"));
-        }
         ThreadItem::Reasoning { summary, .. } => summary.last()?,
         ThreadItem::CommandExecution { command, .. } => {
             let command = truncate_text(
diff --git a/codex-rs/tui/src/app/agent_status_feed_tests.rs b/codex-rs/tui/src/app/agent_status_feed_tests.rs
index c4a671463777..5b8bc4b59b17 100644
--- a/codex-rs/tui/src/app/agent_status_feed_tests.rs
+++ b/codex-rs/tui/src/app/agent_status_feed_tests.rs
@@ -60,64 +60,6 @@ fn agent_status_uses_bounded_buffered_activity() {
     assert!(!rendered.contains("unbounded output"));
 }
 
-#[test]
-fn agent_status_summarizes_inter_agent_communications() {
-    let mut store = ThreadEventStore::new(/*capacity*/ 8);
-    store.push_notification(ServerNotification::ItemCompleted(
-        ItemCompletedNotification {
-            item: ThreadItem::InterAgentCommunication {
-                id: "message-1".to_string(),
-                source_call_id: Some("call-1".to_string()),
-                sender: "/root".to_string(),
-                receiver: "/root/reviewer".to_string(),
-                other_receivers: Vec::new(),
-                content: "Please check the schema output.".to_string(),
-                encrypted: false,
-                trigger_turn: true,
-            },
-            thread_id: "thread-child".to_string(),
-            turn_id: "turn-1".to_string(),
-            completed_at_ms: 1,
-        },
-    ));
-    store.push_notification(ServerNotification::ItemCompleted(
-        ItemCompletedNotification {
-            item: ThreadItem::InterAgentCommunication {
-                id: "message-2".to_string(),
-                source_call_id: Some("call-2".to_string()),
-                sender: "/root/other".to_string(),
-                receiver: "/root/reviewer".to_string(),
-                other_receivers: Vec::new(),
-                content: "opaque-ciphertext".to_string(),
-                encrypted: true,
-                trigger_turn: false,
-            },
-            thread_id: "thread-child".to_string(),
-            turn_id: "turn-1".to_string(),
-            completed_at_ms: 2,
-        },
-    ));
-
-    let preview = AgentStatusThreadPreview::from_store("/root/reviewer".to_string(), &store);
-    let cell = AgentStatusHistoryCell::new(vec![preview]);
-    let rendered = cell
-        .display_lines(/*width*/ 80)
-        .iter()
-        .map(ToString::to_string)
-        .collect::<Vec<_>>()
-        .join("\n");
-
-    insta::assert_snapshot!(rendered, @r###"
-    /agent
-    Sub-agents running
-
-      • `/root/reviewer`
-        Message from /root: Please check the schema output.
-        Encrypted message from /root/other
-    "###);
-    assert!(!rendered.contains("opaque-ciphertext"));
-}
-
 #[test]
 fn agent_status_uses_reasoning_summaries_only() {
     let mut store = ThreadEventStore::new(/*capacity*/ 8);
diff --git a/codex-rs/tui/src/chatwidget/replay.rs b/codex-rs/tui/src/chatwidget/replay.rs
index de60eec42993..a96ab614cac9 100644
--- a/codex-rs/tui/src/chatwidget/replay.rs
+++ b/codex-rs/tui/src/chatwidget/replay.rs
@@ -192,7 +192,6 @@ impl ChatWidget {
                 agents_states,
             }),
             item @ ThreadItem::SubAgentActivity { .. } => self.on_sub_agent_activity(item),
-            ThreadItem::InterAgentCommunication { .. } => {}
             ThreadItem::DynamicToolCall { .. } => {}
             ThreadItem::Sleep { .. } => {}
         }
diff --git a/codex-rs/tui/src/thread_transcript.rs b/codex-rs/tui/src/thread_transcript.rs
index f127c3985802..13b2a3a3897e 100644
--- a/codex-rs/tui/src/thread_transcript.rs
+++ b/codex-rs/tui/src/thread_transcript.rs
@@ -225,7 +225,6 @@ fn fallback_transcript_cell(item: &ThreadItem) -> Option<PlainHistoryCell> {
         }
         ThreadItem::UserMessage { .. }
         | ThreadItem::AgentMessage { .. }
-        | ThreadItem::InterAgentCommunication { .. }
         | ThreadItem::Plan { .. }
         | ThreadItem::Reasoning { .. }
         | ThreadItem::Sleep { .. } => return None,

From add04908ce88015164a9978547002cc37d1be9ff Mon Sep 17 00:00:00 2001
From: jif-oai <jif@openai.com>
Date: Tue, 16 Jun 2026 21:06:55 +0200
Subject: [PATCH 4/6] Update MAv2 spawn notification expectation

---
 codex-rs/core/tests/suite/subagent_notifications.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs
index 764380be7190..2501aa0dde31 100644
--- a/codex-rs/core/tests/suite/subagent_notifications.rs
+++ b/codex-rs/core/tests/suite/subagent_notifications.rs
@@ -1088,6 +1088,9 @@ async fn encrypted_multi_agent_v2_spawn_sends_agent_message_to_child() -> Result
             "type": "agent_message",
             "author": "/root",
             "recipient": "/root/worker",
+            "metadata": {
+                "source_call_id": SPAWN_CALL_ID,
+            },
             "content": [
                 {
                     "type": "input_text",

From 3e657a4eec5ca68a86aa55dd9162ffd0f3643330 Mon Sep 17 00:00:00 2001
From: jif-oai <jif@openai.com>
Date: Wed, 17 Jun 2026 13:37:56 +0200
Subject: [PATCH 5/6] Preserve MAv2 join keys across resume

---
 .../src/protocol/v2/thread.rs                 |  5 ++
 codex-rs/app-server/README.md                 |  4 +
 .../request_processors/thread_processor.rs    |  9 +-
 .../thread_processor_tests.rs                 |  1 +
 .../tests/suite/v2/thread_resume.rs           | 55 ++++++++++++
 codex-rs/core/src/session/mod.rs              | 31 ++++++-
 codex-rs/core/src/tasks/mod.rs                |  6 ++
 .../src/tools/handlers/multi_agents_tests.rs  | 85 ++++++++++++++-----
 .../tests/suite/subagent_notifications.rs     |  3 +
 9 files changed, 176 insertions(+), 23 deletions(-)

diff --git a/codex-rs/app-server-protocol/src/protocol/v2/thread.rs b/codex-rs/app-server-protocol/src/protocol/v2/thread.rs
index 0252c4b048ae..4bb886a33f9c 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/thread.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/thread.rs
@@ -359,6 +359,11 @@ pub struct ThreadResumeParams {
     #[experimental("thread/resume.initialTurnsPage")]
     #[ts(optional = nullable)]
     pub initial_turns_page: Option<ThreadResumeInitialTurnsPageParams>,
+    /// If true, opt into emitting raw Responses API items on the event stream.
+    /// This is for internal use only (e.g. Codex Cloud).
+    #[experimental("thread/resume.experimentalRawEvents")]
+    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
+    pub experimental_raw_events: bool,
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]
diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md
index 336f769d7155..0d1397e7989f 100644
--- a/codex-rs/app-server/README.md
+++ b/codex-rs/app-server/README.md
@@ -1283,6 +1283,10 @@ Recoverable configuration and initialization warnings use the existing `configWa
 
 Generic runtime warnings use the `warning` notification: `{ threadId?, message }`. App-server emits this for non-fatal warnings from the core event stream, including cases where not all enabled skills are included in the model-visible skills list for a session.
 
+### Raw response items (experimental)
+
+Set `experimentalRawEvents: true` on `thread/start` or `thread/resume` to receive `rawResponseItem/completed` notifications. Multi-agent v2 `agent_message` items include `metadata.source_call_id`, which matches the originating `spawn_agent`, `send_message`, or `followup_task` call id. Clients can use that field to join the raw message to the corresponding tool or activity event.
+
 ### Notification opt-out
 
 Clients can suppress specific notifications per connection by sending exact method names in `initialize.params.capabilities.optOutNotificationMethods`.
diff --git a/codex-rs/app-server/src/request_processors/thread_processor.rs b/codex-rs/app-server/src/request_processors/thread_processor.rs
index 09ff0dd6981f..fbecf10f6b0c 100644
--- a/codex-rs/app-server/src/request_processors/thread_processor.rs
+++ b/codex-rs/app-server/src/request_processors/thread_processor.rs
@@ -2593,6 +2593,7 @@ impl ThreadRequestProcessor {
             personality,
             exclude_turns,
             initial_turns_page,
+            experimental_raw_events,
         } = params;
         let include_turns = !exclude_turns;
 
@@ -2695,7 +2696,7 @@ impl ThreadRequestProcessor {
                     self.ensure_conversation_listener(
                         thread_id,
                         request_id.connection_id,
-                        /*raw_events_enabled*/ false,
+                        experimental_raw_events,
                     )
                     .await,
                     thread_id,
@@ -2969,6 +2970,12 @@ impl ThreadRequestProcessor {
                 .thread_state_manager
                 .thread_state(existing_thread_id)
                 .await;
+            if params.experimental_raw_events {
+                thread_state
+                    .lock()
+                    .await
+                    .set_experimental_raw_events(/*enabled*/ true);
+            }
             self.ensure_listener_task_running(
                 existing_thread_id,
                 existing_thread.clone(),
diff --git a/codex-rs/app-server/src/request_processors/thread_processor_tests.rs b/codex-rs/app-server/src/request_processors/thread_processor_tests.rs
index 42711e857012..f30f04e76edc 100644
--- a/codex-rs/app-server/src/request_processors/thread_processor_tests.rs
+++ b/codex-rs/app-server/src/request_processors/thread_processor_tests.rs
@@ -751,6 +751,7 @@ mod thread_processor_behavior_tests {
             personality: None,
             exclude_turns: false,
             initial_turns_page: None,
+            experimental_raw_events: false,
         };
         let config_snapshot = ThreadConfigSnapshot {
             model: "gpt-5".to_string(),
diff --git a/codex-rs/app-server/tests/suite/v2/thread_resume.rs b/codex-rs/app-server/tests/suite/v2/thread_resume.rs
index e67184bf01d3..18bcd0c5293d 100644
--- a/codex-rs/app-server/tests/suite/v2/thread_resume.rs
+++ b/codex-rs/app-server/tests/suite/v2/thread_resume.rs
@@ -3488,6 +3488,61 @@ async fn thread_resume_supports_history_and_overrides() -> Result<()> {
     Ok(())
 }
 
+#[tokio::test]
+async fn thread_resume_can_enable_raw_events_after_restart() -> Result<()> {
+    let server = create_mock_responses_server_repeating_assistant("Done").await;
+    let codex_home = TempDir::new()?;
+    create_config_toml(codex_home.path(), &server.uri())?;
+
+    let RestartedThreadFixture {
+        mut mcp, thread_id, ..
+    } = start_materialized_thread_and_restart(codex_home.path(), "seed history").await?;
+
+    let resume_id = mcp
+        .send_thread_resume_request(ThreadResumeParams {
+            thread_id: thread_id.clone(),
+            experimental_raw_events: true,
+            ..Default::default()
+        })
+        .await?;
+    let resume_resp: JSONRPCResponse = timeout(
+        DEFAULT_READ_TIMEOUT,
+        mcp.read_stream_until_response_message(RequestId::Integer(resume_id)),
+    )
+    .await??;
+    to_response::<ThreadResumeResponse>(resume_resp)?;
+
+    let turn_id = mcp
+        .send_turn_start_request(TurnStartParams {
+            thread_id: thread_id.clone(),
+            client_user_message_id: None,
+            input: vec![UserInput::Text {
+                text: "emit raw events".to_string(),
+                text_elements: Vec::new(),
+            }],
+            ..Default::default()
+        })
+        .await?;
+    timeout(
+        DEFAULT_READ_TIMEOUT,
+        mcp.read_stream_until_response_message(RequestId::Integer(turn_id)),
+    )
+    .await??;
+
+    let notification = timeout(
+        DEFAULT_READ_TIMEOUT,
+        mcp.read_stream_until_notification_message("rawResponseItem/completed"),
+    )
+    .await??;
+    let parsed: ServerNotification = notification.try_into()?;
+    let ServerNotification::RawResponseItemCompleted(notification) = parsed else {
+        anyhow::bail!("expected rawResponseItem/completed notification");
+    };
+    assert_eq!(notification.thread_id, thread_id);
+
+    Ok(())
+}
+
 struct RestartedThreadFixture {
     mcp: TestAppServer,
     thread_id: String,
diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs
index 242e35f37568..2158c3085d1f 100644
--- a/codex-rs/core/src/session/mod.rs
+++ b/codex-rs/core/src/session/mod.rs
@@ -340,6 +340,7 @@ use codex_protocol::config_types::WindowsSandboxLevel;
 use codex_protocol::models::LocalImagePreparation;
 use codex_protocol::models::ResponseInputItem;
 use codex_protocol::models::ResponseItem;
+use codex_protocol::models::ResponseItemMetadata;
 use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
 use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
 use codex_protocol::protocol::AskForApproval;
@@ -380,6 +381,24 @@ use codex_utils_absolute_path::AbsolutePathBuf;
 #[cfg(test)]
 use codex_utils_stream_parser::ProposedPlanSegment;
 
+struct InterAgentCompletionSourceCallId(String);
+
+pub(crate) fn record_inter_agent_completion_source_call_id(
+    turn_context: &TurnContext,
+    communication: &InterAgentCommunication,
+) {
+    if communication.trigger_turn
+        && let Some(source_call_id) = communication
+            .metadata
+            .as_ref()
+            .and_then(|metadata| metadata.source_call_id.as_ref())
+    {
+        let _ = turn_context
+            .extension_data
+            .get_or_init(|| InterAgentCompletionSourceCallId(source_call_id.clone()));
+    }
+}
+
 /// The high-level interface to the Codex system.
 /// It operates as a queue pair where you send submissions and receive events.
 pub struct Codex {
@@ -1773,13 +1792,22 @@ impl Session {
             .rollout_thread_trace
             .is_enabled()
             .then(|| message.clone());
-        let communication = InterAgentCommunication::new(
+        let mut communication = InterAgentCommunication::new(
             child_agent_path.clone(),
             parent_agent_path,
             Vec::new(),
             message,
             /*trigger_turn*/ false,
         );
+        if let Some(source_call_id) = turn_context
+            .extension_data
+            .get::<InterAgentCompletionSourceCallId>()
+        {
+            communication.metadata = Some(ResponseItemMetadata {
+                source_call_id: Some(source_call_id.0.clone()),
+                ..Default::default()
+            });
+        }
         if let Err(err) = self
             .services
             .agent_control
@@ -2673,6 +2701,7 @@ impl Session {
         turn_context: &TurnContext,
         communication: InterAgentCommunication,
     ) {
+        record_inter_agent_completion_source_call_id(turn_context, &communication);
         let response_item = communication.to_model_input_item();
         let items = self.prepare_conversation_items_for_history(
             turn_context,
diff --git a/codex-rs/core/src/tasks/mod.rs b/codex-rs/core/src/tasks/mod.rs
index b2f337ec42f2..17c2e1510583 100644
--- a/codex-rs/core/src/tasks/mod.rs
+++ b/codex-rs/core/src/tasks/mod.rs
@@ -29,6 +29,7 @@ use crate::hook_runtime::inspect_pending_input;
 use crate::hook_runtime::record_additional_contexts;
 use crate::hook_runtime::record_pending_input;
 use crate::session::TurnInput;
+use crate::session::record_inter_agent_completion_source_call_id;
 use crate::session::session::Session;
 use crate::session::turn_context::TurnContext;
 use crate::state::ActiveTurn;
@@ -345,6 +346,11 @@ impl Session {
             .clear_turn(&turn_context.sub_id);
 
         let pending_items = self.input_queue.get_pending_input(&self.active_turn).await;
+        for input_item in input.iter().chain(&pending_items) {
+            if let TurnInput::InterAgentCommunication(communication) = input_item {
+                record_inter_agent_completion_source_call_id(&turn_context, communication);
+            }
+        }
         let turn_state = {
             let mut active = self.active_turn.lock().await;
             let turn = active.get_or_insert_with(ActiveTurn::default);
diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
index 7b541b7cf9b0..5ef17df50507 100644
--- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
+++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
@@ -2007,8 +2007,27 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
         .await
         .expect("worker thread should exist");
     let worker_path = AgentPath::try_from("/root/worker").expect("worker path");
+    let spawn_communication = manager
+        .captured_ops()
+        .into_iter()
+        .find_map(|(id, op)| {
+            (id == agent_id).then_some(op).and_then(|op| match op {
+                Op::InterAgentCommunication { communication }
+                    if communication.encrypted_content.as_deref() == Some("boot worker") =>
+                {
+                    Some(communication)
+                }
+                _ => None,
+            })
+        })
+        .expect("spawn communication should be captured");
 
     let first_turn = thread.codex.session.new_default_turn().await;
+    thread
+        .codex
+        .session
+        .record_inter_agent_communication(first_turn.as_ref(), spawn_communication)
+        .await;
     thread
         .codex
         .session
@@ -2024,23 +2043,26 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
         )
         .await;
 
+    let mut followup_invocation = invocation(
+        session,
+        turn,
+        "followup_task",
+        function_payload(json!({
+            "target": agent_id.to_string(),
+            "message": "continue",
+        })),
+    );
+    followup_invocation.call_id = "followup-call".to_string();
     FollowupTaskHandlerV2
-        .handle(invocation(
-            session,
-            turn,
-            "followup_task",
-            function_payload(json!({
-                "target": agent_id.to_string(),
-                "message": "continue",
-            })),
-        ))
+        .handle(followup_invocation)
         .await
         .expect("followup_task should succeed");
 
-    assert!(manager.captured_ops().iter().any(|(id, op)| {
-        *id == agent_id
-            && matches!(
-                op,
+    let followup_communication = manager
+        .captured_ops()
+        .into_iter()
+        .find_map(|(id, op)| {
+            (id == agent_id).then_some(op).and_then(|op| match op {
                 Op::InterAgentCommunication { communication }
                     if communication.author == AgentPath::root()
                         && communication.recipient == worker_path
@@ -2049,12 +2071,22 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
                             .metadata
                             .as_ref()
                             .and_then(|metadata| metadata.source_call_id.as_deref())
-                            == Some("call-1")
-                        && communication.trigger_turn
-            )
-    }));
+                            == Some("followup-call")
+                        && communication.trigger_turn =>
+                {
+                    Some(communication)
+                }
+                _ => None,
+            })
+        })
+        .expect("followup communication should be captured");
 
     let second_turn = thread.codex.session.new_default_turn().await;
+    thread
+        .codex
+        .session
+        .record_inter_agent_communication(second_turn.as_ref(), followup_communication)
+        .await;
     thread
         .codex
         .session
@@ -2098,7 +2130,12 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
                                     && communication.other_recipients.is_empty()
                                     && !communication.trigger_turn =>
                             {
-                                Some(communication.content)
+                                Some((
+                                    communication.content,
+                                    communication
+                                        .metadata
+                                        .and_then(|metadata| metadata.source_call_id),
+                                ))
                             }
                             _ => None,
                         })
@@ -2106,11 +2143,11 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
                 .collect::<Vec<_>>();
             let first_count = notifications
                 .iter()
-                .filter(|message| **message == first_notification)
+                .filter(|(message, _)| *message == first_notification)
                 .count();
             let second_count = notifications
                 .iter()
-                .filter(|message| **message == second_notification)
+                .filter(|(message, _)| *message == second_notification)
                 .count();
             if first_count == 1 && second_count == 1 {
                 break notifications;
@@ -2121,7 +2158,13 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
     .await
     .expect("parent should receive one completion notification per child turn");
 
-    assert_eq!(notifications.len(), 2);
+    assert_eq!(
+        notifications,
+        vec![
+            (first_notification, Some("call-1".to_string())),
+            (second_notification, Some("followup-call".to_string())),
+        ]
+    );
 }
 
 #[tokio::test]
diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs
index 2501aa0dde31..d017ad477289 100644
--- a/codex-rs/core/tests/suite/subagent_notifications.rs
+++ b/codex-rs/core/tests/suite/subagent_notifications.rs
@@ -1234,6 +1234,9 @@ async fn plaintext_multi_agent_v2_completion_sends_agent_message(
             "type": "agent_message",
             "author": "/root/worker",
             "recipient": "/root",
+            "metadata": {
+                "source_call_id": SPAWN_CALL_ID,
+            },
             "content": [{
                 "type": "input_text",
                 "text": notification,

From 11f62190426b0a3c590fa6c16718355aac1d87e7 Mon Sep 17 00:00:00 2001
From: jif-oai <jif@openai.com>
Date: Wed, 17 Jun 2026 14:14:46 +0200
Subject: [PATCH 6/6] Keep raw join key changes minimal

---
 .../src/protocol/v2/thread.rs                 |  5 --
 codex-rs/app-server/README.md                 |  4 -
 .../request_processors/thread_processor.rs    |  9 +-
 .../thread_processor_tests.rs                 |  1 -
 .../tests/suite/v2/thread_resume.rs           | 55 ------------
 codex-rs/core/src/session/mod.rs              | 31 +------
 codex-rs/core/src/tasks/mod.rs                |  6 --
 .../src/tools/handlers/multi_agents_tests.rs  | 85 +++++--------------
 .../tests/suite/subagent_notifications.rs     |  3 -
 9 files changed, 23 insertions(+), 176 deletions(-)

diff --git a/codex-rs/app-server-protocol/src/protocol/v2/thread.rs b/codex-rs/app-server-protocol/src/protocol/v2/thread.rs
index 4bb886a33f9c..0252c4b048ae 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/thread.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/thread.rs
@@ -359,11 +359,6 @@ pub struct ThreadResumeParams {
     #[experimental("thread/resume.initialTurnsPage")]
     #[ts(optional = nullable)]
     pub initial_turns_page: Option<ThreadResumeInitialTurnsPageParams>,
-    /// If true, opt into emitting raw Responses API items on the event stream.
-    /// This is for internal use only (e.g. Codex Cloud).
-    #[experimental("thread/resume.experimentalRawEvents")]
-    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
-    pub experimental_raw_events: bool,
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]
diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md
index 0d1397e7989f..336f769d7155 100644
--- a/codex-rs/app-server/README.md
+++ b/codex-rs/app-server/README.md
@@ -1283,10 +1283,6 @@ Recoverable configuration and initialization warnings use the existing `configWa
 
 Generic runtime warnings use the `warning` notification: `{ threadId?, message }`. App-server emits this for non-fatal warnings from the core event stream, including cases where not all enabled skills are included in the model-visible skills list for a session.
 
-### Raw response items (experimental)
-
-Set `experimentalRawEvents: true` on `thread/start` or `thread/resume` to receive `rawResponseItem/completed` notifications. Multi-agent v2 `agent_message` items include `metadata.source_call_id`, which matches the originating `spawn_agent`, `send_message`, or `followup_task` call id. Clients can use that field to join the raw message to the corresponding tool or activity event.
-
 ### Notification opt-out
 
 Clients can suppress specific notifications per connection by sending exact method names in `initialize.params.capabilities.optOutNotificationMethods`.
diff --git a/codex-rs/app-server/src/request_processors/thread_processor.rs b/codex-rs/app-server/src/request_processors/thread_processor.rs
index fbecf10f6b0c..09ff0dd6981f 100644
--- a/codex-rs/app-server/src/request_processors/thread_processor.rs
+++ b/codex-rs/app-server/src/request_processors/thread_processor.rs
@@ -2593,7 +2593,6 @@ impl ThreadRequestProcessor {
             personality,
             exclude_turns,
             initial_turns_page,
-            experimental_raw_events,
         } = params;
         let include_turns = !exclude_turns;
 
@@ -2696,7 +2695,7 @@ impl ThreadRequestProcessor {
                     self.ensure_conversation_listener(
                         thread_id,
                         request_id.connection_id,
-                        experimental_raw_events,
+                        /*raw_events_enabled*/ false,
                     )
                     .await,
                     thread_id,
@@ -2970,12 +2969,6 @@ impl ThreadRequestProcessor {
                 .thread_state_manager
                 .thread_state(existing_thread_id)
                 .await;
-            if params.experimental_raw_events {
-                thread_state
-                    .lock()
-                    .await
-                    .set_experimental_raw_events(/*enabled*/ true);
-            }
             self.ensure_listener_task_running(
                 existing_thread_id,
                 existing_thread.clone(),
diff --git a/codex-rs/app-server/src/request_processors/thread_processor_tests.rs b/codex-rs/app-server/src/request_processors/thread_processor_tests.rs
index f30f04e76edc..42711e857012 100644
--- a/codex-rs/app-server/src/request_processors/thread_processor_tests.rs
+++ b/codex-rs/app-server/src/request_processors/thread_processor_tests.rs
@@ -751,7 +751,6 @@ mod thread_processor_behavior_tests {
             personality: None,
             exclude_turns: false,
             initial_turns_page: None,
-            experimental_raw_events: false,
         };
         let config_snapshot = ThreadConfigSnapshot {
             model: "gpt-5".to_string(),
diff --git a/codex-rs/app-server/tests/suite/v2/thread_resume.rs b/codex-rs/app-server/tests/suite/v2/thread_resume.rs
index 18bcd0c5293d..e67184bf01d3 100644
--- a/codex-rs/app-server/tests/suite/v2/thread_resume.rs
+++ b/codex-rs/app-server/tests/suite/v2/thread_resume.rs
@@ -3488,61 +3488,6 @@ async fn thread_resume_supports_history_and_overrides() -> Result<()> {
     Ok(())
 }
 
-#[tokio::test]
-async fn thread_resume_can_enable_raw_events_after_restart() -> Result<()> {
-    let server = create_mock_responses_server_repeating_assistant("Done").await;
-    let codex_home = TempDir::new()?;
-    create_config_toml(codex_home.path(), &server.uri())?;
-
-    let RestartedThreadFixture {
-        mut mcp, thread_id, ..
-    } = start_materialized_thread_and_restart(codex_home.path(), "seed history").await?;
-
-    let resume_id = mcp
-        .send_thread_resume_request(ThreadResumeParams {
-            thread_id: thread_id.clone(),
-            experimental_raw_events: true,
-            ..Default::default()
-        })
-        .await?;
-    let resume_resp: JSONRPCResponse = timeout(
-        DEFAULT_READ_TIMEOUT,
-        mcp.read_stream_until_response_message(RequestId::Integer(resume_id)),
-    )
-    .await??;
-    to_response::<ThreadResumeResponse>(resume_resp)?;
-
-    let turn_id = mcp
-        .send_turn_start_request(TurnStartParams {
-            thread_id: thread_id.clone(),
-            client_user_message_id: None,
-            input: vec![UserInput::Text {
-                text: "emit raw events".to_string(),
-                text_elements: Vec::new(),
-            }],
-            ..Default::default()
-        })
-        .await?;
-    timeout(
-        DEFAULT_READ_TIMEOUT,
-        mcp.read_stream_until_response_message(RequestId::Integer(turn_id)),
-    )
-    .await??;
-
-    let notification = timeout(
-        DEFAULT_READ_TIMEOUT,
-        mcp.read_stream_until_notification_message("rawResponseItem/completed"),
-    )
-    .await??;
-    let parsed: ServerNotification = notification.try_into()?;
-    let ServerNotification::RawResponseItemCompleted(notification) = parsed else {
-        anyhow::bail!("expected rawResponseItem/completed notification");
-    };
-    assert_eq!(notification.thread_id, thread_id);
-
-    Ok(())
-}
-
 struct RestartedThreadFixture {
     mcp: TestAppServer,
     thread_id: String,
diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs
index 2158c3085d1f..242e35f37568 100644
--- a/codex-rs/core/src/session/mod.rs
+++ b/codex-rs/core/src/session/mod.rs
@@ -340,7 +340,6 @@ use codex_protocol::config_types::WindowsSandboxLevel;
 use codex_protocol::models::LocalImagePreparation;
 use codex_protocol::models::ResponseInputItem;
 use codex_protocol::models::ResponseItem;
-use codex_protocol::models::ResponseItemMetadata;
 use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
 use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
 use codex_protocol::protocol::AskForApproval;
@@ -381,24 +380,6 @@ use codex_utils_absolute_path::AbsolutePathBuf;
 #[cfg(test)]
 use codex_utils_stream_parser::ProposedPlanSegment;
 
-struct InterAgentCompletionSourceCallId(String);
-
-pub(crate) fn record_inter_agent_completion_source_call_id(
-    turn_context: &TurnContext,
-    communication: &InterAgentCommunication,
-) {
-    if communication.trigger_turn
-        && let Some(source_call_id) = communication
-            .metadata
-            .as_ref()
-            .and_then(|metadata| metadata.source_call_id.as_ref())
-    {
-        let _ = turn_context
-            .extension_data
-            .get_or_init(|| InterAgentCompletionSourceCallId(source_call_id.clone()));
-    }
-}
-
 /// The high-level interface to the Codex system.
 /// It operates as a queue pair where you send submissions and receive events.
 pub struct Codex {
@@ -1792,22 +1773,13 @@ impl Session {
             .rollout_thread_trace
             .is_enabled()
             .then(|| message.clone());
-        let mut communication = InterAgentCommunication::new(
+        let communication = InterAgentCommunication::new(
             child_agent_path.clone(),
             parent_agent_path,
             Vec::new(),
             message,
             /*trigger_turn*/ false,
         );
-        if let Some(source_call_id) = turn_context
-            .extension_data
-            .get::<InterAgentCompletionSourceCallId>()
-        {
-            communication.metadata = Some(ResponseItemMetadata {
-                source_call_id: Some(source_call_id.0.clone()),
-                ..Default::default()
-            });
-        }
         if let Err(err) = self
             .services
             .agent_control
@@ -2701,7 +2673,6 @@ impl Session {
         turn_context: &TurnContext,
         communication: InterAgentCommunication,
     ) {
-        record_inter_agent_completion_source_call_id(turn_context, &communication);
         let response_item = communication.to_model_input_item();
         let items = self.prepare_conversation_items_for_history(
             turn_context,
diff --git a/codex-rs/core/src/tasks/mod.rs b/codex-rs/core/src/tasks/mod.rs
index 17c2e1510583..b2f337ec42f2 100644
--- a/codex-rs/core/src/tasks/mod.rs
+++ b/codex-rs/core/src/tasks/mod.rs
@@ -29,7 +29,6 @@ use crate::hook_runtime::inspect_pending_input;
 use crate::hook_runtime::record_additional_contexts;
 use crate::hook_runtime::record_pending_input;
 use crate::session::TurnInput;
-use crate::session::record_inter_agent_completion_source_call_id;
 use crate::session::session::Session;
 use crate::session::turn_context::TurnContext;
 use crate::state::ActiveTurn;
@@ -346,11 +345,6 @@ impl Session {
             .clear_turn(&turn_context.sub_id);
 
         let pending_items = self.input_queue.get_pending_input(&self.active_turn).await;
-        for input_item in input.iter().chain(&pending_items) {
-            if let TurnInput::InterAgentCommunication(communication) = input_item {
-                record_inter_agent_completion_source_call_id(&turn_context, communication);
-            }
-        }
         let turn_state = {
             let mut active = self.active_turn.lock().await;
             let turn = active.get_or_insert_with(ActiveTurn::default);
diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
index 5ef17df50507..7b541b7cf9b0 100644
--- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
+++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs
@@ -2007,27 +2007,8 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
         .await
         .expect("worker thread should exist");
     let worker_path = AgentPath::try_from("/root/worker").expect("worker path");
-    let spawn_communication = manager
-        .captured_ops()
-        .into_iter()
-        .find_map(|(id, op)| {
-            (id == agent_id).then_some(op).and_then(|op| match op {
-                Op::InterAgentCommunication { communication }
-                    if communication.encrypted_content.as_deref() == Some("boot worker") =>
-                {
-                    Some(communication)
-                }
-                _ => None,
-            })
-        })
-        .expect("spawn communication should be captured");
 
     let first_turn = thread.codex.session.new_default_turn().await;
-    thread
-        .codex
-        .session
-        .record_inter_agent_communication(first_turn.as_ref(), spawn_communication)
-        .await;
     thread
         .codex
         .session
@@ -2043,26 +2024,23 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
         )
         .await;
 
-    let mut followup_invocation = invocation(
-        session,
-        turn,
-        "followup_task",
-        function_payload(json!({
-            "target": agent_id.to_string(),
-            "message": "continue",
-        })),
-    );
-    followup_invocation.call_id = "followup-call".to_string();
     FollowupTaskHandlerV2
-        .handle(followup_invocation)
+        .handle(invocation(
+            session,
+            turn,
+            "followup_task",
+            function_payload(json!({
+                "target": agent_id.to_string(),
+                "message": "continue",
+            })),
+        ))
         .await
         .expect("followup_task should succeed");
 
-    let followup_communication = manager
-        .captured_ops()
-        .into_iter()
-        .find_map(|(id, op)| {
-            (id == agent_id).then_some(op).and_then(|op| match op {
+    assert!(manager.captured_ops().iter().any(|(id, op)| {
+        *id == agent_id
+            && matches!(
+                op,
                 Op::InterAgentCommunication { communication }
                     if communication.author == AgentPath::root()
                         && communication.recipient == worker_path
@@ -2071,22 +2049,12 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
                             .metadata
                             .as_ref()
                             .and_then(|metadata| metadata.source_call_id.as_deref())
-                            == Some("followup-call")
-                        && communication.trigger_turn =>
-                {
-                    Some(communication)
-                }
-                _ => None,
-            })
-        })
-        .expect("followup communication should be captured");
+                            == Some("call-1")
+                        && communication.trigger_turn
+            )
+    }));
 
     let second_turn = thread.codex.session.new_default_turn().await;
-    thread
-        .codex
-        .session
-        .record_inter_agent_communication(second_turn.as_ref(), followup_communication)
-        .await;
     thread
         .codex
         .session
@@ -2130,12 +2098,7 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
                                     && communication.other_recipients.is_empty()
                                     && !communication.trigger_turn =>
                             {
-                                Some((
-                                    communication.content,
-                                    communication
-                                        .metadata
-                                        .and_then(|metadata| metadata.source_call_id),
-                                ))
+                                Some(communication.content)
                             }
                             _ => None,
                         })
@@ -2143,11 +2106,11 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
                 .collect::<Vec<_>>();
             let first_count = notifications
                 .iter()
-                .filter(|(message, _)| *message == first_notification)
+                .filter(|message| **message == first_notification)
                 .count();
             let second_count = notifications
                 .iter()
-                .filter(|(message, _)| *message == second_notification)
+                .filter(|message| **message == second_notification)
                 .count();
             if first_count == 1 && second_count == 1 {
                 break notifications;
@@ -2158,13 +2121,7 @@ async fn multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn()
     .await
     .expect("parent should receive one completion notification per child turn");
 
-    assert_eq!(
-        notifications,
-        vec![
-            (first_notification, Some("call-1".to_string())),
-            (second_notification, Some("followup-call".to_string())),
-        ]
-    );
+    assert_eq!(notifications.len(), 2);
 }
 
 #[tokio::test]
diff --git a/codex-rs/core/tests/suite/subagent_notifications.rs b/codex-rs/core/tests/suite/subagent_notifications.rs
index d017ad477289..2501aa0dde31 100644
--- a/codex-rs/core/tests/suite/subagent_notifications.rs
+++ b/codex-rs/core/tests/suite/subagent_notifications.rs
@@ -1234,9 +1234,6 @@ async fn plaintext_multi_agent_v2_completion_sends_agent_message(
             "type": "agent_message",
             "author": "/root/worker",
             "recipient": "/root",
-            "metadata": {
-                "source_call_id": SPAWN_CALL_ID,
-            },
             "content": [{
                 "type": "input_text",
                 "text": notification,
