--- title: August 2026 - Human in the Loop description: Mock paused tool calls, approvals, and continuations for the AI SDK with @shadcn/helpers. date: 2026-08-12 --- **@shadcn/helpers** can now mock human-in-the-loop flows for the AI SDK. A scripted conversation can pause for real user input, wait for an approval, and continue with whatever the user decided. Everything streams through the real `useChat` lifecycle, so your tool cards, approval prompts, and question flows behave exactly as they would in production. ```ts showLineNumbers import { createChat } from "@shadcn/helpers/ai-sdk" const chat = createChat() .user("Help me plan the next prototype.") .assistant(({ writer }) => { writer.text("A couple of questions before I start.") writer.tool("askQuestions", { input: { questions } }) }) .assistant(({ writer, toolCall }) => { writer.text( toolCall?.name === "askQuestions" && toolCall.output ? `Starting with ${toolCall.output.answers.direction}.` : "Starting now." ) }) ``` Pass `needsApproval` to pause behind the user's decision. The scripted output streams after approval, and denial streams automatically. ```ts showLineNumbers chat .assistant(({ writer }) => { writer.text("That will archive 3 drafts. I need your approval.") writer.tool("archiveDrafts", { input: { count: 3 }, needsApproval: true, output: { archived: 3 }, }) }) .assistant(({ writer, toolCall }) => { writer.text( toolCall?.approved ? "Archived 3 drafts." : "Okay, leaving them in place." ) }) ```