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

# Automations

> Agents and pods that run on a schedule, with a memory of their own between firings.

> **Last updated: 2026-09-06**

## What is an Automation?

An **automation** is an agent or a pod set to run on a cadence rather than by hand. It carries what runs, the context documents each run is seeded with, an optional opening prompt, the cron expression and timezone, and the window it is allowed to fire in.

<Note>
  The API and the domain model call this an **Automation**. The dashboard calls the same thing a **Schedule** wherever you actually work with one (the task box's **Schedule** chip, the **When to run** popover, the **Save schedule** button), even though its sidebar link is labelled **Automations**. `/api/schedules/*` is an alias over the automation handlers, not a second implementation: the underlying table and the background ticker still say automation.
</Note>

An automation targets exactly one agent or one pod, pinned to the exact target generation it was configured against. If you delete that agent or pod and create a new one with the same name, the automation does not silently pick it up: it is disabled instead (see Lifecycle below).

Running a pod fires through the pod's lead member. The lead delegates to the rest of the pod exactly as it would if a person had started the run, so the pod's normal collaboration applies to a scheduled run too.

***

## Automations, agents, and sessions

An automation does not run in some separate scheduling layer: firing it creates an ordinary run, through the same path as starting a run by hand. The readiness gate, spend caps, the credit gate, the concurrency cap and usage metering all apply exactly as they do to a run you start yourself. A schedule is never a way around those gates.

Each firing opens a session that says it came from the automation, so the run sits in your normal Sessions list beside anything you started by hand.

***

## Lifecycle and states

An automation is one of three statuses:

| Status     | Meaning                                                                                                                |
| ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| `active`   | Fires on its cron expression, within its window.                                                                       |
| `stopped`  | Fires nothing. You stopped it, it was just created from a template, its window closed, or two firings in a row failed. |
| `disabled` | Cannot be started until its target is replaced: the agent or pod it points at was deleted.                             |

An automation created through the API starts **active**, on the schedule it was given. Configuring a cadence is treated as the decision to run on it, and stopping it again is one request away. The one exception is a template install, which creates its automations **stopped**, so a copied workspace does not start spending on a schedule its new owner has never seen.

<Tabs>
  <Tab title="Start">
    `POST /api/automations/{id}/start` sets the status to `active` and recomputes the next run from the schedule starting now; there is no catch-up for time the automation was off, so a schedule stopped on Monday and started on Friday does not owe Monday's run. Starting also clears the automation's consecutive-failure count.
  </Tab>

  <Tab title="Stop / pause">
    `POST /api/automations/{id}/stop` clears the next run outright rather than suspending a countdown. `POST /api/automations/{id}/pause` is the same handler under an older name, kept as an alias. Starting again recomputes the next slot from now.
  </Tab>

  <Tab title="Run now">
    `POST /api/automations/{id}/run` fires one slot immediately, through the same path a scheduled firing takes: same gates, same firing record. It works on a stopped automation, so you can check the target, the context, and the credentials before turning the schedule on. It does not touch the schedule or start the automation; a stopped automation is still stopped afterwards.
  </Tab>
</Tabs>

Creating an automation also enforces one limit: the opening prompt is capped at 8KB.

A cron expression and timezone are validated on every write, so a schedule that could never fire is rejected with a `400` rather than sitting in the list looking healthy. A start date may not fall before today in the automation's own timezone: automations run forward from when they are set up and never backfill.

<Warning>
  Two failed firings in a row switch an active automation to `stopped` on its own, with a paused reason of `failed_twice` recorded. A skip does not count as a failure, and neither does a stop you chose; only a firing whose run actually errored counts. Starting the automation again clears the count.
</Warning>

If the automation's target is deleted, the next firing that discovers this disables the automation (`disabledReason` of `agent_deleted`, `pod_deleted`, or `no_agents_remaining`, plus `disabledAt`). A disabled automation must be pointed at a working target before it can be started again.

***

## Missed slots

Each conductor replica checks for due automations roughly every 30 seconds. A slot more than one whole period late (an hour late matters to an hourly automation; it does not to a nightly one) is not caught up on. It is recorded as an `interrupted` firing and the schedule rolls forward to its next future slot, so a schedule that was offline for a while runs once at its next real slot rather than backfilling everything it missed.

If the previous firing's run is still going when the next slot comes due, the new slot is skipped rather than queued, and recorded as `skipped_overlap`.

***

## Memory between firings

Every automation has a small, hidden agent working behind it that reads what happened after each run and rewrites one short note for the run that follows.

* The note is written by that hidden agent, not by a fixed template, so what is worth remembering can differ per automation and you can read, tune or correct it.
* It writes a note even for a run that crashed, by reading the run's own record (status, failure reason, last thing said) rather than depending on the worker run to report on itself.
* The note is capped at 8KB, is seeded into the next firing's run alongside the automation's attached contexts, and is distinct from those contexts: a context is configuration you attached by hand, the memory note is something an agent wrote.

Read and correct the note through its own endpoint:

<CodeGroup>
  ```bash Read theme={"dark"}
  curl https://api.orcapods.ai/api/automations/{id}/memory
  ```

  ```bash Replace theme={"dark"}
  curl -X PUT https://api.orcapods.ai/api/automations/{id}/memory \
    -H 'Content-Type: application/json' \
    -d '{"body": "Corrected note text, or an empty string to clear it."}'
  ```
</CodeGroup>

```json theme={"dark"}
{
  "automationId": "auto-9f1c2b7e",
  "body": "Last run finished the outline and drafted section 1...",
  "updatedAt": "2026-09-05T21:03:11Z"
}
```

An automation whose agent has not written yet returns an empty body: that is a state, not an error. The dashboard's Memory Bank page shows the note read-only, filed under the automation's own name, but does not offer a way to edit it there; use this endpoint to read or correct it.

***

## Firings and history

Every scheduled slot is recorded as a **firing**, whether or not it started a run. A slot that quietly does nothing would otherwise be indistinguishable from a schedule that is broken, so even a skipped slot is written down with its reason.

| Status                   | Meaning                                                                          |
| ------------------------ | -------------------------------------------------------------------------------- |
| `ok`                     | The run started. Whether it ultimately succeeded is the run's own status.        |
| `error`                  | The run was refused or failed outright.                                          |
| `skipped_credits`        | Refused by the credit gate, a spend cap, or the published-agent cap.             |
| `skipped_overlap`        | The previous run was still going, or the run was refused by the concurrency cap. |
| `skipped_target_deleted` | The target was confirmed deleted; the automation was disabled instead of firing. |
| `interrupted`            | The slot was too late to be worth running and was rolled forward instead.        |

A firing costs up to two runs: the worker run itself, and the memory agent's short follow-up run. Both are joined onto the firing at read time, so duration, tokens, and billed cost stay available without a second copy that could drift.

```bash theme={"dark"}
curl "https://api.orcapods.ai/api/automations/firings?automation={id}&outcome=failed&limit=50"
```

`outcome` groups firings for a history view: `ok`, `failed`, or `skipped`. Omit `automation` to list firings across every automation.

***

## API

There is no CLI or SDK surface for automations today; use the dashboard or the REST API directly.

### Create

```bash theme={"dark"}
curl -X POST https://api.orcapods.ai/api/automations \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "nightly-digest",
    "targetKind": "agent",
    "targetName": "researcher",
    "prompt": "Summarize what changed today.",
    "contexts": ["style-guide"],
    "cronExpr": "0 8 * * *",
    "timezone": "Europe/London"
  }'
```

### List, get, update, delete

| Method   | Path                    | Notes                                                                                                                                                                                         |
| -------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET`    | `/api/automations`      | Paginated, newest first. `q` filters by name, target, schedule, status, prompt, or contexts. `includeDeleted=true` retains soft-deleted rows for history views, and ignores `q` when set.     |
| `GET`    | `/api/automations/{id}` | One automation.                                                                                                                                                                               |
| `PUT`    | `/api/automations/{id}` | The name cannot be changed. Editing an active automation recomputes its next run.                                                                                                             |
| `DELETE` | `/api/automations/{id}` | Blocked (`409`) while a worker run, delegated run, session, or memory update is still active. A successful delete keeps the automation, its firings, sessions, and runs as read-only history. |

### Turning cadence into cron

```bash theme={"dark"}
curl -X POST https://api.orcapods.ai/api/schedules/parse \
  -H 'Content-Type: application/json' \
  -d '{"text": "every weekday at 9am", "timezone": "Europe/London"}'
```

```json theme={"dark"}
{
  "cron": "0 9 * * 1-5",
  "timezone": "Europe/London",
  "humanized": "Every weekday at 09:00",
  "nextRunAt": "2026-09-08T08:00:00Z"
}
```

This is a small, literal grammar rather than a model call, so text outside the accepted shapes is refused with a `422` rather than approximated.

***

## Related

<CardGroup cols={2}>
  <Card title="Pods" href="/concepts/pods">
    Target a pod instead of a single agent.
  </Card>

  <Card title="Workflow orchestration" href="/concepts/workflows">
    DAG-based multi-agent runs, for work with parallel or ordered subtasks.
  </Card>

  <Card title="Conductor API reference" href="/api-reference/conductor">
    Full route reference for the conductor's `/api/*` surface.
  </Card>
</CardGroup>
