@agentick/react
React bindings for Agentick. Provides hooks around @agentick/client for building chat interfaces and real-time AI applications.
Installation
pnpm add @agentick/react
Quick Start
import { AgentickProvider, useSession, useStreamingText, useContextInfo } from "@agentick/react";
function Chat() {
const { send } = useSession({ sessionId: "my-session", autoSubscribe: true });
const { text, isStreaming } = useStreamingText();
const { contextInfo } = useContextInfo();
return (
<div>
<div className="response">
{text}
{isStreaming && <span className="cursor">|</span>}
</div>
{contextInfo && (
<div className="context-bar">
<span>{contextInfo.modelName}</span>
<span>{contextInfo.utilization?.toFixed(1)}% context used</span>
</div>
)}
<button onClick={() => send("Hello!")}>Send</button>
</div>
);
}
export function App() {
return (
<AgentickProvider clientConfig={{ baseUrl: "/api" }}>
<Chat />
</AgentickProvider>
);
}
Hooks
useSession(options?)
Session management hook. Returns methods for sending messages and managing subscriptions.
const {
sessionId,
isSubscribed,
subscribe,
unsubscribe,
send,
abort,
close,
accessor,
} = useSession({
sessionId: "my-session",
autoSubscribe: true,
});
await send("Hello!");
await send({
message: {
role: "user",
content: [{ type: "text", text: "Hello!" }],
},
});
useStreamingText(options?)
Subscribe to streaming text from model responses. Automatically accumulates text deltas.
const {
text,
isStreaming,
clear,
} = useStreamingText({
enabled: true,
});
<div>
{text}
{isStreaming && <span className="cursor">|</span>}
</div>;
useContextInfo(options?)
Subscribe to context utilization information. Updated after each model response with token usage and model capabilities.
const {
contextInfo,
clear,
} = useContextInfo({
sessionId: "my-session",
enabled: true,
});
if (contextInfo) {
console.log(contextInfo.modelId);
console.log(contextInfo.modelName);
console.log(contextInfo.provider);
console.log(contextInfo.contextWindow);
console.log(contextInfo.inputTokens);
console.log(contextInfo.outputTokens);
console.log(contextInfo.totalTokens);
console.log(contextInfo.utilization);
console.log(contextInfo.maxOutputTokens);
console.log(contextInfo.supportsVision);
console.log(contextInfo.supportsToolUse);
console.log(contextInfo.isReasoningModel);
console.log(contextInfo.cumulativeUsage?.inputTokens);
console.log(contextInfo.cumulativeUsage?.outputTokens);
console.log(contextInfo.cumulativeUsage?.ticks);
}
ContextInfo Interface
interface ContextInfo {
modelId: string;
modelName?: string;
provider?: string;
contextWindow?: number;
inputTokens: number;
outputTokens: number;
totalTokens: number;
utilization?: number;
maxOutputTokens?: number;
supportsVision?: boolean;
supportsToolUse?: boolean;
isReasoningModel?: boolean;
tick: number;
cumulativeUsage?: {
inputTokens: number;
outputTokens: number;
totalTokens: number;
ticks: number;
};
}
useEvents(options?)
Subscribe to raw stream events. Use for advanced event handling.
const {
event,
clear,
} = useEvents({
sessionId: "my-session",
filter: ["tool_call", "tool_result"],
enabled: true,
});
useEffect(() => {
if (event?.type === "tool_call") {
console.log("Tool called:", event.name);
}
}, [event]);
useConnection()
Connection state for the SSE transport.
const {
state,
isConnected,
isConnecting,
} = useConnection();
<div className={`status ${isConnected ? "online" : "offline"}`}>
{isConnected ? "Connected" : "Disconnected"}
</div>;
useConnectionState()
Alias for useConnection(). Returns just the connection state string.
const state = useConnectionState();
useClient()
Direct access to the underlying AgentickClient for advanced use cases.
const client = useClient();
const session = client.session("my-session");
const channel = session.channel("custom");
channel.publish("event", { data: "value" });
useLineEditor(options)
React wrapper around @agentick/client's LineEditor class. Provides readline-quality editing with completion support via useSyncExternalStore.
import { useLineEditor } from "@agentick/react";
const { value, cursor, completion, completedRanges, editor } = useLineEditor({
onSubmit: (text) => send(text),
});
useEffect(() => {
return editor.registerCompletion({
id: "file",
match({ value, cursor }) {
const idx = value.lastIndexOf("#", cursor - 1);
if (idx < 0) return null;
return { from: idx, query: value.slice(idx + 1, cursor) };
},
resolve: async ({ query }) => searchFiles(query),
});
}, [editor]);
Returns { value, cursor, completion, completedRanges, handleInput, setValue, clear, editor }. The editor property is the raw LineEditor instance. The completion property is CompletionState | null.
For terminal UIs, use useLineEditor from @agentick/tui which adds Ink keystroke normalization. See COMPLETION.md for the full completion system reference.
Chat Hooks
These hooks wrap the Chat Primitives from @agentick/client. See the client docs for the underlying ChatSession, MessageLog, ToolConfirmations, and MessageSteering classes.
useChat(options?)
Full chat controller hook — messages, steering, tool confirmations, and attachments in one call. Wraps ChatSession with useSyncExternalStore. Auto-subscribes to the SSE transport by default (set autoSubscribe: false to manage subscription separately via useSession).
import { useChat } from "@agentick/react";
function Chat({ sessionId }: { sessionId: string }) {
const {
messages,
chatMode,
toolConfirmation,
lastSubmitted,
queued,
isExecuting,
mode,
attachments,
submit,
steer,
queue,
interrupt,
flush,
respondToConfirmation,
clearMessages,
setMode,
removeQueued,
clearQueued,
addAttachment,
removeAttachment,
clearAttachments,
} = useChat({ sessionId, mode: "queue" });
return (
<div>
{messages.map((msg) => (
<div key={msg.id} className={msg.role}>
{typeof msg.content === "string" ? msg.content : "..."}
</div>
))}
{toolConfirmation && (
<dialog open>
<p>Allow {toolConfirmation.request.name}?</p>
<button onClick={() => respondToConfirmation({ approved: true })}>Allow</button>
<button onClick={() => respondToConfirmation({ approved: false })}>Deny</button>
</dialog>
)}
<input
onKeyDown={(e) => {
if (e.key === "Enter") submit(e.currentTarget.value);
}}
/>
</div>
);
}
Options are captured at mount time. Changing them requires a new sessionId.
Custom Chat Modes
type MyMode = "idle" | "working" | "needs_approval";
const { chatMode } = useChat<MyMode>({
sessionId,
deriveMode: ({ isExecuting, hasPendingConfirmation }) => {
if (hasPendingConfirmation) return "needs_approval";
if (isExecuting) return "working";
return "idle";
},
});
useMessages(options?)
Message accumulation only. Use when you don't need steering or confirmations.
import { useMessages } from "@agentick/react";
const { messages, clear } = useMessages({
sessionId: "my-session",
transform: customTransform,
initialMessages: [],
});
useToolConfirmations(options?)
Tool confirmation management only. Use for custom confirmation UIs.
import { useToolConfirmations } from "@agentick/react";
const { pending, respond } = useToolConfirmations({
sessionId: "my-session",
policy: (req) => (req.name === "read_file" ? { action: "approve" } : { action: "prompt" }),
});
if (pending) {
respond({ approved: true });
}
useMessageSteering(options?)
Input-side message routing with queue/steer modes.
import { useMessageSteering } from "@agentick/react";
const { queued, isExecuting, mode, submit, steer, queue, interrupt, flush, setMode } =
useMessageSteering({
sessionId: "my-session",
mode: "queue",
flushMode: "sequential",
});
Progressive Disclosure
| 0 | useChat | Full chat — one hook does everything |
| 1 | useChat + options | Custom modes, policies, transforms |
| 2 | useMessages + useToolConfirmations + useMessageSteering | Compose individual primitives |
| 3 | useEvents + custom reducer | Full control, build your own |
Provider
AgentickProvider
Wraps your app to provide the Agentick client context.
<AgentickProvider
clientConfig={{
baseUrl: "https://api.example.com",
token: "auth-token",
}}
>
<App />
</AgentickProvider>
Types
All hooks are fully typed. Import types from the package:
import type {
AgentickProviderProps,
AgentickContextValue,
TransportConfig,
UseConnectionOptions,
UseConnectionResult,
UseSessionOptions,
UseSessionResult,
UseEventsOptions,
UseEventsResult,
UseStreamingTextOptions,
UseStreamingTextResult,
UseContextInfoOptions,
UseContextInfoResult,
ContextInfo,
UseChatOptions,
UseChatResult,
UseMessagesOptions,
UseMessagesResult,
UseToolConfirmationsOptions,
UseToolConfirmationsResult,
UseMessageSteeringOptions,
UseMessageSteeringResult,
ChatMode,
ChatMessage,
ToolConfirmationState,
SteeringMode,
FlushMode,
AgentickClient,
ConnectionState,
StreamEvent,
SessionAccessor,
SendInput,
ClientExecutionHandle,
SessionStreamEvent,
ClientTransport,
} from "@agentick/react";
import {
timelineToMessages,
extractToolCalls,
defaultTransform,
defaultDeriveMode,
} from "@agentick/react";
License
MIT