This page documents the request handling architecture of the Codex app-server, centered around the MessageProcessor. It covers the full pipeline from incoming JSON-RPC bytes to domain handler invocation, including initialization handshakes, bidirectional communication via OutgoingMessageSender, and event translation.
Incoming requests pass through a multi-layered processing architecture. The MessageProcessor acts as the primary connection-scoped entry point, while domain-specific logic is delegated to specialized request processors.
Diagram: Request Routing and Component Association
Sources: codex-rs/app-server/src/message_processor.rs101-121 codex-rs/app-server/src/lib.rs85-121
MessageProcessor and InitializationMessageProcessor is the per-connection entry point. It manages the lifecycle of a single client session, enforcing a strict initialization handshake before allowing other operations.
Clients must send an initialize request immediately upon connecting. The server enforces the following state machine:
initialize results in a Not initialized error. The MessageProcessor checks the initialized() state of the ConnectionSessionState before processing most requests codex-rs/app-server/src/message_processor.rs155-157InitializeParams, which includes ClientInfo and InitializeCapabilities (e.g., experimental API opt-in, notification filters, and MCP form elicitation support) codex-rs/app-server-protocol/src/protocol/v1.rs27-60InitializedConnectionSessionState codex-rs/app-server/src/message_processor.rs132-139Key Initialization Fields:
| Field | Purpose |
|---|---|
experimentalApi | Opts into features marked as experimental codex-rs/app-server-protocol/src/protocol/v1.rs49 |
optOutNotificationMethods | Suppresses specific notification types for this connection codex-rs/app-server-protocol/src/protocol/v1.rs59 |
mcpServerOpenaiFormElicitation | Advertises support for extended MCP forms codex-rs/app-server-protocol/src/protocol/v1.rs53-55 |
Sources: codex-rs/app-server/src/message_processor.rs126-163 codex-rs/app-server-protocol/src/protocol/v1.rs27-74
The app-server uses a bidirectional communication model. While the client initiates requests, the server can send asynchronous notifications or requests (e.g., for tool approvals) back to the client.
OutgoingMessageSenderThe OutgoingMessageSender is responsible for routing messages from the server to one or more client connections. It manages the delivery of server-originated messages codex-rs/app-server/src/outgoing_message.rs21-22
route_outgoing_envelope which handles the actual transmission to the transport layer codex-rs/app-server/src/transport.rs68opted_out_notification_methods configured during initialization, skipping suppressed notifications for specific connections codex-rs/app-server/src/transport.rs98-121The system distinguishes between critical and non-critical notifications. Lossless events (e.g., TurnCompleted, AgentMessageDelta) block until the consumer drains capacity, while best-effort events (e.g., progress updates) may be dropped under saturation codex-rs/app-server-client/src/lib.rs130-153
Sources: codex-rs/app-server/src/transport.rs98-121 codex-rs/app-server/src/transport.rs174-189 codex-rs/app-server-client/src/lib.rs141-153
Codex supports both a remote app-server (via WebSocket/Unix sockets) and an in-process host for local embedders like the CLI and TUI.
Diagram: Transport and Routing Logic
Sources: codex-rs/app-server/src/in_process.rs121-154 codex-rs/app-server-client/src/remote.rs165-184
InProcessClientHandleThe in-process runtime host avoids process boundaries while preserving protocol semantics. It uses bounded in-memory channels instead of sockets codex-rs/app-server/src/in_process.rs1-6
initialize / initialized handshake internally upon startup codex-rs/app-server/src/in_process.rs11-12InProcessServerEvent, which includes a Lagged variant to signal when best-effort notifications have been dropped due to consumer slowness codex-rs/app-server/src/in_process.rs156-163The app-server implements several mechanisms to handle high load and slow clients:
mpsc channels with a default capacity codex-rs/app-server/src/transport.rs16OutboundControlEvent::DisconnectAll signal codex-rs/app-server/src/lib.rs177CONNECTION_RPC_DRAIN_TIMEOUT (30 seconds) codex-rs/app-server/src/message_processor.rs90 The ShutdownState struct manages the transition between requested and forced shutdown codex-rs/app-server/src/lib.rs181-185Sources: codex-rs/app-server/src/lib.rs174-185 codex-rs/app-server/src/message_processor.rs90 codex-rs/app-server/src/transport.rs154-172 codex-rs/app-server/src/in_process.rs102-103
Refresh this wiki
This wiki was recently refreshed. Please wait 5 days to refresh again.