---
title: Chat with useChat
description: Compose registry chat primitives with AI SDK streaming, stop, retry, visible errors, and attachments.
icon: messages-square
sidebar:
  badge: New
---

<ComponentPreview name="chat-use-chat-demo" bigScreen />

<a href="/examples/chat-use-chat-demo">Open the standalone preview</a>.

## Installation

```package-install
npx shadcn@latest add @redpanda/chat-use-chat-demo
```

The example installs `ai` and `@ai-sdk/react`. Installing [Message](/docs/message), [Bubble](/docs/bubble), [Message Scroller](/docs/message-scroller), or [Attachment](/docs/attachment) alone does not add either SDK package.

## Try the example

- Send a message to watch a simulated reply arrive progressively.
- Select **Stop response** to keep the partial reply. Select **Retry response** to regenerate the same turn without adding another user message.
- Send `error` to produce a simulated connection failure, then retry to recover. The failure stays visible until another request starts.
- Attach a text, PDF, PNG, or JPEG file, up to 5 MB per file. File parts appear in the transcript. The preview does not upload or analyze files.

The preview uses the real `useChat` hook with a local fixture transport. It makes no model calls, requires no credentials, and does not persist messages. It is not a production agent or backend implementation.

## Connect your application

Replace the fixture transport with the [AI SDK transport](https://ai-sdk.dev/docs/ai-sdk-ui/transport) that matches your backend. Keep its identity stable outside rendering, or create a chat-instance-specific transport once in state.

```tsx
'use client';

import { DefaultChatTransport } from 'ai';

import { ChatUseChatDemo } from '@/components/redpanda-ui/blocks/chat-use-chat';

const transport = new DefaultChatTransport({ api: '/api/chat' });

export function ApplicationChat() {
  return <ChatUseChatDemo transport={transport} />;
}
```

`/api/chat` is an endpoint you implement, not an endpoint supplied by this registry. It must return the [AI SDK UI-message stream protocol](https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol). Configure authentication on your application transport and server; never put model-provider secrets in this client example. Validate file types, sizes, and contents on the server as well as in the composer.

For an A2A or other agent protocol, supply your application's `ChatTransport<UIMessage>` adapter. Do not wrap an agent in a model provider solely to use these visual primitives.

## Ownership

```text
Application transport → useChat messages and status
                              ↓
                  MessageScroller → Message → Bubble / Attachment
```

| Owner | Responsibility |
| --- | --- |
| Registry components | Message layout, surfaces, attachment presentation, scrolling, accessible controls |
| AI SDK `useChat` | Message reconciliation, streaming status, stop, regeneration, request errors |
| Application | Input state, transport, authentication, protocol mapping, sessions, persistence, telemetry, recovery policy |

The integration lives in an installable example, not a registry-owned `useChat` hook. Remove the default `demoTransport` import and fallback when adapting it for production; the fixture is preview-only. Adapt the example in your application; the components remain SDK-agnostic.

## Accessibility and lifecycle

The composer has labeled controls. Empty and concurrent sends are blocked, with file-validation failures shown beside the file input. A separate polite status announces request state without reading every streamed token. The conversation is a labeled, focusable region; it does not auto-announce token changes. Send and Retry stay focusable while blocked. Stopping a response returns focus to the composer.

The example supports text and file parts only. It does not demonstrate tool approval, rich-content rendering, session switching, resumable streams, or production retry policy. Implement those using your application's domain model, and stop active work when leaving a conversation.
