> ## 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.

# Preview and run-now

> Two manual paths for testing a scheduled prompt — schedule.preview (one-off, ephemeral) and schedule.runNow (existing saved row).

A scheduled run with a 15-minute cron isn't the right shape for iterating on a prompt. Two manual paths exist for testing — both Builder-only:

* **`schedule.preview`** — one-off run of any prompt with no saved row. Streams progress over SSE. Use this while you're drafting.
* **Run-now** — fires the saved schedule's exact prompt once, immediately. Use this when the schedule is already saved and you want to confirm it works without waiting for the next tick.

## `schedule.preview` — one-off preview

The streaming MCP tool runs a one-off preview without creating a `scheduledRuns` row. Args mirror `schedule.set` minus `cronExpression`:

```json theme={null}
{
  "apiKeyId": "<byok-key-id>",
  "modelId": "claude-haiku-4-5",
  "prompt": "Update the MRR block with my current Stripe MRR.",
  "blockId": "<optional-block-id>"
}
```

Progress streams as Server-Sent Events:

| Event         | Payload                                                         |
| ------------- | --------------------------------------------------------------- |
| `text-delta`  | Chunk of model output text (throttled to 100ms intervals)       |
| `tool-call`   | `{ toolName, args }` — every time the model invokes a tool      |
| `tool-result` | `{ toolName, result }` — what came back                         |
| `finish`      | `{ success, toolCallCount, errorMessage? }` — the final summary |

<Note>
  Preview tools **execute normally**. If the agent calls `blocks.setWidgetData`, widget data actually updates. Customers iterate by re-running with tweaked prompts; there's no dry-run flag.
</Note>

### How the ephemeral key works

Preview mints a system-flagged `cb_live_*` key just for this invocation, uses it to call MCP, then deletes it in a `finally` block. If the process dies between mint and delete (extremely rare), the orphaned key sits inert with no row pointing at it — acceptable for v1. A janitor cron is deferred.

The audit log records the decrypt with `actor: "system:schedulePreview"`, so preview events are distinguishable from production scheduled runs and from MCP tool calls driven by a human agent.

### From the CLI

The CLI wraps preview at `chatblocks schedule preview`:

```bash theme={null}
chatblocks schedule preview "Update the MRR block with my current Stripe MRR." \
  --byok <byok-id> \
  --model claude-haiku-4-5 \
  --block <block-id>
```

Progress streams to stdout with a `·` prefix per event. See [CLI → Commands](/cli/commands#schedule-preview).

## Run-now — one-off fire of a saved schedule

The list row at `/settings/schedule` has a small `Zap` icon button — visible to admins on a Builder workspace when the row's status is `active`. Clicking it:

1. Calls `scheduledRuns.runNow` (a Convex action).
2. Dispatches `tasks.trigger("scheduled-agent-run", { scheduledRunId })` against Trigger.dev.
3. The standard scheduled-run pipeline runs — same BYOK decrypt, same hidden key, same MCP loop.
4. A `scheduledRunHistory` row appears on the History page within \~10–30 seconds.

Same path via MCP: `schedule.runNow { scheduleId }`. Same path via the CLI: `chatblocks schedule run <id>`.

<Tip>
  Run-now is your end-to-end check that a *saved* schedule actually works. Preview is your iteration loop while you're still writing the prompt.
</Tip>

## When to use which

| Situation                                            | Use                                           |
| ---------------------------------------------------- | --------------------------------------------- |
| Drafting a brand-new prompt                          | `schedule.preview` (no row, instant feedback) |
| Verifying a saved schedule before the next cron tick | Run-now                                       |
| Demoing the agent loop to a teammate                 | `schedule.preview` (one call, one log)        |
| Re-firing yesterday's broken run                     | Run-now                                       |

## What's next

<CardGroup cols={2}>
  <Card title="Concepts" icon="book" href="/scheduled-runs/concepts">
    What a scheduled run actually does, end to end.
  </Card>

  <Card title="CLI → schedule" icon="terminal" href="/cli/commands#schedule">
    Terminal commands for preview, list, history, and run.
  </Card>
</CardGroup>
