Transport-level routing for MCP/ACP protocols

We appreciate your patience. The service is temporarily operating in an external runtime environment.

stdio Bus Specificationv0.1.0

Normative specification for Agent Transport OS (stdio Bus), a minimal, deterministic stdio-based kernel in C providing transport-level routing for ACP/MCP-style agent protocols.

1. Introduction

1.1 Purpose

This document defines the normative specification for Agent Transport OS (stdio Bus), a deterministic stdio-based kernel in C providing transport-level routing for ACP/MCP-style agent protocols.

1.2 Scope

This specification covers:

  • Entity model and terminology
  • Client-to-Daemon contract
  • Worker-to-Daemon contract
  • Routing rules
  • Failure and recovery model
  • Resource limits and configuration

This specification does NOT cover:

  • Protocol semantics (ACP, MCP, JSON-RPC validation)
  • Worker implementation details
  • Platform-specific implementation internals

1.3 Conformance

The key words "SHALL", "SHOULD", "MAY", "MUST", "MUST NOT", "REQUIRED", "RECOMMENDED", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

1.4 References

  • RFC 2119: Key words for use in RFCs to Indicate Requirement Levels
  • JSON-RPC 2.0 Specification
  • NDJSON (Newline Delimited JSON) format

2. Terminology and Definitions

2.1 Entity Model

EntityDefinition
stdio_Bus_DaemonThe main cos process that manages workers and routes messages between clients and workers.
ClientAn external connection (via stdio, Unix socket, or TCP) that sends messages to stdio_Bus_Daemon.
WorkerA child process spawned by stdio_Bus_Daemon that handles protocol logic. Workers communicate via stdin/stdout pipes.
SessionA logical grouping of messages identified by sessionId with worker affinity.
RequestA JSON-RPC message with an id field expecting a response.
NotificationA JSON-RPC message without an id field (no response expected).
ResponseA JSON-RPC message containing result or error field in reply to a Request.

2.2 Message Format

TermDefinition
NDJSONNewline-delimited JSON format. Each message is a single JSON object followed by a newline character (\n).
Routing FieldsThe id, sessionId, and method fields extracted from JSON messages for routing purposes.

2.3 Connection Types

TypeDefinition
Client ConnectionA connection from an external client to stdio_Bus_Daemon.
Worker ConnectionThe stdin/stdout pipe pair between stdio_Bus_Daemon and a Worker process.

3. Entity Model

3.1 stdio_Bus_Daemon

The stdio_Bus_Daemon is the central process that:

  1. SHALL read configuration from a JSON file at startup
  2. SHALL spawn and monitor Worker processes according to pool definitions
  3. SHALL accept Client connections via one of three operating modes
  4. SHALL route messages between Clients and Workers based on routing rules
  5. SHALL operate in a single thread using non-blocking I/O
  6. SHALL handle graceful shutdown on SIGTERM or SIGINT

3.2 Client

A Client represents an external connection to stdio_Bus_Daemon:

  1. A Client SHALL connect via one of: stdio, Unix domain socket, or TCP socket
  2. A Client SHALL send NDJSON-formatted messages
  3. A Client MAY have multiple Sessions associated with it
  4. A Client connection SHALL be uniquely identified by its file descriptor

3.3 Worker

A Worker is a child process managed by stdio_Bus_Daemon:

  1. A Worker SHALL be spawned via fork/exec with stdin/stdout pipes
  2. A Worker SHALL read NDJSON messages from stdin
  3. A Worker SHALL write NDJSON responses to stdout
  4. A Worker SHOULD write diagnostic output to stderr (not stdout)
  5. A Worker SHALL handle SIGTERM for graceful shutdown
  6. A Worker SHALL be uniquely identified by a Worker ID (integer)

3.4 Session

A Session provides worker affinity for related messages:

  1. A Session SHALL be identified by a sessionId string
  2. A Session SHALL be bound to exactly one Worker
  3. A Session SHALL be owned by exactly one Client
  4. A Session SHALL be invalidated when its Worker exits
  5. A Session SHALL be invalidated when its owning Client disconnects

3.5 Request

