Skip to main content
A job is a function the platform runs on a schedule, on behalf of an agent, with no end user talking to it. Jobs exist for work that starts from the clock rather than from a message: a morning digest, an hourly sync, a reminder three days ahead.

How a job runs

There are two kinds. A declared job is a LuaJob in your project: registered on LuaAgent.jobs, pushed as a version with lua push job --name <name>, made live with lua deploy job --name <name> --set-version latest --force or an agent version promote, and paused or resumed with lua jobs deactivate -i <name> and lua jobs activate -i <name>. A dynamic job is created while the agent runs, with Jobs.create(...) from a tool, webhook, or workflow step; it is stored as version 1.0.0 and, unless you pass activate: false, starts on its schedule immediately.
src/jobs/RenewalReminderJob.ts
A schedule has one of three shapes: { type: 'cron', expression, timezone } for recurring times, with an optional IANA timezone; { type: 'once', executeAt } for a single run at a date; and { type: 'interval', seconds } for a fixed period. timeout is in seconds, from 1 to 600, and defaults to 300; an attempt that runs over is failed. A value outside that range is rejected when the job is constructed with LuaJob `timeout` must be between 1 and 600 seconds., and a non-integer with LuaJob `timeout` must be an integer number of seconds. retry sets maxAttempts and an optional backoffSeconds (default 60; 0 is treated as 60). A failed attempt, a timed-out one included, is retried while maxAttempts allows: each retry waits a fixed backoffSeconds, with no jitter, and the platform stops after 10 attempts whatever maxAttempts says. metadata is a JSON object stored with the job and read as job.metadata inside execute; for a dynamic job it is the only way to pass data in, because the execute function is serialized to text when the job is created and cannot close over local variables. Every deployed run also receives job.execution with executionId, attempt, and occurrenceId, a key that stays the same across retries of one scheduled run; the CLI types don’t declare it yet. Two things distinguish a dynamic job. Its stored name is <name> - <timestamp>, so creating reminder twice gives two distinct jobs. And it remembers the end user who was in the conversation when it was created: job.user() returns that user. A declared job has no conversation, so job.user() there resolves to the account that pushed it, or throws User API not initialized when no end user is recorded; a declared job reaches a specific end user with User.get(userId), using an ID it kept in metadata or looked up in Data. Dynamic jobs are left out of Jobs.getAll() unless you pass { includeDynamic: true }. lua jobs trigger -i <name> runs a job immediately, outside its schedule, and lua jobs history -i <name> lists its 20 most recent executions. lua test job --name <name> runs a declared job once on your machine before you push it, and lua jobs view lists the agent’s jobs.

Jobs and workflows

A job is one function with one timeout and no memory between runs. A workflow is a graph of steps with per-step records, retries, approvals, and a schedule of its own. Use a job when the work finishes in one call and nobody needs to intervene. Move to a workflow when the work has several dependent steps, must wait for a person or an external system, needs more than 600 seconds, or should be inspectable step by step afterwards; a workflow with a schedule replaces a job whose only purpose is to call Workflows.start. A job also differs from a trigger, which starts from an external event rather than from time, and from proactive messaging, which a job often performs: the job is the schedule, and Channels.send or user.send() is the message.

When to use it

  • Agent-wide recurring work (a daily report, an hourly sync, a nightly cleanup): a declared LuaJob.
  • A follow-up tied to one end user (“remind me in an hour”): a dynamic job created from a tool, with what it needs in metadata.
  • One run at a fixed future time: type: 'once'.
  • Don’t use a job when the work must react to an event (a webhook or trigger), needs a human decision (a workflow approval), or answers the end user in the same turn (a tool).

Limits

Next steps

Schedule a recurring job

Write, test, push, and deploy a LuaJob.

LuaJob reference

Every schedule type, limit, and retry field.

Jobs reference

Jobs.create, Jobs.getAll, and JobInstance.

lua jobs

Trigger, history, activate, deactivate, and deploy.