Examples

Form-Filling AI Copilot

Open-source AI copilot that fills forms for users. Sidebar UI, field-aware tool calls, and a working React example built with assistant-ui.

source

fig. 01live

Overview

This example shows an AI assistant sidebar that fills out a form for the user. The assistant receives the form structure and populates fields from natural language instructions.

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: Integrates through 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

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

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

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

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

Backend Route

// app/api/chat/route.ts
import { openai } from "@ai-sdk/openai";
import { frontendTools } from "@assistant-ui/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 aiSDKTools = { ...frontendTools(tools) };

  const result = streamText({
    abortSignal: req.signal,
    model: openai("gpt-6-luna"),
    messages: await convertToModelMessages(messages, { tools: aiSDKTools }),
    system,
    tools: aiSDKTools,
  });

  return result.toUIMessageStreamResponse();
}

Page Component

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

import { SignupForm } from "@/components/SignupForm";
import { Thread } from "@/components/assistant-ui/elements/thread.aui";
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,
  AuiConfig,
  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();
  const config = AuiConfig({
    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 extends={aui} config={config}>
      <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">
                  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. AuiProvider with a Suggestions config adds pre-built prompt suggestions to the assistant UI

Source

View full source on GitHub