Frontend Tools
Let your agent interact with and update your application's UI.
What is this?#
Frontend tools let your agent define and invoke client-side functions that run entirely in the user's browser. Because the handler executes on the frontend, it has direct access to component state, browser APIs, and any third-party UI library the page already uses. That's how an agent can "reach into" the app: update React state, trigger animations, read localStorage, pop a toast, or steer the user's view.
This page covers the "agent drives the UI" shape of frontend tools. The same primitive also powers Generative UI and Human-in-the-loop; see those pages for interaction patterns.
When should I use this?#
Use frontend tools when your agent needs to:
- Read or modify React component state
- Access browser APIs like
localStorage,sessionStorage, or cookies - Trigger UI updates, animations, or transitions
- Show alerts, toasts, or notifications
- Interact with third-party frontend libraries
- Perform anything that requires the user's immediate browser context
How it works in code#
Register a frontend tool with useFrontendTool. Give it a name, a Zod schema for parameters, and a handler. The agent can then call it like any other tool and your frontend runs it in the browser.
import React, { useState } from "react";
import {
CopilotKitProvider,
CopilotChat,
useFrontendTool,
useConfigureSuggestions,
} from "@copilotkit/react-core/v2";
import { z } from "zod";
export default function FrontendToolsDemo() {
return (
<CopilotKitProvider runtimeUrl="/api/copilotkit" useSingleEndpoint>
<Chat />
</CopilotKitProvider>
);
}
function Chat() {
const [background, setBackground] = useState<string>(
"var(--copilot-kit-background-color)",
);
useFrontendTool({
name: "change_background",
description:
"Change the background color of the chat. Accepts any valid CSS background value — colors, linear or radial gradients, etc.",
parameters: z.object({
background: z
.string()
.describe("The CSS background value. Prefer gradients."),
}),
handler: async ({ background }: { background: string }) => {
setBackground(background);
return {
status: "success",
message: `Background changed to ${background}`,
};
},
});The handler receives the parsed, type-safe parameters and can do anything the browser can: update state, call an API, touch the DOM. Its return value is sent back to the agent as the tool result so the model can reason about what happened.
handler: async ({ background }: { background: string }) => {
setBackground(background);
return {
status: "success",
message: `Background changed to ${background}`,
};
},