Problem statement / motivation
he gateway currently accepts response.create and serializes requests inside WebSocket lanes. Multi-agent requires response.inject to reach a running response. Enqueuing it behind the response waiting for that input deadlocks. Client-side orchestration, an agent-per-lane design, or buffering all outputs until a new create request does not implement OpenAI's live-injection contract.
The guide's WebSocket examples are client drivers: they execute application functions and inject their outputs. Adapt them to generate actual request/response recordings; the gateway supplies agent scheduling and resumption.
Proposed solution
Apply message passing between state owners, illustrated by Pass data between two threads. The proposed Tokio adaptation sends a typed injection command through bounded mpsc and receives the coordinator's decision through oneshot. A control-response task delivers the decision through the shared relay while the socket reader continues.
Unlike the recipe's unbounded example channel, require entry/byte limits, cancellable waits, and defined overload behavior. Keep direct state mutation inside the coordinator. The acknowledgement protocol and terminal ordering are gateway requirements layered on the message-passing pattern, not features supplied by the Cookbook recipe.
Upgrade the recorder for a persistent duplex session
Extend the existing recorder rather than assuming --transport websocket is sufficient. Its current _send_websocket opens a connection per request, forces store: true, records received events, and stops at completion. The main recorder also overrides the storage setting for WebSocket. The per-request connection and early stop cannot capture active injection or late acknowledgements. Positive multi-agent scenarios use store: true; preserve explicit store: false in negative scenarios so the recorder does not hide the gateway's rejection by rewriting it.
Implement session-scoped recording with an ordered client→server/server→client frame transcript, handshake metadata, close/error frames, multiple creates, and each injection. Preserve response/call correlation and send/receive ordering; an SSE projection may remain a derived convenience but cannot be the authoritative record of a duplex exchange.
Drive the session using the guide's get_proposal example and argument-aware deterministic callbacks. Save the response ID from response.created; send real response.inject commands for calls from any agent; keep reading until response termination and all submitted injections have outcomes. Record immediate outputs, deliberately delayed outputs, multiple outputs, completion-race fallback, and persistent-session continuation. Use store: true for supported runs, and preserve the supplied value when recording unsupported-storage rejection tests.
Extend the shared recording script from MA-01 with OpenAI and gateway WebSocket scenarios. Record the actual beta connection header, SDK/model versions, fixture names, and frame direction. Sanitize credentials without removing protocol fields.
Wire injection into core without creating another engine
Parse typed Create / Inject commands. Core admission requires effective store: true for multi-agent create requests and rejects store: false before execution, including stored-tree continuations. Do not silently change the requested policy. Injection has no separate storage policy and targets an already admitted stored run. Keep create requests FIFO per lane; route injection directly by connection-owned response_id to MA-01's run control. stream_id remains response-routing metadata, not agent identity. Preserve authentication, request admission, and lane isolation.
Core validates response ownership, pending call, kind, and prior resolution and serializes acceptance against finalization. The transport does not mutate histories. The pending call must exist before its public completion reaches the client. Acceptance means the output has been applied to run state, not merely queued by the socket reader; resume its owning agent when that agent's required outputs are available while other agents continue.
{
"type": "response.inject",
"response_id": "resp_123",
"input": [
{"type": "function_call_output", "call_id": "call_123", "output": "result"}
]
}
Return response.inject.created or response.inject.failed through the common relay and response sequence counter. Implement the documented response_not_found and response_already_completed cases; the latter returns submitted input for a new create request continuing the completed response. Malformed injection produces the documented generic status-400 error and connection close. Capture exact error shapes and other rejection cases rather than inventing OpenAI error codes.
Retain bounded completed-response routing information for late injections. Separate public response completion from closing the relay/session: outstanding acknowledgements can arrive after the terminal lifecycle event. Define expiry behavior and verify the reference where observable.
Keep control and outbound event queues independently bounded by entries and bytes. Dispatch controls without blocking the socket reader behind client delivery or holding agent-state locks across awaits. Every admitted command gets a result or explicit connection failure. On shutdown/disconnect, cancel and join core and transport tasks, release leases, and prevent late checkpoint publication.
Alternatives considered
No response
Additional context
Compaction while tools and controls are in flight
Reuse MA-01's per-agent compactor and checkpoint rules; no WebSocket-specific compactor or fallback standalone compact call is added. Record/test these interactions in addition to its C01–C12 matrix:
- Inject a function output immediately before, during, and after the owning agent's compaction. The output must enter the correct canonical window once and keep its call linkage.
- Compact a sibling while another agent waits for or accepts client input; sibling activity must not become a tree-wide pause.
- Deliver mail, child completion, or follow-up work while a summary is running; preserve updates beyond the summary snapshot.
- Complete the response while an injection/compaction commit is racing. Preserve acceptance/commit ordering and the reference fallback; do not acknowledge input that is subsequently lost.
- Disconnect, interrupt, or hit a deadline while compacting or waiting on control delivery. Release permits and preserve only valid published state.
- Continue a compacted tree through a stored response across connections/transports using
previous_response_id. Preserve each agent's effective window and current-response usage. A continuation that requests store: false must fail without altering that stored tree.
Capture externally observable behavior with real OpenAI and gateway requests where reproducible. Use deterministic gateway barriers/fault injection for exact internal races; do not label those tests as recordings of OpenAI internals. Avoid inferring a compaction trigger purely from response latency or a model claiming that it compacted.
Problem statement / motivation
he gateway currently accepts
response.createand serializes requests inside WebSocket lanes. Multi-agent requiresresponse.injectto reach a running response. Enqueuing it behind the response waiting for that input deadlocks. Client-side orchestration, an agent-per-lane design, or buffering all outputs until a new create request does not implement OpenAI's live-injection contract.The guide's WebSocket examples are client drivers: they execute application functions and inject their outputs. Adapt them to generate actual request/response recordings; the gateway supplies agent scheduling and resumption.
Proposed solution
Apply message passing between state owners, illustrated by Pass data between two threads. The proposed Tokio adaptation sends a typed injection command through bounded
mpscand receives the coordinator's decision throughoneshot. A control-response task delivers the decision through the shared relay while the socket reader continues.Unlike the recipe's unbounded example channel, require entry/byte limits, cancellable waits, and defined overload behavior. Keep direct state mutation inside the coordinator. The acknowledgement protocol and terminal ordering are gateway requirements layered on the message-passing pattern, not features supplied by the Cookbook recipe.
Upgrade the recorder for a persistent duplex session
Extend the existing recorder rather than assuming
--transport websocketis sufficient. Its current_send_websocketopens a connection per request, forcesstore: true, records received events, and stops at completion. The main recorder also overrides the storage setting for WebSocket. The per-request connection and early stop cannot capture active injection or late acknowledgements. Positive multi-agent scenarios usestore: true; preserve explicitstore: falsein negative scenarios so the recorder does not hide the gateway's rejection by rewriting it.Implement session-scoped recording with an ordered client→server/server→client frame transcript, handshake metadata, close/error frames, multiple creates, and each injection. Preserve response/call correlation and send/receive ordering; an SSE projection may remain a derived convenience but cannot be the authoritative record of a duplex exchange.
Drive the session using the guide's
get_proposalexample and argument-aware deterministic callbacks. Save the response ID fromresponse.created; send realresponse.injectcommands for calls from any agent; keep reading until response termination and all submitted injections have outcomes. Record immediate outputs, deliberately delayed outputs, multiple outputs, completion-race fallback, and persistent-session continuation. Usestore: truefor supported runs, and preserve the supplied value when recording unsupported-storage rejection tests.Extend the shared recording script from MA-01 with OpenAI and gateway WebSocket scenarios. Record the actual beta connection header, SDK/model versions, fixture names, and frame direction. Sanitize credentials without removing protocol fields.
Wire injection into core without creating another engine
Parse typed
Create/Injectcommands. Core admission requires effectivestore: truefor multi-agent create requests and rejectsstore: falsebefore execution, including stored-tree continuations. Do not silently change the requested policy. Injection has no separate storage policy and targets an already admitted stored run. Keep create requests FIFO per lane; route injection directly by connection-ownedresponse_idto MA-01's run control.stream_idremains response-routing metadata, not agent identity. Preserve authentication, request admission, and lane isolation.Core validates response ownership, pending call, kind, and prior resolution and serializes acceptance against finalization. The transport does not mutate histories. The pending call must exist before its public completion reaches the client. Acceptance means the output has been applied to run state, not merely queued by the socket reader; resume its owning agent when that agent's required outputs are available while other agents continue.
{ "type": "response.inject", "response_id": "resp_123", "input": [ {"type": "function_call_output", "call_id": "call_123", "output": "result"} ] }Return
response.inject.createdorresponse.inject.failedthrough the common relay and response sequence counter. Implement the documentedresponse_not_foundandresponse_already_completedcases; the latter returns submitted input for a new create request continuing the completed response. Malformed injection produces the documented generic status-400 error and connection close. Capture exact error shapes and other rejection cases rather than inventing OpenAI error codes.Retain bounded completed-response routing information for late injections. Separate public response completion from closing the relay/session: outstanding acknowledgements can arrive after the terminal lifecycle event. Define expiry behavior and verify the reference where observable.
Keep control and outbound event queues independently bounded by entries and bytes. Dispatch controls without blocking the socket reader behind client delivery or holding agent-state locks across awaits. Every admitted command gets a result or explicit connection failure. On shutdown/disconnect, cancel and join core and transport tasks, release leases, and prevent late checkpoint publication.
Alternatives considered
No response
Additional context
Compaction while tools and controls are in flight
Reuse MA-01's per-agent compactor and checkpoint rules; no WebSocket-specific compactor or fallback standalone compact call is added. Record/test these interactions in addition to its C01–C12 matrix:
previous_response_id. Preserve each agent's effective window and current-response usage. A continuation that requestsstore: falsemust fail without altering that stored tree.Capture externally observable behavior with real OpenAI and gateway requests where reproducible. Use deterministic gateway barriers/fault injection for exact internal races; do not label those tests as recordings of OpenAI internals. Avoid inferring a compaction trigger purely from response latency or a model claiming that it compacted.