On this page

#Changelog

What changed in Vatio, newest first. One entry per released version.

One changelog for the CLI and the platform, keyed by the version vatio version prints. They are released together, and the CLI never carries a copy of the platform's rules, so a release note describes both at once.

This page is also served as plain markdown at /docs/changelog.md, for reading it somewhere other than a browser.

This changelog starts at 0.27.0. Earlier versions shipped without one rather than being reconstructed after the fact.

#0.79.0 — 2026-10-11

The console is part of the inbox now. Its pages moved to inbox.vatio.ai, one app with sections by role: Start, Test, Channels, Tools, Outreach, Team, Security and Account. The links the CLI prints (Try it: after vatio push, vatio env, vatio tools, vatio whatsapp, vatio instagram) open there, and vatio login lands there after you sign in at vatio.ai. Older CLIs keep working: the platform sends the new links and old console URLs redirect. JSON field names, console_url included, did not change.

The CLI names the inbox's sections. vatio whatsapp and vatio instagram point to the Test page before you publish and to Channels after. vatio init --name before signing in says to set the name with vatio business set --name or on the Business page.

Skills 1.11.0. vatio-init hands over the inbox's Test page, and a teammate who is not in the workspace yet is invited from Team in the inbox.

#0.78.0 — 2026-10-11

A routine is a tool the agent decides to use. Give the agent a routine with tools/NAME.yml and routine: NAME, and add it to agent.tools. The agent calls it once the request is complete, asking first when it is not, and tells the person whether Claude has it in the same turn. A message from a routine's number no longer starts the routine by itself, and --quiet is gone with it. The tool exists only in WhatsApp conversations with the routine's numbers, so nobody else can talk the agent into it, and evals never start a real session. vatio routines create prints the tool file to add. See Routine tools.

#0.77.0 — 2026-10-11

The agent can answer only some numbers on your WhatsApp number. vatio whatsapp only +56912345678, or The agent answers next to the Live switch in the console, makes the agent answer only those numbers; everyone else's messages still reach the inbox, for you to answer. The numbers of your routines always count. vatio whatsapp everyone goes back to answering everyone, the default, and vatio whatsapp shows which it is. Set the list before switching Live on, and the agent never answers anyone else. See Who the agent answers.

A routine's token is checked when you save it. Anything that is not a sk-ant-oat01-… token is refused right away, instead of failing with a 401 on the first message. Pasting the wrong thing from the clipboard is the usual cause.

#0.76.0 — 2026-10-11

A WhatsApp message can start a Claude Code routine. vatio routines create connects a routine's API trigger to the numbers that start it: when one of them writes to your number, Vatio waits for them to finish and starts the routine with where the conversation is, never what it says. The agent waits while they write and answers once, saying whether Claude has it or the routine could not be started. vatio routines runs shows each run with the link to its Claude session. Only WhatsApp starts one, because only there does Meta vouch for the number. See Claude Code routines.

A server key reads a conversation: GET /api/server/v1/:slug/chats/:id/messages, newest last, with what was forwarded, voice notes as text and signed URLs for files. It is how a routine catches up, and every read is in the workspace's Activity.

#0.75.0 — 2026-10-10

vatio share-session leaves out the people a session is about. Email addresses and phone numbers written with a country code become [EMAIL] and [PHONE], next to the keys and tokens that were already [REDACTED], and the summary says how many. The customers that come up in a database query are the team's least useful part of a session, and what made Claude Code's auto mode refuse to send one. Names, and numbers without a +, still go: --save shows exactly what would.

A shared session is deleted 30 days after it arrives. vatio share-session says so before it asks, and prints the date once it is sent; the row saying who sent one, when, and the feedback with it stays. Only the Vatio team reads a session, and every read is logged. The privacy policy lists it.

vatio share-session --list marks the sessions already sent, with their number and when. When a permission check stops the coding agent and you send the session from your own terminal, the agent checks there that it went.

Outside a workspace, the error says where one is. A command run one directory above a vatio.yml (vatio chat show, push, kb …) now names the nearby workspace and the cd to it, instead of asking for an API url.

Skills 1.9.0. When a permission check refuses to send the session, vatio-share-session gives you the command to run yourself instead of retrying, and checks with --list that it arrived. Before asking, it tells you how the session is treated: who reads it, that reads are logged, and when it is deleted.

#0.73.0 — 2026-10-10

vatio flags and vatio eval say when the Vatio skills are out of date. They compare the Claude Code plugin's version, or the copy npx @vatio-ai/skills made in the project, with the latest published skills (asked of npm at most once a day) and say how to update: claude plugin update vatio@vatio, or running npx @vatio-ai/skills again. Claude Code does not auto-update plugins from other people's marketplaces unless you turn it on; see Keeping them up to date.

Skills 1.7.0. vatio-share-session offers to send the session with Claude Code's own question (send it, send it with a comment, not now, don't ask again) instead of a message, and npx @vatio-ai/skills leaves the version it installed next to each copy.

#0.72.0 — 2026-10-10

vatio flags and vatio eval say when the Vatio skills are missing. Without the Claude Code plugin or the skills npx @vatio-ai/skills copies into a project, Claude Code has no /vatio:vatio-improve, so both commands end with one line on stderr saying how to install them. At most once a day per directory, never in CI; VATIO_NO_SKILLS_HINT=1 turns it off. See Improve.

The inbox's Continuous improvement page is simpler. One box says what is next (reports open, with the command for the developer; fixes waiting to be published; a fix that broke something; or all resolved), reports are Pending, Resolved or All with one latest result each, and a report can be removed from its row.

#0.71.0 — 2026-10-10

One loop: your coding agent fixes, Vatio verifies. A supervisor reports a reply in the inbox and writes what it should have said. One session of your coding agent takes every open report: vatio flags, fix, vatio push (updates preview, runs no tests), vatio eval (tests every report on preview), then vatio publish. In Claude Code, /vatio:vatio-improve (skills 1.6.0) runs it, with vatio eval in the background. See Improve your agent from flags.

vatio publish checks preview first. Once the agent is published, publish is refused until vatio eval has tested preview's current version (evals_missing), while its tests are still running (evals_running), and when a report that passes on live fails on preview (evals_regressed, listed by id and title). Reports that still fail on both do not block, so a partial fix can ship. When it goes through, the reports preview passed are resolved with the version that fixed them, without testing again. vatio publish --force publishes over a regression anyway, failing results included. The console's Publish button goes through the same check and publishes directly. See The publish gate.

vatio push does not overwrite an unpublished push from another branch. Once the agent is published, a push is refused when preview holds a version that is not live, pushed from another git branch (preview_has_unpublished_push). Publish it first, or vatio push --force to replace it.

Only preview and live. There is no environment per git branch and there are no named environments: --env takes preview or live (staging and sandbox still mean preview), and any other name is an error. Commands no longer pick an environment from the git branch, and vatio env rm is gone.

Proposals are gone. vatio propose, the inbox's proposals and an owner accepting a change were removed; vatio propose now says so, and the proposals endpoints answer 410 proposals_removed. Test with vatio eval and publish with vatio publish.

The GitHub App integration is gone: pull request previews, publishing by merging, comments and checks on pull requests, the vatio-flags issue and connecting a repository. Signing in with GitHub stays.

"Ask for an improvement" and the Learning view are gone. A report's state now shows on the reported reply in the conversation: open, fixed in preview, or resolved with the version that fixed it. The inbox's Continuous improvement page lists every report with its latest tests and what vatio publish would say, with the prompt /vatio:vatio-improve; the daily email to the workspace's developers links there.

Every report with a note is a test, wherever it was made, live or preview. A report made on preview after the first publish used to be a note with no test.

Evals run five cases at a time. A run of 27 cases takes 3 to 4 minutes instead of about 15.

#0.70.0 — 2026-10-10

vatio logout revokes the token. It used to delete the token from this machine and nothing else, so a copy of the config file kept working. Now the token is revoked on Vatio first; offline, the local copy is still removed.

CLI tokens expire after 90 days without use. Each command slides the expiry forward, so a machine in regular use never notices. One left alone needs vatio login again. Every token alive today starts with the full 90 days.

Two-step verification. Passkeys, an authenticator app and recovery codes, in Settings → Security, which also lists every console browser, inbox device and CLI token signed in to your account and closes any of them. A workspace marked as holding sensitive data requires it from its whole team; for those workspaces the API answers two_factor_required until the account has it. See Two-step verification and sessions.

#0.69.0 — 2026-10-09

