Skip to main content
The ACP TypeScript SDK uses the Web Streams API to provide bidirectional communication between clients and agents. Streams handle the serialization and deserialization of JSON-RPC messages.

Stream Interface

The core Stream type powers all ACP connections:
This interface provides:
  • readable: A ReadableStream for receiving messages from the other side
  • writable: A WritableStream for sending messages to the other side
The AnyMessage type includes all JSON-RPC 2.0 message types: requests, responses, and notifications.

Using ndJsonStream

The most common way to create a Stream is using the ndJsonStream function, which handles newline-delimited JSON encoding:

Example: stdio-based Connection

How ndJsonStream Works

The ndJsonStream function creates a Stream that:
  1. Encodes outgoing messages: Serializes AnyMessage objects to JSON and appends a newline
  2. Decodes incoming messages: Splits input by newlines and parses each line as JSON
  3. Handles errors: Logs parse errors without disrupting the stream
  4. Manages buffering: Accumulates partial lines until complete messages arrive

Implementation Details

The writable stream encodes messages:
The readable stream decodes messages:

Creating Custom Streams

You can create custom Stream implementations for different transport mechanisms:

WebSocket Stream

HTTP Stream (SSE + POST)

Stream Requirements

When creating custom streams, ensure they:
  • Preserve message order: Messages must arrive in the order they were sent
  • Handle backpressure: Respect the writable stream’s ready state
  • Close gracefully: Clean up resources when the stream ends
  • Report errors: Use controller.error() for stream errors

Best Practices

  1. Use ndJsonStream for stdio: It’s battle-tested and handles edge cases
  2. Test custom streams: Verify message ordering and error handling
  3. Handle encoding properly: Ensure UTF-8 encoding for text-based transports
  4. Monitor stream closure: Listen for the connection’s closed promise