#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 it | When it ends | What comes back to the conversation | |
|---|---|---|---|
| An HTTP tool | Anyone the agent talks to (or signed-in users, with access: private) | In seconds, before the agent answers | A result the agent uses in its answer |
| A routine tool | Only conversations with the routine's numbers, on WhatsApp | Minutes or hours later, outside the chat | That Claude has it, with the link to its session; later, what Claude tells the agent to pass on |
| A handoff | Anyone, by your rules or the agent's | When a person takes the conversation | The 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
-
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.
-
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_idis the person's last message when the agent called the tool. -
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.
-
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
- 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.
- 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 asVATIO_SERVER_KEY. Everyone who uses that environment can read its variables. - Let the environment reach
vatio.ai. The default cloud environment only reaches a list of trusted domains; addvatio.aito its network access. - Run
vatio routines create NAME --url URL --phone NUMBERand paste the token when it asks, or pipe it in:op read … | vatio routines create …. Vatio refuses anything that is not ask-ant-oat01-…token. - Run
vatio routines test ID. It starts a real session with apingand no conversation, and prints how the trigger answered and the session's link. - Give it to the agent:
tools/NAME.ymlwithroutine: NAME, adescriptionand awhen_to_use, andNAMEinagent.tools. Thenvatio push, andvatio publishwhen it is ready. A routine tool takes norequest:,access:orparameters:.
#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-payloadblock, and the routine only acts on it if the prompt says to: for example, "read the conversation atmessages_urland 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(userfor whoever wrote on WhatsApp,assistantfor the agent and anything sent through the server API),contentandoccurred_at.forwardedisforwardedorfrequently_forwardedwhen 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 inattachments, with what Vatio read in a PDF or a video. - Answer through the agent with
POST /api/server/v1/:slug/messagesand{ "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.textinstead ofbriefsends 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 testsends 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.