# Automations

Schedule definitions, execution, delivery, limits, and failure recovery.



Use an automation to run an analysis on a recurring schedule. It can refresh an existing Explore or create a new one from a prompt, then optionally send notebook output by email or Slack. A live schedule, a completed run, and a delivered message are three different things to check.

For setup, use [Schedule and deliver an analysis](https://docs.querio.ai/guides/schedule-deliver). This page defines schedule, run, and delivery behavior. [Environments, sessions and runs](https://docs.querio.ai/reference/execution) covers runtime ownership and interruption.

## Definition and published state [#definition-and-published-state]

An automation is a YAML definition at `automations/<id>.yaml`; the filename supplies its ID. The path is relative to the configured context root in [Context files](https://docs.querio.ai/reference/context). For example, a context root of `querio` puts definitions at `querio/automations/<id>.yaml`. The scheduler reads canonical files under that root, not unpublished working-copy edits. A manual test does not prove scheduled discovery.

```yaml
name: Daily notebook refresh
description: Refresh the selected notebook each weekday.
status: draft
createdBy: analyst@example.test
updatedAt: '2026-10-25T09:00:00Z'
trigger:
  type: cron
  cron: '0 9 * * 1-5'
  timezone: UTC
workflow:
  type: explore-sync
  conversationId: example-notebook
action: null
```

| Field                 | Meaning                                                                                                    |
| --------------------- | ---------------------------------------------------------------------------------------------------------- |
| `name`, `description` | Display name and description.                                                                              |
| `status`              | `draft` pauses scheduling; `live` makes the definition eligible for its schedule.                          |
| `createdBy`           | Creator email for run attribution, not a query credential or permission grant.                             |
| `updatedAt`           | Last definition update time.                                                                               |
| `trigger`             | `type: cron`, cron expression, and timezone.                                                               |
| `workflow`            | `explore-sync` or `explore`. Drafts can be incomplete; publishing and testing require a complete workflow. |
| `action`              | `email`, `slack`, or `null` for no delivery.                                                               |

Only `trigger.type: cron` is recognized. A definition with only a top-level `schedule` field is not a current automation; there is no automatic migration of that older shape.

The scheduler reads canonical definitions, not unpublished working-copy edits. It refreshes schedules periodically, every minute by default. Publishing, unpublishing, or deleting a definition does not cancel a run already started. Deleting the definition does not delete its Explores or recorded runs. See [Files and versions](https://docs.querio.ai/reference/files-versions) for canonical publication.

## Cron and timezones [#cron-and-timezones]

The simple builder offers minute, hourly, daily, weekly, and monthly schedules. Minute schedules repeat every 5, 10, 15, 20, or 30 minutes. Hourly schedules can repeat every 1, 2, 3, 4, 6, 8, or 12 hours, and monthly schedules every 1, 2, 3, 4, or 6 months. Intervals count from midnight and from January, so every 6 hours runs at 00, 06, 12, and 18, and every 3 months runs in January, April, July, and October. A new automation starts at `0 9 * * *` in `UTC`. Five-field cron uses this order:

```text
minute hour day-of-month month day-of-week
```

| Expression     | Time in the stored timezone                      |
| -------------- | ------------------------------------------------ |
| `*/15 * * * *` | Every 15 minutes, at minutes 00, 15, 30, and 45. |
| `0 * * * *`    | Every hour at minute zero.                       |
| `0 */6 * * *`  | Every 6 hours at minute zero.                    |
| `0 9 * * *`    | Every day at 09:00.                              |
| `0 9 * * 1-5`  | Monday through Friday at 09:00.                  |
| `0 9 1 * *`    | The first day of each month at 09:00.            |
| `0 9 1 */3 *`  | The first day of every third month at 09:00.     |

`trigger.timezone` controls scheduling. It can be `UTC` or an IANA timezone such as `America/New_York`. The builder displays the stored timezone but has no timezone picker. Its **Next run** preview does not apply that timezone, so check the cron and stored timezone to establish the intended local time.

Six-field expressions with seconds are accepted, but the simple builder can drop nonzero seconds when it reads and saves them. Publishing or unpublishing from the list also rewrites the definition through that builder representation. Use five-field cron if the schedule will make that round trip.

An invalid cron or timezone prevents the schedule from being installed. Missed times after an outage are not promised to replay, and scheduling has no exactly-once guarantee. Check **Runs** after an expected time.

## Workflows and run ownership [#workflows-and-run-ownership]

| Workflow         | Definition                                            | Each run                                                                          |
| ---------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------- |
| **Explore sync** | `type: explore-sync`, `conversationId`                | Reruns the selected notebook with `no-cache` execution in its existing Explore.   |
| **Run a prompt** | `type: explore`, `prompt`, `model`, `datasourceSlugs` | Creates an Explore, then runs the prompt with the selected model and datasources. |

Explore sync uses the notebook/session's datasource and query-variable configuration. Run a prompt needs a nonempty prompt, model, and at least one datasource to publish or test. Both workflows run without a delivery action: sync still refreshes its Explore, and a prompt run still creates one.

Platform-managed execution does not need an open browser tab. An Explore sync can reuse an existing open notebook session; that session stays open after the run. Otherwise, the sync creates a session and environment for the run, retaining saved datasource and query-variable configuration. It closes those resources on success, failure, or cancellation before recording the final outcome, so another editor can open the Explore without restarting the execution server. This applies to scheduled syncs and manual test runs, not Run a prompt. Saved code, live Python values, stored outputs, and run results remain distinct; see [Environments, sessions and runs](https://docs.querio.ai/reference/execution).

Scheduled runs use the automation's creator metadata for attribution, with an existing run creator selected if that attribution cannot be resolved. Manual tests use the caller. Neither attribution nor automation ownership grants query access or selects a database credential. Queries need datasource permission and exactly one authorized credential for that datasource; see [credential selection](https://docs.querio.ai/reference/groups#credential-selection).

### Draft, live, and Test run [#draft-live-and-test-run]

| State or action         | Effect                                                                                                                                   |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Draft**               | Saved definition; automatic scheduling paused.                                                                                           |
| **Live**                | Definition eligible for its recurring schedule.                                                                                          |
| **Publish / Unpublish** | Save as live or draft.                                                                                                                   |
| **Test run**            | Save the current builder definition and submit a real run, including its configured delivery. Works while draft and does not publish it. |

**Test run is not a dry run.** It can refresh a notebook, create an Explore, send email, or post to Slack. Review destinations before testing. The **Runs** tab marks manual executions **Test**, separately from scheduled runs.

## Execution state and concurrency [#execution-state-and-concurrency]

**Runs** lists executions newest first. A returned run ID confirms submission, not completion or delivery.

| Run status    | Meaning                                                                          |
| ------------- | -------------------------------------------------------------------------------- |
| **Pending**   | Execution is reserved, or dispatch has not been confirmed.                       |
| **Running**   | Execution started without a recorded terminal outcome.                           |
| **Completed** | Successful execution outcome recorded; delivery is unconfirmed.                  |
| **Failed**    | Execution, dispatch, or recovery failed. Check existing results before retrying. |
| **Cancelled** | Cancellation recorded; completed effects are not rolled back.                    |

A second ordinary execution of the same session and run kind is rejected while matching work is active. This is not a global limit of one automation per execution server. Interactive editing and execution have their own readiness, ownership, and busy checks.

An unsuccessful dispatch response marks a still-**Pending** run **Failed**. It does not overwrite **Running** or completed work. Execution must claim the Pending reservation before starting; a delayed attempt cannot claim a run already marked Failed.

A connection failure without a response or an uncertain acknowledgement can still leave a run **Pending**. A later manual or scheduled notebook automation request can mark matching Pending automation reservations older than two hours **Failed**, allowing a new attempt. Fresh reservations, queued follow-ups, and unrelated sessions remain protected.

Before another scheduled notebook run is admitted, matching earlier **Running** scheduled work older than two hours can also be marked **Failed** with `Automation run exceeded 2-hour timeout without a recorded outcome`. Unlike an unclaimed Pending reservation, this does not prove an old computation or warehouse query stopped. It does not expire Running manual tests or prompt runs, and is not a universal two-hour execution limit.

## Delivery actions and limits [#delivery-actions-and-limits]

An automation has one optional delivery action. The action settings are captured when a run is submitted; changing the definition later does not change that run's destination.

| Action            | Definition                        | Behavior                                                                                |
| ----------------- | --------------------------------- | --------------------------------------------------------------------------------------- |
| No delivery       | `action: null`                    | Run without a message.                                                                  |
| **Send email**    | `type: email`, `recipients` array | Send rendered notebook output, including inline chart images, to one or more addresses. |
| **Slack message** | `type: slack`, `channel` ID       | Post rendered notebook output to one channel through the workspace Slack installation.  |

Delivery uses cells in the run result. If layout cells are selected, only selected cells present in that result are included; otherwise all result cells are used. The agent's chat reply is not included. With no renderable cell output, no automation email or Slack message is sent, even if the agent replied.

| Surface                 | What to expect                                                                                                                                                                                                             |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Email tables            | At most eight columns are displayed. Truncated rows and compacted columns can point to the full Explore.                                                                                                                   |
| Email charts            | Rendered as PNG images. A render failure can produce a blank image, so inspect the image itself.                                                                                                                           |
| Slack tables and charts | Tables can use native blocks. Up to two supported bar or line charts can use native chart blocks, with at most 20 categories and 12 series. Other charts use images.                                                       |
| Slack channel           | Requires a workspace Slack installation and access to the chosen channel. The picker lists accessible public and private channels, excludes archived channels, and can be unavailable if installation fails or is missing. |
| Slack partial delivery  | A message can arrive while chart uploads fail; upload errors are logged separately.                                                                                                                                        |

Email recipients are explicit addresses and are not limited to workspace members. Choose recipients and channels authorized to receive the rendered data. The delivered **View in Querio** link does not grant Explore access; recipients need their own permission to open it.

### Delivery is separate from execution success [#delivery-is-separate-from-execution-success]

Execution is recorded before delivery is attempted. Delivery errors are logged and do not change a **Completed** run to **Failed**. **Runs** has no persisted delivery success state or receipt, so **Completed** does not prove a message arrived.

There is no exposed durable automatic redelivery queue. Slack can join a channel and retry a `not_in_channel` post, but that is not a general delivery guarantee. Before rerunning, inspect the Explore and destination: another **Test run** repeats analysis and can send duplicate output.

## Permissions and recovery [#permissions-and-recovery]

Saving or removing automation definitions needs workspace file-write access. Listing runs and requesting a test use workspace read permission. These permissions are separate from Explore sharing, datasource access, and access to delivery destinations. A test can send real data, so check its recipients even when the caller has read permission.

| Symptom                              | Check                                                                                                                        |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| Visible automation, no scheduled run | **Live** status, canonical publication, the configured context root, cron, and timezone. Check for a recorded scheduled run. |
| Invalid schedule                     | Correct cron and timezone; check whether a six-field expression changed during a builder round trip.                         |
| Test or run remains **Pending**      | Inspect the existing run and Explore. If unresolved, provide the run ID when asking for help.                                |
| Session busy                         | Wait for active work. Do not assume scheduled work was queued for a later retry.                                             |
| **Failed** run                       | Read its error, check access and configuration, inspect existing effects, then retry deliberately.                           |
| **Completed**, no message            | Check the action, renderable cells, destination, and integration. Run status is not a delivery receipt.                      |
| Slack message missing charts         | Check rendering and upload separately from message delivery.                                                                 |

For the setup and recovery procedure, use [Schedule and deliver an analysis](https://docs.querio.ai/guides/schedule-deliver). For session interruption and cleanup, use [Environments, sessions and runs](https://docs.querio.ai/reference/execution).
