Skip to main content

Scheduled Jobs

Scheduled events run work on a timer without a session attached — invoke an agent, run a tool, or write to an AutessaDB table, once or on a recurring schedule. They are the right home for anything that must keep running after your terminal closes, which makes them the natural counterpart to building headless.

Key concepts​

Two halves: when and what​

Every scheduled event is a scheduleSpec (when it fires) plus an actionType and its one matching action config (what it does). Get either half's shape wrong and the create is rejected — these are the two things worth reading carefully before your first call.

autessa scheduled-events create \
--eventName "..." \
--scheduleSpec '{...}' \
--actionType INVOKE_TOOL \
--toolConfig '{...}'

Schedules are tagged objects​

scheduleSpec sets a pattern plus the one nested object matching it. There are three:

PatternShapeUse
CRON{"pattern":"CRON","cron":{"expression":"0 9 * * ? *","timezone":"America/Los_Angeles"}}A recurring wall-clock schedule
EVERY{"pattern":"EVERY","every":{"value":6,"unit":"HOURS"}}A fixed interval — MINUTES, HOURS or DAYS
ONCE{"pattern":"ONCE","once":{"at":"2026-12-01T07:00:00","timezone":"America/Los_Angeles"}}A single future run

Three rules that cause most first-attempt failures:

  • cron is a nested object, not a bare string. Passing "cron":"0 9 * * ? *" fails.
  • The expression is a 6-field Quartz cron — minute hour day-of-month month day-of-week year — with no cron(...) wrapper, and ? in exactly one of day-of-month or day-of-week.
  • ONCE takes local wall-clock ISO-8601 with no Z and no offset, and it must be in the future.
EVERY needs no timezone — it is interval-based. CRON and ONCE are evaluated in the IANA timezone you name, so always set one rather than relying on a default.

Action configs nest their request​

This is the second common trap. The agent or tool id does not go directly on the action config — it goes inside a nested request object:

// INVOKE_AGENT
{ "agentExecutionRequest": {
"agentId": "K2UYSwk3Yy4i",
"input": [{ "inputType": "TEXT", "content": "Summarize yesterday's tickets." }]
} }

// INVOKE_TOOL
{ "toolExecutionRequest": {
"toolId": "8rkuLgfJaGFuG",
"variables": { "window": "24h" }
} }

Both accept continueOnError (default false) and description as siblings of the nested request. Note that an agent's input is a list of multimodal-input parts — one TEXT element for a plain prompt, not a bare string.

Scheduled runs use static values. Unlike AutessaDB triggers, there is no old/new-record substitution available — a scheduled event has no row that changed.

How to schedule a tool​

autessa scheduled-events create \
--eventName "docs_nightly_scratch" \
--description "Scratch event for CLI docs." \
--scheduleSpec '{"pattern":"CRON","cron":{"expression":"0 9 * * ? *","timezone":"America/Los_Angeles"}}' \
--actionType INVOKE_TOOL \
--toolConfig '{"toolExecutionRequest":{"toolId":"8rkuLgfJaGFuG","variables":{}}}'
{
"scheduledEvent": {
"eventId": "f2126a21-22ed-4ef6-98c7-215b3d46b099",
"eventName": "docs_nightly_scratch",
"resourceType": "TOOL",
"resourceId": "8rkuLgfJaGFuG",
"isRecurring": true,
"enabled": true,
"completed": false,
"cronExpression": "cron(0 9 * * ? *)",
"scheduleSpec": {
"pattern": "CRON",
"cron": { "expression": "0 9 * * ? *", "timezone": "America/Los_Angeles" }
},
"timezone": "America/Los_Angeles",
"nextExecutionAt": "2026-09-11T09:00:00",
"executionCount": 0,
"sharingLevel": "PRIVATE",
"userPermission": "ADMIN",
"actionType": "INVOKE_TOOL",
"toolConfig": {
"toolExecutionRequest": { "variables": {}, "toolId": "8rkuLgfJaGFuG" },
"continueOnError": false
}
},
"eventId": "f2126a21-22ed-4ef6-98c7-215b3d46b099",
"scheduleArn": "..."
}

