Skip to main content

Overview

The Jobs API allows you to dynamically create scheduled tasks from within your tools. Use this to defer work, schedule reminders, or automate recurring tasks.
Automatic User Context: Dynamic jobs created from tools automatically know which user triggered them. Use jobInstance.user() to get the user - no userId required! This is different from pre-defined LuaJob which requires User.get(userId).
Dynamically create jobs at runtime from within your tools. Pairs with the LuaJob class for pre-defined jobs.

Import

Capabilities

Dynamic Creation

Create jobs on-demand from tools

One-time Tasks

Schedule tasks for specific times

Recurring Jobs

Set up intervals or cron patterns

Automatic User Context

Jobs automatically know which user triggered them - use jobInstance.user()

Jobs API vs LuaJob

Understanding user access in different job types:
Why the difference? Dynamic jobs are created during a user conversation, so they automatically capture that user’s context. Pre-defined jobs run on a schedule with no specific user, so you must explicitly provide a userId if you want to notify someone.

Methods

Jobs.create(config)

Creates a new scheduled job.
JobConfig
required
Job configuration object
Returns: Promise<JobInstance> Example:

Jobs.getJob(jobId)

Retrieves a job by ID.
string
required
Job ID to retrieve
Returns: Promise<JobInstance> Example:

Jobs.getAll(options?)

Retrieves all jobs for the current agent.
boolean
Include dynamically created jobs (default: false)
Returns: Promise<JobInstance[]> Example:

Job Configuration

Required Fields

string
required
Unique job name
JobSchedule
required
When/how often to run the job
function
required
Function that executes when job runsSignature: (job: JobInstance) => Promise<any>

Optional Fields

string
Job description for documentation
object
Data to pass to execute functionImportant: Use metadata to pass data - the execute function cannot access parent scope!
number
Maximum execution time in secondsDefault: 300 (5 minutes)
object
Retry configuration
boolean
Whether to activate immediatelyDefault: true

Schedule Types

Once (One-time execution)

Examples:

Interval (Recurring at fixed intervals)

Examples:

Cron (Schedule with cron pattern)

Examples:

Complete Examples

Reminder Tool

Follow-up Tool

Recurring Report

Important: Metadata Pattern

Jobs execute functions must be self-contained! They cannot access parent scope variables.
Why? Jobs are serialized, bundled, and executed in an isolated sandbox. They can’t access the parent function’s scope.

JobInstance Methods

The JobInstance passed to execute functions provides:

Properties

jobInstance.user()

Gets the user who triggered the job. Returns: Promise<UserDataInstance>
Automatic User Context: This method is ONLY available for dynamic jobs created via Jobs.create(). The user context is automatically captured when the job is created from a tool. Pre-defined LuaJob must use User.get(userId) instead.
Example:
Comparison with LuaJob:

job.metadata

Access to the metadata passed during creation. Example:

job.updateMetadata(data)

Updates job metadata. Example:

job.trigger(versionId?)

Manually triggers the job execution (ignores schedule). Uses the active version by default. Parameters:
  • versionId (optional): Specific version to execute. Defaults to activeVersion.
Returns: Promise<JobExecution> Example:

job.delete()

Deletes the job (or deactivates if it has versions). Example:

job.activate()

Activates the job, enabling it to run on schedule. Returns: Promise<JobInstance> Example:

job.deactivate()

Deactivates the job, preventing it from running on schedule. Useful for jobs that should stop themselves. Returns: Promise<JobInstance> Example:

Retry Configuration

Delivery Semantics

Jobs run at least once. Each scheduled occurrence is durably queued and executed on isolated infrastructure, and a failed attempt is retried according to your retry configuration. A job may therefore run more than once for a single scheduled occurrence, so keep side effects idempotent — guard them with your own state (for example, a flag in metadata or a record in Data).
  • Retries happen only when an attempt fails, using your maxAttempts and backoffSeconds.
  • The platform caps attempts at 10 regardless of config — a higher maxAttempts is clamped to 10.
Each execution receives metadata on job.execution:
job.execution is only present when a job runs on Lua’s infrastructure. It is undefined during local lua test / lua dev runs, which execute in-process — so always read it optionally (job.execution?.occurrenceId).

Idempotency

Because a job runs at least once, design your side effects to be safe to repeat. The occurrenceId is stable across all retries of one occurrence, so it makes a natural idempotency key: record it after the side effect succeeds, and skip the work if you’ve already processed it. Attempts of one occurrence never run concurrently, so a simple check-then-write guard like the one below is safe.
Prefer occurrenceId over executionId for deduplication: executionId is re-minted on every retry, so keying on it would let each attempt’s side effect through. For scheduled jobs you can instead key on scheduledTime when you want one run per schedule slot.

Timeout Configuration

Best Practices

Give each job a descriptive, unique name
Always use metadata to pass data to execute function
Implement error handling in execute function
Execute functions are isolated - use metadata!
If a job isn’t behaving as expected, add console.log statements and check execution logs:
Then check: lua logs --type job --name my-job-name --limit 10. See the Debugging Skills guide for the full workflow.

LuaJob

Pre-defined scheduled jobs

User API

Send messages from jobs

Data API

Store and retrieve data

LuaAgent

Agent configuration

Debugging Skills

Inspect runtime return values

See Also