# Routines that run themselves

> Asks that run by themselves: on a schedule in plain words, or whenever your system calls, one for each user.

A routine is an ask that runs by itself: on a schedule in plain words, or whenever your system calls. Each user can have their own.

About 10 minutes. It uses [`routines`](https://vestra.ai/developers/routines.md), [`events`](https://vestra.ai/developers/events.md).

## 1. Say when, in plain words

Words like `weekday at 08:00` or `mon, wed, fri at 18:30`, read in the user's own time zone ([`routines`](https://vestra.ai/developers/routines.md)).

**TypeScript**

```ts
const traveller = vestra.user('traveller-42');
const daily = await traveller.routines.create({
  ask: 'Check my trips for today and tell me about any delay.',
  every: 'weekday at 08:00',
});
console.log(daily.schedule?.cron, daily.next_run_at);
```

**Python**

```python
traveller = vestra.user("traveller-42")
daily = traveller.routines.create(
    "Check my trips for today and tell me about any delay.",
    every="weekday at 08:00",
)
print(daily.schedule.cron, daily.next_run_at)
```

**CLI**

```bash
vestra routines add "Check my trips for today and tell me about any delay." --every "weekday at 08:00" --user traveller-42
```

**HTTP**

```bash
curl "$VESTRA_BASE_URL/v1/routines" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "traveller-42",
    "ask": "Check my trips for today and tell me about any delay.",
    "every": "weekday at 08:00"
  }'
```

**MCP**

```json
{
  "method": "tools/call",
  "params": {
    "name": "routines_add",
    "arguments": {
      "user": "traveller-42",
      "ask": "Check my trips for today and tell me about any delay.",
      "every": "weekday at 08:00",
      "timezone": "Asia/Kolkata"
    }
  }
}
```

**What happens:** Bash answers with the cron it made and the next run. Each run lands in the routine's own conversation.

## 2. Or run on a call

For when something happens in your system, such as a late train.

**TypeScript**

```ts
const traveller = vestra.user('traveller-42');
const onDelay = await traveller.routines.create({
  ask: 'A train of mine is late. Find me another way.',
  on: 'call',
});

// From your system, with what happened.
await traveller.routines.trigger(onDelay.id, {
  train: '12127',
  delay_minutes: 45,
});
```

**Python**

```python
traveller = vestra.user("traveller-42")
on_delay = traveller.routines.create(
    "A train of mine is late. Find me another way.", on="call"
)

# From your system, with what happened.
traveller.routines.trigger(
    on_delay.id, {"train": "12127", "delay_minutes": 45}
)
```

**CLI**

```bash
# It answers with its trigger_url: your system posts there, with your key.
vestra routines add "A train of mine is late. Find me another way." --on call --user traveller-42
```

**HTTP**

```bash
curl "$VESTRA_BASE_URL/v1/routines" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "user_id": "traveller-42", "ask": "A train of mine is late. Find me another way.", "on": "call" }'

# From your system, with what happened.
curl "$VESTRA_BASE_URL/v1/routines/rtn_7qp/trigger" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "train": "12127", "delay_minutes": 45 }'
```

**MCP**

```json
{
  "method": "tools/call",
  "params": {
    "name": "routines_add",
    "arguments": {
      "user": "traveller-42",
      "ask": "A train of mine is late. Find me another way.",
      "on": "call"
    }
  }
}
```

**What happens:** Each call runs it once. Your payload rides along as data, never as instructions.

## 3. Give each user their own

A routine per user, from one loop.

**TypeScript**

```ts
// One for each user: 08:00 is each one's own morning.
for (const user of travellers) {
  await vestra.user(user).routines.create({
    ask: 'Check my trips for today and tell me about any delay.',
    every: 'weekday at 08:00',
  });
}
```

**Python**

```python
# One for each user: 08:00 is each one's own morning.
for user in travellers:
    vestra.user(user).routines.create(
        "Check my trips for today and tell me about any delay.",
        every="weekday at 08:00",
    )
```

**CLI**

```bash
# One for each user: 08:00 is each one's own morning.
vestra routines add "Check my trips for today and tell me about any delay." --every "weekday at 08:00" --user traveller-42
vestra routines add "Check my trips for today and tell me about any delay." --every "weekday at 08:00" --user traveller-77
```

**HTTP**

```bash
# One for each user: 08:00 is each one's own morning.
curl "$VESTRA_BASE_URL/v1/routines" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "user_id": "traveller-42", "ask": "Check my trips for today and tell me about any delay.", "every": "weekday at 08:00" }'

curl "$VESTRA_BASE_URL/v1/routines" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "user_id": "traveller-77", "ask": "Check my trips for today and tell me about any delay.", "every": "weekday at 08:00" }'
```

**MCP**

An agent adds one at a time with `routines_add`, naming each `user`.

**What happens:** `08:00` is each user's own morning, in the time zone you [named them](https://vestra.ai/developers/guides/many-customers.md) with.

## 4. Read its runs

Each run is an ask: its status, and the conversation it ran in.

**TypeScript**

```ts
const traveller = vestra.user('traveller-42');
const runs = await traveller.routines.runs('rtn_5kd');
for (const run of runs.data)
  console.log(run.status, run.conversation_id);
```

**Python**

```python
traveller = vestra.user("traveller-42")
for run in traveller.routines.runs("rtn_5kd").data:
    print(run.status, run.conversation_id)
```

**CLI**

```bash
vestra routines runs rtn_5kd --user traveller-42
```

**HTTP**

```bash
curl "$VESTRA_BASE_URL/v1/routines/rtn_5kd/runs" \
  -H "Authorization: Bearer $VESTRA_API_KEY"
```

**MCP**

Runs are read from an SDK, the CLI or HTTP. An agent lists routines with `routines_list`.

**What happens:** `routine.fired` reaches your webhooks each time one runs.

## 5. Pause it

Paused, it skips its runs until you resume it.

**TypeScript**

```ts
const traveller = vestra.user('traveller-42');
await traveller.routines.pause('rtn_5kd');

// Later: it says when it runs next.
const back = await traveller.routines.resume('rtn_5kd');
console.log(back.next_run_at);
```

**Python**

```python
traveller = vestra.user("traveller-42")
traveller.routines.pause("rtn_5kd")

# Later: it says when it runs next.
print(traveller.routines.resume("rtn_5kd").next_run_at)
```

**CLI**

```bash
vestra routines pause rtn_5kd --user traveller-42

# Later: it says when it runs next.
vestra routines resume rtn_5kd --user traveller-42
```

**HTTP**

```bash
curl -X PATCH "$VESTRA_BASE_URL/v1/routines/rtn_5kd" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

# Later: "enabled": true, and it says when it runs next.
curl -X PATCH "$VESTRA_BASE_URL/v1/routines/rtn_5kd" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
```

**MCP**

Pausing is done from an SDK, the CLI or HTTP.

**What happens:** Resuming says when it runs next.

The CLI prints:

```text
Paused rtn_5kd.
```

## 6. The whole thing

One for each user, one on a call, its runs and a pause, in one program.

**TypeScript**

```ts
import { Vestra } from '@vestra/sdk';

const vestra = new Vestra();
const travellers = ['traveller-42', 'traveller-77'];

// Say when, in plain words: one for each user
for (const user of travellers) {
  await vestra.user(user).routines.create({
    ask: 'Check my trips for today and tell me about any delay.',
    every: 'weekday at 08:00',
  });
}

// Or run on a call from your system
const traveller = vestra.user('traveller-42');
const onDelay = await traveller.routines.create({
  ask: 'A train of mine is late. Find me another way.',
  on: 'call',
});
await traveller.routines.trigger(onDelay.id, { train: '12127' });

// Read its runs, and pause it
const runs = await traveller.routines.runs(onDelay.id);
console.log(runs.data.length);
await traveller.routines.pause(onDelay.id);
```

**Python**

```python
from vestra import Vestra

vestra = Vestra()
travellers = ["traveller-42", "traveller-77"]

# Say when, in plain words: one for each user
for user in travellers:
    vestra.user(user).routines.create(
        "Check my trips for today and tell me about any delay.",
        every="weekday at 08:00",
    )

# Or run on a call from your system
traveller = vestra.user("traveller-42")
on_delay = traveller.routines.create(
    "A train of mine is late. Find me another way.", on="call"
)
traveller.routines.trigger(on_delay.id, {"train": "12127"})

# Read its runs, and pause it
print(len(traveller.routines.runs(on_delay.id).data))
traveller.routines.pause(on_delay.id)
```

**CLI**

```bash
# Say when, in plain words: one for each user
vestra routines add "Check my trips for today and tell me about any delay." --every "weekday at 08:00" --user traveller-42
vestra routines add "Check my trips for today and tell me about any delay." --every "weekday at 08:00" --user traveller-77

# Or run on a call from your system
vestra routines add "A train of mine is late. Find me another way." --on call --user traveller-42

# Read its runs, and pause it
vestra routines runs rtn_5kd --user traveller-42
vestra routines pause rtn_5kd --user traveller-42
```

**HTTP**

```bash
# Say when, in plain words
curl "$VESTRA_BASE_URL/v1/routines" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "user_id": "traveller-42", "ask": "Check my trips for today and tell me about any delay.", "every": "weekday at 08:00" }'

# Or run on a call from your system
curl "$VESTRA_BASE_URL/v1/routines/rtn_7qp/trigger" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "train": "12127" }'

# Read its runs, and pause it
curl "$VESTRA_BASE_URL/v1/routines/rtn_5kd/runs" \
  -H "Authorization: Bearer $VESTRA_API_KEY"

curl -X PATCH "$VESTRA_BASE_URL/v1/routines/rtn_5kd" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'
```

**MCP**

An agent adds routines with `routines_add` and lists them with `routines_list`.

**What happens:** Bash runs each one by itself, and your webhooks hear every run.

Next: [Work from your editor](https://vestra.ai/developers/guides/your-editor.md)
