# useView `useView` subscribes to a session's default view and returns the visible messages, branch navigation, write operations, and pagination state. It is the primary hook for rendering a conversation UI. By default the hook subscribes to the nearest [`ClientSessionProvider`](https://ably.com/docs/ai-transport/api/react/core/providers.md#client-session-provider)'s default view. Pass `session` to use a different session's default view, or `view` to subscribe to a specific view created with [`useCreateView`](https://ably.com/docs/ai-transport/api/react/core/use-create-view.md) or [`session.createView()`](https://ably.com/docs/ai-transport/api/javascript/core/client-session.md#create-view). #### Javascript ``` import { useView } from '@ably/ai-transport/react'; function Conversation() { const { messages, send } = useView({ limit: 30 }); return ( <> {messages.map(({ codecMessageId, message }) => ( ))} send({ kind: 'user-message', message: { role: 'user', parts: [{ type: 'text', text }] } }) } /> ); } ``` This hook must be used within a [`ClientSessionProvider`](https://ably.com/docs/ai-transport/api/react/core/providers.md#client-session-provider) unless `session` or `view` is supplied explicitly. ## Parameters | Parameter | Required | Description | Type | | --- | --- | --- | --- | | session | optional | A client session whose default view to subscribe to. Defaults to the nearest provider. | `ClientSession` | | view | optional | A specific view to subscribe to directly. Takes priority over `session`. | `View` | | limit | optional | Maximum number of older Runs to reveal per page. When provided, auto-loads the first page on mount. | Number | | skip | optional | When `true`, skip all subscriptions and return an empty handle immediately. | Boolean |
## Returns | Property | Description | Type | | --- | --- | --- | | messages | The visible messages along the selected branch, each paired with its `codecMessageId`. Read the domain object from each entry's `message` field. | `CodecMessage[]` | | hasOlder | Whether there are older Runs that can be revealed via `loadOlder`. | Boolean | | loading | Whether a page load is currently in progress. | Boolean | | loadError | Set when the most recent `loadOlder` call failed. Cleared automatically on the next successful load. | `Ably.ErrorInfo` or Undefined | | loadOlder | Reveal older Runs. No-op if already loading. | `() => Promise` | | runOf | Look up the `RunInfo` for the Run that owns the given `codecMessageId`. |
| | run | Direct lookup by Run id. |
| | runs | Snapshot of the visible Runs along the selected branch, in chronological order. Returns `[]` when the view isn't resolved. | `() => RunInfo[]` | | branchSelection | Resolve the `BranchSelection` bundle anchored at `codecMessageId`. Always returns a safe object. |
| | selectSibling | Select a sibling at the branch point anchored at `codecMessageId`. | `(codecMessageId, index) => void` | | send | Send one or more `TInput`s on the channel and fire a POST. Wrap a domain message via `codec.createUserMessage` (or build the `{ kind: 'user-message', message }` literal) to send a fresh user message. Takes optional
. | `(events, options?) => Promise` | | regenerate | Regenerate an assistant message using this view's branch for history. | `(messageId, options?) => Promise` | | edit | Edit a user message, forking from this view's branch. | `(messageId, inputs, options?) => Promise` |
| Property | Description | Type | | --- | --- | --- | | runId | The Run's unique identifier. | String | | clientId | Identity of the Ably client that started this Run. Empty string when the wire didn't carry an owner client id. | String | | status | Run lifecycle status. `'active'` while streaming, `'suspended'` while paused awaiting input, otherwise the `RunEndReason` the Run terminated with. | `'active' \| 'suspended' \| RunEndReason` | | invocationId | The agent-minted `invocationId` observed for this Run, adopted from `ai-run-start`. Empty string until run-start arrives, or if the wire didn't carry an invocation-id. | String |
| Property | Description | Type | | --- | --- | --- | | hasSiblings | True when the anchor has more than one sibling. | Boolean | | siblings | The selected sibling and any alternatives in tree-order. Always contains the currently rendered message for known ids. | `TMessage[]` | | index | Index of the selected sibling within `siblings`. `0` when there is no real branching. | Number | | selected | Convenience reference to `siblings[index]`. `undefined` only when `siblings` is empty. | `TMessage` or Undefined |
| Property | Description | Type | | --- | --- | --- | | forkOf | The codec-message-id of the message this send replaces (fork). | String | | parent | The codec-message-id of the predecessor in the conversation thread. Auto-computed when omitted. | String | | runId | Reuse an existing `runId` (for example to resume a suspended run). | String | | inputEventId | Override the `inputEventId` for this send. Defaults to `crypto.randomUUID()`. | String |
## Reveal older Runs `loadOlder(): Promise` Load older messages into the view by revealing more Runs. When `limit` is set on the hook, the first page auto-loads on mount. Call `loadOlder` again to reveal more. The call is gated so concurrent invocations collapse to one in-flight request. On failure, `loadError` is set. On the next successful load, `loadError` is cleared automatically. ## Look up a Run by message id `runOf(codecMessageId: string): RunInfo | undefined` Look up the [`RunInfo`](#returns) for the Run that owns the given `codecMessageId`. Returns `undefined` when the codec-message-id has not been observed. ## Look up a Run by id `run(runId: string): RunInfo | undefined` Direct lookup by Run id. Symmetric with [`runOf`](#run-of) for callers that already hold a `runId`. ## Resolve a branch selection `branchSelection(codecMessageId: string): BranchSelection` Resolve the `BranchSelection` bundle anchored at `codecMessageId`. Always returns a safe object: for branch anchors with N siblings, `siblings` carries every sibling Run's view of the anchor slot; for non-anchor messages, `siblings` is `[thisMessage]` and `hasSiblings` is `false`. ## Select a sibling `selectSibling(codecMessageId: string, index: number): void` Select a sibling at the branch point anchored at `codecMessageId`. `index` is clamped to `[0, siblings.length - 1]`. Silent no-op when the message is not a branch anchor. Emits `'update'` on the underlying view when the visible output changes. ## Send inputs `send(events: TInput | TInput[], options?: SendOptions): Promise` Send one or more `TInput`s on the channel and fire a POST. Each `TInput` carries its own routing metadata (`parent`, `target`, `codecMessageId`). To send a fresh user message, build a `UserMessage` input. Use the codec factory (`codec.createUserMessage(message)`) or build the literal directly: `{ kind: 'user-message', message }`. A send containing at least one `UserMessage` mints a fresh Run. A send containing only tool-resolution inputs (`tool-result`, `tool-result-error`, `tool-approval-response`) is a continuation; pair it with `options.runId` to extend a suspended Run. ## Regenerate an assistant message `regenerate(messageId: string, options?: SendOptions): Promise` Regenerate an assistant message. Creates a new Run that targets the message and threads under its parent user message. Both ids are computed automatically from this view's branch. ## Edit a user message `edit(messageId: string, inputs: TInput | TInput[], options?: SendOptions): Promise` Edit a user message. Creates a new Run that forks the target message with the replacement inputs. `forkOf`, `parent`, and history are computed automatically from this view's branch. ## Example A conversation component that loads older messages on mount, renders branch navigation when a sibling is available, and offers a regenerate button on each assistant turn. ### Javascript ``` import { useView } from '@ably/ai-transport/react'; function Conversation() { const { messages, hasOlder, loadOlder, branchSelection, selectSibling, send, regenerate, } = useView({ limit: 30 }); return ( <> {hasOlder && } {messages.map(({ codecMessageId, message }) => { const branch = branchSelection(codecMessageId); return (
{branch.hasSiblings && ( selectSibling(codecMessageId, i)} /> )} {message.role === 'assistant' && ( )}
); })} send({ kind: 'user-message', message: { role: 'user', parts: [{ type: 'text', text }] } }) } /> ); } ```
## Related Topics - [Providers](https://ably.com/docs/ai-transport/api/react/core/providers.md): API reference for the AI Transport React providers: ClientSessionProvider and the createSessionHooks factory. - [useClientSession](https://ably.com/docs/ai-transport/api/react/core/use-client-session.md): Read a ClientSession from the nearest ClientSessionProvider in the AI Transport React integration. - [useCreateView](https://ably.com/docs/ai-transport/api/react/core/use-create-view.md): Create an independent View over the AI Transport conversation tree from React, with its own branch selections and pagination. - [useTree](https://ably.com/docs/ai-transport/api/react/core/use-tree.md): Stable structural query callbacks for the AI Transport conversation tree from React. - [useAblyMessages](https://ably.com/docs/ai-transport/api/react/core/use-ably-messages.md): Subscribe to raw Ably InboundMessages on the AI Transport channel from React. ## 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.