useChat
useChat comes from @ai-sdk/react (not the ai package). It POSTs to /api/chat, reassembles the UI Message stream into messages, and tracks status / error. You still write the layout in React. The hook does not own the input box—keep that in useState.
The default transport hits POST /api/chat. For a custom URL, headers, or body, pass DefaultChatTransport from ai.
Minimal page
The server must return a UI Message Stream (see createUIMessageStreamResponse in Quick start). If the protocols do not match, the UI spins forever or errors.
Message shape: parts
Each UIMessage has id, role, and parts. parts is an ordered array that may include:
Do not treat legacy message.content as the main path. Tool results and reasoning tokens live on parts.
status and controls
stop() aborts the in-flight fetch. regenerate() asks the model to rewrite the last assistant message. Show a generic error to users; do not leak server stacks into the browser.
History, throttle, callbacks
messages / setMessages behave like useState. Delete by id:
On React you can set throttle: 50 (ms) so every token does not force a render.
Optional callbacks: onFinish (assistant done), onError, onData (data parts). Throwing inside onData aborts and runs onError.
Request configuration
Hook-level (every request):
headers / body may be functions so you can refresh tokens. Per-request options override hook-level config. Never hard-code secrets in client code; read tokens from the signed-in session.
Sibling hooks (awareness)
Production chat = Core + UI. Do not default to experimental RSC; see RSC.