nextExecutionAt is the field to sanity-check — if it is not when you expected, your cron expression or timezone is wrong, and it is much cheaper to catch that here than after a missed run.

The tool must be published before a scheduled event can run it. A draft-only tool creates the event fine and then fails at fire time.

How to schedule an agent​

autessa scheduled-events create \
--eventName "Daily ticket digest" \
--description "Emails a digest of yesterday's tickets each morning." \
--scheduleSpec '{"pattern":"CRON","cron":{"expression":"0 16 * * ? *","timezone":"America/Los_Angeles"}}' \
--actionType INVOKE_AGENT \
--agentConfig '{
"agentExecutionRequest": {
"agentId": "bMR35XZD37Ol",
"input": [{"inputType":"TEXT","content":"Summarize the tickets filed today and email me the digest."}]
},
"continueOnError": false
}'

The agent runs its published version, exactly as a one-shot agents execute would — but with no session and no caller, so anything it needs must come from its instructions, its tools, or the prompt you set here.

How to schedule a database write​

UPDATE_AUTESSADB performs a static write to one table when the event fires:

autessa scheduled-events create \
--eventName "Archive stale tickets" \
--scheduleSpec '{"pattern":"EVERY","every":{"value":1,"unit":"DAYS"}}' \
--actionType UPDATE_AUTESSADB \
--autessaDbConfig '{
"operation": "UPDATE",
"targetTableId": "ayXduiaLeFKh",
"values": {
"status": { "columnType": "SINGLE_SELECT", "textValue": "archived" }
},
"whereGroups": [
{ "logicalOperator": "AND",
"conditions": [{ "columnName": "status", "operator": "EQUALS", "value": "closed" }] }
],
"groupsLogicalOperator": "AND"
}'
  • operation is one of INSERT, BULK_INSERT, UPDATE, UPSERT.
  • values uses the same typed column values as every other AutessaDB write — columnType plus the one matching field (textValue, integerValue, floatValue, booleanValue, multiSelectValue, filePath, or variableValue).
  • For UPDATE, choose rows with either recordId (a single row) or whereGroups — they are mutually exclusive, and INSERT accepts neither.
  • skipIfTargetTableMissing turns a missing target table into a logged warning instead of an error.

How to list, inspect and change events​

autessa scheduled-events all --output table
eventId eventName resourceType isRecurring enabled cronExpression nextExecutionAt executionCount actionType
------------------------------------ -------------------- ------------ ----------- ------- ------------------ ------------------- -------------- ------------
ee33c922-d174-47f0-93a9-ee23777423bd Daily message digest AGENT true true cron(0 16 * * ? *) 2026-09-10T16:00:00 4 INVOKE_AGENT

Results are grouped by owned, company-shared and shared-with-you. --full opts out of the trimmed listing summary.

autessa scheduled-events get --scheduledEventId <id>
autessa scheduled-events update --scheduledEventId <id> --scheduleSpec '{...}'
autessa scheduled-events delete --scheduledEventId <id>

update takes the same fields as create — send only what changes, but if you change actionType you must supply the matching action config alongside it.

Pausing instead of deleting​

autessa scheduled-events toggle --scheduledEventId <id> --enabled false
{ "eventId": "f2126a21-22ed-4ef6-98c7-215b3d46b099", "enabled": false }

Reach for toggle while debugging. delete is permanent, and re-creating an event loses its execution history.

Sharing​

autessa scheduled-events get-sharing-details --scheduledEventId <id>

autessa scheduled-events share --scheduledEventId <id> --level COMPANY

autessa scheduled-events share --scheduledEventId <id> --level SPECIFIC_MEMBER \
--usersToAdd '[{"userEmail":"teammate@example.com","accessLevel":"READ"}]'

