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

# Creating a schedule

> The /settings/schedule UI — list, create, edit, and inspect run history.

The schedule UI lives under `/settings/schedule`. Admins on a Builder workspace can create and manage scheduled runs from here; Free workspaces see an upgrade panel instead of the form.

## Routes

| Route                             | Purpose                                                 |
| --------------------------------- | ------------------------------------------------------- |
| `/settings/schedule`              | List with status badges, run-now button, manage actions |
| `/settings/schedule/new`          | Create a new schedule (Builder + admin only)            |
| `/settings/schedule/[id]/edit`    | Edit an existing schedule (Builder + admin only)        |
| `/settings/schedule/[id]/history` | Last 50 runs, with "Load more" up to 200                |

Scheduled runs have their own tab in the settings header nav (`/settings/schedule`), alongside Account, Billing, API keys, Workspace, and Data sources.

## The form

`/settings/schedule/new` and `/settings/schedule/[id]/edit` share `<ScheduleFormFields>`. Field order:

<Steps>
  <Step title="BYOK key">
    Dropdown of every BYOK key on the workspace. The selection drives which models are available in the next field.

    No BYOK key? Add one at `/settings/api-keys` → BYOK panel before coming back. See [BYOK keys](/connecting-data/byok-keys).
  </Step>

  <Step title="Model">
    Filtered against `KNOWN_MODELS[provider]` based on the BYOK selection:

    * **Anthropic** — `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5`
    * **OpenAI** — `gpt-5.5`, `gpt-5.4-mini`, `gpt-5`

    The runner rejects anything outside the whitelist at save time.
  </Step>

  <Step title="Block (optional)">
    Optional. Pick a block to focus the run on — usually so the prompt can refer to "this block" and the agent has an obvious write target via `blocks.setWidgetData`. Leave blank for a workspace-wide run.
  </Step>

  <Step title="Prompt">
    Plain-English instructions, up to 4000 chars. The runner passes this verbatim into `generateText` along with the tool set discovered from `tools/list`.

    Treat the prompt like a system prompt for a one-off agent. Be specific about which tool to call and on which block / data source.
  </Step>

  <Step title="Cron expression">
    Preset dropdown (`every-15-min` / `every-hour` / `daily-9am` / `weekdays-9am` / `custom`) plus a raw cron field. **All cron times are UTC** — Trigger.dev does not respect any local-timezone hint in v1.

    See [Concepts → Cron presets](/scheduled-runs/concepts#cron-presets) for the preset values.
  </Step>
</Steps>

After save, the row syncs to Trigger.dev via `schedules.create`. The returned schedule id is stored on the row as `triggerScheduleId` — you don't see it in the UI, but it's how pause/resume/delete sync back through the SDK.

## The list view

`/settings/schedule` shows one row per saved schedule with:

* **Status badge** — `active` / `paused` / `error`. Errors include the most recent `errorMessage`.
* **Cron expression** plus a human label if it matches a preset.
* **Last run** — relative timestamp from the most recent `scheduledRunHistory` row.
* **Actions** — Run now (admin + active only), Pause / Resume, Edit, History, Delete.

<Tip>
  The Run-now button is the small `Zap` icon. It calls `scheduledRuns.runNow`, which dispatches `tasks.trigger("scheduled-agent-run", { scheduledRunId })` against Trigger.dev. A new `scheduledRunHistory` row appears in History within \~10–30 seconds.
</Tip>

## Pause and resume

Both flip the row's `status` field and call Trigger.dev's `schedules.update` to toggle the schedule on the Trigger side. Paused schedules stay in the list but don't fire on the cron until resumed.

## History

`/settings/schedule/[id]/history` lists `scheduledRunHistory` rows in reverse chronological order. Columns:

| Column     | Notes                                                         |
| ---------- | ------------------------------------------------------------- |
| Ran at     | UTC timestamp                                                 |
| Success    | ✓ if the agent loop returned without throwing; ✗ on any error |
| Duration   | Wall-clock milliseconds from start to finish                  |
| Tool calls | Count of MCP tools the agent invoked                          |
| Error      | Truncated `errorMessage` if `success: false`                  |

First page is 50; "Load more" extends to 200. Beyond that, drop into the Convex dashboard.

## Delete

Deleting a scheduled run:

1. Removes the `scheduledRuns` row.
2. Cascades the per-row system-flagged `cb_live_*` key (so the runner can never invoke MCP with this key again).
3. Calls Trigger.dev `schedules.del` to remove the cron from their side.
4. Leaves `scheduledRunHistory` rows in place (for audit; they'll fall off via retention later).

## Plan gating

The form components include UI-only checks (e.g. disabling Save), but the authoritative gate is server-side. `requireProPlan` (the function name predates the Pro → Builder rename) runs at the top of `schedule.set`, `schedule.pause`, `schedule.resume`, `schedule.delete`, `schedule.preview`, and `schedule.runNow` — both UI mutations and MCP tool calls go through it.

Free workspaces calling these via MCP get a `PRO_REQUIRED` error on the wire; the UI shows a Builder upsell panel linking to `/settings/billing`.

## What's next

<CardGroup cols={2}>
  <Card title="Preview and run-now" icon="play" href="/scheduled-runs/preview-and-run-now">
    Test a prompt without waiting for the cron, or fire a one-off run of a saved schedule.
  </Card>

  <Card title="BYOK keys" icon="key" href="/connecting-data/byok-keys">
    Manage the LLM keys that scheduled runs decrypt at runtime.
  </Card>
</CardGroup>
