> ## Documentation Index
> Fetch the complete documentation index at: https://vetta.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployments & cron

> Run an agent on a schedule, then collect the results of every fire.

A **deployment** runs an [agent](https://vetta.sh/docs/concepts/agents.md) on a schedule. Each scheduled fire wakes the [durable runtime](https://vetta.sh/docs/concepts/runtime.md), starts a fresh [session](https://vetta.sh/docs/concepts/sessions.md), runs it to [idle](https://vetta.sh/docs/concepts/sessions.md#lifecycle), and stops — all within a per-run budget you set. A deployment is just a recurring session factory: everything you already know about sessions (events, files, budgets, outcomes) applies to each fire.

## Create a deployment

```bash CLI theme={"system"}
vetta deploy create --agent agt_01j8rk2vq6m4zx9kp7n3c5hwae \
  --cron "0 9 * * *" \
  --budget-usd 5 \
  --window loose \
  --prompt "Summarize what changed in main overnight and open issues for regressions." \
  --identity ava-sales \
  --on-idle https://acme.dev/hooks/vetta
```

```typescript TypeScript theme={"system"}
const deployment = await vetta.deployments.create({
  agent: agent.id,
  cron: "0 9 * * *",
  budgetUsd: 5,
  window: "loose",
  prompt: "Summarize what changed in main overnight.",
  onIdle: "https://acme.dev/hooks/vetta", // webhook fired when each run goes idle
});
```

> [!TIP]
>
> Scheduled agents are the canonical `loose` use case: an agent that starts at midnight and delivers at nine has no reason to pay the `immediate` tariff. See [Completion window](https://vetta.sh/docs/concepts/completion-window.md).

## How a fire flows

```
 cron tick ──▶ new session (deployment_id set)
                    │
                    ├─▶ events stream (resumable, per session)
                    ├─▶ published files (org-scoped, survive the session)
                    ├─▶ outcome score        (if an outcome is attached)
                    └─▶ session.idle ──▶ webhook  POST  { deployment_id, session_id, stop_reason, structured_output, outcome_evaluations[], files[] }
```

**A run waiting on you holds the schedule.** When the last run is still waiting for your answer or approval, the next fire is skipped rather than started: a new run would only add a second question under the first. The skip is written on the schedule's card as "Skipped: waiting on you". Answer the waiting run and the next fire goes ahead.

Every fire is a **normal session**. It shows up in `vetta session list`, streams the same [events](https://vetta.sh/docs/concepts/events-and-streaming.md), writes to the same [Files API](https://vetta.sh/docs/capabilities/files.md), and is subject to the same [budgets](https://vetta.sh/docs/concepts/budgets.md). The only difference is that it carries a `deployment_id` — and, if the deployment sets one, the `identity_id` of the [persona](https://vetta.sh/docs/identity/personas.md) it speaks as.

### The schedule's card on the board

If the agent is seated on a [team board](https://vetta.sh/docs/team/board.md), every fire runs against **one standing card
for that schedule** — not one card per fire. The card is created on the schedule's first fire, titled
`Recurring:` and the first line of the prompt, and from then on each fire re-opens the same card:
moved to `doing`, assigned to the agent, and named in the message the run starts with, so the run
reads its own history before it works and comments what it did before it finishes.

That is how scheduled work becomes visible. A card per fire would be a board row per run — a daily
schedule alone is seven a week, a crew's template is dozens — and a board nobody can read is a board
nobody uses. One card means the owner sees a schedule, with its runs as comments under it, rather
than a list that has to be scrolled past to find the work a person actually assigned.

* The card is on the board the agent is **seated on**, the one its owner reads. A schedule never
  opens a board of its own.
* The card is claimed by the fire before the session starts, so the board's own clock never starts a
  second session for it.
* An organization whose agents sit on no board sees no cards, and its schedules fire exactly as they
  did before.
* A board write that fails is logged and the fire runs anyway. The schedule is the work; the card is
  where it is shown, and the second must never be able to stop the first.

## Receiving results

There are three ways to collect what a scheduled run produced. Use the webhook for push; use listing/polling for pull; use published files for the actual artifacts.

**1. Push — subscribe to the run finishing**

Set `on_idle` on the deployment (or a `session.idle` [webhook](https://vetta.sh/docs/capabilities/webhooks.md) filtered by `deployment_id`). When a fire goes idle, Naive Managed Agents POSTs a signed, [enveloped](https://vetta.sh/docs/capabilities/webhooks.md#delivery--verification) payload:

```json theme={"system"}
{
  "id": "evt_7h...",
  "type": "session.idle",
  "created_at": "2026-08-20T09:00:12Z",
  "data": {
    "deployment_id": "dep_9f...",
    "session_id": "ses_4a...",
    "stop_reason": "end_turn",
    "consumed_micro_usd": 410000,
    "structured_output": {
      "regressions": 2,
      "issues_opened": ["ISSUE-4821", "ISSUE-4822"]
    },
    "outcome_evaluations": [
      { "outcome_id": "out_9k...", "result": "satisfied" }
    ],
    "files": ["file_1c...", "file_2d..."]
  }
}
```

Read the machine-readable result straight off `data.structured_output` — no transcript to scrape — when the agent (or deployment) has an [output schema](https://vetta.sh/docs/capabilities/structured-outputs.md) set; it is `null` otherwise. Fetch the deliverables by ID from the [Files API](https://vetta.sh/docs/capabilities/files.md). The `outcome_evaluations[]` array matches the outcomes shape on the session — one `{ outcome_id, result }` per attached outcome.

**`on_idle` is a webhook endpoint.** Setting it creates one for that URL, so these pushes get the same signing, retries, auto-disable and [delivery log](https://vetta.sh/docs/capabilities/webhooks.md#delivery-log--redelivery) as any subscription. It appears in `vetta webhook list` / `GET /v1/webhooks` alongside your own, with `events: ["deployment.on_idle"]` — it is pushed by the deployment rather than subscribed, so it never also receives every other session's `session.idle`.

```bash theme={"system"}
vetta webhook list                         # find the endpoint for your on_idle URL
vetta webhook rotate <webhook_id>          # the secret to verify these deliveries with
vetta webhook deliveries <webhook_id>      # what was sent, and whether it landed
```

Change `on_idle` to move the endpoint's URL (which also re-enables it if a dead target had disabled it); set it to `null` to stop pushing.

**2. Pull — list the runs a deployment produced**

Each fire is a session tagged with the `deployment_id`.

```bash CLI theme={"system"}
vetta deploy runs dep_01j8rs4vm6k2xq9zn3c7h5wtpb --limit 20   # sessions this deployment fired
vetta session get $SID                                        # status, stop_reason, consumed_micro_usd, structured_output
```

```typescript TypeScript theme={"system"}
for await (const s of vetta.sessions.list({ deploymentId: deployment.id, limit: 20 })) {
  if (s.status === "idle") console.log(s.id, s.stop_reason, s.consumed_micro_usd, s.structured_output);
}
```

**3. Read the artifacts and the transcript**

The durable outputs are the files a run published, its typed [`structured_output`](https://vetta.sh/docs/capabilities/structured-outputs), and its event history.

```bash CLI theme={"system"}
vetta file list --session $SID           # what this run published
vetta file download file_1c... > report.md
vetta session events $SID                # full transcript (resumable with --from-seq)
```

```typescript TypeScript theme={"system"}
const files = await vetta.files.list({ sessionId: sid });
const report = await vetta.files.download(files[0].id);
```

> [!NOTE]
>
> Scheduled runs go **`idle`**, not terminated — so their files, events, and outcome scores persist and are retrievable long after the fire. Nothing is lost between the cron tick and when you read it.

## Manage runs

```bash CLI theme={"system"}
vetta deploy list
vetta deploy runs dep_01j8rs4vm6k2xq9zn3c7h5wtpb                   # history of fired sessions
vetta deploy run dep_01j8rs4vm6k2xq9zn3c7h5wtpb                    # fire once, now (for testing)
vetta deploy pause dep_01j8rs4vm6k2xq9zn3c7h5wtpb
vetta deploy resume dep_01j8rs4vm6k2xq9zn3c7h5wtpb
vetta credits ledger --deployment dep_01j8rs4vm6k2xq9zn3c7h5wtpb   # metered spend across all fires
```

If a run would exceed the deployment budget, its calls are refused exactly as with any [budget](https://vetta.sh/docs/concepts/budgets.md) — the run goes idle early with `stop_reason: "budget_paused"` and still reports whatever it completed.

## Configuration reference

**agent** `string` *required*

The agent to run on each fire.

**cron** `string` *required*

A standard 5-field cron expression, evaluated in UTC.

**budget\_usd** `number` *required*

Per-run budget ceiling. Each fire gets a fresh allowance.

**prompt** `string`

The instruction sent to each scheduled session.

**window** `string`

Override the [completion window](https://vetta.sh/docs/concepts/completion-window.md) for scheduled runs — `loose` is often ideal for overnight jobs.

**identity** `string`

The [persona](https://vetta.sh/docs/identity/personas.md) every fire speaks as — an `idn_` id or the persona's name, the same value `session create --identity` takes. The agent must already hold a grant to it. Without one a scheduled fire runs as no persona, which is rarely what you want for an agent that owns an inbox.

**on\_idle** `string`

A webhook URL POSTed when each fire goes idle, carrying an enveloped `session.idle` event whose `data` holds the run's `session_id`, `stop_reason`, `deployment_id` and typed `structured_output`. Setting it provisions a [webhook endpoint](https://vetta.sh/docs/capabilities/webhooks.md) for that URL — rotate it for the signing secret, and read its delivery log like any other.

**output\_schema** `object`

A [JSON Schema](https://vetta.sh/docs/capabilities/structured-outputs.md) the run's final result must conform to, exposed as `structured_output` on each fire's idle session and webhook payload. Overrides the agent's default schema.

**outcome** `string`

An outcome to grade every fire against a rubric.

**metadata** `object`

Arbitrary key-value pairs copied onto each session this deployment creates.

> [card] [Next: webhooks](https://vetta.sh/docs/capabilities/webhooks.md)
>
> The full event catalog, delivery, retries, and signature verification.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.