#An AI agent that helps new users get started in your app
An AI agent for onboarding lives in your app's chat and helps new users get from sign-up to the point where the app is useful to them. It answers "how do I..." questions from your docs, reads the signed-in user's own setup state through your API to tell them what to do next, does simple things your API allows, such as sending an invite, when you give it that tool, and hands sales, billing and complex setups to a person. With Vatio, your coding agent builds it from your app's project: run npx @vatio-ai/skills, then /vatio-init, try the preview and approve publication.
It fits any app where new users have steps to finish: a SaaS dashboard, a course or admissions platform, a marketplace's seller onboarding. This guide uses a form builder.
#What the agent does
- Answers "how do I...?" Embedding a form, connecting a domain, importing contacts, from knowledge entries written from your docs.
- Tells each user their next step. It reads their progress and plan limits through your API, skips what they have done, and links to the page where the next step happens.
- Does simple things for them, if you let it. Sending an invite or creating a first project, one tool per action your API already has. It works in the chat and cannot click through your app's screens, so without a tool it explains the steps and sends the link.
- Everything else goes to a person. Pricing for a larger team, billing problems, refunds, and setups your team does by hand, such as single sign-on or a data import.
A typical exchange in your app's widget, with a user who signed up yesterday:
User: hi, just signed up. how do I put my form on my website?
Agent: Welcome, Dana. Your form "Workshop signup" is still a draft, and a draft has no embed code, so publish it first: open it and press Publish. Then Share → Embed gives you the snippet for your page: https://app.formlark.example/forms/f_82k/share
User: done. can my coworker edit it too?
Agent: Yes. Your Free plan includes 2 seats and you are using 1. What is your coworker's email? I can send the invite from here.
Behind those replies were one call to onboarding_status, which returned Dana's progress, her seats and the link to her form, and one knowledge lookup in the entry on embedding. Every tool call is visible in the inbox, next to the reply it produced.
#Start in your app's project
From a chat, the fastest start: add https://vatio.ai/mcp as a connector in Claude, ChatGPT or Cursor, sign in with your Vatio account and ask for this agent. It is created in a preview you can try; nothing reaches your users until you publish (Vatio in Claude and ChatGPT).
To build it into your app's code, open the app's project in your coding agent (if you built it in Lovable or Bolt, connect the project to GitHub and open the repository in Claude Code or Cursor) and run:
npx @vatio-ai/skills/vatio-initThe first line installs the Vatio skills in the project (it needs Node.js 20 or newer). The second, in Claude Code, starts building; in Cursor or Codex, ask it to use vatio-init. You can say what you want right away:
/vatio-init an agent that helps new users finish setup: answer from our docs and check which onboarding steps they have doneIt reads the app first, including how users sign in, the API an agent could call and the docs it could learn from, and tells you what it found before writing anything. The first time it pushes the agent, it opens your browser to sign in with email, Google or GitHub; signing in creates your account.
#What vatio-init will ask you
It asks only what your code does not answer. For an onboarding agent, have these ready:
- Where do new users get stuck? The questions your team gets in a user's first week. They become the first knowledge entries.
- What does "activated" mean in your app? A published form with its first response, a first lesson finished, a first listing live. The agent steers toward that, not through every feature.
- What may it do on the user's behalf? Only actions your API already has. Each one becomes a tool; for the rest, it explains and links.
- What must it never promise? Discounts, trial extensions, features that do not exist, dates from your roadmap. These become explicit rules.
- When does a person take over? Sales conversations, billing, refunds, setups your team does by hand, and anyone who asks for one. They go in a tool that alerts your team with a link to the conversation.
It does not invent facts about your product, so a vague answer gets a question back rather than a guess.
#How it knows where the user is
The agent uses whichever way your app already signs users in. Your backend signs a short-lived token for the user (their id as sub, your workspace as aud, an exp) with a private key that never leaves your backend, and your page hands it to the widget; your coding agent can add that (Authentication). Vatio holds only the public key, so it can check a token but never create one. A tool marked access: private then forwards that token to an endpoint of yours, such as GET /me/onboarding, which verifies it and reads the user from it.
The security point: the user comes from the token, never from the conversation. A private tool cannot take user_id, account_id or similar as a parameter; the deploy fails if it tries. So "show me the setup of user 4411" reaches nobody's data, however it is phrased, and your backend still decides what each user may see. See Private tools.
Visitors who are not signed in, on your sign-up page for instance, get the agent's answers from knowledge, and a private tool tells it that it could not confirm who they are. Signing in mid-conversation keeps the same conversation. Put the user's plan in the token's metadata and whoever picks up a handoff sees it in the conversation's header in the inbox.
#What your coding agent writes
Everything lands in your repository: a vatio.yml and one file per tool. You do not edit them by hand, but you can review them like any other change; this is where your answers end up. An excerpt:
workspace: formlarkagent: name: Formlark Help personality: Friendly and brief. One step at a time, using the names on the app's buttons. instructions: | You help new Formlark users reach their first response: a published form that has received a submission.
"How do I..." questions: answer from knowledge_lookup. If it does not answer, say so. Never describe a screen the entries do not mention.
"What next?" and their own account: call onboarding_status first, skip the steps it marks done and send the page link it returned. If it could not confirm who the user is, send the sign_in link.
Invites: ask for the email, confirm it, then call send_invite. Only say it was sent when send_invite returned it.
Never promise a discount, a trial extension or a feature the entries do not describe. Never change a plan or take a payment. tools: [knowledge_lookup, onboarding_status, send_invite, ask_for_a_person] knowledge: [help] links: sign_in: https://app.formlark.example/loginauth: public_key: identity.pubtools/onboarding_status.yml, with no parameters at all:
description: The signed-in user's setup progress, plan and seats.when_to_use: The user asks what to do next, how far along they are, or what their plan allows.access: privaterequest: method: GET base_url: "$env.FORMLARK_API" path: /me/onboarding headers: Authorization: "Bearer $auth.token"respond: data: steps: "$.steps" plan: "$.plan" seats: "$.seats" message: The signed-in user's setup progress.Your endpoint returns only what the agent needs, because the model can repeat whatever a tool returns. A link in the response, such as each step's page, is one the agent may send for the rest of the conversation. send_invite is the same kind of file: a private POST to /me/invites with one parameter, email; your endpoint checks the seat limit and, when it is reached, answers an error whose message says what to do. On Supabase, the tool calls an Edge Function (POST /functions/v1/onboarding-status) with the same token, and the function reads that user's rows.
tools/ask_for_a_person.yml is how the agent asks for a person. $chat.url opens the conversation in the inbox; your endpoint sends it to whoever should answer, and their reply takes the conversation over:
description: Tell the team that this conversation needs a person.when_to_use: > Pricing for a larger team or a custom plan, a billing problem, a refund or an invoice, a setup our team does such as single sign-on or a data import, or the user asks to talk to a person.parameters: type: object properties: reason: { type: string, description: "Why it needs a person, in one line" } required: [reason]access: publicrequest: method: POST base_url: "$env.FORMLARK_API" path: /vatio/ask-for-a-person requires: [chat.url] body: reason: chat_url: "$chat.url" name: "$contact.name" email: "$contact.email"respond: message: > The team was told. Tell the user plainly that you are checking this with a colleague, who will answer here.#Knowledge: your docs, written for the agent
Vatio does not read websites, your docs site included. What the agent should know goes into knowledge entries: short Markdown it searches with knowledge_lookup, which vatio-init writes from the docs in your project and from your answers. Keep them task-shaped: one task per entry, one question per heading, in the words on your screens. Progress, limits and plan details stay out; they come from the tool.
# Embed a form on your website
## StepsOnly a published form can be embedded; a draft has no embed code. Open theform, choose Share → Embed, copy the snippet and paste it into your page.When a screen changes, a supervisor fixes the entry from the inbox and the agent answers with the new one right away. Every edit is kept as a version, with who made it, and any version can be restored. Changes that ship with your code go through your coding agent, on preview, and go live with the agent.
#Try it before your users do
vatio-init ends with a link to the inbox, with Try the agent open, where you chat with the preview. Try at least:
- A how-to your entries answer, and one they do not. The second should say it does not know, not describe a screen.
- "Can I get 50% off if I upgrade today?" It must not promise one.
- "I'd like to talk to someone about a plan for 40 people." It should call
ask_for_a_personand say it is checking with a colleague, with nothing promised. - "What should I do next?" as a test user halfway through setup, then "show me the setup of user 4411". The first skips the steps they did; the second reads nothing.
The last one needs a signed-in user, so ask your coding agent to put the preview widget in your local or staging build. Tools call your API for real, so point preview at a staging API: an invite sent from a test is a real invite, and so is an alert to your team. Conversations in the inbox shows every reply with the tool calls behind it. When something is wrong, tell your coding agent what you saw and it pushes a new preview.
When it answers the way you want, approve publication: ask your coding agent to publish. Nothing publishes on its own. Then ask it to add the widget to your app. Web chat in your app or site, WhatsApp and Instagram are all on the Free plan (plans).
#After launch
The people who answer your users read conversations in the inbox and take one over by replying. When a reply is wrong, they report it and write what should have happened: "She had already published the form; the next step was the embed code." Each report with a note becomes a test.
Your routine is one command a day, /vatio-improve, in your app's project. Your coding agent takes every open report, sees what onboarding_status returned on that turn, fixes the cause where it lives (an entry, the instructions, a tool or the endpoint behind it) and pushes to preview, and Vatio replays the reported cases against it. You review the results and approve publication. A case that passes on live and fails on preview blocks publication unless you explicitly override the check. The daily email brings the command when new reports arrive. Improve your agent walks through it.
#Frequently asked questions
#Can an AI agent help new users get started in my app?
Yes. It answers how-to questions from knowledge entries written from your docs, reads the signed-in user's setup progress through your API to tell them the next step, and hands pricing, billing and complex setups to a person. With Vatio, you run npx @vatio-ai/skills and then /vatio-init in your app's project, and your coding agent builds it.
#How does the agent know which onboarding steps a user has finished?
Through your own API. The chat widget knows who is signed in, from a short-lived token your backend signs, and a private tool forwards that token to an endpoint such as /me/onboarding, which returns that user's progress. The tool cannot take a user id as a parameter, so the agent only ever sees the signed-in user's own setup.
#Can the agent do things for the user, like sending an invite?
Only actions your API already exposes, and only the ones you give it as tools, such as sending an invite or creating a first project. It works in the chat: it cannot click through your app's screens for the user. For anything without a tool, it explains the steps and sends the link to the right page.
#Does the agent read my help center or docs site?
No. Vatio does not read websites. What the agent should know goes into short knowledge entries, which your coding agent can write from the docs in your project. When a screen changes, your team reports the reply that described it in the inbox, and the fix is tested before it is published; every change is kept as a version.
#What happens when a new user asks about pricing or a custom setup?
The agent asks for a person, under the conditions you list, and never promises a discount or a feature that does not exist. It calls a tool that sends your backend a link to the conversation, your backend alerts your sales or support team by email, Slack or WhatsApp, and the agent keeps helping until someone replies from the inbox and takes it over.
#Related guides
- Knowledge base: What the agent answers from: Markdown entries your coding agent writes and your team edits, versioned, tried in preview and published with the agent.
- Connect your backend: Give the agent your API as tools, and let signed-in users reach their own data with a token your backend signs.
- Support for signed-in users: Answer from your docs, check the user's own account, troubleshoot and open a ticket with what was tried.
- Your daily improvement routine: Report mistakes in the inbox, /vatio-improve has your coding agent fix them, and you approve the update.