Skip to main content
The @polpo-ai/react package provides type-safe React hooks with real-time SSE updates, built on top of @polpo-ai/client.
For non-React environments (Node.js scripts, Vue, Svelte, server-side), use @polpo-ai/client directly. The React SDK re-exports all client types and classes for convenience.

Installation

npm install @polpo-ai/react
This automatically installs @polpo-ai/client as a dependency. Peer dependencies: React 18 or 19.

PolpoProvider

Wrap your app to provide Polpo context:
import { PolpoProvider } from "@polpo-ai/react";

function App() {
  return (
    <PolpoProvider
      baseUrl="http://localhost:3000"
      projectId="my-project"
      apiKey="optional-key"
    >
      <MyApp />
    </PolpoProvider>
  );
}

Props

PropTypeRequiredDescription
baseUrlstringyesPolpo server URL
projectIdstringyesProject ID
apiKeystringnoAPI key for authentication
childrenReactNodeyesChild components
autoConnectbooleannoAuto-connect to SSE on mount (default: true)
eventFilterstring[]noGlob patterns to filter SSE events

usePolpo

Access the Polpo client and connection status.
const { client, connectionStatus } = usePolpo();

Returns

FieldTypeDescription
clientPolpoClientHTTP client with request deduplication
connectionStatus"connected" | "connecting" | "disconnected"SSE connection state

useTasks

List tasks with real-time updates.
const { tasks, isLoading, error, createTask, deleteTask, retryTask, refetch } = useTasks();

Returns

FieldTypeDescription
tasksTask[]All tasks (auto-updated via SSE)
isLoadingbooleanInitial load in progress
errorError | nullFetch error
createTask(opts) => Promise<Task>Create a new task
deleteTask(id) => Promise<void>Delete a task
retryTask(id) => Promise<void>Retry a failed task
refetch() => Promise<void>Force refetch

useTask

Single task details with actions.
const { task, isLoading, error, updateTask, deleteTask, killTask, reassessTask, retryTask } = useTask("task-1");

Parameters

ParamTypeDescription
taskIdstringTask ID to subscribe to

Returns

FieldTypeDescription
taskTask | undefinedTask object
isLoadingbooleanInitial load in progress
errorError | nullFetch error
updateTask(opts) => Promise<Task>Update description, assignment, expectations
deleteTask() => Promise<void>Delete the task
killTask() => Promise<void>Kill running agent
reassessTask() => Promise<void>Re-run assessment
retryTask() => Promise<void>Retry failed task

useMissions

List missions with management actions.
const { missions, isLoading, createMission, updateMission, executeMission, resumeMission, abortMission, deleteMission, refetch } = useMissions();

Returns

FieldTypeDescription
missionsMission[]All missions
isLoadingbooleanInitial load in progress
errorError | nullFetch error
createMission(opts) => Promise<Mission>Save new mission
updateMission(id, opts) => Promise<Mission>Update mission metadata
executeMission(id) => Promise<{ tasks: Task[] }>Execute a draft mission
resumeMission(id, opts?) => PromiseResume failed mission
abortMission(id) => Promise<{ aborted: number }>Abort active mission
deleteMission(id) => Promise<void>Delete mission
refetch() => Promise<void>Force refetch

useMission

Single mission with actions and completion report.
const { mission, report, isLoading, error, updateMission, executeMission, resumeMission, abortMission, deleteMission } = useMission("mission-1");

Parameters

ParamTypeDescription
missionIdstringMission ID to subscribe to

Returns

FieldTypeDescription
missionMission | undefinedMission object
reportMissionReport | undefinedCompletion report (populated from mission:completed SSE event)
isLoadingbooleanInitial load in progress
errorError | nullFetch error
updateMission(opts) => Promise<Mission>Update mission metadata
executeMission() => Promise<{ tasks: Task[] }>Execute the mission
resumeMission(opts?) => PromiseResume failed mission
abortMission() => Promise<{ aborted: number }>Abort active mission
deleteMission() => Promise<void>Delete mission

