Mirror the latest bundled-skill content for the August 5 Managed Agents
launch wave:
- Session budgets: budget object at session create (minor-unit cents
string), budget_reached pause semantics, settle-event allowlist,
session.usage event, change/remove-to-resume, multiagent shared cap
- Deployment budgets: same budget object on deployments, copied onto
each fired session, clearable and re-addable
- Inference geo pinning: inference_geo on the agent model object,
per-session override, roster uniformity, never grandfathered
- Skills from a GitHub repository: root .claude/skills discovery at
session start (cloud sandboxes only), trust-boundary warning
- Advisor: {type: "advisor", model} multiagent roster entry, reserved
anthropic.advisor thread, plaintext vs redacted delivery; advisor
tool max_uses/max_tokens/caching options and error result variant
- Multiagent: new when-to-use guidance (start with self, add cheaper
workers, dedicated specialists), delegation tools, docs URL rename
- Corrections: agent versions are sequential integers, Files API
uploads take a purpose param, stop_details refusal categories are an
open set, Sonnet 5 added to the prefill-removed list, vault_ids is
create-only on sessions, deployments gain an update endpoint
No-Verification-Needed: markdown-only skill content sync
8.2 KiB
Managed Agents — Scheduled Deployments
A scheduled deployment runs an agent on a recurring cron schedule — each firing creates a session autonomously. Use it for predictable-cadence work: nightly triage, weekly compliance scans, hourly monitors.
Requires the managed-agents-2026-04-01 beta header (the SDK sets it automatically for client.beta.deployments.* / client.beta.deployment_runs.* calls).
Create a deployment
A deployment bundles everything a session needs (agent, environment, optional files / GitHub / memory stores / vaults) plus a schedule and the initial_events that kick off each run:
agentandenvironment_idare required — same shapes assessions.create(seeshared/managed-agents-core.md).initial_eventsmust contain at least one starting event — auser.messageor auser.define_outcome. (A deployment'sinitial_eventsalso acceptssystem.message, which a session's does not.)scheduletakes a cronexpressionand an IANAtimezone. Minute-level granularity is the maximum.
curl -fsSL https://api.anthropic.com/v1/deployments \
-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
{
"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
deployment = client.beta.deployments.create(
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",
},
)
The response is a deployment object (depl_ ID prefix). Check schedule.upcoming_runs_at — the next fire times — to confirm the schedule parses the way you intended:
{
"id": "depl_01xyz",
"status": "active",
"paused_reason": null,
"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"]
}
}
upcoming_runs_at reflects the exact configured schedule, but execution is jittered to distribute load: up to 15% of the interval between runs, floored at 5 seconds and capped at 9 minutes. An hourly deployment can therefore fire up to 9 minutes late; don't build a downstream deadline that assumes the listed timestamp. Maximum 1000 scheduled deployments per organization (contact Anthropic support for more).
Cron and timezone semantics
- Expression: standard POSIX cron (
minute hour day-of-month month day-of-week). - Timezone: IANA identifier (e.g.
"America/Los_Angeles"). - DST: literal wall-clock matching —
"0 20 * * *"inAmerica/New_Yorkfires at 8:00 PM local regardless of EST/EDT.
⚠️ DST edge: wall-clock times that don't exist on a spring-forward day (e.g. 2AM) are skipped; times that occur twice on a fall-back day fire twice. Schedule outside the 1–3AM local window, or use UTC, when missed or duplicate executions are unacceptable.
Deployment budgets
A deployment accepts the same budget object as a session ({type: "limit", max_list_cost: {amount, currency}} — minor-unit cents string, USD only; see shared/managed-agents-core.md § Session budgets). The cap is copied onto each session at fire time, and that session then behaves exactly like any budgeted session.
Deployment budget update semantics differ from a session's:
budgetis accepted on create and update — it is not create-only.budget: nullon update clears it, and a cleared budget can be re-added later — there is no one-way door.- A change applies from the next fired session — sessions already running keep the cap they were created with (change those via their own session update).
Deployment runs
Every trigger attempt — successful or not — writes a deployment run record (drun_ prefix), so you can audit failures independent of the session lifecycle. A successful run carries the created session_id; follow that session via the event stream (shared/managed-agents-events.md) or webhooks (shared/managed-agents-webhooks.md) as usual. A failed run carries an error whose type explains why session creation was rejected.
# All runs for a deployment
for run in client.beta.deployment_runs.list(deployment_id=deployment.id):
print(run.created_at, run.session_id or run.error.type)
# Failures only
for run in client.beta.deployment_runs.list(deployment_id=deployment.id, has_error=True):
print(run.created_at, run.error.type, run.error.message)
for await (const run of client.beta.deploymentRuns.list({
deployment_id: deployment.id,
has_error: true,
})) {
console.log(run.created_at, run.error?.type, run.error?.message);
}
Raw HTTP: GET /v1/deployment_runs?deployment_id=...&has_error=true. To retrieve a single run by ID, GET /v1/deployment_runs/{deployment_run_id} (SDK: client.beta.deployment_runs.retrieve(run_id)) — a deployment_run.* webhook event carries the run ID as its data.id.
A failed run looks like:
{
"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", "message": "environment `env_01abc` is archived" },
"agent": { "type": "agent", "id": "agent_01ghi789", "version": 3 },
"created_at": "2026-05-09T00:00:01Z"
}
Error types include environment_archived, agent_archived, vault_not_found, session_rate_limited, and service_unavailable.
The outcome of each scheduled run (started/succeeded/failed) and each deployment lifecycle change (created/updated/paused/unpaused/archived/deleted) is also delivered as a webhook event — see shared/managed-agents-webhooks.md for the deployment.* and deployment_run.* event types — so you can react without polling. Manual runs do not emit deployment_run.* webhook events.
Lifecycle: pause / unpause / archive
| Operation | SDK | Effect |
|---|---|---|
| Pause | client.beta.deployments.pause(id) |
Suppresses scheduled triggers go-forward. Sessions already running continue. Manual runs are still permitted while paused. Sets paused_reason: {"type": "manual"}. |
| Unpause | client.beta.deployments.unpause(id) |
Resumes from the next scheduled occurrence. Missed triggers are not backfilled. Clears paused_reason. |
| Archive | client.beta.deployments.archive(id) |
Terminal — the schedule stops and the deployment can no longer be modified. Use pause for anything reversible. |
Raw HTTP: POST /v1/deployments/{deployment_id}/pause (likewise /unpause, /archive).
Failure behavior
- Rate-limited: recorded immediately as a
session_rate_limitedrun, no retry — the schedule simply tries again at the next occurrence. (Rate limits on API calls inside a session are handled by the session itself.) - Other failed runs (e.g.
environment_archived,vault_not_found,service_unavailable): the run records theerror.type— monitor runs and fix the referenced resource, or pause the deployment. - Agent archived: the deployment is automatically archived (terminal) in the same operation. Agent deleted: the next scheduled trigger detects the missing agent and archives the deployment then. Either way no deployment run is recorded, and no further sessions are created.
Manual runs
POST /v1/deployments/{deployment_id}/run (SDK: client.beta.deployments.run(id)) creates a session immediately and writes a run with trigger_context.type: "manual". Use it to test a deployment before committing to the schedule — and remember it works even while the deployment is paused.