A Request is a message expecting a response:

  1. A Request SHALL contain an id field
  2. A Request SHALL contain a method field
  3. A Request MAY contain a sessionId field
  4. A Request MAY contain a params field

4. Client-to-Daemon Contract

4.1 Connection Semantics

4.1.1 Operating Modes

stdio_Bus_Daemon SHALL support three operating modes:
ModeFlagDescription
stdio--stdioSingle Client via stdin/stdout (default)
Unix socket--unix <path>Multiple Clients via Unix domain socket
TCP--tcp <host:port>Multiple Clients via TCP socket

4.1.2 Connection Lifecycle

  1. In stdio mode, there SHALL be exactly one Client connection
  2. In socket modes, stdio_Bus_Daemon SHALL accept multiple concurrent Client connections
  3. A Client connection SHALL remain open until: the Client closes the connection, stdio_Bus_Daemon closes the connection due to error or resource limits, or stdio_Bus_Daemon initiates graceful shutdown

4.2 Message Format Requirements

4.2.1 Input Format

  1. Clients SHALL send messages in NDJSON format (one JSON object per line)
  2. Each message SHALL be a valid JSON object
  3. Each message SHALL be terminated by a newline character (\n)
  4. Messages SHOULD conform to JSON-RPC 2.0 structure

4.2.2 Routing Fields

stdio_Bus_Daemon SHALL extract the following fields for routing:
FieldTypePurpose
idstring or numberRequest-response correlation
sessionIdstringSession-based worker affinity
methodstringRequest identification

Note: stdio_Bus_Daemon performs minimal JSON parsing. It SHALL NOT validate complete JSON-RPC structure beyond extracting routing fields.

4.2.3 Output Format

  1. stdio_Bus_Daemon SHALL forward Worker responses to Clients in NDJSON format
  2. Each response SHALL be terminated by a newline character (\n)
  3. stdio_Bus_Daemon SHALL NOT modify message content (pass-through)

4.3 Malformed Input Handling

  1. If a Client sends data that cannot be parsed as JSON, stdio_Bus_Daemon SHALL close the Client connection
  2. If routing fields cannot be extracted, stdio_Bus_Daemon SHALL log a warning and close the Client connection
  3. stdio_Bus_Daemon SHALL NOT validate JSON-RPC semantics (e.g., required fields, method existence)

5. Worker-to-Daemon Contract

5.1 I/O Expectations

5.1.1 Input (Worker stdin)

  1. stdio_Bus_Daemon SHALL write NDJSON messages to Worker stdin
  2. Each message SHALL be terminated by a newline character (\n)
  3. Messages SHALL be forwarded unchanged from Client input

5.1.2 Output (Worker stdout)

  1. Workers SHALL write NDJSON responses to stdout
  2. Each response SHALL be terminated by a newline character (\n)
  3. Workers SHALL NOT write non-JSON content to stdout

5.1.3 Diagnostic Output (Worker stderr)

  1. Workers SHOULD write logs and diagnostics to stderr
  2. stdio_Bus_Daemon SHALL NOT process Worker stderr content
  3. Worker stderr output is implementation-defined (TBD: whether it is forwarded or discarded)

5.2 Response Requirements

5.2.1 Request-Response Correlation

  1. For each Request received, a Worker SHOULD send exactly one Response
  2. The Response SHALL contain the same id as the Request
  3. The Response SHALL contain either a result field or an error field

5.2.2 Session Preservation

  1. If a Request contains a sessionId, the Response SHOULD include the same sessionId
  2. Notifications sent by Workers SHOULD include sessionId for routing

5.3 Malformed JSON Handling

If a Worker sends data that cannot be parsed as JSON, stdio_Bus_Daemon SHALL:
  • Log an error with Worker context
  • Invalidate all Sessions assigned to that Worker
  • Terminate the Worker (send SIGTERM)
  • Attempt to restart the Worker per restart policy

6. Routing Rules

Loading diagram...

Client-to-Worker message routing decision flow
Routing rules diagram showing session-based message routing flow

6.1 Session-Based Routing (Client → Worker)

6.1.1 New Session Assignment

