AG-UI Headless UI Integration
@cloudbase/agent-react-core provides the core APIs needed to integrate AG-Kit conversational capabilities in React applications, enabling quick integration with AI Agents that conform to the AG-UI protocol.
Feature Overview
- Chat state management
- Message sending and aborting
- Session thread switching
- Client-side tool registration
- Custom Tool Call rendering
- Transport layer integration
Installation
npm install @cloudbase/agent-react-core
Quick Start
It is recommended to first initialize the runtime with AgKit, then read messages and send content in child components via useChat.
import cloudbase from "@cloudbase/js-sdk";
import { AgKit, CloudBaseTransport, useChat } from "@cloudbase/agent-react-core";
const app = cloudbase.init({ env: "your-env-id" });
const transport = new CloudBaseTransport({
app,
agentId: "your-agent-id",
});
function ChatView() {
const { uiMessages, sendMessage, streaming, abort } = useChat();
return (
<div>
<button onClick={() => sendMessage("你好")}>Send</button>
<button onClick={abort} disabled={!streaming}>
Stop
</button>
{uiMessages.map((message) => (
<div key={message.id}>
<strong>{message.role}:</strong> {message.content}
</div>
))}
</div>
);
}
export function App() {
return (
<AgKit transport={transport}>
<ChatView />
</AgKit>
);
}
API Reference
AgKit
AgKit is used to initialize the chat runtime and provide context to child components.
AgKitProps
| Option | Required | Type | Description |
|---|---|---|---|
transport | Yes | Transport | Transport layer instance responsible for sending messages to the backend and consuming the event stream |
defaultThreadId | No | string | Default thread ID used during initial initialization, only effective at runtime initialization |
instanceId | No | string | Instance identifier for isolating state in multi-chat instance scenarios |
children | Yes | React.ReactNode | Child components |
Example
<AgKit transport={transport} defaultThreadId="thread-001">
<ChatView />
</AgKit>
useChat
useChat provides the core state and operation methods during the chat process.
Parameters UseChatOptions
| Option | Required | Type | Description |
|---|---|---|---|
instanceId | No | string | Instance identifier for multi-instance scenarios, used to associate with a specific AgKit instance |
Return Value UseChatReturn
| Option | Type | Description |
|---|---|---|
messages | Message[] | Underlying raw message data |
uiMessages | UIMessage[] | Message list suitable for direct rendering (merges consecutive assistant messages, supports parts structure) |
streaming | boolean | Whether a streaming response is in progress |
error | AGUIClientError \| null | Current error state |
initialized | boolean | Whether the runtime has completed initialization |
actions | Record<string, Action> | Dictionary of currently registered tools (Actions) |
sendMessage | (input: string \| ToolMessage) => Promise<void> | Send a text message or tool message |
clearMessages | () => void | Clear all messages |
addAction | (action: Action) => void | Register an Action |
removeAction | (actionName: string) => void | Remove an Action by name |
switchThread | (threadId: string, options?: SwitchThreadOptions) => void | Switch session thread |
abort | () => void | Abort the current request |
SwitchThreadOptions
| Option | Required | Type | Description |
|---|---|---|---|
clearMessages | No | boolean | Whether to clear current messages when switching threads |
abortActiveRun | No | boolean | Whether to abort the ongoing request when switching threads |
Example
function ChatActions() {
const { uiMessages, sendMessage, streaming, abort, clearMessages } = useChat();
return (
<div>
<button onClick={() => sendMessage("介绍一下 AG-Kit")}>Send Message</button>
<button onClick={abort} disabled={!streaming}>
Stop Generating
</button>
<button onClick={clearMessages}>Clear Messages</button>
{uiMessages.map((message) => (
<div key={message.id}>{message.content}</div>
))}
</div>
);
}
useHeadlessChat
useHeadlessChat is a standalone version of useChat that can be used without the AgKit Provider, suitable for scenarios that require full control over the runtime lifecycle.
Parameters UseHeadlessChatOptions
| Option | Required | Type | Description |
|---|---|---|---|
transport | Yes | Transport | Transport layer instance |
threadId | No | string | Initial thread ID |
instanceId | No | string | Instance identifier for multi-instance scenarios |
Return Value
Same as the useChat return value, see UseChatReturn.
Example
function HeadlessChat() {
const transport = useMemo(() => new CloudBaseTransport({ app, agentId: "xxx" }), []);
const { uiMessages, sendMessage } = useHeadlessChat({ transport });
return (
<div>
{uiMessages.map((msg) => (
<div key={msg.id}>{msg.parts.map((p) => p.type === "text" && p.text)}</div>
))}
<button onClick={() => sendMessage("Hello")}>Send</button>
</div>
);
}
useClientTool
useClientTool is used to register client-side tools. Once registered, the model can initiate corresponding tool calls, and the frontend can optionally execute them locally and return results.
Parameters UseClientToolOptions
| Option | Required | Type | Description |
|---|---|---|---|
name | Yes | string | Tool name (unique key) |
description | Yes | string | Tool description sent to the model |
parameters | Yes | object | JSON Schema parameter definition sent to the model |
handler | No | (params: ToolHandlerParams) => string \| Promise<string> | Local tool handler function |
render | No | (context: ToolRenderContext) => string \| React.ReactElement | Custom tool render function |
instanceId | No | string | Instance identifier for multi-instance support |
enabled | No | boolean | Whether to enable tool registration, defaults to true |
ToolHandlerParams
| Option | Type | Description |
|---|---|---|
name | string | Tool name |
description | string | Tool description |
toolCallId | string | Unique ID for this call |
args | Record<string, unknown> | Parameters passed by the model |
ToolRenderContext
| Option | Type | Description |
|---|---|---|
toolCall | ToolCallState | Complete state of the tool call |
respond | (result: string) => void | Return tool result to the model |
Example
import { useClientTool } from "@cloudbase/agent-react-core";
function ToolRegistration() {
useClientTool({
name: "get_local_weather",
description: "Get local weather",
parameters: {
type: "object",
properties: {
city: { type: "string" },
},
},
handler: ({ args }) => {
return JSON.stringify({
city: String(args.city ?? "Shanghai"),
weather: "sunny",
});
},
});
return null;
}
Suitable for the following scenarios:
- Reading browser local capabilities
- Calling business methods in the frontend context
- Returning tool results as structured data to the model
useToolCall
useToolCall is used to register a custom render function for a specified tool, making it easy to display interaction interfaces tailored to business scenarios in the message list.
Parameters UseToolCallOptions
| Option | Required | Type | Description |
|---|---|---|---|
name | Yes | string | Tool name (unique key) |
render | Yes | (context: ToolRenderContext) => string \| React.ReactElement | Custom render function |
instanceId | No | string | Instance identifier for multi-instance support |
enabled | No | boolean | Whether to enable render registration, defaults to true |
Example
import { useToolCall } from "@cloudbase/agent-react-core";
function ToolRenderer() {
useToolCall({
name: "get_local_weather",
render: ({ toolCall }) => (
<div>
Weather tool parameters: {JSON.stringify(toolCall.args)}
</div>
),
});
return null;
}
Suitable for the following scenarios:
- Displaying tool parameters and execution results
- Adding confirmation interactions for tool calls
- Rendering tool output as cards, tables, or custom views
Transport
Transport Interface
All transport layers need to implement the Transport interface:
| Method | Type | Description |
|---|---|---|
run | (input: RunAgentInput) => AsyncIterable<BaseEvent> | Execute an agent run and return an async event iterator |
abort | () => void | Abort the current run |
To connect to a custom backend, you can implement the Transport interface yourself.
CloudBaseTransport
Built-in transport layer for connecting to the CloudBase Agent SSE interface. Supports Bearer Token authentication, automatic retry on token expiration, and AbortController cancellation.
Constructor Parameters
| Option | Required | Type | Description |
|---|---|---|---|
app | Yes | cloudbase.app.App | CloudBase JS SDK application instance |
agentId | Yes | string | Agent ID |
fetch | No | typeof globalThis.fetch | Custom fetch function, defaults to globalThis.fetch |
headers | No | Record<string, string> | Custom request headers |
Example
import cloudbase from "@cloudbase/js-sdk";
import { CloudBaseTransport } from "@cloudbase/agent-react-core";
const app = cloudbase.init({ env: "your-env-id" });
const transport = new CloudBaseTransport({
app,
agentId: "your-agent-id",
});