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-jobplugin — 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
- Create a new subdirectory under the mounted
plugins/path (one directory per job/plugin). - Add a
plugin.jsonfile in it containing anaitm.jobsarray. - Add the script file the job's
handler.pathpoints at. - Restart the AITM container.
plugin.json shape
| Field | Description |
|---|---|
name | Unique job identifier. |
label | Human-readable name shown in the UI. |
intervalMs | How often the job repeats, in milliseconds. |
priority | Scheduling priority — see the safety note below; "high" is reserved for AITM's own internal jobs. |
timeoutMs | Maximum run time before the job is terminated. |
onTimeout | What happens when the timeout is hit. |
heavy | Marks the job as resource-intensive. |
parallel | Whether it may run concurrently with other jobs. |
concurrencyGroup | Group within which jobs never run concurrently. |
after | Jobs that must finish before this one runs. |
next | Job to run after this one finishes successfully. |
minFreeRamMb / minFreeCpuPercent | Minimum free resources required to run. |
kind | 'in-process' | 'child-process' | 'remote' — how the job executes. |
allowedModes | Server 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/overridePUT /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.