When a message contains a sessionId not in the Session table:
  • stdio_Bus_Daemon SHALL assign a Worker using round-robin selection
  • stdio_Bus_Daemon SHALL create a Session entry mapping sessionId to the assigned Worker
  • stdio_Bus_Daemon SHALL record the Client as the Session owner

6.1.2 Existing Session Routing

When a message contains a sessionId in the Session table:
  • stdio_Bus_Daemon SHALL route the message to the assigned Worker
  • stdio_Bus_Daemon SHALL NOT reassign the Session to a different Worker

6.1.3 No Session Routing

When a message does not contain a sessionId:
  • stdio_Bus_Daemon SHALL route the message using round-robin Worker selection
  • stdio_Bus_Daemon SHALL NOT create a Session entry

6.2 Request-Based Routing (Client → Worker)

When a message contains an id field (Request):
  • stdio_Bus_Daemon SHALL record the id in the pending Request table
  • stdio_Bus_Daemon SHALL associate the id with the originating Client
  • stdio_Bus_Daemon SHALL associate the id with the target Worker

6.3 Response Routing (Worker → Client)

6.3.1 Response Messages

When a Worker message contains result or error field (Response):
  • stdio_Bus_Daemon SHALL look up the id in the pending Request table
  • If found, stdio_Bus_Daemon SHALL route the Response to the originating Client
  • stdio_Bus_Daemon SHALL remove the entry from the pending Request table
  • If not found, stdio_Bus_Daemon SHALL log a warning and discard the Response

6.3.2 Notification Messages

When a Worker message contains sessionId but no result/error (Notification):
  • stdio_Bus_Daemon SHALL look up the sessionId in the Session table
  • If found, stdio_Bus_Daemon SHALL route the Notification to the Session owner
  • If not found, stdio_Bus_Daemon SHALL log a warning and discard the Notification

6.3.3 Unroutable Messages

When a Worker message contains neither id with result/error nor sessionId:
  • stdio_Bus_Daemon SHALL log a warning
  • stdio_Bus_Daemon SHALL discard the message

7. Failure and Recovery Model

7.1 Worker Exit Handling

7.1.1 Detection

  1. stdio_Bus_Daemon SHALL detect Worker exit via SIGCHLD signal
  2. stdio_Bus_Daemon SHALL reap exited Workers using waitpid with WNOHANG

7.1.2 Cleanup

When a Worker exits, stdio_Bus_Daemon SHALL:
  • Transition Worker state to STOPPED
  • Close communication file descriptors
  • Invalidate all Sessions assigned to that Worker
  • Discard all pending Requests to that Worker (log warnings)

7.1.3 Restart Policy

  1. stdio_Bus_Daemon SHALL attempt to restart Workers that exit unexpectedly
  2. stdio_Bus_Daemon SHALL use exponential backoff for restart delays
  3. stdio_Bus_Daemon SHALL stop restarting if max_restarts is exceeded within restart_window_sec

7.2 Client Disconnect Handling

When a Client disconnects, stdio_Bus_Daemon SHALL:
  • Invalidate all Sessions owned by that Client
  • Discard all pending Requests from that Client
  • Close the Client connection file descriptor

7.3 Queue Overflow Behavior

7.3.1 Output Queue Overflow

When a connection's output queue exceeds max_output_queue:
  • stdio_Bus_Daemon SHALL apply backpressure (pause reading from corresponding input)
  • stdio_Bus_Daemon SHALL record the timestamp when the queue became full
When the output queue drains below 50% of max_output_queue:
  • stdio_Bus_Daemon SHALL release backpressure (resume reading)
When the output queue remains full beyond backpressure_timeout_sec:
  • stdio_Bus_Daemon SHALL close the connection

7.3.2 Input Buffer Overflow

When a connection's input buffer exceeds max_input_buffer:
  • stdio_Bus_Daemon SHALL close the connection
  • stdio_Bus_Daemon SHALL log an error with connection context

8. Resource Limits

8.1 Default Values

