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

# Schedules

Create recurring tasks that run on a cron schedule inside a box. You can schedule shell commands or agent prompts. Available on both `box.schedule` and `ephemeralBox.schedule`.

***

## API

### Schedule a shell command

Run a shell command on a cron schedule.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  const schedule = await box.schedule.exec({
    cron: "* * * * *",
    command: ["bash", "-c", "date >> /workspace/home/cron.log && echo scheduled-ok"],
    webhookUrl: "https://example.com/hook",          // optional
    webhookHeaders: { Authorization: "Bearer ..." }, // optional
    folder: "/workspace/home",                       // optional, defaults to box.cwd
  })

  console.log(schedule.id)
  ```

  ```python box.py theme={"system"}
  schedule = box.schedule.exec(
      cron="* * * * *",
      command=["bash", "-c", "date >> /workspace/home/cron.log && echo scheduled-ok"],
      webhook_url="https://example.com/hook",            # optional
      webhook_headers={"Authorization": "Bearer ..."},   # optional
      folder="/workspace/home",                          # optional, defaults to box.cwd
  )

  print(schedule.id)
  ```
</CodeGroup>

| Parameter        | Required | Description                                                                  |
| ---------------- | -------- | ---------------------------------------------------------------------------- |
| `cron`           | Yes      | 5-field cron expression (UTC)                                                |
| `command`        | Yes      | `string[]` — the command to run                                              |
| `webhookUrl`     | No       | URL to notify when the scheduled run completes                               |
| `webhookHeaders` | No       | Headers to include in the webhook request                                    |
| `folder`         | No       | Working directory. Defaults to `box.cwd`; relative paths resolved against it |

***

### Schedule an agent prompt

Run an agent prompt on a cron schedule. Requires an agent to be configured on the box.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  const schedule = await box.schedule.agent({
    cron: "0 9 * * *",
    prompt: "Run the test suite and fix any failures",
    model: "anthropic/claude-sonnet-4-6",          // optional, overrides box's model
    timeout: 300_000,                     // optional, kill the run after 5 minutes
    options: { maxBudgetUsd: 1.0 },      // optional, provider-specific agent options
  })

  console.log(schedule.id)
  ```

  ```python box.py theme={"system"}
  schedule = box.schedule.agent(
      cron="0 9 * * *",
      prompt="Run the test suite and fix any failures",
      model="anthropic/claude-sonnet-4-6",   # optional, overrides box's model
      timeout=300_000,                        # optional, kill the run after 5 minutes
      options={"max_budget_usd": 1.0},        # optional, provider-specific agent options
  )

  print(schedule.id)
  ```
</CodeGroup>

| Parameter        | Required | Description                                                                                 |
| ---------------- | -------- | ------------------------------------------------------------------------------------------- |
| `cron`           | Yes      | 5-field cron expression (UTC)                                                               |
| `prompt`         | Yes      | The prompt to send to the agent                                                             |
| `folder`         | No       | Working directory. Defaults to `box.cwd`; relative paths resolved against it                |
| `model`          | No       | Override the box's default model for this schedule                                          |
| `options`        | No       | Provider-specific agent options (e.g. `maxBudgetUsd`, `effort`, `systemPrompt`, `maxTurns`) |
| `timeout`        | No       | Timeout in milliseconds — kills the run if exceeded                                         |
| `webhookUrl`     | No       | URL to notify when the scheduled run completes                                              |
| `webhookHeaders` | No       | Headers to include in the webhook request                                                   |

***

### List schedules

Retrieve all non-deleted schedules for the current box.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  const schedules = await box.schedule.list()

  for (const s of schedules) {
    console.log(s.id, s.type, s.cron, s.status)
  }
  ```

  ```python box.py theme={"system"}
  schedules = box.schedule.list()

  for s in schedules:
      print(s.id, s.type, s.cron, s.status)
  ```
</CodeGroup>

***

### Get a schedule

Retrieve a single schedule by ID.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  const schedule = await box.schedule.get("schedule_abc123")

  console.log(schedule.type)   // "exec" | "prompt"
  console.log(schedule.status) // "active" | "paused" | "deleted"
  console.log(schedule.cron)
  ```

  ```python box.py theme={"system"}
  schedule = box.schedule.get("schedule_abc123")

  print(schedule.type)    # "exec" | "prompt"
  print(schedule.status)  # "active" | "paused" | "deleted"
  print(schedule.cron)
  ```
</CodeGroup>

***

### Pause a schedule

Pause an active schedule so it stops running.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  await box.schedule.pause("schedule_abc123")
  ```

  ```python box.py theme={"system"}
  box.schedule.pause("schedule_abc123")
  ```
</CodeGroup>

***

### Resume a schedule

Resume a paused schedule.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  await box.schedule.resume("schedule_abc123")
  ```

  ```python box.py theme={"system"}
  box.schedule.resume("schedule_abc123")
  ```
</CodeGroup>

***

### Delete a schedule

