Skip to main content

Prepatu

Define voice agents in YAML. The state machine runs the show. The LLM does the talking.


The Problem

Every team building voice agents hits the same wall. You want the AI to follow a script — collect a name, confirm it, pick a date, review, done. But LLMs are probabilistic. They skip steps. They invent transitions. They hallucinate a confirmation the user never gave. They forget where they are in the flow.

Prompt engineering helps, but it doesn't guarantee anything. And when your voice agent is booking real appointments, running real interviews, or handling real onboarding — "usually works" isn't good enough.

How Prepatu Solves This

Prepatu separates what LLMs are good at (understanding language) from what they're bad at (following a script). It introduces two core ideas:

1. The LLM is a Guest, Not the Host

The conversation flow is defined as a YAML state machine. The engine — not the LLM — controls which state you're in, what transitions are possible, and what the user sees on screen.

The LLM operates inside each state. It can talk naturally, understand what the user says, and call tools to capture data. But it cannot:

  • Jump to a state not in the current state's transitions
  • Call tools not listed in the current state's agent.tools
  • Skip or reorder steps

2. Every Transition Has a Deterministic Fallback

What if the LLM never calls the expected tool? What if it hallucinates? Every LLM-driven transition has a backup path that doesn't require LLM cooperation:

  • on_ui_event — user taps a button or submits a form
  • on_utterance — regex matches the user's speech directly
  • on_timeout — automatic advance after N seconds of silence

The flow completes no matter what the model does.


What You Build With It

A Prepatu app is a YAML flow file + a frontend that renders artifacts.

Here's a real flow — a voice-powered appointment booking wizard:

id: appointment-booking
version: "1.0.0"
initial_state: collect_contact

settings:
base_system_prompt: |
You are a warm, friendly booking assistant called Aria.
Be concise. Never make up information the user hasn't provided.

states:
collect_contact:
ui:
artifact_type: form
prompt: "Let's start with your contact details."
fields:
- id: full_name
label: Full Name
type: text
- id: email
label: Email
type: email

agent:
prompt: |
Ask for the user's name and email.
Call `save_contact` when you have both.
tools: [save_contact]

tools:
save_contact:
description: "Save name and email, move to appointment details."
parameters:
full_name: { type: string, required: true }
email: { type: string, required: true }

transitions:
on_tool_call:
save_contact: collect_appointment # Engine advances here
on_ui_event:
form_submit: collect_appointment # User can also type + submit

collect_appointment:
# ... next step

When the user says "I'm Alice, [email protected]", the LLM calls save_contact. The engine stores the variables, pushes a field_update artifact to the frontend (so the form fields fill in visually), and transitions to collect_appointment. If the user types into the form and hits submit instead, on_ui_event fires the same transition — no LLM involvement at all.


Key Concepts

ConceptWhat it means
FlowA YAML file defining a complete conversation as a state machine
StateOne step in the flow — has a UI artifact, an LLM prompt, allowed tools, and transitions
TransitionAn edge between states — triggered by a tool call, UI event, utterance match, or timeout
ArtifactA UI instruction pushed to the client: forms, cards, option pickers, navigation
VariableData collected during the flow (e.g. first_name), interpolated into prompts via {first_name}
Confirmation GateA pattern where the engine blocks transitions until the user explicitly confirms captured data

Three Ways to Use Prepatu

PathBest forGet started
☁️ Cloud ServiceShip fast — no backend to deployCloud Quickstart →
📦 pip install vfdlUse the engine in your own Python backendSelf-Hosted Quickstart →
🍴 Fork the monorepoFull starter kit with reference appsGitHub →

What's in the Box

PackageWhat it is
vfdlPython flow engine — pip-installable, runs on Pipecat + FastAPI
Voice SDKTypeScript browser SDK — WebSocket + WebRTC transports
Cloud ServiceManaged backend — upload flows, get a WebSocket URL, pay per minute

Example Apps

AppWhat it shows
10 QuestionsVoice game — all card-based UI, no forms
Booking WizardMulti-step form with voice-to-form autofill
IELTS CoachComplex multi-flow app with scoring callbacks

Next Steps