Step 2 / 5

Ship a streaming chat UI

Build a complete chat interface with streaming — without a backend.

`useChat` wires state, streaming, abort, and retries. Drop it into any component. The preview below runs a mock adapter. Try it: send a message, watch it stream.

Try it live
Hi, ask me something.
Source
import { useChat, ChatContainer, Message, InputBar } from '@agentskit/react'import '@agentskit/react/theme'import './styles.css'// Mock adapter — streams fake replies. Swap for `anthropic({ apiKey })`, `openai({ apiKey })`,// or any adapter from @agentskit/adapters in your own app.const FAKE = [  'Welcome to AgentsKit. Streaming is on by default.',  'Swap the adapter in one line to change providers.',  'Tools and memory are optional — compose what you need.',]let turn = 0const mockAdapter = {  createSource: () => ({    async *stream() {      const reply = FAKE[turn++ % FAKE.length]      for (const ch of reply) {        await new Promise((r) => setTimeout(r, 18))        yield { type: 'text', content: ch }      }      yield { type: 'done' }    },    abort() {},  }),}export default function App() {  const chat = useChat({    adapter: mockAdapter,    initialMessages: [      { id: 'init', role: 'assistant', content: 'Hi, ask me something.', status: 'complete' },    ],  })  return (    <div style={{ display: 'flex', flexDirection: 'column', height: '100vh', fontFamily: 'system-ui' }}>      <ChatContainer className="ak-chat">        {chat.messages.map((msg) => (          <Message key={msg.id} message={msg} />        ))}      </ChatContainer>      <InputBar chat={chat} />    </div>  )}