Skip to main content

Put the user in the loop

Some steps should not happen without a human saying yes. Human-in-the-loop pauses the agent mid-run, renders an interactive component in the frontend, and waits. The user makes a choice; the agent resumes with that choice and continues. The mechanism is a tool the frontend registers. When the model calls it, the run halts at that tool call until the user responds. Nothing happens automatically: the agent stays parked until respond() hands control back. In the example below, the agent proposes a list of task steps. The user enables or disables each step and confirms. The agent then continues, respecting exactly what the user approved.
This pattern works with Flows. It relies on the Flow’s chat loop re-entering after respond(): the returned value comes back as a tool result, and the agent’s next turn acts on it.

Build it

1

Bind the frontend actions into the model's tools

In your Flow, add the frontend-registered actions to the model’s tool list with *self.state.copilotkit.actions. Those actions are the tools your frontend registered (via useHumanInTheLoop). Binding them lets the model call them; the run pauses at that tool call until the user responds.
CopilotKitState carries the frontend-registered actions on self.state.copilotkit.actions. When the model calls one, the run pauses there. After the user responds, the returned value lands in self.state.messages as the tool result, and the Flow loops back through chat so the model can act on the decision.
2

Serve the Flow over AG-UI

Expose the Flow from your FastAPI server with add_crewai_flow_fastapi_endpoint, the same way as every other agent. See Frontend Overview for the full server, runtime, and provider setup.
3

Register the interactive tool on the frontend

useHumanInTheLoop registers the tool the agent pauses on and gives you a render function to draw the interactive UI. When the agent calls the tool, your component appears; when the user acts, you call respond() to resume the agent.
The render function receives:
  • args — the tool arguments the model produced (here, the proposed steps). These stream in as the model generates them.
  • status — the tool call’s lifecycle. While it is "executing", the agent is paused and waiting on the human.
  • respond(value) — resumes the agent with the user’s decision. The agent’s next turn sees the returned value and acts on it.
4

Let the user decide, then respond

Your component reads args.steps, lets the user toggle each one, and calls respond() with the final selection. That value is what the agent continues with.
Once the user clicks Confirm, respond() fires, the run resumes, and the Flow’s chat step runs again with the user’s choices in the message history.

Frontend Actions

Let the agent call functions that run in the browser.

Shared State

Keep agent state and your app UI in two-way sync.

Agentic Generative UI

Render live agent state as custom components.