Skip to main content

Scheduler — Cloud Function reference

Cron for agents — the database wakes the agent. See the Scheduler subsystem for the narrative.

createJob

Caller: authenticated agent onCall

createJob({
name: string;
cron: string; // standard 5-field cron expression
webhookUrl: string;
payload?: unknown; // forwarded verbatim to the webhook body
maxAttempts?: number; // default 5
}) => {ok: true}

Errors

CodeReason
invalid-argumentname/cron/webhookUrl missing or cron invalid
resource-exhaustedscheduler.createJob quota exhausted

Side effects

  • Writes agents/{agentId}/jobs/{name} with a freshly-generated 256-bit hmacSecret
  • Computes nextRunAt from the cron expression
  • Audit: scheduler.createJob with {cron}

dispatch

Caller: Cloud Scheduler (internal, every 1 minute) onSchedule — not callable by users

Pages up to 50 due jobs (enabled == true && nextRunAt <= now) and dispatches each:

  1. Creates a runs/{runId} doc with status: 'running', attempt: 1
  2. Signs the body: HMAC-SHA256(hmacSecret, JSON.stringify({job, payload}))
  3. POSTs to webhookUrl with header x-ujex-signature: <hex>
  4. Updates the run doc: status, responseCode, finishedAt
  5. Advances nextRunAt via the cron schedule

Your webhook

Ujex expects the webhook endpoint to:

  • Accept POST
  • Verify x-ujex-signature against the body with the hmacSecret returned at job creation
  • Return 2xx for success, any other status counts as a failed run

The request body shape:

{
"job": "daily-digest",
"payload": { "...": "whatever you passed to createJob" }
}

dlqReplay

Caller: authenticated human (owner of agentId) onCall

dlqReplay({
agentId: string;
jobName: string;
runId: string; // the specific failed run to re-queue
}) => {ok: true}

Errors

CodeReason
permission-deniedCaller does not own agentId

Behaviour

  • Updates the run doc: status: 'queued', attempt: +1
  • The next dispatch tick will pick it up

Firestore state

PathWritten byContents
agents/{agentId}/jobs/{name}createJobname, cron, webhookUrl, payload, hmacSecret, maxAttempts, enabled, nextRunAt, timestamps
agents/{agentId}/jobs/{name}/runs/{runId}dispatchstatus, attempt, startedAt, finishedAt, responseCode, error
audit/{seq}createJobscheduler.createJob event

Quota bucket

BucketCharged byCredited by
scheduler.createJobsuccessful job creationjob creation failure after meter

SLO target

The reference deployment targets dead-letter ratio < 1% of runs and the median dispatch latency under 2 minutes (cron minute + dispatch tick).