Skip to content

About

Add an AI agent to a Flutter app with the CopilotKit Flutter SDK

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

17 Commits

Folders and files

Repository files navigation

Calaverita Generator

Add an AI agent to a Flutter app, one small step at a time.

The app writes a funny, rhyming "literary skull" (a calaverita) about a friend or coworker from a name, a job and a tone, and draws a sugar-skull portrait to go with it. You start with a plain Flutter app and end with an agent that fills the form, dresses the skull and shows the finished calaverita in the chat, using the CopilotKit Flutter SDK.

Built with Flutter on the web, Very Good Engineering and Feature-First Clean Architecture.

The steps

Each folder is a complete, runnable snapshot. Every step starts from the one before it, so compare two folders to see exactly what changed.

Folder What the app does What you learn
00-foundations The app with local state and no agent. You fill the form, dress the skull and press a button. The architecture: a domain, a data and a presentation package per feature.
01-shared-state A copilot panel appears. You tell it about your friend and it fills the form and dresses the skull. Shared state: AgentStateBuilder, patchSharedState and setSharedState.
02-generative-ui You ask for the calaverita and the agent writes it: a card with the skull appears in the chat and the verse shows under the skull on the stage. Generative UI: a frontend tool registered with CopilotTool whose builder renders a widget.
03-custom-server The same app, talking to a small server of its own instead of the built-in agent. Optional. Server logic: validating what the agent changes and shaping its prompt.

Quick start

Install FVM and Node.js 20 or later, then run one command:

node tool/setup.mjs

It installs Flutter 3.47.0 through FVM, checks your machine, asks which step to run and which backend to use, and starts the app in Chrome. The backend is one of:

  • The shared backend: nothing to set up.
  • Your own runtime: it asks for your Anthropic API key (hidden as you type) and starts the runtime in runtime/ for you.
  • A custom backend: any CopilotKit runtime you have a URL for, for example one made with CopilotKit's own tool (npx copilotkit with-claude).

node tool/setup.mjs --help lists the options, such as --step 02 --backend local to skip the questions. The rest of this page does the same thing by hand.

Set up

You need:

  • FVM. The repository pins Flutter 3.47.0 in .fvmrc, and the SDK needs Dart 3.13 or later.
  • Node.js 20 or later, for the runtime.
  • An Anthropic API key.
  • Chrome.
fvm install

Then check that everything is in place. It runs the same on Windows, macOS and Linux, and it never prints your key:

node tool/doctor.mjs

Note

Windows: turn on Developer Mode (Settings → System → For developers) before fvm install, because FVM uses symlinks. The commands below work in PowerShell and in a macOS or Linux terminal. Where they differ, both are shown.

Note

The CopilotKit Flutter SDK is not on pub.dev yet, so each snapshot gets it from GitHub, pinned to one commit (see dependency_overrides in the pubspec.yaml at the root of each snapshot). Your first pub get needs to reach VGVentures/copilotkit_flutter_sdk.

Run a step

The app talks to a Copilot Runtime, a small server that sits between the app and the model. Steps 01 and 02 use the one in runtime/; step 03 has its own.

1. Start the runtime (steps 01 and 02) in a first terminal:

cd runtime
npm install

Create your runtime/.env from the example, then open it and set ANTHROPIC_API_KEY=<your key>:

cp .env.example .env             # macOS and Linux
Copy-Item .env.example .env      # Windows PowerShell
npm start

It prints http://localhost:8200/api/copilotkit. Check it from another terminal with node tool/doctor.mjs.

Important

The key lives only in runtime/.env (git-ignored) or in your shell. Never commit it.

To use another model, set COPILOTKIT_MODEL in runtime/.env. The default is anthropic:claude-sonnet-5-5.

2. Run the app in a second terminal. 00-foundations needs no runtime.

cd 01-shared-state            # or 00-foundations, 02-generative-ui
fvm flutter pub get
cd apps/calaverita_app
fvm flutter run -d chrome

