CapabilitiesRun your Agent

Tasks and schedules

A Task is persisted configuration for running an Agent asynchronously; a Task run is one execution and owns the lifecycle state. Use Tasks for durable background work that runs on demand, once, at an interval, or from a cron schedule.

Task definitions and Task runs

A Task has a tk_… ID, Tenant and Agent ownership, a name, fixed prompt, optional Agent Version Pin, schedule, enabled state, and immutable userId Attribution. Its metadata and other mutable definition fields can be updated. Each submitted or scheduled execution creates a tr_… Task-run ID and copies the Task's Agent, resolved Version, prompt, userId, and metadata.

The Task is only the definition. activeRunId, latestRunId, and recent terminal summaries make run state visible without turning the definition itself into an execution.

Choose on-demand, once, interval, or cron

ScheduleConfigurationBehavior
On demandschedule: nullRuns only through createRun or submit: true during creation
Once{ kind: "once", config: { at } }Runs at one ISO 8601 timestamp; an overdue fire found by recovery starts immediately
Interval{ kind: "interval", config: { everyMs } }Runs on creation-anchored boundaries; minimum 60,000 ms
Cron{ kind: "cron", config: { expression, timezone, staggerMs? } }Uses five numeric cron fields and an IANA timezone; timezone defaults to UTC

Cron staggerMs optionally spreads load by a stable per-Task offset without crossing the next cron boundary. Cron scheduling disables automatic backfill, and interval reconciliation selects the next future creation-anchored boundary rather than replaying missed intervals.

Changing the schedule or enabled state advances its schedule generation so stale fires cannot create runs. Disabling a Task removes scheduled execution but does not disable its Agent, erase the definition, or prevent an explicit on-demand createRun; scheduled fires for a disabled Agent are skipped. Enabling allows the next eligible fire—skipped cron or interval fires are not added later as catch-up runs.

Run lifecycle and fresh Sessions

Public run statuses are:

GroupStatusMeaning
ActivequeuedAdmitted as the Task's active run and awaiting execution
ActiverunningExecution began and cancellation can be observed cooperatively
TerminalblockedQuota stopped the run before execution completed
TerminalsucceededThe Turn completed successfully
TerminalfailedPreparation or execution failed
TerminalcanceledA queued or running cancellation request took effect

An executing run receives one fresh ss_… Session, attached before the live Turn. Its messages persist incrementally and can be read through runMessages; a quota-blocked run can finish without a Session. The Version Pin stored on the Task is resolved when the run is enqueued; otherwise the Agent's then-current Version is recorded on the run and its usage.

Submit and inspect a run

Create an on-demand Task, submit a run with a stable idempotency key, then poll the run resource. Once terminal, read the fresh Session transcript through the Task-run operation.

const { task } = await client.tasks.create({
  agentId,
  name: "Account report",
  prompt: "Prepare the account report as concise Markdown.",
});

const { runId } = await client.tasks.createRun(task.id, {
  idempotencyKey: "account-report:2026-07-20",
});

const terminal = new Set<string>([
  "blocked",
  "succeeded",
  "failed",
  "canceled",
]);
let run = await client.tasks.getRun(task.id, runId);
while (!terminal.has(run.status)) {
  await new Promise((resolve) => setTimeout(resolve, 1_000));
  run = await client.tasks.getRun(task.id, runId);
}

if (!terminal.has(run.status)) {
  throw new Error("Task run did not reach a terminal state");
}
const transcript = await client.tasks.runMessages(task.id, runId);
console.log(run.status, transcript.data);

For a blocked run, runMessages returns an empty transcript, but sessionId depends on which quota gate stopped it. An early Task preflight blocks before Session creation, so sessionId is null; the ordinary Turn quota gate runs after the fresh Session is attached, so a run blocked there retains that Session ID with no messages. Inspect run.error and run.status to distinguish the outcome from execution failure.

Idempotency, overlap, and cancellation

An on-demand idempotency key is scoped to its Tenant and Task. Repeating the same key resolves to the same admitted run ID, including concurrent retries while that run is active. Task creation with submit: true is not idempotent because it creates a new Task and run.

At most one queued or running run exists per Task. While one is active, a new submission without an idempotency key or with a different key is rejected; a retry with the same key returns the already admitted run. A scheduled overlap is skipped without a Task-run row. Cancellation is cooperative: cancelRun records the request, queued cancellation terminalizes before execution, and a running worker stops when it observes the request.

Quotas, failures, and recovery

Task execution has an early quota preflight before Session creation or Sandbox admission. After the run attaches its fresh Session, the ordinary Turn gate checks quota again before the model and Tool loop. Either quota denial produces terminal blocked, distinct from execution failed; a Turn that starts execution is metered under the same usage model as interactive work.

Run submission directly enqueues a deterministic durable workflow. Reconciliation repairs schedule drift, and a separate repair scan re-enqueues a committed queued run if enqueue failed. Recovery returns an already recorded product outcome without rerunning the Turn; an interrupted, unrecorded attempt becomes failed. This is at-most-once Turn execution, not exactly-once execution or exactly-once external side effects.

See usage and quotas and limits and reliability for platform-wide behavior.

Reference

On this page