Same sharing model as tools, agents and tables, though the flags differ slightly — this command takes --level plus per-user accessLevel inside usersToAdd, with no top-level --accessLevel. Ownership transfer is done in the web app.

How to read execution history​

autessa scheduled-events history --scheduledEventId <id> --year 2026 --month 9
{
"executions": [
{
"id": "b45b2f61-853e-4ab6-b319-898f921e1577",
"scheduledEventId": "f2126a21-22ed-4ef6-98c7-215b3d46b099",
"eventName": "docs_nightly_scratch",
"resourceType": "TOOL",
"resourceId": "8rkuLgfJaGFuG",
"startedAt": "2026-09-10T09:56:26.005409",
"endedAt": "2026-09-10T09:56:28.810326",
"durationMs": 2804,
"status": "SUCCESS",
"scheduledFireTime": "2026-09-10T09:56:25.515",
"actualFireTime": "2026-09-10T09:56:26.005",
"attemptNumber": 1,
"payloadJson": "{\"metadata\":{...},\"payload\":{\"toolExecutionRequest\":{...}}}",
"responseJson": "{\"status\":\"success\",\"responseData\":{...}}"
}
],
"totalElements": 1
}

History is paginated by month and year, with a 0-based --page. The fields that matter when something went wrong:

  • scheduledFireTime vs actualFireTime — the gap is dispatch lag. A large one points at queue pressure, not at your action.
  • attemptNumber — greater than 1 means the run was retried.
  • payloadJson — exactly what was dispatched, so you can confirm the event carried the config you meant.
  • responseJson — what the action returned, including the error on a failure.

Because the action itself also records a run, a scheduled tool invocation appears in autessa tools history list too — tagged source: "SCHEDULED", which is how you tell a timer-driven run from an interactive one. The same data backs the History page described in Scheduled jobs.

Why this matters for headless work​

autessa login mints a tenant-scoped credential that expires in roughly eight hours, with no silent refresh. That makes the CLI a poor place to host recurring work — a cron job wrapping autessa will start failing the moment the session lapses.

Scheduled events sidestep that entirely: they run server-side with no session to expire. The durable pattern is to use the CLI to create the schedule and let the platform run it:

#!/usr/bin/env bash
set -euo pipefail

TOOL_ID=$(autessa tools create --toolName nightly_rollup --toolDescription "..." | jq -r '.tool.toolId')
autessa tools update --toolId "$TOOL_ID" --updatedTool '{...}'
autessa tools publish --toolId "$TOOL_ID"

EVENT_ID=$(autessa scheduled-events create \
--eventName "Nightly rollup" \
--scheduleSpec '{"pattern":"CRON","cron":{"expression":"0 2 * * ? *","timezone":"UTC"}}' \
--actionType INVOKE_TOOL \
--toolConfig "{\"toolExecutionRequest\":{\"toolId\":\"$TOOL_ID\"}}" \
| jq -r '.eventId')

echo "scheduled $EVENT_ID"

The script exits, your session eventually expires, and the job keeps running. Table triggers and inbound webhooks fill the same role for event-driven rather than time-driven work.

Full command reference​

10 commands9 runnable1 in the web app
CommandWhat it does
autessa scheduled-events allList the scheduled events you can access, grouped by owned, company-shared, and shared-with-you.
autessa scheduled-events createCreate a scheduled event.
autessa scheduled-events deleteDelete a scheduled event.
autessa scheduled-events getFetch one scheduled event by id.
autessa scheduled-events get-sharing-detailsRead who a scheduled event is shared with, the company-wide permission, and your own access level.
autessa scheduled-events historyList a scheduled event's execution history (each run's status, timing, and payload), paginated by month/year.
autessa scheduled-events shareShare a scheduled event with company members, or with the whole company.
autessa scheduled-events toggleEnable or disable a scheduled event without deleting it.
autessa scheduled-events transfer-ownershipWeb appScheduled-event ownership is transferred from the web app.
autessa scheduled-events updateUpdate a scheduled event's name, description, schedule, or action.