Routines
A routine makes an agent act on its own, on a schedule. It binds the events to deliver on each fire to a target — create a fresh session per run, or send the turn into an existing long-lived session — and a cron schedule. Every fire records a routine run you can list, and can push webhooks.
Create one
curl -X POST ${PUBLIC_API_BASE}/routines \
-H "Authorization: Bearer ast_..." -H "Content-Type: application/json" \
-d '{
"name": "Weekly compliance scan",
"target": { "type": "new_session", "agent": "agent_..." },
"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 echoes the routine with schedule.upcoming_runs_at — the next (up to 5) fire times — so you can confirm the cron before it runs. POST /v1/routines/{id}/run fires immediately, outside the schedule, to test it.
Two target modes
{"type": "new_session", "agent": "agent_...", "environment_id"?, "vault_ids"?}— each fire creates a fresh session (lazily provisioned) and deliversinitial_eventsas its first turn. Sessions are ordinary sessions: they show up in lists, bill normally, and keep their history.{"type": "session", "session_id": "sess_..."}— each fire sendsinitial_eventsas a turn into the same long-lived session, so the agent keeps its memory, files, and history across runs. If the session already has a turn in flight at fire time, the fire is skipped and recorded as a failed run (session_busy_error); nothing queues, and the next occurrence tries again.
Schedule semantics
5-field POSIX cron (minute hour day-of-month month day-of-week, day-of-week 0–7 with both 0 and 7 = Sunday) plus a required IANA timezone. Extended syntax (L W # ?, @daily, seconds fields) is rejected. Matching is literal wall-clock in the configured timezone: 0 20 * * * in America/New_York fires at 8 PM local year-round. On DST days, a time that doesn't exist fires at the first valid instant after the gap and a time that occurs twice fires twice — schedule outside 1–3 AM local (or in UTC) if that matters. Missed occurrences are never backfilled: any number of missed fires collapse into one at the next tick. Minimum granularity is one minute. schedule is nullable — a routine without one only fires manually.
Budgets
Pass the optional budget (same shape as a session budget — see the API reference) to bound each run separately:
- new_session mode: the cap is copied onto each session the routine creates.
- session mode: each fire grants a delta allowance — the target session's cap becomes
consumed + budgetat fire time (overwritten each run, never accumulated). The target must have been created with a budget.
Runs
Every fire attempt — scheduled or manual — records a run with exactly one of session_id or a typed error:
curl "${PUBLIC_API_BASE}/routine-runs?routine=rtn_...&has_error=true" -H "Authorization: Bearer ast_..."Unrecoverable errors (an archived or deleted agent/session/environment/vault) also pause the routine with the error mirrored in paused_reason, so you can fix the reference and unpause (which resumes from the next occurrence). Transient errors — insufficient_credits_error, rate_limited_error, session_busy_error — leave the routine active.
Lifecycle
POST .../pause suppresses scheduled fires (manual run still works); POST .../unpause resumes from the next occurrence; POST .../archive is terminal. Updates are omit-to-preserve: initial_events replaces wholesale, metadata is key-patched, schedule/budget clear with null.
Webhooks
Register an endpoint to be notified without polling:
curl -X POST ${PUBLIC_API_BASE}/webhooks \
-H "Authorization: Bearer ast_..." -H "Content-Type: application/json" \
-d '{"url": "https://example.com/hooks/agentsky", "events": ["routine_run.failed", "routine.paused"]}'The create response is the only place the whsec_... signing secret appears — store it. Deliveries carry x-asteroids-event, x-asteroids-delivery, x-asteroids-timestamp, and x-asteroids-signature: v1=<hex hmac-sha256(secret, "<timestamp>.<body>")>; verify the signature, dedupe on the event id, and fetch the resource by data.id — payloads are thin and ordering is not guaranteed. Event types: routine.created/updated/paused/unpaused/archived and routine_run.started/succeeded/failed (scheduled fires only; manual runs emit none). Failed deliveries retry twice (5s, 30s); sustained failure disables the endpoint until you PATCH {"status": "active"}.
AgentSky