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 chat interfaces. It supports two modes:

  • Client mode (default) — runs the processor locally in the browser
  • Server mode — connects to a backend API via apiUrl and chatId

Client mode

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

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

function ChatComponent() {
const { segments, sendStreaming, isStreaming } = useChat({
model: 'openai|gpt-4.1-mini',
systemPrompt: 'Answer concisely and accurately',
responseSchema: ResponseSchema, // converted to Output.object() internally
});

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

return (
<div>
{segments.map((segment) => {
if (segment.type === 'user') {
return <div key={segment.id}><b>You:</b> {segment.content}</div>;
}
if (segment.type === 'text') {
return <div key={segment.id}><b>Response:</b> {segment.content}</div>;
}
return null;
})}
</div>
);
}

Server mode

When apiUrl is set, useChat connects to a backend instead of running locally. Use chatId to persist conversations.

import { useChat } from '@baleybots/react';

function ChatComponent() {
const { segments, sendStreaming, isStreaming } = useChat({
apiUrl: 'https://your-api.com/chat',
chatId: 'conversation-123',
});

// Same rendering code as client mode
}

Return values

The hook returns:

PropertyTypeDescription
segmentsStreamSegment[]All segments in the conversation
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 one or more pending tool calls in a single resume

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() on the underlying Baleybot)
maxToolIterationsnumberTool loop step cap (maps to stopWhen: stepCountIs(n); default 50)
apiUrlstringBackend URL (activates server mode)
chatIdstringConversation ID (server mode)
storageHistoryStorageCustom history storage backend
proxyUrlstringProxy URL for API requests
fetchtypeof fetchCustom fetch (e.g., for React Native)
shouldAskApproval(toolName: string) => booleanAuto-approve/deny without prompting; remaining approvals still require respondToToolApprovals
onApprovalRequest(pending: PendingApproval) => voidFired when a new approval request appears

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.

Deprecated: useGroupChat

useGroupChat is deprecated. Use useChat with apiUrl and chatId instead:

// Before (deprecated)
import { useGroupChat } from '@baleybots/react';
const { messages } = useGroupChat({ apiUrl: '...', chatId: '...' });

// After
import { useChat } from '@baleybots/react';
const { segments } = useChat({ apiUrl: '...', chatId: '...' });

See the Unified useChat Hook migration guide for details.