useAgents

Team and agent management.
const { agents, team, isLoading, addAgent, removeAgent, renameTeam, refetch } = useAgents();

Returns

FieldTypeDescription
agentsAgentConfig[]All agents
teamTeam | nullTeam info
isLoadingbooleanInitial load in progress
errorError | nullFetch error
addAgent(opts) => Promise<void>Register new agent
removeAgent(name) => Promise<void>Remove agent
renameTeam(name) => Promise<void>Rename the team
refetch() => Promise<void>Force refetch

useAgent

Single agent by name.
const { agent, isLoading, error, refetch } = useAgent("backend-dev");

Parameters

ParamTypeDescription
namestringAgent name

Returns

FieldTypeDescription
agentAgentConfig | nullAgent configuration
isLoadingbooleanInitial load in progress
errorError | nullFetch error
refetch() => Promise<void>Force refetch

useProcesses

Active agent processes.
const { processes, isLoading, error, refetch } = useProcesses();

Returns

FieldTypeDescription
processesAgentProcess[]Active processes with PID, activity, alive status
isLoadingbooleanInitial load in progress
errorError | nullFetch error
refetch() => Promise<void>Force refetch
AgentProcess fields:
  • agentName, pid, taskId, startedAt, alive
  • activity: { lastTool, lastFile, lastUpdate, toolCalls, filesCreated, filesEdited, summary }

useEvents

SSE event stream.
const { events } = useEvents(["task:*", "assessment:*"], 100);

Parameters

ParamTypeDefaultDescription
filterstring[]Glob patterns to filter events
maxEventsnumber200Max events to keep in buffer

Returns

FieldTypeDescription
eventsEvent[]Buffered events (newest first)

useStats

Aggregated statistics. Returns null when not yet connected.
const stats = useStats();
// stats: { pending, running, done, failed, queued } | null

useMemory

Project memory access.
const { memory, isLoading, saveMemory, refetch } = useMemory();

Returns

FieldTypeDescription
memory{ exists: boolean, content: string } | nullMemory state
isLoadingbooleanInitial load in progress
saveMemory(content: string) => Promise<void>Save memory
refetch() => Promise<void>Force refetch

useSkills

Discover available skills in the project.
const { skills, isLoading, error, refetch } = useSkills();

Returns

FieldTypeDescription
skillsSkillInfo[]Available skills discovered from .polpo/skills/ and other locations
isLoadingbooleanInitial load in progress
errorError | nullFetch error
refetch() => Promise<void>Force refetch

useNotifications

Notification records and sending.
const { notifications, stats, sendNotification, loading, refetch } = useNotifications({
  limit: 50,
  status: "sent",
  channel: "slack",
});

Parameters

ParamTypeDescription
opts.limitnumberMax notifications to fetch
opts.statusstringFilter by status
opts.channelstringFilter by channel

Returns

FieldTypeDescription
notificationsNotificationRecord[]Notification records
statsNotificationStats | nullAggregate stats (sent, failed, pending counts)
sendNotification(req) => Promise<SendNotificationResult>Send a notification
loadingbooleanInitial load in progress
refetch() => voidForce refetch

useApprovals

Approval gate management.
const { approvals, pending, approve, reject, loading, refetch } = useApprovals();

Parameters

ParamTypeDescription
statusApprovalStatusOptional: filter by approval status

Returns

FieldTypeDescription
approvalsApprovalRequest[]All approval requests
pendingApprovalRequest[]Only pending approvals
approve(id, opts?) => Promise<void>Approve a request (opts: { resolvedBy?, note? })
reject(id, feedback, resolvedBy?) => Promise<void>Reject a request
loadingbooleanInitial load in progress
refetch() => voidForce refetch

usePlaybooks

Playbook discovery and execution.
const { playbooks, loading, getPlaybook, runPlaybook, refetch } = usePlaybooks();

Returns

