Claude Managed Agents sessions normally start when you call the Sessions API. A scheduled deployment is the exception: it starts sessions on its own, on a recurring cadence you configure once. Anthropic ships this as the Deployments API, part of the Claude API's Managed Agents beta, and it's the closest thing on the API side to what Claude Code's Routines do for the CLI: a saved configuration that fires without anyone in the loop.
This piece walks through creating one, the cron and timezone details that actually trip people up, budgets, watching run history, and the lifecycle operations (pause, unpause, archive).
What a scheduled deployment is
A deployment bundles the pieces a session needs (agent, environment, and optionally files, a GitHub repository, memory stores or vaults) with a schedule. Every deployment needs at least one initial event, a user.message or user.define_outcome, that starts the session's work the moment it's created; there's no equivalent of a deployment that fires with nothing to do.
All Managed Agents API requests, including deployments, need the managed-agents-2026-04-01 beta header. The SDKs and the ant CLI's beta: namespace set it for you automatically.
Creating a scheduled deployment
You need an agent and an environment already created. From there:
DEPLOYMENT_ID=$(
curl --fail-with-body -sS "https://api.anthropic.com/v1/deployments?beta=true" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d @- <<EOF | jq -er '.id'
{
"name": "Weekly compliance scan",
"agent": "$AGENT_ID",
"environment_id": "$ENVIRONMENT_ID",
"initial_events": [
{"type": "user.message", "content": [{"type": "text", "text": "Run the weekly compliance scan."}]}
],
"schedule": {
"type": "cron",
"expression": "0 20 * * 5",
"timezone": "America/New_York"
}
}
EOF
)
The equivalent with the ant CLI:
DEPLOYMENT_ID=$(ant beta:deployments create <<YAML | jq -er '.id'
name: Weekly compliance scan
agent: $AGENT_ID
environment_id: $ENVIRONMENT_ID
initial_events:
- type: user.message
content:
- type: text
text: Run the weekly compliance scan.
schedule:
type: cron
expression: "0 20 * * 5"
timezone: America/New_York
YAML
)
The response echoes schedule.upcoming_runs_at, a list of the next fire times computed from your expression, so you can sanity-check the schedule was parsed the way you intended before waiting for the first real run:
{
"id": "depl_01xyz",
"status": "active",
"schedule": {
"type": "cron",
"expression": "0 20 * * 5",
"timezone": "America/New_York",
"last_run_at": null,
"upcoming_runs_at": [
"2026-05-09T00:00:00Z",
"2026-05-16T00:00:00Z",
"2026-05-23T00:00:00Z"
]
}
}
A workspace supports a maximum of 1,000 scheduled deployments.
Cron and timezone semantics
The expression is standard POSIX cron (minute hour day-of-month month day-of-week), validated and generatable in the Claude Console if you'd rather not hand-write one. timezone is an IANA identifier such as America/Los_Angeles.
Two behaviours worth knowing before you rely on this in production:
- Actual execution is jittered. To spread load, Anthropic applies jitter of up to 15% of the interval between runs, with a floor of 5 seconds and a ceiling of 9 minutes. A daily deployment scheduled for 8:00pm might actually fire a few minutes either side of that.
- DST transitions are literal, not smoothed over. Cron matches wall-clock time in the configured timezone, so
"0 20 * * *"inAmerica/New_Yorkfires at 8:00pm local time whether the zone is currently on EST or EDT. The edge cases are the transition days: a wall-clock time that doesn't exist on a spring-forward day (like 2:30am when clocks jump from 2am to 3am) never triggers that day, and a time that occurs twice on a fall-back day fires twice. Anthropic's explicit advice: avoid scheduling inside the 1am-3am local window, or schedule in UTC, if a missed or duplicate execution would actually be a problem for you.
Setting a budget on each run
Pass an optional budget object, using the same shape as a session budget:
curl --fail-with-body -sS "https://api.anthropic.com/v1/deployments/$DEPLOYMENT_ID?beta=true" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d @- <<'EOF'
{
"budget": {
"type": "limit",
"max_list_cost": {"amount": "2000", "currency": "USD"}
}
}
EOF
amount is US cents as a string, so "2000" caps each run at about $20. This is the important part: the budget bounds every individual run, not the deployment cumulatively. A deployment that fires daily with a $20 cap can spend up to $20 each day, indefinitely, not $20 total. A session started by a deployment behaves like any budgeted session: it pauses with stop reason budget_reached once its own cost hits the cap. Unlike a session budget, a deployment's budget can be cleared later with "budget": null and reattached, since the deployment itself is a long-lived resource rather than a one-shot run.
Watching deployment runs
Every trigger attempt, successful or not, produces a deployment run record, tracked independently of whether the resulting session (if any) is still going:
ant beta:deployment-runs list --deployment-id "$DEPLOYMENT_ID"
A successful run carries a session_id you follow through the normal event stream or webhooks. Filter to just the failures:
ant beta:deployment-runs list --deployment-id "$DEPLOYMENT_ID" --has-error
{
"type": "deployment_run",
"id": "drun_01abc124",
"deployment_id": "depl_01xyz",
"trigger_context": {"type": "schedule", "scheduled_at": "2026-05-09T00:00:00Z"},
"session_id": null,
"error": {
"type": "environment_archived_error",
"message": "environment `env_01abc` is archived"
},
"agent": {"type": "agent", "id": "agent_01ghi789", "version": 3},
"created_at": "2026-05-09T00:00:01Z"
}
A session-creation rate limit is recorded immediately as a session_rate_limited_error with no retry; the schedule simply tries again next time. Deployment lifecycle changes and each scheduled run's outcome are also delivered as webhook events, so you don't have to poll deployment_runs to know when something failed.
Pause, unpause, and archive
Three lifecycle operations, each emitting a webhook event:
# Suppress future triggers; sessions already running from a prior run continue
ant beta:deployments pause --deployment-id "$DEPLOYMENT_ID"
# Resume from the next scheduled occurrence. Missed triggers are not backfilled
ant beta:deployments unpause --deployment-id "$DEPLOYMENT_ID"
# Terminal. The schedule stops and the deployment can no longer be modified
ant beta:deployments archive --deployment-id "$DEPLOYMENT_ID"
Pausing still allows a manual run through the run endpoint; only the automatic schedule is suppressed. Two failure paths pause a deployment automatically rather than leaving it silently broken: if a subagent the coordinator references has been archived, or if a needed resource such as the environment or a vault has been archived, the next trigger records a failed run and pauses the deployment, with paused_reason.error.type mirroring the failed run's error.
Triggering a manual run
To test a deployment before trusting the schedule, or to run it on demand outside the cadence entirely, call run directly:
ant beta:deployments run --deployment-id "$DEPLOYMENT_ID"
This creates a session immediately and records a deployment run with trigger_context.type: "manual", so manual and scheduled executions are distinguishable in the run history afterward.
How this compares to Claude Code's scheduling surfaces
If you already use Claude Code's Routines, the shape will feel familiar: both are saved configurations that fire independently of anyone watching, both survive your machine being off, and both support a recurring cron-style cadence with a minimum granularity in that neighbourhood (Routines cap at a one-hour minimum for recurring runs; a scheduled deployment's cron expression can in principle go to the minute). The difference is what's on the other end: a Routine runs a full Claude Code session against a cloned repository, while a scheduled deployment runs a Managed Agent inside an API-managed sandbox you configured yourself, with no coding-assistant framing at all. Pick a Routine when the job is "act like Claude Code against my repo on a schedule"; pick a scheduled deployment when you're already building on the Managed Agents API and want the same agent definition to run unattended.
Troubleshooting
A deployment never fires. Check schedule.upcoming_runs_at on the deployment object first; if it's empty or looks wrong, the cron expression or timezone was probably misread. Confirm the deployment's status isn't paused, since a paused deployment accepts manual runs but silently skips its schedule.
Runs fail with environment_archived_error or agent_archived_error. A resource the deployment depends on was archived out from under it. The deployment auto-pauses on this specific failure so it doesn't keep burning failed attempts; fix or replace the resource, then unpause.
A run's cost looks higher than the budget should allow. Budget enforcement happens between model requests, not mid-request, so the request that crosses the cap finishes first. The final cost can land slightly past the configured max_list_cost, which is expected rather than a bug.
Two runs fired at once, or a run was skipped entirely. Check whether the scheduled time falls in the 1am-3am window on a daylight saving transition day in your configured timezone. That's the one case where cron's literal wall-clock matching produces a duplicate or a gap; switching the schedule to UTC removes the ambiguity.
Where to go next
Anthropic's own scheduled deployments page is the primary reference for the full request and response schema. For the concepts a deployment builds on, see Claude Managed Agents explained and, if the coordinator you're deploying delegates to other agents, multiagent orchestration in Claude Managed Agents. For the CLI used throughout this guide, see Anthropic's ant CLI. Browse the wider catalogue at getclaudeskills.com/skills or by platform.
Verified 25 August 2026 directly against Anthropic's scheduled deployments documentation at platform.claude.com/docs/en/managed-agents/scheduled-deployments, read in full.