LimitDefault ValueDescription
max_input_buffer1,048,576 (1 MB)Maximum bytes buffered per input connection
max_output_queue4,194,304 (4 MB)Maximum bytes queued per output connection
max_restarts5Maximum Worker restarts within time window
restart_window_sec60Time window for counting restarts (seconds)
drain_timeout_sec30Graceful shutdown timeout (seconds)
backpressure_timeout_sec60Close connection if queue full this long (seconds)

8.2 Hard-Coded Limits

LimitValueDescription
MAX_CONNECTIONS1024Maximum number of file descriptors
STDIO_BUS_MAX_SESSIONS1024Maximum number of active Sessions
STDIO_BUS_MAX_PENDING_REQUESTS4096Maximum number of pending Requests
STDIO_BUS_MAX_SESSION_ID_LEN256Maximum length of sessionId string
STDIO_BUS_MAX_REQUEST_ID_LEN128Maximum length of request id string

8.3 Limit Enforcement

  1. stdio_Bus_Daemon SHALL enforce max_input_buffer by closing connections that exceed it
  2. stdio_Bus_Daemon SHALL enforce max_output_queue by applying backpressure
  3. stdio_Bus_Daemon SHALL enforce max_restarts by stopping Worker restart attempts
  4. stdio_Bus_Daemon SHALL enforce backpressure_timeout_sec by closing stalled connections

9. Configuration Schema

9.1 Configuration File Format

stdio_Bus_Daemon SHALL read configuration from a JSON file specified via --config <path>.

9.2 Schema Definition

config.json

{
"pools": [
{
"id": "string", // REQUIRED: unique pool identifier
"command": "string", // REQUIRED: executable path
"args": ["string", ...], // OPTIONAL: command-line arguments
"instances": number // REQUIRED: number of worker instances (1)
}
],
"limits": {
"max_input_buffer": number, // OPTIONAL: per-FD input buffer limit (bytes)
"max_output_queue": number, // OPTIONAL: per-FD output queue limit (bytes)
"max_restarts": number, // OPTIONAL: max restarts within time window
"restart_window_sec": number, // OPTIONAL: time window for restart counting
"drain_timeout_sec": number, // OPTIONAL: graceful shutdown timeout
"backpressure_timeout_sec": number // OPTIONAL: backpressure timeout
}
}
Code block: config.json (JSON), 18 lines

9.3 Validation Rules

  1. The pools array SHALL contain at least one pool definition
  2. Each pool SHALL have a unique id
  3. Each pool SHALL have a valid command path
  4. Each pool SHALL have instances ≥ 1
  5. If limits is omitted, default values SHALL be used
  6. If individual limit fields are omitted, default values SHALL be used

10. Graceful Shutdown

10.1 Shutdown Trigger

stdio_Bus_Daemon SHALL initiate graceful shutdown on SIGTERM or SIGINT.

10.2 Shutdown Sequence

  1. Stop accepting new Client connections (close listening socket if applicable)
  2. Send SIGTERM to all running Workers
  3. Wait up to drain_timeout_sec for Workers to exit
  4. Send SIGKILL to any remaining Workers
  5. Clean up all resources (close file descriptors, free memory)
  6. Exit with code 0

Appendix A: Return Codes

CodeNameValueDescription
STDIO_BUS_OKSuccess0Operation succeeded
STDIO_BUS_ERRError-1Generic error
STDIO_BUS_EAGAINWould Block-2Non-blocking I/O would block
STDIO_BUS_EOFEnd of File-3Connection closed
STDIO_BUS_EFULLBuffer Full-4Buffer or queue limit exceeded
STDIO_BUS_ENOTFOUNDNot Found-5Resource not found
STDIO_BUS_EINVALInvalid-6Invalid argument

Appendix B: Worker States

StateDescription
STARTINGWorker is being spawned (fork/exec in progress)
RUNNINGWorker is running and accepting messages
STOPPINGWorker is being terminated (SIGTERM sent)
STOPPEDWorker has exited and been reaped

Appendix C: Log Levels

LevelDescription
DEBUGDebug-level messages (verbose)
INFOInformational messages
WARNWarning messages
ERRORError messages

All log messages SHALL be written to stderr, never stdout.

stdioBus
© 2026 stdio Bus. All rights reserved.