On this page

#Claude Code routines

Ask your agent on WhatsApp, and Claude gets to work. A Claude Code routine is a saved prompt, with its repositories and connectors, that runs in the cloud. Connect one to Vatio, give it to your agent as a tool, and when one of the numbers you trust asks for something Claude should do, the agent hands the conversation over. What Claude does next is up to the routine's prompt: review something, change code and open a pull request, answer a client.

Setting it up for the first time? Follow Connect Vatio to Claude Code, step by step. This page is the reference.

vatio keys create --env live --label encargos
vatio routines create encargos \
  --url https://api.anthropic.com/v1/claude_code/routines/trig_…/fire \
  --phone +56912345678
# tools/encargos.yml
description: Pass a request to Claude, which reviews or changes the code of our apps in a separate session.
when_to_use: Someone asks to review or change something in our apps and you know what it is. If what to change or where is missing, ask first.
routine: encargos
# vatio.yml
agent:
  tools: [encargos]

#What a routine is

Your agent serves your users. A routine is for what needs Claude: changing your app, fixing something, looking into something. The agent decides when, Claude works in your code, and the agent tells the person.

It is a tool, with two differences from the ones that call your API:

Who can use itWhen it endsWhat comes back to the conversation
An HTTP toolAnyone the agent talks to (or signed-in users, with access: private)In seconds, before the agent answersA result the agent uses in its answer
A routine toolOnly conversations with the routine's numbers, on WhatsAppMinutes or hours later, outside the chatThat Claude has it, with the link to its session; later, what Claude tells the agent to pass on
A handoffAnyone, by your rules or the agent'sWhen a person takes the conversationThe conversation, to a person

The agent chooses the moment, so it can ask what is missing first: "implement the requirement" gets a question back, not a session that has to guess. Vatio decides who the tool exists for, in code: anyone else's conversation never has it, so nobody can talk the agent into it.

#How it works

  1. One of the routine's numbers writes on WhatsApp, and the agent answers as always. In that conversation it has the routine's tool; in anyone else's, it does not.

  2. When the request is complete, the agent calls the tool. Vatio calls the routine's trigger with JSON that says where the conversation is, and nothing it says:

    {
      "source": "vatio",
      "event": "message.received",
      "run_id": 41,
      "routine": "encargos",
      "workspace": "acme",
      "environment": "live",
      "chat_id": 349,
      "message_id": 9876,
      "messages_url": "https://vatio.ai/api/server/v1/acme/chats/349/messages"
    }

    message_id is the person's last message when the agent called the tool.

  3. The tool answers within the same turn, so the agent tells the person what it asked Claude for ("I'm asking Claude Code to look at the open pull requests"), with the link to Claude's session, or that it did not go through. A second call before the person writes again starts nothing new.

  4. Claude reads the conversation, does the work, and tells the agent with a brief. The agent passes it on in its own words ("Claude tells me that…"), and keeps it for when the person answers.

Each call starts a new Claude session: the trigger cannot continue one. To carry on in the same session, open the link the agent gave. It opens on claude.ai for the account that owns the routine.

#Set it up

  1. On claude.ai/code/routines, create the routine, pick its repositories, and add an API trigger. Copy its URL and generate its token: claude.ai shows the token once.
  2. Create a server key for the routine, so it can read the conversation and answer: vatio keys create --env live. Put it in the routine's cloud environment, for example as VATIO_SERVER_KEY. Everyone who uses that environment can read its variables.
  3. Let the environment reach vatio.ai. The default cloud environment only reaches a list of trusted domains; add vatio.ai to its network access.
  4. Run vatio routines create NAME --url URL --phone NUMBER and paste the token when it asks, or pipe it in: op read … | vatio routines create …. Vatio refuses anything that is not a sk-ant-oat01-… token.
  5. Run vatio routines test ID. It starts a real session with a ping and no conversation, and prints how the trigger answered and the session's link.
  6. Give it to the agent: tools/NAME.yml with routine: NAME, a description and a when_to_use, and NAME in agent.tools. Then vatio push, and vatio publish when it is ready. A routine tool takes no request:, access: or parameters:.

#What the prompt needs from Vatio

The prompt is yours. These are the parts that come from Vatio:

  • Claude treats the payload as data. It arrives in a routine-fire-payload block, and the routine only acts on it if the prompt says to: for example, "read the conversation at messages_url and do what the last messages ask".
  • Read the conversation with curl -H "Authorization: Bearer $VATIO_SERVER_KEY" "$messages_url". The newest messages come last, up to 100; ?before=<oldest_id> gets the page before. See Read a conversation.
  • Each message has role (user for whoever wrote on WhatsApp, assistant for the agent and anything sent through the server API), content and occurred_at. forwarded is forwarded or frequently_forwarded when it came from another chat, which is how a client's messages that were passed along differ from the instruction typed after them. A voice note arrives as its transcript; a photo or a file as a signed URL in attachments, with what Vatio read in a PDF or a video.
  • Answer through the agent with POST /api/server/v1/:slug/messages and { "to": "+569…", "brief": "Tell Iván that Claude finished: …" }. The agent writes the message from it, as news from Claude, and keeps the brief for when they answer. text instead of brief sends Claude's words exactly as written. The person has just written, so the 24-hour window is open; after a task that took hours it may have closed, and then only an approved template goes out.
  • A ping ("event": "ping") has no conversation. vatio routines test sends one.

#Who can use it

  • Only on WhatsApp. Meta vouches for the number a WhatsApp message comes from. A number typed into the widget or an app is whatever the visitor says it is, and a routine can write code.
  • Only the numbers you list, up to 20 per routine. Everyone else talks to the agent as always, and the tool is not there for them.
  • What a client wrote ends up in the session. A forwarded message is someone else's words, inside a session that can change your repositories. Keep the routine to branches and draft pull requests that you review.
  • Evals never start one. A replayed conversation gets a simulated success.

Each routine belongs to one environment, like a server key: a preview routine serves your test phones on Vatio's test number, a live one your own number. A tool whose routine is missing or switched off in an environment is not offered there.

To switch Live on without the agent answering your clients, have it answer only your own numbers first, with vatio whatsapp only (see Who the agent answers). A routine's numbers always count, and everyone else's messages wait in the inbox for you.

#Runs and failures

vatio routines runs ID lists the last 50 runs: when, for which chat, how the trigger answered, and the link to the Claude session it started. The inbox's Tools page shows each call next to your other tools.

The first attempt happens inside the agent's turn. If it surely did not start anything (a connection that never opened, a 5xx, or a 429), Vatio keeps trying for a few minutes and the agent says it is on its way; it gives up after 30 minutes, because an instruction that starts an hour late is worse than one that says it failed. A call that timed out is not retried: the trigger has no idempotency key, and the session may already be running.

After 10 failed runs in a row, Vatio switches the routine off; vatio routines enable ID turns it back on. A revoked token is the usual cause: generate a new one on claude.ai and pass it with vatio routines update ID --new-token. claude.ai runs a routine at most 30 times an hour.

Last updated:

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