Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Human in the Loop

What This Demo Shows

Interactive components from the agent; user approves actions from within the chat

How to Interact

Try asking your Copilot to:

  • "Plan a trip to Mars in 5 steps"
  • "Please plan a pasta dish in 10 steps"
  • "Draft a product launch checklist in 7 steps"

The agent proposes a plan as a StepSelector card with a checkbox per step. Toggle individual steps on or off (the selected count updates as "N/N selected"), then click Perform Steps (N) / Confirm (N) to approve, or Reject to cancel. The card reflects the final decision ("Accepted" / "Rejected") and disables its buttons afterward.

Technical Details

What's happening technically:

  • Human-in-the-Loop (HITL) lets the agent pause and hand control back to the user to review a proposed plan before continuing
  • The agent calls a tool (e.g. generate_task_steps) whose payload is a list of steps; the frontend renders a StepSelector card rather than executing immediately
  • useHumanInTheLoop (frontend-tool flow) or useLangGraphInterrupt (interrupt flow) registers a render that receives { args, respond, status } — the StepSelector keeps local state for which steps are enabled and calls respond({ accepted, steps }) on Confirm / Reject (CopilotKit v2 API; existing showcase packages use v1 useLangGraphInterrupt for the interrupt-flow demo alongside v2 hooks like useHumanInTheLoop — new integrations generated by create-integration default to the v2 useInterrupt.)
  • The card exposes per-step checkboxes, a live "N/N selected" count, and Confirm / Reject buttons; after a decision the buttons disable and the card shows "Accepted" or "Rejected" so the outcome is auditable in the transcript
  • This pattern is essential for plan-style flows — multi-step actions where the user needs to curate, edit, or veto what the agent is about to do before any of it runs

Building With This

If you're extending this demo or building something similar, here are key things to know:

Styling Inside the Chat

Content rendered inside CopilotKit's chat area (via useRenderTool, useHumanInTheLoop, useFrontendTool) runs inside CopilotKit's component tree. Standard Tailwind classes may not work here because Tailwind v4 can't statically detect them.

Use inline styles for any UI rendered inside the chat:

// Do this
<div style={{ padding: "24px", borderRadius: "12px", background: "#fff" }}>

// Not this — Tailwind may purge these classes
<div className="p-6 rounded-xl bg-white">

Chat Layout

Wrap CopilotChat in a constraining div for proper spacing:

<div className="flex justify-center items-center h-screen w-full">
  <div className="h-full w-full md:w-4/5 md:h-4/5 rounded-lg">
    <CopilotChat className="h-full rounded-2xl max-w-6xl mx-auto" />
  </div>
</div>

Overriding CopilotKit Styles

CopilotKit uses cpk: prefixed classes internally. To override them, create a separate CSS file (not in globals.css — Tailwind purges it):

/* copilotkit-overrides.css */
.copilotKitInput {
  border-radius: 0.75rem;
  border: 1px solid var(--copilot-kit-separator-color) !important;
}

Import it in layout.tsx after globals.css.

Images and Icons

  • Don't reference local image files from agent-generated content (they won't exist). Add onError fallbacks.
  • Use emoji instead of SVG icons inside chat messages (fill="currentColor" renders unpredictably in the chat context).

See the full Styling Guide for more details.