FieldTypeDescription
playbooksPlaybookInfo[]Available playbooks
loadingbooleanInitial load in progress
getPlaybook(name) => Promise<PlaybookDefinition>Fetch full playbook definition
runPlaybook(name, params?) => Promise<PlaybookRunResult>Execute a playbook
refetch() => voidForce refetch

useSessions

Chat session management.
const { sessions, activeSessionId, setActiveSessionId, getMessages, renameSession, deleteSession } = useSessions();

Returns

FieldTypeDescription
sessionsChatSession[]All chat sessions
isLoadingbooleanInitial load in progress
errorError | nullFetch error
activeSessionIdstring | nullCurrently selected session
setActiveSessionId(id: string | null) => voidSelect a session
getMessages(sessionId: string) => Promise<ChatMessage[]>Fetch messages for a session
renameSession(sessionId: string, title: string) => Promise<void>Rename a session
deleteSession(sessionId: string) => Promise<void>Delete a session
refetch() => Promise<void>Force refetch

useTaskActivity

Per-task activity history from run logs.
const { entries, isLoading, error, refetch } = useTaskActivity("task-1");

// With auto-polling
const { entries } = useTaskActivity("task-1", { pollIntervalMs: 5000 });

Parameters

ParamTypeDescription
taskIdstring | nullTask ID to fetch activity for. Pass null to skip.
options.pollIntervalMsnumberAuto-poll interval in ms (optional)

Returns

FieldTypeDescription
entriesRunActivityEntry[]Activity log entries (tool calls, file edits, summaries)
isLoadingbooleanInitial load in progress
errorError | nullFetch error
refetch() => Promise<void>Force refetch

useAuthStatus

Per-provider authentication status: config keys, environment variables, and OAuth profiles (metadata only — tokens are never exposed).
const { authStatus, isLoading, error, refetch } = useAuthStatus();

Returns

FieldTypeDescription
authStatusAuthStatusResponse | nullPer-provider auth health
isLoadingbooleanInitial load in progress
errorError | nullFetch error
refetch() => Promise<void>Force refetch
AuthStatusResponse.providers is a Record<string, ProviderAuthInfo> with:
FieldTypeDescription
hasEnvKeybooleanAPI key set via environment variable
envVarstring?Environment variable name
profilesAuthProfileMeta[]OAuth / API key profiles
oauthAvailablebooleanWhether OAuth login is supported
oauthProviderNamestring?Human-readable OAuth provider name
oauthFlowstring?OAuth flow description
Each AuthProfileMeta includes id, type ("oauth" | "api_key"), email, status ("active" | "cooldown" | "billing_disabled" | "expired"), expiry, and cooldown details.

useLogs

Event log sessions and entries.
const { sessions, isLoading, getLogEntries, refetch } = useLogs();

Returns

FieldTypeDescription
sessionsLogSession[]All log sessions
isLoadingbooleanInitial load in progress
errorError | nullFetch error
getLogEntries(sessionId: string) => Promise<LogEntry[]>Fetch entries for a log session
refetch() => Promise<void>Force refetch

Imports

// Full import (hooks + re-exported client types)
import { PolpoProvider, useTasks, useMissions } from "@polpo-ai/react";
import type { Task, Mission } from "@polpo-ai/react";

// Individual hook imports
import { useTasks } from "@polpo-ai/react/hooks/use-tasks";

// Use the client SDK directly for non-React code
import { PolpoClient } from "@polpo-ai/client";
All types and classes from @polpo-ai/client are re-exported from @polpo-ai/react for backward compatibility.

Architecture

The SDK uses useSyncExternalStore for push-based state management:
  1. @polpo-ai/client — Framework-agnostic HTTP client, SSE manager, reactive store
  2. PolpoProvider — Wires client + SSE + store into React context
  3. 24 hooks — Thin wrappers that subscribe to the store and expose mutation callbacks
  4. Memoized selectors — Multi-key cached selectors per hook
  5. Microtask batchingqueueMicrotask for batched re-renders
The React SDK depends on @polpo-ai/client (auto-installed) and has React as a peer dependency. Both packages are tree-shakeable with sideEffects: false.