Remove a schedule so it no longer runs.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  await box.schedule.delete("schedule_abc123")
  ```

  ```python box.py theme={"system"}
  box.schedule.delete("schedule_abc123")
  ```
</CodeGroup>

***

## Schedule response

Most schedule methods return a `Schedule` object:

<CodeGroup>
  ```typescript box.ts theme={"system"}
  interface Schedule {
    id: string
    box_id: string
    type: "exec" | "prompt"
    cron: string
    command?: string[]         // present when type is "exec"
    prompt?: string            // present when type is "prompt"
    folder?: string
    model?: string
    agent_options?: Record<string, unknown>
    timeout?: number
    status: "active" | "paused" | "deleted"
    webhook_url?: string
    webhook_headers?: Record<string, string>
    last_run_at?: number
    last_run_status?: "completed" | "failed" | "skipped"
    last_run_id?: string
    total_runs: number
    total_failures: number
    created_at: number
    updated_at: number
  }
  ```

  ```python box.py theme={"system"}
  # Schedule is a pydantic model; access fields as attributes:
  schedule.id              # str
  schedule.box_id          # str
  schedule.type            # "exec" | "prompt"
  schedule.cron            # str
  schedule.command         # list[str] | None   (present when type == "exec")
  schedule.prompt          # str | None          (present when type == "prompt")
  schedule.folder          # str | None
  schedule.model           # str | None
  schedule.agent_options   # dict | None
  schedule.timeout         # float | None
  schedule.status          # "active" | "paused" | "deleted"
  schedule.webhook_url     # str | None
  schedule.webhook_headers # dict | None
  schedule.last_run_at     # int | None
  schedule.last_run_status # "completed" | "failed" | "skipped" | None
  schedule.last_run_id     # str | None
  schedule.total_runs      # int
  schedule.total_failures  # int
  schedule.created_at      # int
  schedule.updated_at      # int
  ```
</CodeGroup>

***

## Cron syntax

Schedules use standard 5-field cron expressions (UTC):

```
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sun=0)
│ │ │ │ │
* * * * *
```

| Expression    | Description         |
| ------------- | ------------------- |
| `* * * * *`   | Every minute        |
| `0 * * * *`   | Every hour          |
| `0 9 * * *`   | Daily at 9:00 AM    |
| `0 9 * * 1-5` | Weekdays at 9:00 AM |
| `*/5 * * * *` | Every 5 minutes     |

***

## Examples

### Periodic health check

Schedule a command that checks whether your service is healthy.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  import { Agent, Box } from "@upstash/box"

  const box = await Box.create({ runtime: "node" })

  await box.schedule.exec({
    cron: "*/5 * * * *",
    command: ["bash", "-c", "curl -sf http://localhost:3000/health || echo UNHEALTHY >> /workspace/home/health.log"],
  })
  ```

  ```python box.py theme={"system"}
  from upstash_box import Box

  box = Box.create(runtime="node")

  box.schedule.exec(
      cron="*/5 * * * *",
      command=["bash", "-c", "curl -sf http://localhost:3000/health || echo UNHEALTHY >> /workspace/home/health.log"],
  )
  ```
</CodeGroup>

### Daily code review agent

Schedule an agent to review recent changes every morning.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  import { Agent, Box } from "@upstash/box"

  const box = await Box.create({
    runtime: "node",
    agent: {
      harness: Agent.ClaudeCode,
      model: "anthropic/claude-sonnet-4-5",
      apiKey: process.env.ANTHROPIC_API_KEY,
    },
    git: { token: process.env.GITHUB_TOKEN },
  })

  await box.git.clone({ repo: "github.com/your-org/your-repo" })

  await box.schedule.agent({
    cron: "0 9 * * 1-5",
    prompt: "Pull latest changes, review the last 24h of commits, and open issues for any bugs or style violations",
    timeout: 600_000,
    options: { maxBudgetUsd: 2.0, effort: "high" },
  })
  ```

  ```python box.py theme={"system"}
  import os
  from upstash_box import Box, Agent

  box = Box.create(
      runtime="node",
      agent={
          "harness": Agent.CLAUDE_CODE,
          "model": "anthropic/claude-sonnet-4-5",
          "api_key": os.environ["ANTHROPIC_API_KEY"],
      },
      git={"token": os.environ["GITHUB_TOKEN"]},
  )

  box.git.clone(repo="github.com/your-org/your-repo")

  box.schedule.agent(
      cron="0 9 * * 1-5",
      prompt="Pull latest changes, review the last 24h of commits, and open issues for any bugs or style violations",
      timeout=600_000,
      options={"max_budget_usd": 2.0, "effort": "high"},
  )
  ```
</CodeGroup>

### Manage schedules

List active schedules, pause, resume, and clean up ones you no longer need.

<CodeGroup>
  ```typescript box.ts theme={"system"}
  const schedules = await box.schedule.list()

  for (const s of schedules) {
    console.log(`${s.id} — ${s.type} — ${s.cron} — ${s.status}`)
  }

  // Pause a schedule
  await box.schedule.pause(schedules[0].id)

  // Resume it later
  await box.schedule.resume(schedules[0].id)

  // Remove a specific schedule
  await box.schedule.delete(schedules[0].id)
  ```

  ```python box.py theme={"system"}
  schedules = box.schedule.list()

  for s in schedules:
      print(f"{s.id} — {s.type} — {s.cron} — {s.status}")

  # Pause a schedule
  box.schedule.pause(schedules[0].id)

  # Resume it later
  box.schedule.resume(schedules[0].id)

  # Remove a specific schedule
  box.schedule.delete(schedules[0].id)
  ```
</CodeGroup>