base_url keeps its path. A tool's path is appended to the base URL's own path: https://<ref>.supabase.co/functions/v1 plus /my-tools/check_stock calls .../functions/v1/my-tools/check_stock. Until now the base URL's path was dropped without a word and the call went to /my-tools/check_stock on the host. A path that already repeats the base URL's path, the way around it, is not prefixed twice. See Declarative HTTP tools.

A reply makes at most 12 tool calls. After the twelfth, or after the same tool fails three times with the same message, the agent is told to answer with what it has and say what it could not do; a call after that is refused, so a tool that keeps failing no longer leaves the person without an answer. vatio chat show marks it with a [tool limit] line. See Tool results.

A failing tool's own words reach the agent. On a non-2xx, a body with no message but a string error ({ "error": "...", "hint": "..." }) uses it as the message, instead of a bare "HTTP 422".

A typed phone number is not asked for. Off WhatsApp, a tool that requires contact.phone_number used to tell the agent to ask for it, but a number typed in the chat never fills $contact.phone_number: only WhatsApp or the visitor's sign-in do. The agent is now told not to ask and to say it cannot be done from that chat. See Required values.

vatio secrets list shows every environment. Each secret on its own line with its scope (every environment, only preview, tests), so a value set from a branch or with --env is never missing from the list; --env NAME still shows only what that environment reads. set and rm say which scope they touched. A key starting with VATIO_ is refused with a message that says so, instead of "Translation missing".

#0.68.0 — 2026-10-09

Start by installing the skills. The prompt on vatio.ai now has the coding agent run npx @vatio-ai/skills in the project first and follow the vatio-init skill it installs, and installing them is step one of Starting a new agent and of the quickstart. The skills stay in the repository, so the next session — or a different coding agent — finds how to start and improve the agent without being told again.

vatio-new is now vatio-init, and it looks first. Before creating anything it searches the whole repository for a vatio.yml, reads the app (its API, how its users sign in, its docs) and says what it found and what it recommends. With no agent it builds one, asking the owner only what the code does not answer. With one, it follows Joining an existing workspace: it never runs vatio init there, compares the folder with live, explains the agent and points at open flags and failing tools. npx @vatio-ai/skills removes the old vatio-new copy when it installs vatio-init.

vatio share-session: send the Vatio team your Claude Code session. When a sentence in vatio feedback is not enough, vatio share-session sends the session the coding agent is in (or the most recent one for this directory): what you asked, what it ran and what it was shown. Feedback in your words is optional: vatio share-session "what got in the way". Images and Claude Code's own bookkeeping are left out, anything that looks like a key, token, password or private key becomes [REDACTED], and it shows which session goes and asks before sending; a coding agent sends only with --yes, after asking you. --save FILE writes exactly what would be sent instead, --list and --id pick another session. It needs you signed in, and only the Vatio team reads it. See Share a session.

A third skill, vatio-share-session. Say "send this session to Vatio" or run /vatio-share-session: Claude Code shows you what would go, asks, suggests adding feedback in your words, and runs vatio share-session. npx @vatio-ai/skills (1.5.0) installs it with the other two. When vatio-init or vatio-improve finish, Claude Code offers to send the session, with three answers: send it, not now, or don't ask again. vatio share-session --should-ask decides whether to offer — at most once a week, never twice in a session — and vatio share-session --never stops it. See Claude Code.

#0.67.0 — 2026-10-09

Tool metrics for your coding agent. vatio tools prints the console's Tools page as a document a coding agent works from: each tool's calls, error rate, timeouts and p50/p95 latency, then the calls that failed with what your backend answered and the vatio chat show that opens the conversation. --json gives the same as data. It reads the branch's environment on a branch and live elsewhere (--env), over the last 7 days (--period). A failing tool seldom gets flagged, because the agent apologizes and moves on: this is where your agent finds it. See Tool metrics.

The last hour. The Tools page and vatio tools read the last hour as well as the last day, 7 and 30 days: enough to see whether a fix you just published stopped the errors.

Each tool call in vatio flags says how it went: the HTTP status, outcome and duration of the call to your backend, next to its arguments and response. The vatio-improve skill (1.4.0) and the AGENTS.md section vatio init writes point at vatio tools too.

#0.66.0 — 2026-10-09

Publish through your tests. The console's Publish buttons (the Test page and Environments) no longer publish at once: they propose the environment and take you to it in the inbox, where every eval case is replayed on it and the owner or a developer publishes it. preview can be proposed now, and deciding never removes it. Accepting an improvement publishes the version that was tested and takes its results live with it, instead of replaying every case on live again. vatio publish and a merge to the default branch still publish directly. See Eval runs.

A failing case is retried. The same case can fail once and pass the next time on the same version, so a case the judge fails is replayed again in a fresh chat, up to 3 attempts; only one failing all three counts as failing. One that passed on a later attempt says how many it took, in the report (F-7K2QX (2 attempts)), on the improvement and in Learning: it is unstable.

Test values for secrets. vatio secrets set KEY VALUE --tests sets the value every environment but live uses, and every eval replay, live's included: one staging URL for everything that is not a visitor on live. list marks it (tests). A replay's tool calls carry an X-Vatio-Test: 1 header, and a write (any method but GET) whose URL has no test value is not sent: the agent gets a success, and the judge still checks the call and its arguments. See Secrets.

Tests come from live. A report made on live is a test, and so is one made before the agent's first publish. After that, a report from a preview or a branch is a note for whoever fixes the agent: it is in vatio flags, with Eval case: no, but nothing replays it.

Learning, simpler. The inbox lists each report as solved or not, under one card with what to do next. Asking for an improvement, and accepting one, happen on live only. Nobody overrules the judge any more: a supervisor who disagrees rewrites the note, which starts the case over.

#0.65.0 — 2026-10-08

The docs live at vatio.ai/docs. Same pages, same Markdown contract, now under the main domain:

  • /docs/docs.md is the whole contract, and every page is also at its path plus .md, indexed in /docs/llms.txt.
  • Every docs.vatio.ai address answers with a 301 to the same path under vatio.ai/docs, so existing links keep working.
  • vatio docs fetches the same file as before, and any version of the CLI follows the redirect. This release only updates the URLs the CLI prints.

The widget is on npm, and open source. npm install @vatio-ai/widget mounts the same widget from your app's code with mountVatioWidget(), returning identify and unmount — see From your app's code. Its source is public under MIT at github.com/vatio-ai/widget. The script tag at cdn.vatio.ai/v1/widget.js is unchanged.

The skills are on npm. npx @vatio-ai/skills copies vatio-new and vatio-improve into a project's .agents/skills/ and .claude/skills/, so Codex, Cursor, Gemini CLI, GitHub Copilot and Claude Code pick them up without the plugin. See Claude Code.

The browser SDK is back on the CDN as a classic script, cdn.vatio.ai/v1/sdk.js, which leaves the SDK on window.Vatio for a page without a bundler (Without a bundler). The old vatio.ai/vatio-widget.js and vatio.ai/sdk/1.js redirect to the CDN again.

#0.64.0 — 2026-10-07

vatio propose: a fix the owner accepts from the inbox, without GitHub. On a workspace with no repository connected, push the fix to the branch's environment and run vatio propose --title "What it fixes" (plus --summary or --summary-file for why). Vatio replays every eval case there and mails the workspace's owner when the replays finish. In the inbox, under Learning → Improvements, the owner sees why, every case on live next to this version, what changes line by line against live, and a link to try it, then accepts (which publishes the environment, prompt, tools and knowledge together) or discards it. Accepting is refused while the replays run, when the environment was pushed again after proposing, and when a case that passes on live fails there. Either way the environment is removed and the proposal keeps its record. Proposing the same environment again updates it and replays the evals; vatio propose --list shows where each one stands. preview and main cannot be proposed: they are shared. See Without GitHub: propose it to the owner.

Ask for an improvement, from the inbox. On Learning, the owner and developers can have Vatio review the open flags. It reads each conversation, what every tool answered and how the agent is set up, and sorts the flags by cause. A fix in the agent's instructions or knowledge it writes itself and opens as a proposal, tests running. A missing tool or one that fails (an error, a 500) it never works around in the prompt: Vatio has no access to your backend's code, so it gives you a prompt for your coding agent instead. One review at a time, up to ten a day. See Ask for an improvement.

#0.63.0 — 2026-10-07

Create WhatsApp templates from the CLI, and test them before you have a number. vatio templates create submits a template for Meta's review on Vatio's test number, so your coding agent no longer stops at the console to write one:

vatio templates create order_shipped --language es \
  --body "Hola {{1}}, tu pedido {{2}} va en camino." --example Ana --example "#1042"

