---
title: "useHumanInTheLoop"
description: "The useHumanInTheLoop hook enables human approval and interaction workflows."
---
`useHumanInTheLoop` is still supported, but we recommend migrating to [`useHumanInTheLoop`](/reference/v2/hooks/useHumanInTheLoop) from the v2 API.
`useHumanInTheLoop` pauses AI execution to request human input or approval. When the AI calls this
tool, it stops and waits for the user to respond through your custom UI before continuing. This is
essential for sensitive operations, confirmations, or collecting information that only the user can provide.
Unlike `useFrontendTool`, there's no handler function—instead, your render function receives a `respond`
callback that sends the user's input back to the AI. The AI execution remains paused until `respond` is called,
making this a true blocking interaction.
## Usage
### Simple Confirmation Example
```tsx
import { useHumanInTheLoop } from "@copilotkit/react-core";
useHumanInTheLoop({
name: "confirmDeletion",
description: "Ask user to confirm before deleting items",
parameters: [
{
name: "itemName",
type: "string",
description: "Name of the item to delete",
required: true,
},
{
name: "itemCount",
type: "number",
description: "Number of items to delete",
required: true,
},
],
render: ({ args, status, respond, result }) => {
if (status === "executing" && respond) {
return (
Are you sure you want to delete {args.itemCount} {args.itemName}(s)?
);
}
return null;
},
});
```
## Best Practices
1. Always check for the `respond` function before rendering interactive elements
2. Handle all status states to provide good user feedback
3. Validate user input before calling `respond`
4. Provide clear instructions in your UI about what input is expected
5. Consider timeout scenarios for time-sensitive operations
## Migration from useCopilotAction
If you're migrating from `useCopilotAction` with `renderAndWaitForResponse`:
```tsx
// Before with useCopilotAction
useCopilotAction({
name: "confirmAction",
parameters: [
{ name: "message", type: "string", required: true },
],
renderAndWaitForResponse: ({ args, respond, status }) => {
return (
respond(true)}
onCancel={() => respond(false)}
isActive={status === "executing"}
/>
);
},
});
// After with useHumanInTheLoop
useHumanInTheLoop({
name: "confirmAction",
parameters: [
{
name: "message",
type: "string",
description: "The message to display",
required: true,
},
],
render: ({ args, respond, status }) => {
if (status === "executing" && respond) {
return (
respond(true)}
onCancel={() => respond(false)}
isActive={true}
/>
);
}
return null;
},
});
```
The main differences are:
1. The property is called `render` instead of `renderAndWaitForResponse`
2. You need to check for the `respond` function's existence
## Parameters
The name of the tool.
A description of the tool. This is used to instruct the Copilot on when to request human input.
Array of parameter definitions that will be passed to the render function. Each parameter object should have:
- `name` (string): The parameter name
- `type` (string): The parameter type (e.g., "string", "number", "boolean", "string[]", "object")
- `description` (string): A description of what the parameter is for
- `required` (boolean): Whether the parameter is required
- `properties` (array, optional): For object types, define nested properties using the same schema
Simple example: `[{ name: "itemName", type: "string", description: "Name of the item", required: true }]`
Nested example:
```typescript
[
{
name: "approval",
type: "object",
description: "Approval request details",
required: true,
properties: [
{ name: "action", type: "string", description: "Action requiring approval", required: true },
{ name: "reason", type: "string", description: "Reason for the action", required: false }
]
}
]
```
A React component that renders the interactive UI for human input. The component receives props including `args`, `status`, and `respond` function.
Whether the tool is available. Set to "disabled" to prevent the tool from being called.