Interactive Components
Register interactive React components that users can click, type into, or manipulate in the chat — results flow back to the agent as tool results.
What is this?#
Interactive generative UI extends display components with user interaction. Your agent renders components that users can click, type into, or manipulate — and the results flow back to the agent as tool results.
This is how you build human-in-the-loop flows: the agent requests a decision, the user responds, and the agent continues with that response as input.
When should I use this?#
Use interactive generative UI when you want to:
- Let users confirm or modify agent suggestions inline
- Build form-like interactions within the chat
- Create approval workflows where users can accept/reject agent actions
- Add interactive controls (sliders, toggles, selectors) to agent outputs
How it works in code#
The primitive is useHumanInTheLoop. Unlike useComponent (display-only) or useFrontendTool (handler-driven), useHumanInTheLoop exposes a respond callback to your render function. When the user clicks a button or submits a form, you call respond(value) — that value becomes the tool's result and the agent continues the turn.
import { z } from "zod";
import { useHumanInTheLoop } from "@copilotkit/react-core/v2";
useHumanInTheLoop({
name: "humanApprovedCommand",
description: "Ask a human for approval to run a command.",
parameters: z.object({
command: z.string().describe("The command to run"),
}),
render: ({ args, respond, status }) => {
if (status !== "executing") return null;
return (
<div>
<pre>{args.command}</pre>
<button onClick={() => respond?.("Command is APPROVED")}>Approve</button>
<button onClick={() => respond?.("Command is DENIED")}>Deny</button>
</div>
);
},
});
Statuses:
"inProgress"— the LLM is still streaming arguments; don't render anything irreversible yet."executing"— the agent is waiting for the user's response. Show your form / buttons."complete"— the user has responded (or the call was cancelled). Collapse to a confirmation view.
Working with the Built-in Agent#
No backend wiring needed — the Built-in Agent sees the interactive tool in its tool list the same way it sees a regular frontend tool, and respond(value) feeds the result straight back into the next agent turn.
Pattern: approval flow#
The cell above demonstrates a command-approval flow:
- The agent proposes a command (e.g.
rm -rf ./cache) - The UI renders an Approve / Deny pair
respond(...)sends"APPROVED"or"DENIED"back- The agent reads the result and either executes or bails
Related#
- Display Components — when you don't need user interaction, just rich rendering.
- Frontend Tools — handler-driven tools (no UI, just logic).
- Tool Rendering — wrap a real backend tool in custom UI.