Once Meta approves it, a preview key sends it to your test phones when the 24-hour window is closed — before, a preview key could not send a template at all. When you connect your own number, Vatio moves your templates to it under the same names, so the template your backend sends does not change when it goes live, and removes them from its test number. From then on your backend sends from your number with a live key: a preview key is refused with 409 use_live_key, and templates create submits straight to your number.

The template is checked before Meta sees it — the name's format, {{1}}, {{2}}, … in order, one --example per placeholder, and no placeholder at the very start or end of the body. utility is the default category; pass --category marketing for promotions. vatio templates list --env preview shows the ones on Vatio's test number, and vatio templates list tells a workspace with no number of its own where its templates are.

#0.62.1 — 2026-10-05

vatio whatsapp and vatio instagram link to a page you can see. Before your first publish the console shows only the Test page, so they now print its WhatsApp or Instagram tab, where you verify a test phone or account and talk to your agent. After you publish they print that channel's page under Integrations, where you connect your own number or account. vatio status reports published, plus whatsapp_url and instagram_url next to integrations_url, which also points at the Test page until you publish.

#0.62.0 — 2026-10-04

Sign in with Supabase, with no code. If your users sign in with Supabase Auth, vatio auth --supabase names the project in vatio.yml (auth: supabase:) and stores its URL and anon key as secrets. Then:

  • Web: the widget reads the Supabase session already on the page and follows sign-in, sign-out and token refreshes. Nothing to add to the page.
  • WhatsApp and Instagram: the Sign in button opens your login page, and the widget on it hands the session to Vatio once the person is signed in.
  • Tools: forward $auth.token to the project's REST API and your Row Level Security decides what the visitor sees.

Or skip the command: Connect Supabase in the console (Channels) signs in to Supabase, picks the project, sets the secrets and shows the auth: line; vatio auth --supabase then uses that project, and vatio diff warns when vatio.yml names a different one.

Vatio verifies against the project's public keys, so the project has to use JWT signing keys (ES256 or RS256); a push with a project still on the legacy HS256 secret is refused with the fix. See Supabase.

#0.61.0 — 2026-10-04

Send WhatsApp messages from your backend. Your backend calls POST /api/server/v1/:slug/messages with a number and what to tell them, and the agent keeps answering when the person replies:

  • text goes out exactly as written, when the person wrote in the last 24 hours.
  • brief has the agent write the message itself.
  • template is the approved template to send when the window is closed, which is the only thing WhatsApp delivers then.

The request answers 202 at once and Vatio sends right after. The agent is shown the brief when the person answers. Around it:

  • Idempotency-Key, so a retry never messages anyone twice.
  • identity, a JWT your workspace signed, so private tools run when the person answers.
  • Signed webhooks: message.sent, failed, delivered, read, delivery_failed and replied, with a delivery log and a ping.
  • GET /messages and GET /templates, with each template's parameter count.

Server keys. The server API takes a server key (vsk_…), not your CLI token. A key belongs to the workspace and one environment, and survives vatio login.

New commands.

  • vatio keys list|create|revoke.
  • vatio templates list.
  • vatio webhooks list|create|test|deliveries|enable|rm.

#0.60.0 — 2026-10-03

Signing in works when a coding agent runs the CLI. vatio push (the first time) and vatio login open the browser on Vatio's sign-in page for that terminal and print the terminal's code; on a machine with no browser they print the link, and tell a coding agent to show it to its human. There you sign in with your email — Vatio mails a link that signs you in on any device, creating the account if there is none — or with Google or GitHub, check that the page shows the same code, and confirm the terminal. After vatio push, the page then waits for the push and turns into the console's Test screen. If the wait is cut off, running the same command again picks up the same sign-in page instead of starting over. The CLI no longer asks for an email. The device authorization start endpoint takes an optional workspace slug.

The hosted pages at vatio.ai/w/ are gone. Try an agent in the console's Test screen — web chat, WhatsApp and Instagram — at the link vatio push and vatio env print after Try it:. To put it in front of customers, embed the widget on your own site, connect WhatsApp or Instagram, or use the SDKs. vatio env no longer prints a page link, and page_url is gone from the environment API.

The Test screen handles several numbers and accounts. Its WhatsApp and Instagram tabs list and verify up to five test phones and five test accounts, instead of only the latest one.

#0.59.0 — 2026-10-03

vatio feedback. Tell the Vatio team what got in the way, in a sentence: vatio feedback "push said the tool was invalid but not which field". Coding agents are asked to run it when an error or the docs left them guessing; it arrives with the commands the session ran before it. See Feedback.

Errors say what to do next. API errors now carry a hint when there is a known next step, and the CLI prints it as Next: along with the error code and request_id. See Errors.

Telemetry. The CLI now reports how each command ended — its name, exit code and, on failure, the error it printed — with its version, the coding agent running it and a session id. Arguments, file contents and secrets are never sent. The first command on a machine says so once, and VATIO_TELEMETRY=0 turns it off. See Telemetry.

#0.58.1 — 2026-10-03

A flag's note is what should have happened. Supervisors write more than the sentence the agent should have said: an action, a tool it should have used, a handover. The inbox now asks for What should have happened, and vatio flags, the GitHub issue and the daily mail say the same.

The judge sees tool calls. Eval replays now show the judge every tool the agent called, so a note that asks for a tool passes when the agent calls it. An answer the judge could not read is an error, no longer a fail against the agent.

Analytics and Learning in the inbox. Analytics shows conversations per channel, handoffs, open flags and visitor ratings over 7, 30 or 90 days. Learning shows what became of every flag (pending, in testing, fixed, failing again) with every replay of its case, and lets a supervisor overrule the judge. A person's verdict wins, and on the newest live replay it decides whether the flag is fixed.

#0.58.0 — 2026-10-03

The brand belongs to the business too. The logo, the brand color and the widget's "about" are set on the inbox's Business page, next to the name and hours, and no longer on the console's Widget page, which keeps the rest of the widget's look. From a terminal: vatio business set --logo FILE | --remove-logo, --color #RRGGBB | --color default and --about TEXT. PATCH /business takes about, accent_color and logo (base64). See Business.

#0.57.0 — 2026-10-03

The business and its hours belong to whoever runs it. The business name, description and opening hours live on the workspace and are set on the new Business page of the inbox — a time zone and shifts per day, or someone always available. They apply to every environment as soon as they are saved. The agent now also gets the weekly hours, so it can tell a customer when you are open.

hours: is ignored in vatio.yml. A push that still has it succeeds and prints a warning with a link to the inbox page; existing hours were carried over to the workspace. handoff: stays in vatio.yml. The console's Widget page no longer edits the name and summary; it links to the inbox.

vatio business. Read and set the same business from a terminal: vatio business, vatio business set --name … --description …, and vatio business hours --timezone … --mon 09:00-18:00 … or --clear. See Business.

#0.56.0 — 2026-10-02

One agent per workspace. agents: and entry: are gone from vatio.yml; a workspace runs one agent:, and private tools behind auth: cover what a second, signed-in agent was for. A push that still has them fails and says what to change.

vatio issue is gone; report on GitHub. Bugs and feature requests now go to the public repositories: cli, sdk, ios and ruby. Running vatio issue says where to go, and so does an older CLI that still has the command.

A smaller CLI. It now keeps only the commands a developer runs to build and ship an agent:

  • vatio chat is two commands. vatio chat "message" [--new] talks to the agent, and --new starts over as a visitor it never met. vatio chat show [CHAT_ID] prints the chat you are in, or any chat, with every tool call. transcript, debug, reset and destroy are gone, and each one tells you what to use instead.
  • vatio tools check is gone. vatio push validates before it deploys, and vatio diff validates without deploying.
  • vatio widget is gone. vatio env prints the snippet and its token, and the look is edited on the console's Widget page.
  • vatio mcp is gone. Point your coding agent at vatio docs --save.
  • WhatsApp and Instagram are set up in the console, on the Channels page: your own number or account, test phones, and test accounts. vatio whatsapp and vatio instagram print that link. Older CLIs get the same answer.

