Skip to main content

React Hooks

The @baleybots/react package provides React hooks for building chat interfaces and using Baleybots processors in React applications.

Installation

npm install @baleybots/react @baleybots/core

useChat

useChat is the primary hook for building client-side chat interfaces. It runs the processor in the browser (or React Native) and exposes segments as the canonical UI representation.

For server-hosted multi-agent crew chat, use the product UI's /api/chat endpoint and useCrewSessions — not useChat server mode (removed).

Basic usage

import { useChat, ChatTurns, ChatTurn } from '@baleybots/react';
import { openai } from '@baleybots/core';
import { z } from 'zod';

const ResponseSchema = z.object({
response: z.string(),
});

function ChatComponent() {
const { segments, sendStreaming, isStreaming, pendingApprovals, respondToToolApprovals } =
useChat({
model: openai('gpt-5.6-luna'),
systemPrompt: 'Answer concisely and accurately',
responseSchema: ResponseSchema,
});

const handleSend = async (text: string) => {
await sendStreaming(text);
};

return (
<div>
<ChatTurns segments={segments}>
{(turn) => (
<ChatTurn key={turn.id} turn={turn} />
)}
</ChatTurns>
{isStreaming && <div>Typing…</div>}
{pendingApprovals.length > 0 && (
<button
onClick={() =>
respondToToolApprovals(
pendingApprovals.map((p) => ({ approvalId: p.approvalId, approved: true })),
)
}
>
Approve all
</button>
)}
</div>
);
}

Prefer ChatTurns / ChatTurn (or useChatTurns + groupByTurn) over mapping raw segments or the deprecated messages array.

Return values

PropertyTypeDescription
segmentsStreamSegment[]Canonical conversation timeline (includes user segments)
isLoadingbooleanWhether a request is in progress
isStreamingbooleanWhether a response is currently streaming
errorError | nullLast error, if any
send(text: string) => PromiseSend a message (no streaming)
sendStreaming(text: string) => PromiseSend a message with streaming
clearHistory() => Promise<void>Clear the conversation
stopStreaming() => voidAbort the current stream
pendingApprovalsPendingApproval[]Gated tools awaiting approval (derived from segments)
respondToToolApprovals(responses: ToolApprovalResponse[]) => voidApprove/reject every pending id in one batch resume
messagesUIChatMessage[]Deprecated — derived from segments for legacy UIs only

Options

OptionTypeDescription
modelstring | ModelConfigLLM model to use
systemPromptstringSystem prompt for the processor
toolsRecord<string, ToolDefinition>Tools available to the processor
responseSchemaZodSchema | JSON SchemaStructured response schema (maps to Output.object())
maxToolIterationsnumberTool loop step cap (default 50)
storageHistoryStorageCustom history storage backend
proxyUrlstringProxy URL for API requests (browser CORS)
fetchtypeof fetchCustom fetch (e.g., for React Native)
shouldAskApproval(toolName: string) => booleanAuto-approve/deny without prompting
onApprovalRequest(pending: PendingApproval) => voidFired when a new approval request appears

ChatTurns and custom rendering

ChatTurns groups segments into conversational turns via groupByTurn. Override per-segment rendering with a function child on ChatTurn:

import { useChat, ChatTurns, ChatTurn, SegmentRenderer } from '@baleybots/react';

function Chat() {
const { segments, sendStreaming } = useChat({ model: 'openai|gpt-5.6-luna' });

return (
<ChatTurns segments={segments}>
{(turn) => (
<ChatTurn
key={turn.id}
turn={turn}
className={turn.role === 'user' ? 'user-bubble' : 'assistant-bubble'}
>
{(segment) =>
segment.type === 'text' ? (
<p key={segment.id}>{segment.content}</p>
) : undefined
}
</ChatTurn>
)}
</ChatTurns>
);
}

For legacy code that still expects OpenAI-shaped rows, derive messages locally — do not treat hook messages as primary:

import { deriveUIMessages } from '@baleybots/core';

const uiMessages = deriveUIMessages(segments);

useBaleybot

useBaleybot wraps a Baleybot processor for direct use in React. It manages the agent lifecycle and provides a simple interface.

The hook accepts outputSchema (Zod or JSON Schema) and converts it to Output.object() when creating the underlying processor.

import { useBaleybot } from '@baleybots/react';
import { z } from 'zod';

function SentimentAnalyzer() {
const { process, result, isProcessing } = useBaleybot({
name: 'sentiment',
analysisGoal: 'Analyze the sentiment of text',
outputSchema: z.object({
sentiment: z.enum(['positive', 'negative', 'neutral']),
confidence: z.number(),
}),
});

return (
<div>
<button onClick={() => process('I love this product!')}>
Analyze
</button>
{result && <p>Sentiment: {result.sentiment} ({result.confidence})</p>}
</div>
);
}

For direct Baleybot.create() usage outside React, prefer the output config with Output.object() — see Structured Outputs.

Removed APIs

The following were removed from @baleybots/react useChat:

  • useGroupChat — use client useChat; for hosted crew chat use /api/chat
  • Server mode options: apiUrl, chatId, multiAgent, agents, loadHistory, isResuming
  • Scalar approvals: pendingApproval, approveToolCall, rejectToolCall
  • SendStreamingOptions (mentions, etc.)

See useChat migration for before/after patterns.