What to try

Each step adds one thing the one before it couldn't do. The Write my calaverita button always uses the offline template, so it works in every step. In steps 02 and 03 the agent can write a verse too.

00 · Foundations (no agent)

  1. Type a name and a job. The button stays disabled until both are filled.
  2. Pick a tone, then put a hat or glasses on the skull and change its color.
  3. Press Write my calaverita.

You should see: the skull change as you click, and a four-line verse under it. There is no chat and no agent yet.

01 · Shared state (the agent fills the form)

Type in the Copilot panel: "Mario is a chef, dramatic please". You can also click a suggestion.

You should see: the name, the job and the tone fill in, the skull gets dressed, and the Shared state box shows the same values. The agent replies in a sentence and tells you to press Write my calaverita.

Then edit a field by hand and ask "who is this for?". The agent answers with your edit, because it reads the same shared state.

Not yet: the agent can't write the verse. Press Write my calaverita to get the template one.

02 · Generative UI (the agent writes the calaverita)

Type: "Mario is a chef, dramatic please. Write his calaverita!"

You should see: the form fill in and the skull get dressed, then a card with the skull portrait and a four-line verse appear in the chat. The same verse shows under the skull on the stage.

If the name or the job is missing, the agent asks for it instead.

03 · Custom server (optional)

Start the server in a first terminal. It uses port 4100, so the runtime of steps 01 and 02 can keep running:

cd 03-custom-server/server
cp .env.example .env          # set ANTHROPIC_API_KEY
npm install
npm start                     # http://localhost:4100/api/copilotkit

Then run the app from 03-custom-server as above and try the same messages as in step 02.

What's different: this server checks every change the agent makes to the form and tells the model what it rejected, so it can fix it and try again. It also puts the current form in the prompt on every run. npm run smoke runs its checks offline, with no key.

Point the app at another backend

The runtime URL is set in one place per snapshot: apps/calaverita_app/lib/app/app_config.dart. To use a hosted backend, change AppConfig.defaultRuntimeUrl, or run with --dart-define=RUNTIME_URL=<url>.

How the code is organized

Each step is a Dart workspace of small packages:

apps/calaverita_app/               composes the features into an app
features/calaverita/
  calaverita_domain/               models and the repository interface
  calaverita_data/                 the offline template that writes the verse
  calaverita_presentation/         the screen, the cubit and the skull portrait
features/assistant/
  assistant_presentation/          the chat (from step 01)
shared/app_ui/                     the design system

A presentation package never imports a data package, and a feature never reaches into another feature's internals. Run fvm flutter analyze and fvm flutter test inside a snapshot, and fvm dart test in the domain and data packages.

Keep building

  • Give the skull more parts: a beard, a different pattern, a bandana. Add the SVG and the variant in SkullPart, and teach the agent in the prompt.
  • Let the agent ask before it guesses, with a human-in-the-loop tool (CopilotHumanInTheLoop): "make it fancier" could offer three options.
  • Replace the template repository with a call to the agent, so the Write my calaverita button uses the model too.
  • Save the calaverita as an image, or share it.
  • Move the step 03 server somewhere public and point AppConfig at it.

Troubleshooting

  • "The copilot could not answer": the app can't reach the runtime. Check that it is running and that the URL in app_config.dart matches the one it printed.
  • The runtime starts but every message fails: the model or the key is wrong. Send a run straight to the runtime and read the RUN_ERROR event (see the SDK example README).
  • pub get can't fetch the SDK: you need access to the SDK repository.

License

MIT. The skull art and the design system come from calaverita_builder, the fonts in shared/app_ui keep their own licenses, and the CopilotKit and Very Good Ventures names and logos belong to their owners.


Leading a team that wants to ship AI features in Flutter? Talk to Very Good Ventures.

About

Add an AI agent to a Flutter app with the CopilotKit Flutter SDK

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages