Skip to main content
Workflows let you run on-demand operations — restarts, migrations, backfills, data exports — across one or more job agents. Unlike deployments, workflows are not tied to versions or release targets; they accept typed inputs at runtime and fan out jobs to whichever agents match the conditions you specify.

Core Concepts

Specifying Inputs

Inputs are declared in the inputs array of a workflow. Each input has a key, a type, and an optional default.

Scalar inputs

Array inputs

There are two kinds of array inputs: Manual array — the caller provides a list of items directly:
Selector array — dynamically resolved from your inventory using a CEL expression. Instead of the caller listing items, Ctrlplane queries entities matching the selector:
entityType can be resource, environment, or deployment. The default is a CEL expression used when the caller does not override the selector.

Input resolution

When a run is created, Ctrlplane merges the caller’s provided values with the workflow’s defaults:
  1. Start with the values provided by the caller.
  2. For each input defined on the workflow, if no value was provided, apply the default (if set).
  3. The final merged map is stored on the WorkflowRun record and passed to every dispatched job.
If the caller omits an input and no default is defined, that key will not appear in the resolved inputs.

Wiring in Job Agents

The jobAgents array defines which executors the workflow uses. Each entry has:

Selector evaluation

Before dispatching, Ctrlplane evaluates each agent’s selector against the dispatch context:
Use "true" to always dispatch to this agent, or write a CEL expression to make it conditional:
This lets a single workflow definition fan out differently depending on what the caller provides — e.g., only trigger a manual approval agent for production. Multiple agents can run in the same workflow run: every agent whose selector evaluates to true receives its own job.

Templating Inputs into Job Agents

Both config values and the selector field support Go text/template syntax. Templates are rendered before dispatch using the same dispatch context:

Example: GitHub Actions

When the run is created with { "repo": "api-service", "branch": "main" }, the rendered config becomes:
This rendered config is stored on the Job record and passed to the job agent dispatcher. The agent then uses it to construct the actual dispatch call (e.g., the GitHub API workflow_dispatch event).

Conditional agent selection

The approval agent only runs when environment is "production".

Full Example: Database Migration Workflow

This workflow runs a database migration via GitHub Actions, with a dry-run option and environment targeting.

Workflow definition (API)

GitHub Actions workflow

The GitHub Actions workflow receives a job_id from Ctrlplane. Use the ctrlplanedev/get-job-inputs action to fetch the resolved inputs:
Workflow inputs are surfaced on the job as inputs_<key> outputs by get-job-inputs.

Triggering a run (API)

If dry_run were omitted, Ctrlplane would fall back to the default true.

Example: Multi-Agent Workflow (GitHub + Terraform Cloud)

A single workflow can dispatch to multiple agents simultaneously. Here, a restart workflow notifies Slack via GitHub Actions and triggers a Terraform Cloud run to scale down and back up:
The notify agent runs for every environment. The terraform-restart agent only runs when targeting production.

Terraform Provider

Use the ctrlplane Terraform provider to manage workflows as code.

Create a workflow

Reference other resources

API Reference

Create workflow run request body

Only inputs is required. Omit keys to use their defaults; keys with no default and no provided value will be absent from the dispatch context.

How It Works Internally

  1. Input resolution — user-provided values are merged with defaults declared on the workflow.
  2. Selector evaluation — each agent’s selector CEL expression is evaluated against { workflow, inputs }. Only agents whose selector returns true receive a job.
  3. Job creation — a Job is inserted with the rendered jobAgentConfig and the full DispatchContext (which includes the resolved inputs).
  4. Job dispatch — the workspace engine picks up the job and calls the agent-specific dispatcher (GitHub, TFC, ArgoCD, etc.).
  5. Status tracking — agents report back via webhooks or the Ctrlplane API, updating job status in real time.

Next Steps

GitHub Actions

Wire up GitHub Actions as a job agent

Terraform Cloud

Trigger Terraform Cloud runs from workflows

ArgoCD

Sync ArgoCD applications on demand

Argo Workflows

Execute Argo Workflow templates