Skip to main content
assistant-ui is a headless React UI framework for AI chat. It provides a full runtime layer—thread management, message branching, attachment handling—that connects to useStream via the useExternalStoreRuntime adapter.
Clone and run the full assistant-ui example to see a Claude-style chat interface wired to a LangChain agent with useExternalStoreRuntime.

How it works

  1. Stream with useStream — connect to your agent and get reactive messages, loading state, and submit/cancel callbacks
  2. Adapt with useExternalStoreRuntime — bridge stream.messages into assistant-ui’s runtime format by converting BaseMessage[] to ThreadMessageLike[]
  3. Provide the runtime — wrap your UI in AssistantRuntimeProvider and render any assistant-ui thread component

Installation

Wiring useStream

The useExternalStoreRuntime adapter bridges stream.messages into the assistant-ui runtime. Pass it to AssistantRuntimeProvider and render any thread component:

Converting messages

toThreadMessages maps LangChain BaseMessage[] to the ThreadMessageLike[] format assistant-ui expects. Handle each message type — human, AI, and tool — and convert content blocks, tool calls, and reasoning tokens:

Customising the thread UI

<Thread /> ships a complete default thread UI including message list, composer, and scroll management. Customise individual parts by overriding component slots:

Best practices

  • Memoise message conversion: wrap toThreadMessages(stream.messages) in useMemo to avoid re-running the conversion on every render
  • Handle attachments: use CompositeAttachmentAdapter with SimpleImageAttachmentAdapter for image uploads; extend with custom adapters for files
  • Use branching: assistant-ui has built-in message branching support via MessageBranch; pair edits with useMessageMetadata and forkFrom when you need LangGraph checkpoint forks
  • Thread persistence: persist threadId with onThreadId and pass it back into useStream on page load so assistant-ui reconnects to the same thread