Skip to main content

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.

A scheduled run is a Trigger.dev cron job that wakes up on its schedule, runs the AI SDK generateText loop with your BYOK key, and writes back to your blocks via the same MCP tools your coding agent uses. Think of it as a worker that lives in your workspace and runs a prompt on a clock.
Scheduled runs are a Builder plan feature. Free workspaces can read this page but the /settings/schedule/new route shows an upgrade panel instead of the form.

What a run actually does

Every tick runs the same sequence:
1

Trigger.dev fires the cron

Each scheduled run row is registered with Trigger.dev via schedules.create. Pause / resume / delete sync through the same SDK. Cron expressions are interpreted as UTC.
2

Decrypt the BYOK key

The runner action looks up the configured BYOK row, calls _decryptForRunner({ actor: "system:scheduledRunner" }), and gets the provider plaintext just-in-time. Every decrypt writes an auditLog row.
3

Connect to your workspace MCP

A hidden, system-flagged cb_live_* key is generated per scheduled-run row. The runner uses it to call tools/list against ${RUNNER_MCP_BASE_URL}/api/mcp/v1, then wraps each discovered tool as an AI SDK tool() definition.
4

Run the agent loop

generateText({ model, prompt, tools, stopWhen: stepCountIs(25) }) with the BYOK plaintext as the provider API key. The model sees the same MCP tool surface your coding agent does — blocks.setWidgetData, dataSources.triggerRefresh, etc.
5

Record history

The runner writes a scheduledRunHistory row whether the run succeeded or failed (try/finally). Config-level failures (BYOK decrypt, MCP connect, provider 401/403) also flip the row’s status to error with an errorMessage.

The per-row hidden API key

Each scheduled-run row has its own system-flagged cb_live_* key, encrypted and stored on the row (internalApiKeyId + internalApiKeyCiphertext). It doesn’t appear in your /settings API Keys list (filtered out via apiKeys.system: true). This matters because:
  • Revoking a schedule revokes only its own key. Deleting the row cascades the key.
  • Audit log granularity. Tool calls from a scheduled run show up as actor: "mcp:<apiKeyId>" with a workspace-unique id per row.
  • You can’t accidentally reuse a runner key elsewhere. It’s not user-visible.

Cron presets

Five presets ship in packages/shared/src/cronPresets.ts:
PresetCronDescription
every-15-min*/15 * * * *Every 15 minutes
every-hour0 * * * *Every hour
daily-9am0 9 * * *Every day at 9am UTC
weekdays-9am0 9 * * 1-5Weekdays at 9am UTC
custom(user input)Anything else — standard 5-field cron
The form’s cron field accepts custom expressions for anything beyond the preset list. Validation accepts 5- to 7-field cron strings; semantics are whatever Trigger.dev’s parser does with them.

Provider routing

Per-workspace BYOK uses @ai-sdk/anthropic or @ai-sdk/openai directly, not the AI Gateway. Gateway BYOK is project-scoped, so per-workspace billing only works when the runner instantiates the provider SDK with the customer’s key. The model dropdown is filtered against KNOWN_MODELS[provider] in packages/shared/src/byokProviders.ts:
  • Anthropicclaude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5
  • OpenAIgpt-5.5, gpt-5.4-mini, gpt-5
Google is intentionally deferred in v1; see BYOK keys.

How runs differ from preview and run-now

SurfaceTriggerPersistencePlan gate
Scheduled runCron tickSaved row, persistentBuilder
schedule.previewOne-off MCP callEphemeral key, no rowBuilder
Run-now buttonManual clickUses saved row, one extra history entryBuilder
See Preview and run-now for the two manual paths.

Failure modes

A few categories of failure surface differently:
The BYOK key was rejected by Anthropic or OpenAI — usually rotated or deleted on the provider side. The row flips to status: "error" with a clear errorMessage. Fix by rotating the BYOK key in /settings.
The runner couldn’t reach ${RUNNER_MCP_BASE_URL}. Usually means the env var is misconfigured. The row flips to status: "error".
The workspace DEK couldn’t be unwrapped — typically a KEK rotation issue. Surfaces with a KEK_V1 is not set or “unable to unwrap” message. Contact us.
Individual tool calls (blocks.setWidgetData, dataSources.triggerRefresh, etc.) can fail inside the agent loop without failing the whole run. The model sees the JSON-RPC error in its tool_result and decides what to do.

What’s next

Creating a schedule

The /settings/schedule/new form, field-by-field, plus history and edit.

Preview and run-now

Two manual paths for testing a prompt without waiting for the cron.