React Client (@kortyx/react)
Updated 5 hours ago • May 22, 2026
@kortyx/react is the recommended client entry for React apps consuming streamed chat responses.
Start here when you want:
useChat(...)for batteries-included streamed chat stateuseStructuredStreams()for custom React UIs without the full chat abstraction- route/server-action transport helpers
- default browser storage for chat history
Use kortyx/browser only when you want raw stream readers or the low-level structured reducer outside React.
Recommended path: useChat(...)
For most React apps, useChat(...) should be the first stop.
useChat(...) owns:
- finalized
messages - live
streamContentPieces isStreamingerrorandclearError()abort()andcanAbort- interrupt resume handling
- structured stream accumulation
- default browser storage unless you override it
Messages and active streams
messages contains finalized chat history only. While the assistant is still streaming, render the active assistant response from streamContentPieces.
This separation is intentional:
- persisted history does not change on every token
- active text, structured data, interrupts, and errors can render before finalization
- finalized assistant messages can keep their debug chunks after the stream ends
When a stream finishes, useChat(...) builds the assistant message and appends it to messages.
Request context and message preparation
Pass context when the client should send non-message request data, such as a selected tenant id, visible thread id, or UI state needed by the server.
By default, useChat(...) sends finalized history plus the outgoing user message. Use prepareContextMessages when your app owns a different history strategy, such as server-side history, summaries, or key facts.
prepareContextMessages returns the context/history messages only. useChat(...) appends the outgoing user or resume message automatically.
Good to know: Client
contextis request metadata, not trusted authorization state. Authenticate the route, rate-limit it, and derive sensitive values such as user id or permissions on the server.
Inside nodes, read server-approved request context with useRuntimeContext(...).
See Runtime Context for the full client-to-route-to-node flow.
Runtime controls
useChat(...) exposes controls for common chat lifecycle cases:
abort()stops the active stream when the transport supportsAbortSignalcanAbortis true while a stream is activeerrorstores the latest transport or stream errorclearError()clears that error stateclearMessages()clears visible/persisted messages and keeps the current sessionresetSession()clears the current session idresetChat()clears messages, active stream state, errors, and session id
clearChat() remains available as a compatibility alias for resetting the chat.
Good to know:
clearMessages()is the right choice for a "clear visible history" button. UseresetChat()when you want a new local chat session.
Interrupt responses
For low-level control, call respondToHumanInput(...) with the resume token and request id.
For UI components rendering a HumanInputPiece, use respondToInterrupt(...) so the component can pass back the same interrupt piece it received.
respondToInterrupt(piece, { selected }) handles choice and multi-choice interrupts. respondToInterrupt(piece, { text }) handles text interrupts.
When the server sets interrupt routing metadata, HumanInputPiece preserves schemaId, schemaVersion, interruptId, and public meta.
Switch on piece.schemaId for custom controls such as job pickers, file uploaders, or address autocompletes.
Abort support
Route transports created with createRouteChatTransport(...) receive the AbortSignal from useChat(...) and pass it to fetch.
Custom transports should forward context.signal to their own request layer if they want abort() to stop the active stream.
useChat(...) options
Notes:
transportis requiredstoragedefaults to browser storagecreateIdis optional when you want custom message/piece idscontextdefaults to{}prepareContextMessagesdefaults to the finalized message history whenincludeHistoryis truetoHumanInputPiecelets advanced clients customize interrupt projection before pieces enterstreamContentPiecesand finalized assistant messages
Transport helpers
API route / SSE transport
Use this when your backend returns SSE chunks from a route handler. createBody is optional; without it the route body is { sessionId, workflowId, messages, context }.
Custom transport
If your app does not use an SSE route, provide your own transport.
Use this when you already have an app-specific function that returns chunks.
Storage
By default, useChat(...) uses browser storage.
If you want to provide storage explicitly:
You can also provide your own ChatStorage implementation for app APIs, databases, or hybrid sync strategies.
Custom React UI: useStructuredStreams()
If you want structured stream state without the full chat abstraction, use useStructuredStreams().
That gives you:
items: stable ordered structured piecesbyStreamId: record-style accessget(streamId): direct lookupclear(): reset between runs
When to drop to kortyx/browser
Use kortyx/browser when:
- you are not using React
- you want raw
readStream(...)/consumeStream(...) - you want the low-level
applyStructuredChunk(...)reducer directly
That path is lower-level by design. React apps should usually start with @kortyx/react and only drop down when they need custom wiring.