# 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.