---
title: Form-Filling AI Copilot
description: Open-source AI copilot that fills forms for users — sidebar UI, field-aware tool calls, and a working React example built with assistant-ui.
---


<div className="not-prose h-[600px]">
  <DemoIframe
    title="Form Filling Co-Pilot demo"
    className="h-full w-full border-none"
    src="https://assistant-ui-form-demo.vercel.app/"
  />
</div>

## Overview

This example demonstrates how to create an AI assistant sidebar that helps users fill out forms automatically. The assistant understands form structure and can populate fields based on natural language instructions, making complex forms easier to complete.

## Features

- **Sidebar Integration**: AI assistant lives alongside your form
- **Field Mapping**: Assistant directly modifies form field values
- **Smart Suggestions**: Pre-built prompt suggestions for common actions
- **React Hook Form**: Seamless integration via `useAssistantForm`

## Use Cases

- **Complex Applications**: Multi-step forms with many fields
- **Data Entry**: Bulk data input from natural language
- **Accessibility**: Voice-driven form completion
- **Onboarding**: Guide users through registration flows

## Integration

The example uses `useAssistantForm` from `@assistant-ui/react-hook-form` to connect the AI with form state. This hook replaces the standard `useForm` and automatically registers `set_form_field` and `submit_form` tools with the assistant.

### Runtime Provider

```tsx
// app/MyRuntimeProvider.tsx
"use client";

import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";

export function MyRuntimeProvider({
  children,
}: Readonly<{ children: React.ReactNode }>) {
  const runtime = useChatRuntime();

  return (
    <AssistantRuntimeProvider runtime={runtime}>
      {children}
    </AssistantRuntimeProvider>
  );
}
```

### Backend Route

```ts
// app/api/chat/route.ts
import { openai } from "@ai-sdk/openai";
import { frontendTools } from "@assistant-ui/react-ai-sdk";
import { convertToModelMessages, streamText } from "ai";

export const maxDuration = 30;

export async function POST(req: Request) {
  const { messages, system, tools } = await req.json();

  const result = streamText({
    model: openai("gpt-5.4-nano"),
    messages: await convertToModelMessages(messages),
    system,
    tools: {
      ...frontendTools(tools),
    },
  });

  return result.toUIMessageStreamResponse();
}
```

### Page Component

```tsx
// app/page.tsx
"use client";

import { SignupForm } from "@/components/SignupForm";
import { Thread } from "@/components/assistant-ui/thread";
import { Form } from "@/components/ui/form";
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable";
import { useAssistantForm } from "@assistant-ui/react-hook-form";
import {
  useAssistantInstructions,
  useAui,
  AuiProvider,
  Suggestions,
} from "@assistant-ui/react";

const SetFormFieldTool = () => {
  return (
    <p className="text-center font-bold font-mono text-blue-500 text-sm">
      set_form_field(...)
    </p>
  );
};

const SubmitFormTool = () => {
  return (
    <p className="text-center font-bold font-mono text-blue-500 text-sm">
      submit_form(...)
    </p>
  );
};

const panelStyle = { overflow: "hidden" } as const;

export default function Home() {
  useAssistantInstructions("Help users sign up for Simon's hackathon.");

  const form = useAssistantForm({
    defaultValues: {
      firstName: "",
      lastName: "",
      email: "",
      cityAndCountry: "",
      projectIdea: "",
      proficientTechnologies: "",
    },
    assistant: {
      tools: {
        set_form_field: {
          render: SetFormFieldTool,
        },
        submit_form: {
          render: SubmitFormTool,
        },
      },
    },
  });

  const aui = useAui({
    suggestions: Suggestions([
      {
        title: "Fill out the form",
        label: "with sample data",
        prompt: "Please fill out the signup form with sample data for me.",
      },
      {
        title: "Help me register",
        label: "for the hackathon",
        prompt:
          "I'd like to sign up for the hackathon. My name is Jane Doe and my email is jane@example.com.",
      },
    ]),
  });

  return (
    <AuiProvider value={aui}>
      <ResizablePanelGroup orientation="horizontal">
        <ResizablePanel defaultSize={60} minSize={40} style={panelStyle}>
          <div className="h-full overflow-y-auto bg-muted/30">
            <main className="mx-auto w-full max-w-2xl px-4 py-10 sm:px-6 sm:py-12">
              <header className="mb-8 space-y-2">
                <p className="font-medium text-muted-foreground text-sm uppercase tracking-wide">
                  Simon's Hackathon
                </p>
                <h1 className="font-semibold text-3xl tracking-tight">
                  Apply to join
                </h1>
                <p className="text-muted-foreground">
                  A weekend hackathon on AI UX. Be the first to get an invite.
                </p>
              </header>

              <Form {...form}>
                <SignupForm />
              </Form>
            </main>
          </div>
        </ResizablePanel>
        <ResizableHandle />
        <ResizablePanel defaultSize={40} minSize={30} style={panelStyle}>
          <Thread />
        </ResizablePanel>
      </ResizablePanelGroup>
    </AuiProvider>
  );
}
```

### How It Works

1. `useAssistantForm` wraps React Hook Form's `useForm` and automatically exposes `set_form_field` and `submit_form` as frontend tools
2. The backend receives these tool definitions via `frontendTools()` and passes them to the model
3. When the AI calls `set_form_field`, the form field is updated directly via React Hook Form
4. Custom `render` components display a visual indicator in the chat while the tool executes
5. `useAui` with `Suggestions` adds pre-built prompt suggestions to the assistant UI

## Source

<SourceLink href="https://github.com/assistant-ui/assistant-ui/blob/main/examples/with-react-hook-form/app/page.tsx" />
