# Client transport API The client transport subscribes to an Ably channel, decodes incoming messages through a codec, and builds a conversation tree. It provides views for paginated, branch-aware access to the conversation, and methods for cancellation and turn tracking. Import from the core entry point: #### Javascript ``` import { createClientTransport } from '@ably/ai-transport' ``` Or use the [Vercel entry point](https://ably.com/docs/ai-transport/api-reference/vercel.md) which pre-binds the codec. ## createClientTransport Factory function that creates a `ClientTransport` instance. ### Javascript ``` function createClientTransport(options: ClientTransportOptions): ClientTransport ``` ### ClientTransportOptions | Property | Required | Type | Description | | --- | --- | --- | --- | | channel | required | `Ably.RealtimeChannel` | The Ably channel for the session. | | codec | required | `Codec` | Codec for encoding and decoding messages. See [Codec API](https://ably.com/docs/ai-transport/api-reference/codec.md). | | clientId | optional | `string` | The client ID for this transport instance. Used for scoping cancel signals and identifying user messages. | | api | optional | `string` | URL of the API endpoint to send user messages to. Defaults to `"/api/chat"`. | | headers | optional | `Record \| (() => Record)` | Additional HTTP headers to include in API requests. Use the function form for dynamic values such as auth tokens. | | body | optional | `Record \| (() => Record)` | Additional fields to merge into the API request body. Use the function form for dynamic values. | | credentials | optional | `RequestCredentials` | Credentials mode for the fetch request (`'include'`, `'same-origin'`, `'omit'`). | | fetch | optional | `typeof globalThis.fetch` | Custom fetch implementation. Defaults to `globalThis.fetch`. | | messages | optional | `TMessage[]` | Initial messages to seed the conversation tree with. Forms a linear chain. | | logger | optional | `Logger` | Logger instance for debug output. | ## ClientTransport The `ClientTransport` object returned by the factory. ### tree The underlying conversation tree. The tree contains every message received on the channel, organized into branches. #### Javascript ``` const tree = transport.tree ``` ### view The default `View` for the transport. Created automatically when the transport is instantiated. #### Javascript ``` const view = transport.view ``` ### createView Create an additional `View` of the conversation tree. Each view maintains its own branch selection and pagination state. #### Javascript ``` function createView(): View ``` Use multiple views when you need different perspectives on the same conversation, for example a main chat panel and a sidebar showing an alternative branch. ### cancel Publish a cancel signal on the channel. The optional filter scopes which turns are cancelled. #### Javascript ``` function cancel(filter?: CancelFilter): Promise ``` | Filter property | Type | Effect | | --- | --- | --- | | own | `true` | Cancel all turns started by this client (default). | | turnId | `string` | Cancel one specific turn. | | clientId | `string` | Cancel all turns by a specific client. | | all | `true` | Cancel all active turns on the channel. | When called with no argument, `cancel()` defaults to `{ own: true }`. ### waitForTurn Wait for active turns matching the given filter to complete. Returns a promise that resolves when all matching turns have ended. Resolves immediately if no matching turns are active. Defaults to `{ own: true }`. #### Javascript ``` function waitForTurn(filter?: CancelFilter): Promise ``` ### on('error') Subscribe to transport-level errors. #### Javascript ``` transport.on('error', (error: ErrorInfo) => { console.error('Transport error:', error) }) ``` ### close Close the transport and release resources. Optionally cancel active turns before closing. #### Javascript ``` function close(options?: CloseOptions): Promise ``` ## View A `View` is a paginated, branch-aware projection of the conversation tree. It tracks which branch is selected at each fork point and supports lazy loading of older messages. ### getMessages Return the visible domain messages along the selected branch. #### Javascript ``` function getMessages(): TMessage[] ``` ### flattenNodes Return the visible nodes along the selected branch, filtered by the pagination window. Each node wraps the domain message with tree metadata. #### Javascript ``` function flattenNodes(): MessageNode[] ``` ### hasOlder Whether there are older messages that can be loaded or revealed. #### Javascript ``` function hasOlder(): boolean ``` ### send Send one or more user messages and start a new turn. Messages are optimistically inserted into the tree. The parent is auto-computed from the view's selected branch unless overridden in options. Returns an `ActiveTurn` handle for the server's response stream. #### Javascript ``` function send(messages: TMessage | TMessage[], options?: SendOptions): Promise> ``` ### regenerate Regenerate an assistant message. Creates a new turn that forks the target message with no new user messages. Automatically computes `forkOf`, `parent`, and truncated `history` from the view's branch. #### Javascript ``` function regenerate(messageId: string, options?: SendOptions): Promise> ``` ### edit Edit a user message and regenerate from that point. Creates a new turn that forks the target message with replacement content. Automatically computes `forkOf`, `parent`, and `history` from the view's branch. #### Javascript ``` function edit(messageId: string, newMessages: TMessage | TMessage[], options?: SendOptions): Promise> ``` ### update Update an existing message and start a continuation turn. The local tree is updated optimistically, then the events are sent to the server in the POST body. The server publishes them to the channel and streams a continuation response. #### Javascript ``` function update(msgId: string, events: TEvent[], options?: SendOptions): Promise> ``` ### loadOlder Load older messages from channel history. Loads from history if the tree does not have enough messages, then advances the pagination window. #### Javascript ``` function loadOlder(limit?: number): Promise ``` ### select Select a sibling at a fork point by index. Updates the view's branch selection. The index is clamped to `[0, siblings.length - 1]`. #### Javascript ``` function select(msgId: string, index: number): void ``` ### getSelectedIndex Get the index of the currently selected sibling at a fork point. #### Javascript ``` function getSelectedIndex(msgId: string): number ``` ### getSiblings Get all messages that are siblings at a given fork point, ordered chronologically by serial. #### Javascript ``` function getSiblings(msgId: string): TMessage[] ``` ### hasSiblings Whether a message has sibling alternatives at its fork point. #### Javascript ``` function hasSiblings(msgId: string): boolean ``` ### getNode Get a node by its message ID, or `undefined` if not found. #### Javascript ``` function getNode(msgId: string): MessageNode | undefined ``` ### getActiveTurnIds Get active turn IDs for turns with visible messages, grouped by client ID. #### Javascript ``` function getActiveTurnIds(): Map> ``` ### on Subscribe to view events. Each handler returns an unsubscribe function. #### Javascript ``` // Fired when the visible message list changes (new message, branch switch, window shift) const unsubscribe = view.on('update', () => { }) // Fired when a raw Ably message arrives for a visible node view.on('ably-message', (msg: Ably.InboundMessage) => { }) // Fired when a turn starts or ends for a turn with visible messages view.on('turn', (event: TurnLifecycleEvent) => { }) ``` ### close Tear down the view. Unsubscribes from tree events and clears internal state. #### Javascript ``` function close(): void ``` ## ActiveTurn A handle to an active client-side turn, returned by `send()`, `regenerate()`, `edit()`, and `update()`. | Property | Type | Description | | --- | --- | --- | | stream | `ReadableStream` | The decoded event stream for this turn. | | turnId | `string` | The unique identifier for this turn. | | cancel | `() => Promise` | Cancel this specific turn. Publishes a cancel message and closes the local stream. | ## SendOptions Per-send options for customizing the HTTP POST and branching metadata. | Property | Required | Type | Description | | --- | --- | --- | --- | | headers | optional | `Record` | Additional HTTP headers for this request. | | body | optional | `Record` | Additional fields to merge into the request body. | | forkOf | optional | `string` | The msg-id of the message this send replaces (creates a fork). | | parent | optional | `string \| null` | The msg-id of the preceding message in the conversation thread. `null` means the message is a root. If omitted, auto-computed from the last message in the view. | ## CloseOptions | Property | Type | Description | | --- | --- | --- | | cancel | `CancelFilter` | Cancel in-progress turns before closing. Publishes a cancel message to the channel. | ## MessageNode A node in the conversation tree, representing a single domain message. | Property | Type | Description | | --- | --- | --- | | kind | `'message'` | Discriminator identifying this as a message node. | | message | `TMessage` | The domain message. | | msgId | `string` | The `x-ably-msg-id` of this node. Primary key in the tree. | | parentId | `string \| undefined` | Parent node's msg-id, or `undefined` for root messages. | | forkOf | `string \| undefined` | The msg-id this node forks from, or `undefined` if first version. | | headers | `Record` | Full Ably headers for this message. | | serial | `string \| undefined` | Ably serial for ordering. Absent for optimistic messages. | ## TurnLifecycleEvent A structured event describing a turn starting or ending. ### Javascript ``` type TurnLifecycleEvent = | { type: 'x-ably-turn-start'; turnId: string; clientId: string } | { type: 'x-ably-turn-end'; turnId: string; clientId: string; reason: TurnEndReason } ``` ## TurnEndReason ### Javascript ``` type TurnEndReason = 'complete' | 'cancelled' | 'error' ``` ## CancelFilter Filter for cancel operations. At most one field should be set. | Property | Type | Description | | --- | --- | --- | | turnId | `string` | Cancel a specific turn by ID. | | own | `boolean` | Cancel all turns belonging to the sender's client ID. | | clientId | `string` | Cancel all turns belonging to a specific client ID. | | all | `boolean` | Cancel all turns on the channel. | ## Related Topics - [Overview](https://ably.com/docs/ai-transport/api-reference.md): API reference for Ably AI Transport. Client transport, server transport, React hooks, Vercel integration, codec, and error codes. - [Server transport](https://ably.com/docs/ai-transport/api-reference/server-transport.md): API reference for the AI Transport server transport. Turn lifecycle, cancel routing, and configuration. - [React hooks](https://ably.com/docs/ai-transport/api-reference/react-hooks.md): API reference for AI Transport React hooks. Generic hooks and Vercel-specific hooks for building chat UIs. - [Vercel integration](https://ably.com/docs/ai-transport/api-reference/vercel.md): API reference for the AI Transport Vercel AI SDK integration. UIMessageCodec, ChatTransport, and pre-bound factories. - [Codec](https://ably.com/docs/ai-transport/api-reference/codec.md): API reference for the AI Transport codec interface. Build custom codecs to integrate any AI framework. - [Error codes](https://ably.com/docs/ai-transport/api-reference/error-codes.md): Error codes in Ably AI Transport. Codes, descriptions, HTTP status, and recovery guidance. ## Documentation Index To discover additional Ably documentation: 1. Fetch [llms.txt](https://ably.com/llms.txt) for the canonical list of available pages. 2. Identify relevant URLs from that index. 3. Fetch target pages as needed. Avoid using assumed or outdated documentation paths.