A complete chat application built with React, Vite, and the Polpo React SDK. Features streaming responses, session history, agent selection, tool call display, and dark/light theme.
Quick start
# Install dependencies
npm install
# Configure
cp .env.example .env.local
# Edit .env.local with your API key
Environment variables
| Variable | Description | Default |
|---|
VITE_POLPO_URL | Polpo API URL (leave empty to use proxy) | — |
VITE_POLPO_API_KEY | Your project API key | — |
VITE_POLPO_AGENT | Default agent name (optional) | — |
Run locally
# Set your API key in .env.local and run
npm run dev
What’s included
Polpo React SDK integration
The app uses PolpoProvider for context and hooks for data:
import { PolpoProvider } from "@polpo-ai/react";
<PolpoProvider baseUrl={BASE_URL} apiKey={API_KEY} autoConnect={false}>
<App />
</PolpoProvider>
Agent selection
On first load, the app fetches available agents using useAgents() and displays a selector:
const { agents } = useAgents();
// Renders a list of agents to choose from
{agents.map((a) => (
<button onClick={() => setSelectedAgent(a.name)}>
{a.name}
</button>
))}
Streaming chat completions
The app uses the useChat hook from the React SDK, which handles streaming, session management, and abort automatically:
import { useChat } from "@polpo-ai/react";
const { messages, sendMessage, isStreaming, abort, sessionId } = useChat({
agent: selectedAgent,
});
// Send a message — streaming and session tracking happen automatically
sendMessage("Explain the auth module");
useChat manages the session ID internally. The first message creates a new session, and subsequent messages continue the same conversation automatically. You can call newSession() to start fresh.
For lower-level control, you can also use chatCompletionsStream() directly from the client SDK:
const { client } = usePolpo();
const stream = client.chatCompletionsStream({
messages: history,
stream: true,
agent: selectedAgent,
sessionId: sessionId, // required to continue a conversation
});
for await (const chunk of stream) {
const delta = chunk.choices?.[0]?.delta?.content;
// Append delta to the current message
}
When using chatCompletionsStream directly, you must capture and pass the session ID yourself. Without sessionId, every request creates a new session.
Session history
Sessions are loaded from the server using useSessions():
const { sessions, getMessages, deleteSession } = useSessions();
// Load a previous session
const msgs = await getMessages(sessionId);
// Delete a session
await deleteSession(sessionId);
The sidebar shows all past sessions with agent name and date.
When the agent executes tools (bash, read, write, etc.), tool call events appear as collapsible blocks showing the tool name, arguments, and result:
const tc = choice.tool_call;
if (tc) {
// Add to message's toolCalls array
}
Abort / Stop
Streaming can be stopped at any time using the Stop button, which calls stream.abort().
Customization
Change the proxy target
Edit vite.config.ts to point to a different server:
const API_TARGET = process.env.POLPO_PROXY_TARGET ?? "http://api.polpo.localhost";
Add more features
The example is intentionally minimal. You can extend it with:
- File references — using
file content parts with workspace paths
- Approval gates — using
useApprovals() hook
- Task monitoring — using
useTasks() and useMissions() hooks
- Vault credentials — using
useVaultEntries() hook
All hooks are available from @polpo-ai/react. See the React SDK docs for the full API.