Documentation > Professional+ > Automation Engine
⭐ PRO+

Automation Engine

Server-side script automation: a versioned saved-script library, multi-host execution with per-host result tracking, multi-shell support, cron-style scheduling, and approval workflows for privileged scripts. Migrates ~328 lines of agent-side script orchestration to a Cython engine so the agent retains only a thin execution shim.

Overview

The Automation Engine owns every aspect of script execution: storing the script, tracking its version history, validating typed parameters, picking the right shell per host, dispatching to many hosts in one call, and capturing the per-host stdout/stderr. The agent's role shrinks to "run the deploy plan the server hands me" via the existing apply_deployment_plan handler.

Open Source vs Professional+

  • Community Edition: ad-hoc one-shot script runs against a single host via backend/services/script_plan_builder.py
  • Professional+: persisted, versioned saved-script library (every edit snapshots the prior body for audit / rollback)
  • Professional+: queue one execution against many hosts; per-host result rolls up into an aggregate status
  • Professional+: cron-triggered scheduled executions with last-run / next-run tracking
  • Professional+: scripts flagged requires_approval queue an ApprovalRequest reviewers must clear before the execution dispatches
  • Professional+: typed parameter declarations (string / integer / boolean / float / secret) with validation + ${name} substitution

Deploy Plan Shape

Every execution produces a deploy plan that the agent runs step-by-step: write the rendered script body to a tempfile, invoke the right interpreter, then clean up. The plan is wire-compatible with apply_deployment_plan so the same agent handler runs both Pro+ and ad-hoc paths:

{
  "files": [
    {"path": "/tmp/sysmanage_script_.sh", "content": "", "mode": 0o700}
  ],
  "commands": [
    {"argv": ["/bin/bash", ""], "timeout": N, "ignore_errors": false, "description": "..."},
    {"argv": ["rm", "-f", ""], "timeout": 10, "ignore_errors": true, "description": "..."}
  ]
}

Saved Scripts & Versioning

A SavedScript bundles a name, shell, body, typed parameter declarations, timeout, and an optional requires_approval flag. Updating an existing script bumps its version and snapshots the previous body into the version-history table; older versions remain executable for rollback / audit replays.

Endpoints

  • GET /api/v1/automation/scripts — list current versions
  • POST /api/v1/automation/scripts — create or update; auto-bumps version and snapshots history
  • GET /api/v1/automation/scripts/{id} — fetch the current version
  • GET /api/v1/automation/scripts/{id}/versions — full version history newest-first
  • DELETE /api/v1/automation/scripts/{id} — remove script + all version history

Multi-host Execution

A single POST dispatches one rendered script body to many hosts. Each host gets its own ScriptExecutionHostResult tuple tracking start / completion timestamps, return code, and captured output. The overall ScriptExecution.status rolls up from the per-host states (all-succeeded → succeeded; any-failed → failed; etc.).

POST /api/v1/automation/scripts/{id}/execute
{
  "host_ids": ["..uuid-a..", "..uuid-b..", "..uuid-c.."],
  "parameter_values": {"target_dir": "/var/www", "dry_run": false}
}

Approval Workflows

Scripts marked requires_approval dispatch into the pending_approval state and create a paired ApprovalRequest. An authorized reviewer either approves (the linked execution promotes to queued and dispatches) or rejects with an optional reason (the linked execution flips to rejected). Approvals are scoped per-execution, not per-script, so reuse is explicit.

  • GET /api/v1/automation/approvals?status=pending — pending approval queue
  • POST /api/v1/automation/approvals/{id}/approve — promote linked execution to queued
  • POST /api/v1/automation/approvals/{id}/reject?reason=... — reject with optional reason

Scheduled Execution

A ScheduledExecution binds a saved script + a host list + a cron expression. The engine validates the 5-field cron form on insert; the dispatcher polls and fires matching schedules, recording last_run and last_status. Schedules can be disabled in place without deleting the record.

Parameters & Substitution

Each script declares a list of ScriptParameter entries with a typed signature (string, integer, boolean, float, secret), a required flag, and an optional default. Submitted values are type-coerced and required-checked before the script body's ${name} placeholders are substituted left-to-right. Unknown parameter names are rejected; unknown placeholders are left untouched.

Multi-shell Support

Supported shells: bash, zsh, sh, ksh, powershell, cmd. The engine validates the script's declared shell against each target host's advertised shells (or per-platform defaults) before queueing; hosts that don't support the script's shell appear in the execution's skipped_hosts list rather than being dispatched and failing at the agent.

Feature Codes

Endpoints in this engine are gated by these feature codes (returned 402 by the open-source server when the module isn't loaded):

  • automation_script_library — saved-script CRUD + version history
  • automation_script_exec — execute / list / cancel executions
  • automation_script_schedule — scheduled executions CRUD
  • automation_script_approval — approvals queue + decisions

Architecture

The engine is a Cython-compiled binary (automation_engine.so) loaded by the open-source server's module_loader at startup. It exports the same get_module_info() + get_automation_router() contract as the other Pro+ modules, so mount_automation_routes() wires it under /api/v1/automation alongside the 402 stub routes.