AITM lets you run your own periodic maintenance and automation scripts directly inside your running instance — no Docker image rebuild, no redeploy, just a container restart.

User Jobs (Scheduled Plugin Jobs)

Where the plugins folder lives

Every AITM release build (full, online, and thin Docker variants) ships a plugins-runtime/ layer baked into the image. The folder that actually matters to you, though, is the persistent, bind-mounted data volume: plugins inside your data directory — typically $AITM_DATA_DIR/plugins inside the running container, not a path inside the image.

  • It starts empty on first install.
  • On first boot, the container's entrypoint seeds it with the reference example-scheduled-job plugin — but only if that subdirectory doesn't already exist, so your own edits to that folder survive upgrades and restarts.
  • AITM re-scans the plugins directory on every container boot — so after adding or editing a job, you must restart the container for it to be picked up (no rebuild required).

Adding your own job

  1. Create a new subdirectory under the mounted plugins/ path (one directory per job/plugin).
  2. Add a plugin.json file in it containing an aitm.jobs array.
  3. Add the script file the job's handler.path points at.
  4. Restart the AITM container.

plugin.json shape

FieldDescription
nameUnique job identifier.
labelHuman-readable name shown in the UI.
intervalMsHow often the job repeats, in milliseconds.
priorityScheduling priority — see the safety note below; "high" is reserved for AITM's own internal jobs.
timeoutMsMaximum run time before the job is terminated.
onTimeoutWhat happens when the timeout is hit.
heavyMarks the job as resource-intensive.
parallelWhether it may run concurrently with other jobs.
concurrencyGroupGroup within which jobs never run concurrently.
afterJobs that must finish before this one runs.
nextJob to run after this one finishes successfully.
minFreeRamMb / minFreeCpuPercentMinimum free resources required to run.
kind'in-process' | 'child-process' | 'remote' — how the job executes.
allowedModesServer modes in which the job is allowed to run.
handler{ type: 'script', path, args, env } — what runs and how.

Worked example

An illustrative shape consistent with the shipped example-scheduled-job:

{
  "aitm": {
    "jobs": [
      {
        "name": "example-scheduled-job",
        "label": "Example Scheduled Job",
        "intervalMs": 3600000,
        "priority": "normal",
        "timeoutMs": 60000,
        "kind": "child-process",
        "handler": {
          "type": "script",
          "path": "./run.js",
          "args": [],
          "env": {}
        }
      }
    ]
  }
}

Tuning a job without redeploying

An operator can override a live job's interval, priority, or enabled state via REST, without restarting the container or redeploying:

  • GET /api/scheduler/jobs/:name/override
  • PUT /api/scheduler/jobs/:name/override

Safety: never use priority "high"

A customer-authored job must never set priority: "high" — that priority tier is reserved for AITM's own internal scheduler jobs, and using it from a custom job is not supported.

The full technical reference (job-manifest schema internals, kind/allowedModes semantics, timeout/retry mechanics) lives in AITM's own documentation.