Every API is named after who calls it.

  • The developer API (what the CLI uses) lives at /api/developer/v1.
    • Its routes read like the CLI: /:slug/deploy/* is now /:slug/check, /push, /publish, /rollback, /status, /manifest, /env and /secrets.
    • Signing in and creating a workspace move from /cli/* to /api/developer/v1/device_authorizations and /api/developer/v1/workspaces.
    • /deploy/revisions is gone.
  • The visitor API (the widget and both SDKs) lives at /api/visitor/v1. The JavaScript SDK 3.3.0 and the iOS SDK 0.3.0 call it there.

/api/v1, /cli/* and /api/public/v1 keep answering, for clients released before these.

Server-to-server is removed. None of it was in use:

  • The phone verification API, along with agent: false.
  • Conversations over the API with no visitor (the api channel).
  • The identity mint, and auth.mint in vatio.yml. WhatsApp and Instagram visitors are anonymous, and only public tools run for them. Signed-in visitors on the web work exactly as before. vatio-identity 0.3.0 signs and verifies the JWT, and no longer mounts a mint endpoint.

The widget is a bubble only. data-display="page" and data-mount are gone.

Agent modes are removed. modes, initial_mode and mode_reset_after in vatio.yml, and the switch_mode tool, no longer do anything. A push that still has them succeeds and warns that they are ignored; each agent works from its own tools and knowledge.

Knowledge is what you write. vatio kb follow, unfollow and refresh are gone, and Vatio no longer reads or re-reads websites. Pages it had already read stay as ordinary entries you can now edit (vatio kb cat / kb write).

Console notices show their message again. Inviting, resending or removing a team member, and registering, verifying or moving a test WhatsApp number, showed "Translation missing" instead of the confirmation or the error. They read correctly now.

#0.55.0 — 2026-10-01

Flagged replies become work your coding agent can do. vatio flags prints every reply a supervisor flagged in the inbox as one document for a coding agent: the conversation, each tool call of that turn with what your backend answered, and what the reply should have been. Each flag is now an eval case, and vatio eval replays every case against an environment — the branch's by default — with a judge comparing each reply to the supervisor's note; it exits 1 when a case fails. Evals also run on every pull request preview, commented on the pull request, and after every publish to live, which is what marks a flag fixed in the inbox. The judge is a model from a different family than the agent's, and replay chats stay out of the inbox and out of the conversation count. vatio init now adds a short Vatio section to the workspace's AGENTS.md, and the Claude Code plugin at github.com/vatio-ai/skills adds two skills: vatio-new to build an agent from scratch and vatio-improve to work through flags. The docs' For coding agents section now spells out how to start a new agent, so any coding agent reading vatio docs follows the same steps. Every morning, workspaces with new flags get a mail and, with GitHub connected, one issue labelled vatio-flags holding the digest, ready for a coding agent on GitHub to pick up. See Improve your agent from flags.

#0.54.1 — 2026-10-01

Source and issues are public. The CLI, the JavaScript SDK, the iOS SDK and the vatio-identity gem each have a public repository under github.com/vatio-ai, where you can read the code and open issues. Swift packages now install from https://github.com/vatio-ai/ios, and the gem installs with gem "vatio-identity", git: "https://github.com/vatio-ai/ruby". Nothing else changed.

#0.54.0 — 2026-10-01

Every git branch is an environment of its own. On a branch other than the default one, the CLI works in that branch's environment without --env — fix/pagos is fix-pagos — and says so on stderr: push, chat, kb write, secrets set, tokens and publish all use it. The branch's pull request deploys to the same environment instead of a separate pr-N, so what was tried there before the pull request existed is still there. On the default branch and outside a repository, every command keeps its old default. Several people or coding agents can now fix several conversations at once, each in a worktree, without their changes meeting before they merge.

Knowledge changes belong to an environment, and go live with it. The entries are what live answers from; a supervisor's edit in the inbox, the console and a site re-reading a page change live directly. On a branch, vatio kb write makes a change only that branch answers from, and publishing the branch — vatio publish, or merging its pull request — takes the prompt and the knowledge live together. When live changed an entry the branch also changed, publishing is refused and names it; rewriting the entry on top of live clears it. Each environment has a page in the console with the diff of every entry it changed, where a conflict is resolved in place — keep the branch's version, take live's, or combine them. Pull requests get a vatio/knowledge status that turns red before the merge and links to that page, and a comment listing their knowledge changes. Today's unpublished draft became the changes of preview.

A deployment is a snapshot of the whole agent. Once live, it records the version of every knowledge entry written by hand it answered from. Publishing, and a supervisor's edit in the inbox or console, leave a new snapshot; vatio rollback moves live back one, prompt and knowledge together. Pages a site reads are not part of it. Environments other than live are disposable, with everything in them.

vatio env. Shows the environment you are in: its publishable token, the widget snippet, the link to try it, its knowledge changes and any conflicts. vatio env list shows every environment and vatio env rm NAME removes one. An environment with nothing left to publish is removed after 14 days idle.

A secret can have its own value in one environment. On a branch, or with --env, vatio secrets set sets the value only that environment uses, so a branch's tools can call staging while live calls production.

A simpler console. Its menu is now Environments, Test and Channels. Environments lists live, preview and every branch, each with its deployment, agents, knowledge changes and conflicts, and secret names; GitHub is connected there too. Under Channels, the Widget page holds the install snippet, the brand settings and the tokens with their allowed origins, which used to be three pages. Knowledge is edited in the inbox (or the CLI); the console keeps each environment's knowledge review. The public page, /w/<slug>, is live's: the business with the widget's bubble, no longer a full-screen chat. Each other environment has the same page at /w/<slug>/<environment>, for the workspace's members; push, vatio env and pull request comments link to the console's Test screen for it, and the /w/<slug>/p/… share links are gone.

Every channel can point at a branch. Each test phone on the shared WhatsApp number and each test account on the shared Instagram one reaches the environment it points at — vatio whatsapp numbers point PHONE --env NAME, vatio instagram accounts point ID --env NAME, or a selector in the console — instead of always preview. With the CLI on the branch, the widget and SDKs on its token, and /w/<slug>/<environment> for the workspace's members, a branch is tried on every surface without touching live.

#Breaking

  • Preview share links (/w/<slug>/p/…) no longer open: try an environment in the console's Test screen, signed in. The API's share_url now points there.

  • vatio kb rollback and the knowledge publications behind it are gone. vatio rollback now takes the knowledge back with the prompt; to go back on one entry alone instead: vatio kb history BASE lists what reached live, vatio kb cat BASE ENTRY --version N prints one, and writing it again with --env live restores it. The API's snapshots paths answer 410.

  • vatio kb publish no longer takes -m, and publishes the current environment's changes to one base.

  • Pages a site reads go live as soon as they are read, instead of waiting for a publish.

#0.53.0 — 2026-09-30

The workspace's brand is edited in the console, not in vatio.yml. The business name and summary, and the widget's look (accent color, about, logo, locale, greeting, suggestions and the rest), live on the workspace's new Brand page. They are one setting for every environment and apply as soon as you save. business:, widget: and root allowed_origins: in an existing vatio.yml still push, but they are ignored: vatio push, vatio check and the GitHub pull request comment print a warning with the console link. Remove them when convenient.

Allowed origins belong to each publishable token. A token works only from the origins listed on it, plus Vatio's own pages. Every token started with the origins your workspace had, so nothing stops working. Edit them on the console's Tokens page (the install snippet's token is there too), or with vatio tokens create --origin URL (repeatable) and vatio tokens origins PREFIX URL.... vatio tokens list shows each token's origins, and vatio init no longer writes business:.

#0.52.0 — 2026-09-30

With GitHub connected, live changes only by merging. A workspace bound to a repository publishes when a commit lands on its default branch, and nowhere else: vatio publish is refused with a message naming the repository and the branch, and so are vatio push --env main and vatio push --env pr-N, which belong to the integration. vatio push to preview or another named preview still works, and vatio rollback stays as the emergency button.

Every GitHub deploy shows on its commit. Previews and publications post a commit status (vatio/preview (workspace), vatio/live (workspace)), green or red, linking to the preview, live or the console. A failed publication used to leave no trace outside a server log. Deploys to one workspace now run one at a time, and a merge that finishes late never replaces a newer one already live.

vatio publish without GitHub prints a notice. It works as before; the notice says publishing from the CLI will soon require a connected repository.

#0.51.0 — 2026-09-30

Knowledge has a draft, a live version, and history. Every write to a base — vatio kb write, a site re-reading a page, an edit in the console or the supervisor inbox — lands in the base's draft and is kept as a numbered version of its entry. Preview answers from the draft; live answers from what was last published. vatio kb status BASE shows what live does not have yet, vatio kb publish BASE -m NOTE takes it live, vatio kb history BASE lists every publication, and vatio kb rollback BASE NUMBER points live back at one instantly. Everything a base held before this release is already published, so live answers exactly as it did.

Supervisors can edit knowledge from the inbox. Written entries can be created, edited and deleted there, each entry shows its history with a diff and a restore button, and "answered from" in a conversation now links to the exact version the agent had.

#0.50.0 — 2026-09-29

vatio secrets set KEY asks for the value. Leave VALUE out and the CLI prompts ? Paste your secret: and echoes a * per character, so the value never lands in your shell history. Off a terminal it reads stdin instead: op read op://Vault/item/field | vatio secrets set KEY. set KEY VALUE works as before.

The CLI tells you when a new release is out. After a command, if npm has a newer @vatio-ai/cli, you see the version and the command to upgrade. It checks the registry at most once a day, only when stderr is a terminal, and never in CI or under vatio mcp. VATIO_NO_UPDATE_NOTIFIER=1 turns it off.

#0.49.0 — 2026-09-29

The identity token can enrich the inbox. Add a metadata claim to the JWT you already sign, and the inbox shows it in the conversation header:

"metadata": {
  "profile": "https://acme.com/admin/users/42",
  "badges": { "plan": { "value": "Premium", "tone": "green" }, "country": "CL" }
}

profile becomes a Profile ↗ link to the person in your own admin. If it is not an http(s) URL, the header shows a quiet "Invalid profile link" warning instead. Each entry in badges is a chip, and an optional tone (green, amber, red, gray) colours it. Nothing changes for tokens without metadata. vatio auth --new-key now lists the claim. See Enrich the inbox.

#0.48.1 — 2026-09-28

vatio update now points to the correct npm package. The command recommended vatio@latest, which returns a 404 from npm. The package is @vatio-ai/cli; the executable it installs is vatio. The message now recommends npm install -g @vatio-ai/cli@latest for a global install and npx @vatio-ai/cli@latest to run the latest release directly.

#0.48.0 — 2026-09-28

A bare vatio publish promotes your latest push. It used to promote whatever the preview alias pointed at, so vatio push --env pr-42 followed by vatio publish re-published the old preview and live never changed. Now it takes the most recent deployment, whichever preview it landed on, and says which one: Published live deployment #80 from pr-42. --env NAME still promotes a specific preview.

vatio chat show CHAT_ID reads any chat in the workspace. A visitor's chat on the web or WhatsApp, not only the one your CLI opened: the channel, the environment and deployment that answered it, every message and every tool call. --json prints the raw payload.

#0.47.1 — 2026-09-26

The README this package publishes was describing a runtime that no longer exists. It said tools/, lib/ and auth/ next to vatio.yml were "plain JavaScript the agent runs"; tools have been one HTTP request in YAML for a while now, and there is no JavaScript runtime. Its command list was also nine commands short — chat, kb, docs, mcp, issue, whatsapp and instagram among them.

Nothing in the CLI changed. The version moves because the README ships inside the tarball, and npmjs.com is where most people meet this package for the first time — a wrong README there is wrong in the one place it is read most.

#0.47.0 — 2026-09-26

init no longer asks for an account, and push asks by email.

vatio init used to stop and wait for a human to approve a code in a browser before it would write a file. That put the one step only a person can do at the very front — before your coding agent had built anything, and before you had any reason to care.

Now docs, init and tools check never touch the network. Your agent can write the whole workspace before an account exists. vatio push is the first command that makes something run on a server, so it is the one that asks who you are:

$ vatio push
  Before I can push this, I need to know whose it is.
  Your email (we send you a link): you@example.com

  We emailed you a link.
  This terminal is HXKT-4820 — check it matches before you approve.

One click on that link creates your account if it did not exist, authorizes the terminal, and drops you in the console. No password, no separate sign-up, no code to retype — the device code is still there, but you compare it instead of typing it. It has to match what your terminal printed.

Signing in to the console with an email we have never seen now creates the account too, which is what Google and GitHub always did here.

The console opens as your agent exists. Before your first push it is one screen with one command. After it, it is the screen you test on: your agent behind three doors — web, WhatsApp, Instagram — and beside them what the terminal cannot show you. Which tool it called with which arguments and how long each took, which knowledge it read, whether a handoff rule fired, tokens and latency. That panel keeps its shape whichever channel you pick, because it is one agent with three entrances.

WhatsApp and Instagram verification happens on that same screen now, as three steps, instead of being a detour to another page.

Publishing lands on one question — where will people write to it? — with what WhatsApp and Instagram each need from Meta listed before the button rather than halfway through their popup.

#Breaking

  • The push response field whatsapp_preview_hint is now first_push_hint, and it points at the test screen. A CLI older than this one stops printing that one-time nudge after a first push; nothing else changes.
  • The Widget page, the Usage page and the full-window preview visitor page are gone. Installing the chat on your site is part of Integrations, testing is the test screen, and usage comes back as analytics when there is something to analyse.

#0.46.0 — 2026-09-25

The docs are their own site: docs.vatio.ai.

They used to be one 1,700-line page built into the platform's Docker image. That cost two things worth losing. Fixing a typo paid for an image build and a rollout, and every reader — person or agent — got all of it or none of it.

Now there is a page per topic, with a search field, four tabs — Documentation, CLI, SDK, API Reference — and Spanish alongside English. Everything that pointed at vatio.ai/docs still works: it redirects, including the anchors of the old single page.

For agents, the contract is still one fetch. vatio docs is unchanged and still prints the whole thing, because vatio.ai/docs.md redirects to docs.vatio.ai/docs.md — no upgrade was needed for that. What is new is that every page is also Markdown on its own path plus .md, indexed at /llms.txt, so an agent working on one thing can read the one page about it instead of spending a context window on the whole contract.

Where the CLI prints a docs link — vatio --help, vatio auth --new-key, the message when vatio docs cannot reach the host — it now names the new site.

#0.45.0 — 2026-09-25

vatio issue sends the workspace, not just the sentence.

Run from a workspace, the command now attaches the directory — the same files vatio push sends. A report about a tool arrives with the tool, and a report about a manifest that will not push arrives with the manifest that will not push, which is precisely the one Vatio could not see before: what it held was the last version that pushed successfully.

Vatio keeps vatio.yml and everything under tools/, lists the rest of the directory by name, and records what its own checks made of it at that moment. Anything a check complained about comes along too, so the tools/*.js and lib/*.js that 0.42.0 stopped accepting arrive with the report that asks how to port them.

Hidden files are never included, so .env and .git/ stay where they are. The command prints what it is attaching before it sends, and --no-source sends the report on its own.

#0.44.0 — 2026-09-24

vatio issue list shows your issues. It reported that you had sent none while vatio issue show <id> returned those same issues, because the command read the wrong key off the response and got an empty list every time. list is the only way back to a report whose number you did not keep, and an empty one reads as "it never went through" — which is how the same problem gets filed twice.

Each row now says where the report stands — sent, in progress, with us, answered or closed — and prints the pull request when there is one, so a coding agent can watch the fix land instead of waiting to be told.

vatio kb create takes several names. A first push that declares two knowledge bases refused twice and cost a round trip per name. It now refuses once, for all the missing bases at once, and names the single command that creates them:

knowledge: no knowledge base named "docs" or "policies" on this workspace.
Create them with `vatio kb create docs policies`, then push again.

Still nothing implicit: a base exists because someone typed its name. That is what keeps knowledge: [defualt] a failed push rather than an empty base the agent searches forever, quietly answering with nothing.

Docs: the root-key table listed identity, knowledge and links, all three of which were removed in 0.41.0 and 0.43.0 and now fail the push. It lists auth, agents and entry instead.

All three were reported through vatio issue.

#0.43.0 — 2026-09-24

A workspace can run several agents, and the manifest says which one answers.

Key them under agents: instead of agent:, and add an entry: table:

agents:
  home:
    name: Ana
    instructions: Answer product questions. Nobody here is signed in.
    tools: [knowledge_lookup]
  portal:
    name: Ana
    instructions: You are talking to a signed-in customer.
    tools: [my_orders, knowledge_lookup]
    knowledge: [portal_kb]

entry:
  - { authenticated: false, agent: home }
  - { claims: { role: staff }, agent: staff }
  - { agent: portal }

The table is ordered and the order is the rule: the first row whose conditions hold wins, and the last row is the fallback. Letting each agent declare its own entry condition was the other design, and it loses on precedence — two agents that both say "authenticated" need a specificity rule nobody wants to reason about. Here the whole policy reads top to bottom in one place, and a reviewer can check it without knowing how Vatio works.

This is for the marketing site and the customer portal that embed the same widget. The anonymous visitor asking about prices and the signed-in customer asking about their own records are not the same conversation, and one set of instructions serving both serves neither. Until now that meant two workspaces: two manifests, two knowledge bases and two tokens to keep in step.

agent: still means exactly what it did — one agent, keyed main.

knowledge: and links: move onto the agent. They used to sit at the root and apply to the workspace; now each agent states its own, and there is no inherited default. A manifest that still declares either at the root fails the push and says where to put it — one edit, and vatio diff shows nothing else changed.

The repetition is the point. What an agent knows and which urls it may hand out are the two things you check when it answers wrongly, and an inherited value means looking somewhere else and then working out whether this agent overrode it. It also matters in the prompt: every declared url is listed there, so a portal agent would otherwise carry a marketing agent's whole link list around without ever handing one out. Duplication you can see beats inheritance you have to reconstruct.

Which agent you get is settled before the first reply, on every channel: Vatio verifies the token as the conversation opens, so the choice happens before the first message is answered rather than after. Sign in mid-conversation and identify() runs the table again — same thread, same history, and from the next message on, the agent for who you now are.

entry: is not a security control and is not built as one. A visitor with no valid token has no verified identity, so no access: private tool runs for them whatever agent they land on: a wrong row shows the wrong prompt, never someone else's data. Protect data with access: private on the tool, as before.

No migrations. A workspace with one agent needs one edit: move knowledge: and links: inside the agent: block.

#0.42.0 — 2026-09-24

A tool is one HTTP call to your backend. JavaScript tools are gone.

tools/*.js ran in a sandbox Vatio operated, and lib/*.js were the helpers bundled with them. Both are removed, along with the runtime behind them.

The reason is the same one that removed auth/*.js in 0.41.0: the file you wrote was never really the point. Every JavaScript tool deployed on Vatio was either a call to a backend the workspace already ran, or the scaffold nobody edited. Meanwhile the platform was carrying a bundler, a sandbox, a deploy step and a second execution model so that code with somewhere better to live could live here instead.

So it lives there. Describe the call in tools/<key>.yml with request: and respond:, and put whatever the call needs to do — branching, a second request, composing a response — in the endpoint it hits. That endpoint is yours: it can already read your database, and it does not have to be redeployed through us to change.

vatio push and vatio tools check refuse a tools/*.js or lib/*.js and name the file. Nothing else in a manifest changes, and access: private, $auth, $env and the result contract all work exactly as they did.

Also gone: the 301 from /vatio-widget.js to the CDN, which no page still used, and a route: field documented on tool results that was never implemented.

#0.41.1 — 2026-09-23

vatio auth --new-key told you to keep identity.pem secret and stopped there, which left the one question a developer actually has unanswered: secret where. It says it now, and so do the docs — the private half goes into your own backend, because your backend is what signs, and then out of the workspace directory.

Explicitly not into vatio secrets. That store is read by Vatio, and a private key in it would let Vatio mint tokens for your users rather than only check them, which is the property the whole design is built around.

#0.41.0 — 2026-09-23

Authentication is one JWT you sign, on every channel.

There used to be two ways to tell Vatio who a visitor is: an identity: block that verified a token your page signed, and auth/*.js — a JavaScript file you wrote, deployed and maintained, whose whole job turned out to be one HTTP call. The second existed because WhatsApp carries a phone number and nothing else, so someone has to ask your backend whose it is. Asking is fine. What was wrong is what came back: a plain answer Vatio then asserted to your own API. The platform ended up being something you had to trust about identity.

Now it carries proof instead. You sign a JWT, Vatio verifies it with your public key, and your tools get it as $auth.token. On the web your page puts it on the widget. On WhatsApp Vatio posts the phone number to your mint: endpoint and you sign one back — the same token, verified the same way. Vatio holds only a public key, so it can check a token and never mint one, and that is now true on every channel rather than only on the web.

auth:
  public_key: identity.pub
  mint:                                  # only for channels with no session
    url: $env.API_URL/api/vatio/identity

vatio auth --new-key generates the pair, gitignores the private half, and prints the exact claims to sign.

Also: the token's expiry means something now. The old design resolved a visitor once and cached the answer for the life of the conversation, so a twelve-hour token stopped being checked after the first minute of a chat that ran longer. Verifying a signature costs microseconds, so it happens on every tool call. On WhatsApp an expired token re-mints itself and the conversation carries on.

Signing in no longer costs you the conversation. Someone asks a question, the agent tells them to sign in, they do, and they come back: the chat they already had is still there, now with a name on it. Whether they signed in through identify() or by navigating away and reloading the page with a token makes no difference.

It used to start over — and a visitor who was already signed in lost their conversation on every page reload, because the SDK's session key was computed over the whole token and a backend signs a fresh one on each render. The key is the subject now.

What is never carried over is somebody else's conversation: a chat that belonged to sub A never passes to sub B, so signing in as a different person looks exactly like arriving for the first time. The server decides that, not the page.

Breaking. identity: is auth:. authentication.schemes and auth/*.js are gone, and so are scheme names: a tool is access: private or public. audience is no longer declared — it is your workspace slug, and it is now required in the token, so a JWT you signed for something else cannot be replayed as an identity. A private tool that declares user_id (or customer_id, account_id, member_id, patient_id, subject) as a parameter now fails the deploy instead of warning: the model fills parameters, so that one was always a way to ask for someone else's data. Every error names what to do instead.

#0.40.0 — 2026-09-23

A knowledge base holds entries, and an entry is Markdown.

It used to hold "sources", and a source was either a crawl — which produced documents you could not open, let alone fix a typo in — or an upload, which kept only the chunks it was cut into. Three words for two things, and you had to know which was which to read the screen. Now there is one kind of content: an entry, written by you or written by a site.

A site is one URL. No include or exclude lists: the URL says it, and a URL is that URL while a pattern is every page that matches it.

What you writeWhat it reads
acme.comthe home page, and only it
acme.com/helpthat one page
acme.com/**every page of the site
acme.com/help/**that section, however deep

Vatio reads each site again every night and rewrites the entries it owns, so a base keeps up with the pages it mirrors without anyone pressing a button. A page whose Markdown has not changed costs one request and nothing else — it is not re-indexed and not re-embedded. An entry a site wrote is not editable: the next read would overwrite it without a word, so you change the site.

Same actions everywhere. vatio kb write BASE ENTRY [FILE] puts Markdown under a name — creating it or replacing it, reading stdin when no file is given — vatio kb cat prints exactly what Vatio holds, and vatio kb follow, unfollow and refresh manage sites. add-source, upload, rm-source and reindex are gone, along with the two kinds of source they addressed. In the API, entries live at /knowledge_bases/:name/entries/:entry (PATCH to write, GET for the Markdown) and sites at /knowledge_bases/:name/sites.

Redirects are followed. A site that answers 301 or 302 — an apex sending you to www, a / sending you to /home — used to index nothing at all and report that it had completed. So did a sitemap behind a redirect. And a page that produces no text now says why, instead of disappearing from a run that claims success.

Accents survive. A page whose charset lives only in its HTTP header was parsed as Latin-1, so "Narváez" was indexed as "Narváez" and nobody searching for the name would find it.

#0.39.0 — 2026-09-23

One API, one view, and environment said out loud.

The docs used to describe two chat APIs under one heading, as though you got to pick. You never did: one is you holding a vat_ token, the other is a stranger's browser. The browser one is now documented as what it is — methods of the SDK, its only client — and the API section is what your developer token opens, each group naming the vatio command that does the same thing.

view is gone from the chat endpoints. It took visitor or developer and quietly turned anything else into visitor, so view=debug — the guess almost everyone made — returned a smaller payload with no error and looked complete. Holding the developer token is the developer view, so both reads now answer in full: deleted messages, tool calls with their results, attachments, delivery receipts, and the identity block. Print what you need. vatio chat transcript is unchanged for you; it filters the visitor's half of the thread itself now instead of asking the server for less.

environment is required on POST /chats and POST /chats/:id/reset. It was the one field in the API that defaulted to live — leave it out of a hand-written request and you were holding a real conversation with your published agent: billed, in your inbox, tools running against live secrets. A missing or unparseable environment is now 422 and creates nothing. The CLI always sent preview, so nothing changes if you talk to Vatio through it.

#0.38.0 — 2026-09-22

The SDK is on npm, and the widget is the only thing you paste into a page. Two changes with one shape: everything Vatio ships is now either a package you install or a page you visit, and the list of scripts that go into somebody else's HTML is one item long.

npm install @vatio-ai/sdk
import { Vatio } from "@vatio-ai/sdk";

cdn.vatio.ai/v1/sdk.js is gone, and so is the /sdk/1.js redirect to it. Nothing fetches the SDK at runtime any more: widget.js bundles it, which is a little larger and one whole failure mode smaller. That mode was worth losing — a dynamic import() is a module fetch, so it was a CORS request from every page that wasn't vatio.ai, and when it failed all the browser said was "Failed to fetch dynamically imported module", which reads like a 404 and never was one. It cost a production afternoon once.

No bundler is still fine — https://cdn.jsdelivr.net/npm/@vatio-ai/sdk/+esm serves the same module. Pin the major the ordinary way, "^2.0.0": a semver range in your package.json is what the /v1/ in the old URL was reaching for, and says it better.

The inbox is a page in Vatio, and there is no credential anywhere near it. It used to be a second embeddable script (inbox.js) you mounted in your own product and authenticated by signing a JWT against an inbox: block in vatio.yml. All of it is gone: the script, the block, and the API behind them. vatio push refuses inbox: now, so delete it and the key file it names.

Invite supervisors from Team in the console. They sign in with a code to their email and land on /workspaces/<id>/inbox — every conversation, replies, human takeover, ratings, the runtime trace. Remove them from the same page and the next request they make is refused, including a socket they already had open.

That is the whole access model, and it is deliberately the smallest one available: being signed in to Vatio, as someone this workspace invited. No token to mint, nothing to sign, nothing that expires on its own schedule, and no second place that can grant access to a conversation.

The old design asked every developer to build and run a small authentication system — generate a keypair, guard the private half, pick an algorithm, pick an expiry, remember to rotate — to answer a question Vatio can already answer, and the answer granted read-and-reply on every conversation in the workspace. The version that replaced it had Vatio issue the credential instead, which was better, and it was still a credential, an exchange endpoint, a token table and a CLI command in service of a supervisor UI nobody outside Vatio had built. Withdrawing the option is what actually removed the cost.

Building a supervisor UI inside your own product is not supported for now. If that is something you want, say so — reopening it means adding a credential back to a client that already works, not rebuilding the feature.

https://vatio.ai/vatio-inbox.js no longer redirects anywhere, because there is no longer anything to redirect to. vatio-widget.js still does, and will.

#0.37.2 — 2026-09-22

The package is @vatio-ai/cli. The command is still vatio — a package's name and the binary it installs are separate things:

npx @vatio-ai/cli init my-agent           # nothing installed
npm install -g @vatio-ai/cli && vatio push

Two reasons for the scope. The first is forced: npm will not publish a package called vatio, because it reads as a typo of valtio, an unrelated state library, and the registry refuses names close enough to an existing one to be mistaken for it. That rule is worth respecting rather than routing around.

The second is the one that decided it. The CLI will not be the only thing Vatio publishes — a frontend built on the SDK wants npm i @vatio-ai/sdk, not a script tag — and a scope claimed now is one name that stays coherent instead of two that have to be reconciled later.

Nothing else changed: same commands, same flags, same ~/.vatio/config.json.

#0.37.1 — 2026-09-22

vatio whatsapp connect opens the browser too. It printed the link and stopped, while vatio instagram connect printed it and opened it — two sibling commands behaving differently for no reason a developer could see.

The link is still printed first and still printed in full, so nothing is lost where there is no browser to open: over SSH, in a container, on a headless machine, the call quietly does nothing and the URL is there to paste.

#0.37.0 — 2026-09-21

vatio whatsapp connect prints a link, and pasted credentials are gone. The command took --phone-number-id, --waba-id and --token. It takes no flags now: it prints a URL and stops, the same shape as vatio instagram connect and vatio login.

This is not a CLI preference, it is what connecting a number actually is. Meta's Embedded Signup is a consent screen a person has to read, and the three ids the flags wanted only exist after it has run — so for the case that matters most, a number sitting in the WhatsApp Business app on someone's phone, the flags could never have worked at all. That number can now be connected and stay in the phone app, which only this flow can do.

The form in the app is gone with it, along with "Enter details manually instead". An expired access token is renewed by running the same connect flow again: Meta hands back a fresh token for the same number and it replaces the old one in place. Connecting a different number still has to be a disconnect first.

If you were scripting vatio whatsapp connect with flags, it now exits telling you the option is unknown. Everything else about the command group — status, check, activate, deactivate, disconnect, and all of numbers — is unchanged.

#0.36.0 — 2026-09-21

The CLI is an npm package now. There is nothing to install:

npx @vatio-ai/cli init my-agent
npx @vatio-ai/cli push

If you have Node 20 or newer you have the CLI. The Ruby one that curl … /install.sh | bash put in ~/.vatio-cli/ is gone, and so is /install.sh itself.

Why: Node is the runtime this audience already has, and Ruby is the one some of them do not. A CLI that asks you to find a runtime before it can help you is a CLI that loses the people it was written for.

What carries over: your login. It is the same ~/.vatio/config.json, with the same keys — run npx @vatio-ai/cli push and you are already authenticated. Every command keeps its name, its flags and its output.

To migrate: delete ~/.vatio-cli/ and the vatio symlink in ~/.local/bin/, then use npx @vatio-ai/cli (or npm install -g @vatio-ai/cli). Nothing else to do.

vatio update is gone with it: npx @vatio-ai/cli runs the current release every time, so there is no version of the CLI that can fall behind the platform. A global install updates with npm install -g @vatio-ai/cli@latest.

vatio pull is removed. It overwrote your local files from a deployed manifest, and the reason to stop is that it could never tell you anything your repository did not already contain.

A deployed manifest is only ever produced by a push. Nothing else writes one — no screen in the Vatio app edits your agent, your tools or your widget, because vatio.yml owns all of it. So what pull handed back was your own repository, one round trip later, and less: the logo it admitted it could not restore, because a revision keeps that file's name and digest and never its bytes.

If you want to see what is actually deployed:

vatio diff --env live    # what your directory would change there
vatio diff --full        # both manifests in full

And the manifest itself is one request: GET /api/v1/:slug/deploy/manifest.

The CLI test suite is removed too, along with the Ruby 2.6 CI job that ran it. It tested a CLI that is being replaced, and the drift guard it carried — the one that reconciled the command dispatch against vatio help and against these docs — is gone with it. Adding or renaming a command now needs those three read against each other by hand.

#0.35.0 — 2026-09-21

A chat is you, and vatio chat can talk to live. vatio chat --channel whatsapp --from +56912345678 let you arrive at your own agent as a simulated WhatsApp visitor. It is gone, on both sides — the CLI no longer sends it and the platform no longer accepts it.

It was a fake version of something that exists for real. The shared WhatsApp preview number and Instagram test accounts put a genuine message through a genuine channel, with the real verified phone number attached; the simulation only ever produced something channel-shaped, and it had to be kept in step with the real path forever. It drifted instead: the same module decided which contact a chat attached to, in two places at once.

What replaces it: nothing, for identity. A chat belongs to the token you are holding, on the cli channel. What you gain instead is the deployment:

vatio chat "Hi"              # preview, as before
vatio chat "Hi" --env live   # the published agent
vatio chat reset             # a visitor this workspace has never met

A chat against live is a real conversation. It lands in your inbox next to the ones visitors started, and nothing downstream knows it came from a terminal. The CLI says so when it opens one; it does not ask twice.

#Breaking

  • vatio chat --channel and --from are removed, and so are vatio config set channel / from. A config file carrying them is cleaned up on next use.
  • --sandbox-url is now --api-url, and VATIO_SANDBOX_URL is gone. Nothing else is called sandbox any more: the word was already preview everywhere else.
  • .vatio-sandbox.json is now .vatio-chat.json, and holds one open chat per deployment instead of one overall — switching to --env live and back no longer loses your place. The old file is deleted, not migrated: half of what it stored was the simulated identity.
  • POST /api/v1/:slug/chats and /reset take environment and nothing else. channel, from, session_id, reply_style, email, phone_number and as are all refused with removed_field and a message saying to run vatio update. A CLI older than this one sends channel and session_id on every chat, so vatio chat stops working until you update — deliberately, rather than accepting fields it would ignore and letting the next request, the one that actually meant something, be the one that breaks.
  • Nothing is called sandbox any more. Instagram's shared test surface now reads the way WhatsApp's always did: the shared Instagram preview, not "the sandbox". Same change in the CLI help, the docs, the console labels and the API error messages. The JS sandbox that tools run in keeps its name, because that is what it is.

#Also fixed

The one-time nudge after a workspace's first push — the one pointing at the free WhatsApp preview number — never printed. The server renamed the field to whatsapp_preview_hint when sandbox became preview and the CLI kept reading whatsapp_sandbox_hint.

#0.34.0 — 2026-09-21

One flag picks the deployment: --env. Saying which deployment a command was about used to depend on the command. push and publish took --as NAME, pull took --preview, tokens and widget took --environment or -e, and diff took nothing at all — it compared against preview and there was no way to ask it anything else.

Now every command that touches a deployment takes --env NAME, where NAME is live, preview, or a named preview like pr-42:

vatio diff --env live           # what would publishing change?
vatio pull --env pr-42          # bring that preview's manifest down
vatio tokens create --env pr-42 # a publishable token for it

Two things this unlocks that were not possible before:

  • vatio diff --env live. The question "what does publishing actually change" had no CLI answer; you had to push, then read the console.
  • Named previews outside push. tokens and widget rejected anything but live or preview, so a workspace could deploy to pr-42 and then have no way to mint the publishable token that makes it embeddable. The CLI refused a name the platform had just accepted.

Nothing is removed. --as, --preview, --environment and -e all still work, and every default is the one it was: push writes a preview, pull brings down live.

#0.33.0 — 2026-09-21

The CLI stopped parsing your workspace; Vatio does it. vatio tools check, vatio diff and vatio push used to read vatio.yml, your tools/, auth/ and lib/ files and build the manifest on your machine, against rules compiled into whichever CLI version you happened to have installed. They now send the directory to the platform, which builds the manifest, validates it and answers with the errors, the warnings and the diff.

What this fixes: the rules are the platform's, so a workspace that checks clean is a workspace that deploys, and a contract change reaches you without an upgrade. vatio diff and the console no longer disagree about links: — they were two implementations of the same comparison, and one of them had drifted.

What it costs, and you should know before upgrading:

  • vatio tools check and vatio diff need the network and a login. They were local commands; they are not any more. Run vatio login first, and expect a round trip where there used to be none.
  • They also need the workspace to exist on Vatio. vatio push still creates it for you; a check before your first push will say the remote is missing.

Nothing about vatio.yml, tools/, auth/ or lib/ changed. The same directory that deployed on 0.32.0 deploys on 0.33.0.

Your workspace is sent as files, so the usual exclusions apply: anything hidden (.env, .git/) and node_modules/, tmp/ and log/ are never uploaded. A workspace is capped at 500 files, 2 MB per file and 8 MB in total.

#0.32.0 — 2026-09-20

vatio.yml owns the whole widget, and the snippet drops to two attributes. The widget: block set the accent, the logo, the locale and the about text; everything else about how the widget looked — its corner, its colour scheme, its radius, its font, its greeting, the suggestions on the empty state — could only be said as a data-* attribute on every page that embedded it. A workspace with the same widget on five pages repeated the same ten attributes five times, and changing one meant a website deploy.

All of it is widget: now:

widget:
  accent_color: "#2563eb"
  position: right
  scheme: light
  font: inherit
  radius: 20px
  greeting: What can I help you with?
  suggestions:
    - Where is my order?
    - How do returns work?

The precedence is the host page's data-*, then vatio.yml, then the platform default — field by field, so a page that has to differ still can, and the snippet only carries what is specific to it:

<script async src="https://cdn.vatio.ai/v1/widget.js"
        data-workspace="acme" data-token="vatpub_..."></script>

data-display and data-mount have no widget: key on purpose: they say where the widget goes in one page's DOM, which is the part a page really does own.

A key widget: does not recognise fails the push. possition: right validated, pushed, exited 0 and did nothing — the only signal was a bubble that had not moved. It is an error now, and the message names what the block accepts.

#0.31.0 — 2026-09-20

A source name belongs to one kind of source, permanently. An upload whose filename matched an existing crawl used to win, without saying so: the crawl's site_url and globs were overwritten, the pages it had already indexed stayed underneath answering lookups for a source that no longer said where they came from, and the command exited 0. Declaring a crawl over an existing upload did the same in reverse, which is worse — a crawl can be rebuilt from the site, an upload is the only copy of what it holds.

Both directions are refused now, and the error names what is already there:

$ vatio kb upload default kb/ayuda.md
Error: default already has a source named "ayuda", and it is a crawl of
https://home.saludtech.cl include=/ayuda/pacientes/**. An upload cannot
take over a crawl -- rename the file, or drop the crawl first with
`vatio kb rm-source default ayuda`.

Refusing beats merging or renaming for you: upload ayuda.md onto a crawl named ayuda reads as both "replace my crawl" and "I did not realise the names collide", and only you know which one you meant.

A batch upload is all-or-nothing. vatio kb upload BASE kb/*.md now checks every file against the base before it sends the first one, so a collision on file twenty no longer leaves nineteen uploaded and the rest refused.

#0.30.0 — 2026-09-17

vatio issue --template is prompts now, not a form. A written-up issue used to have to carry four headings — Motivation, Proposal, Open questions, Prior art — and a document that skipped one came back rejected. That asked for an RFC. It mostly produced either an RFC-shaped wrapper around one real sentence, or nothing at all, because the person with something to tell us did not feel like filing a proposal.

There are no required sections any more. --template prints prompts you are free to keep, delete or answer out of order, and the platform asks only for a one-line title of your own and a body that says something — so a document that came back untouched is still refused, and a rough one is not:

vatio issue --template > issue.md   # prompts, not a form
vatio issue --file issue.md

"I don't know what the right fix is" is a fine thing to send.

The mail around an issue says less, and the thread says it instead. The acknowledgement used to promise that a person reads every one and invite a reply — which made the inbox look like the channel when it is not. It is now a short confirmation that the issue was submitted, plus where to read it. Two mails go out per issue, submitted and answered; the notes while it is worked on and the pull request are posted to the thread and never mailed, and a reply to either mail does not reach the thread. vatio issue show prints the whole of it.

#0.29.0 — 2026-09-17

An issue is now a conversation, and it lives in the CLI. vatio issue was one-way: you sent something, we replied by email, and the reply landed in a mail client — the wrong place for it, because the thing that has to act on the answer is the coding agent in the repo the issue came from.

vatio issue list                     your issues, and who owes a reply
vatio issue show 4                   the whole thread, as markdown
vatio issue show 4 --save            write it beside your code, for your agent
vatio issue comment 4 "still broken" add to the thread

show prints the same document our own triage reads — the problem, the diagnostics the CLI attached, and every message either side has written — so your agent can pick up the answer and implement it without anyone retyping a summary. comment adds to it; a person reads it and answers into the same document. Replying to an issue we already handled reopens it.

Comment rather than opening a second issue: a follow-up that arrives as a new report throws away everything the first one established. You see your own issues and nothing else, and email still carries every message — it is a mirror of the thread now, not the only copy.

links: now survives a push. A block the platform could not store used to be dropped in silence — a successful push, a vatio diff reporting it as added forever, and an agent behaving as if you had never written it. links:, identity: and inbox: were all affected. They now deploy, and a root block the platform does not understand fails the push instead of vanishing.

#0.28.0 — 2026-09-16

An unknown key in vatio.yml is now an error. Before this, a key the CLI did not recognize was dropped on the way to the platform: a typo deployed a workspace missing whatever you meant to configure, and a block from a newer version of the manifest deployed as if you had never written it. Both were silent. Now the push stops and names the key, and says to run vatio update if the key is one you expect to exist — which is the case this is really for:

vatio.yml: unknown key `links:`
If this is a newer manifest feature, your CLI is behind — run `vatio update`.

vatio update says what it is about to install. It prints the changelog entries between the version you have and the one being installed, so an update is a decision rather than a version number going up.

#0.27.0 — 2026-09-16

links: — the URLs your agent is allowed to share. A URL written into instructions: never reached a visitor: the no-unauthorized-links safeguard allows only URLs the agent was actually given, and instructions: is text the model may rephrase, so the draft was discarded and the link stripped. links: is where a URL is given:

links:
  login: https://saludtech.cl/login
  agendar:
    url: https://saludtech.cl/{especialidad}
    when: The visitor wants to book an appointment
    values:
      especialidad: [nutricion, kinesiologia, psicologia]

A {placeholder} always lists the values it can take, and a deploy expands the link into one concrete URL per value. Those are what the agent is shown and what the safeguard allows: it copies one, it never assembles one. Leaving values: out is an error — an open template would have the agent fill in the slug itself, and nothing downstream could tell a real one from a plausible one.

See Links for the full field reference.

Last updated:

Latest CLI version: 0.79.0 · Changelog · The whole contract as Markdown: /docs/docs.md · or vatio docs