Atlas

Scheduled Tasks

Run recurring queries on a cron schedule and deliver results via email, Slack, or webhook.

Scheduled tasks run natural language queries on a cron schedule and deliver results to configured recipients. Use them for daily reports, weekly digests, or real-time alerting via webhooks.

Prerequisites

  • ATLAS_SCHEDULER_ENABLED=true
  • An internal database (DATABASE_URL) for task persistence
  • Authentication enabled (any mode except none)

Task Definition

A scheduled task consists of a question, a cron schedule, and delivery configuration.

curl -X POST http://localhost:3001/api/v1/scheduled-tasks \
  -H "Authorization: Bearer <key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily revenue check",
    "question": "What was yesterday total revenue?",
    "cronExpression": "0 9 * * *",
    "deliveryChannel": "email",
    "recipients": [
      { "type": "email", "address": "team@example.com" }
    ]
  }'
FieldTypeRequiredDescription
namestringYesTask name (1--200 chars)
questionstringYesNatural language question (1--2000 chars)
cronExpressionstringYesStandard 5-field cron expression
deliveryChannelstringNoemail, slack, or webhook (default: webhook)
recipientsarrayNoDelivery destinations
connectionIdstringNoTarget datasource (default if omitted)
approvalModestringNoauto or manual (default: auto)

Cron Expression Format

Standard 5-field cron syntax:

minute  hour  day-of-month  month  day-of-week
0-59    0-23  1-31          1-12   0-6 (0=Sunday)
ExpressionSchedule
0 9 * * *Daily at 9:00 AM
0 9 * * 1-5Weekdays at 9:00 AM
0 0 * * 1Every Monday at midnight
0 9 1 * *First of every month at 9:00 AM
*/15 * * * *Every 15 minutes

Delivery Channels

Email

Requires Resend for email delivery.

RESEND_API_KEY=re_...
ATLAS_EMAIL_FROM="Atlas <reports@example.com>"  # Optional, default: Atlas <noreply@useatlas.dev>

Recipient format:

{ "type": "email", "address": "user@example.com" }

Slack

Requires the Slack integration to be configured.

{ "type": "slack", "channel": "#analytics" }

For multi-workspace OAuth, include teamId:

{ "type": "slack", "channel": "#analytics", "teamId": "T0123456" }

Webhook

Sends a JSON payload to an HTTPS endpoint.

{
  "type": "webhook",
  "url": "https://hooks.example.com/atlas",
  "headers": { "X-Custom-Header": "value" }
}

Webhook URLs must use HTTPS in production. Private/internal IPs (localhost, 127., 10., 172.16-31., 192.168., 169.254.*) are blocked. Sensitive headers (authorization, cookie) are filtered.


Execution Backends

The scheduler needs a mechanism to trigger periodic checks for due tasks.

bun (Default)

In-process tick loop using setInterval. No external dependencies.

ATLAS_SCHEDULER_BACKEND=bun

Best for single-instance deployments. The tick loop starts automatically when the API server boots.

webhook

External cron service calls the tick endpoint. Multi-instance safe.

ATLAS_SCHEDULER_BACKEND=webhook
ATLAS_SCHEDULER_SECRET=your-random-secret

Configure your external cron to call:

curl -X POST https://api.example.com/api/v1/scheduled-tasks/tick \
  -H "Authorization: Bearer $ATLAS_SCHEDULER_SECRET"

vercel

Uses Vercel's built-in cron service. Configure in vercel.json:

{
  "crons": [{
    "path": "/api/v1/scheduled-tasks/tick",
    "schedule": "*/5 * * * *"
  }]
}
ATLAS_SCHEDULER_BACKEND=vercel
# CRON_SECRET is auto-injected by Vercel

Execution Model

Each tick cycle:

  1. Fetch all enabled tasks where next_run_at <= now()
  2. Lock each task atomically (prevents double-execution across instances)
  3. Run up to ATLAS_SCHEDULER_MAX_CONCURRENT tasks in parallel
  4. For each task: execute the agent query, deliver results, log the run
  5. Recompute next_run_at from the cron expression

Concurrency and Timeouts

SettingEnv VarDefaultDescription
Max concurrentATLAS_SCHEDULER_MAX_CONCURRENT5Max tasks per tick
Task timeoutATLAS_SCHEDULER_TIMEOUT60000Per-task deadline (ms)
Tick intervalATLAS_SCHEDULER_TICK_INTERVAL60Seconds between ticks (bun backend only)

Failure Handling

  • Task timeout -- Run marked as failed with timeout error
  • Agent error -- Run marked as failed, error logged
  • Partial delivery failure -- If 1 of 3 recipients fails, the run is still success. Delivery failures are logged separately
  • Lock contention -- Second instance skips the task (atomic locking)

API Endpoints

All routes require authentication and are available at /api/v1/scheduled-tasks.

MethodPathDescription
GET/List tasks (paginated, filterable by enabled)
POST/Create a new task
GET/:idGet task with recent runs
PUT/:idUpdate task fields
DELETE/:idDisable task (soft delete for audit trail)
POST/:id/runTrigger immediate execution
GET/:id/runsList past runs
POST/tickServerless tick (webhook/vercel backends)

See the SDK for typed client methods.


Environment Variables

VariableDefaultDescription
ATLAS_SCHEDULER_ENABLEDSet to true to enable
ATLAS_SCHEDULER_BACKENDbunbun, webhook, or vercel
ATLAS_SCHEDULER_MAX_CONCURRENT5Max concurrent tasks
ATLAS_SCHEDULER_TIMEOUT60000Per-task timeout (ms)
ATLAS_SCHEDULER_TICK_INTERVAL60Tick interval in seconds
ATLAS_SCHEDULER_SECRETShared secret for /tick endpoint
RESEND_API_KEYRequired for email delivery
ATLAS_EMAIL_FROMAtlas <noreply@useatlas.dev>Email from address

The scheduled tasks default email address (noreply@useatlas.dev) differs from the actions framework default (atlas@notifications.useatlas.dev). Set ATLAS_EMAIL_FROM to use a consistent address across both.

See Environment Variables for the full reference.

On this page