Give HeroUI Agent typed access to browser data and actions with createToolHelper.
Client tools execute in the user's browser with the user's current session. Only each tool's name, description, JSON schema, and approval flag are sent to the hosted Agent; implementation code and shared context stay on the page.
They are one of three kinds of tool an agent can use. See Tools for how client tools compare to built-in toolkits and MCP servers, and which to reach for.
createToolHelper<Context>() returns a tool factory bound to your application context type. Zod parameters provide typed arguments and runtime parsing.
Add zod to your own dependencies to use it in parameters. It ships inside @heroui/agent, but
strict package managers such as pnpm do not let application code import a package it did not
declare. Passing raw JSON Schema instead needs no extra dependency.
import {HeroUIAgent, createToolHelper} from "@heroui/agent";
import {z} from "zod";
type AppContext = {
apiClient: ApiClient;
page: () => {route: string};
};
const tool = createToolHelper<AppContext>();
const tools = [
tool({
name: "search_users",
displayName: "Search users",
description: "Search users by name or email",
parameters: z.object({query: z.string()}),
execute: ({query}, context) => context.apiClient.searchUsers(query),
}),
];
<HeroUIAgent
getAuthToken={getAuthToken}
context={{apiClient, page: () => ({route: location.pathname})}}
agentId={process.env.NEXT_PUBLIC_HEROUI_AGENT_ID!}
tools={tools}
/>;| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Stable machine-readable tool name. |
displayName | string | No | Human-readable name shown in the default tool card. |
description | string | Yes | Clear instruction that helps the model decide when to call the tool. |
parameters | ZodType | Record<string, unknown> | Yes | Zod schema or raw JSON Schema for tool arguments. |
execute | (args, context) => unknown | Promise<unknown> | Yes | Browser implementation. Returned data can feed generated UI. |
needsApproval | boolean | No | Require user approval in the default auto permission mode. |
icon | ComponentType<ClientToolIconProps> | No | Icon for the default tool card. |
iconColor | string | No | Color passed to the default tool icon. |
render | (props: ClientToolRenderProps) => ReactNode | No | Custom tool UI. Return null to use the default card for a state. |
For a complete custom tool component example, see Custom Components.
ClientToolRenderProps<TArgs> is passed to a client tool's optional render function. TArgs is inferred from the tool's Zod schema when you use createToolHelper.
type ClientToolRenderProps<TArgs = unknown> = {
args: TArgs;
error?: string;
onApprove?: () => void;
onReject?: () => void;
result?: unknown;
status: ClientToolStatus;
};| Property | Available when | Description |
|---|---|---|
args | Every state | Arguments supplied by the Agent. |
status | Every state | Current ClientToolStatus. |
onApprove | status === "approval-requested" | Approve an approval-gated call. |
onReject | status === "approval-requested" | Reject an approval-gated call. |
result | status === "completed" | Value returned by execute. Narrow or validate before use. |
error | status === "error" | Error message produced when execution fails. |
ClientToolRenderProps.status is one of:
input-streamingapproval-requestedexecutingcompletedrejectederrorApproval renderers receive onApprove and onReject. Completed renderers receive result, and failed renderers receive error.
Every tool receives the same context object. It may contain API clients, authenticated user details, state setters, and other browser-only values. The optional page() key is reserved: its JSON-serializable return value is sent with every turn as page context and is limited to 16 KB.
Mark destructive or consequential actions with needsApproval: true. Permission modes only govern
declared client tools; they do not grant additional account, filesystem, or network access.