Skip to content
← Docs

Workflows

A workflow composes tasks, queries, server commands and AI steps into a visual DAG — a graph of connected steps — that runs end to end, on demand, on a schedule or from a webhook. The whole thing runs as one governed agent identity, so every step is RBAC-scoped and audited like an interactive session.

Workflows are built and run from the Workflows page in the console at app.subnomic.com.

You draw the graph on a canvas, wire one step's output into the next, and the engine runs it. Crucially, the whole workflow runs as a single governed agent identity, so every step is RBAC-scoped and written to the audit log exactly like an interactive session.

Run as — the governance model

Every workflow is bound to one agent credential (you pick it when you create the workflow). That credential is the identity the workflow acts as, and it decides what the workflow is allowed to touch — which databases, servers, agents, clusters and apps, and which actions on them. Steps inherit this credential; they can never exceed it. Nothing in a workflow runs with broader access than the credential it was built under.

The effective access of a step is the credential's scopes intersected with your own permissions, and re-checked against guardrails at run time. This is the same scoped, time-boxed mechanism behind Agent access (MCP) — workflows simply drive those governed primitives from a graph instead of from a chat. Every step is audited as the bound credential.

Build a workflow

  1. Go to Workflows → New workflow. Optionally start from a template.
  2. Give it a name, an optional description, and choose the agent credential it runs as (see above).
  3. Add steps from the node palette on the left — drag a node onto the canvas, or click to add it. Every workflow starts with a single Trigger node that can't be deleted.
  4. Connect nodes by dragging from one node's output handle to the next node's input handle. The graph must stay acyclic (no loops) with exactly one trigger.
  5. Select a node to configure it in the inspector on the right — its target, SQL, command, prompt, etc., plus error handling. Select empty canvas to edit the workflow's name, credential and trigger.
  6. Save, then enable it (for scheduled / webhook triggers) or Run now.

Triggers

The trigger decides when a workflow runs. Set it on the canvas with nothing selected.

  • Manual — runs only when you click Run now (or call its webhook).
  • Schedule — runs on a recurrence (daily / weekly / monthly), or a custom 5-field cron expression, at a wall-clock time in an IANA timezone (e.g. Europe/Istanbul). The editor previews the next run. Like scheduled tasks, the time is DST-correct — it keeps firing at the same local time across daylight-saving changes.
  • Once — runs exactly once at a date + time you pick.
  • Webhook — generate a URL (in edit mode) and POST to it to start a run; the request body is delivered as the trigger input.
A webhook's token is the secret — anyone with the URL can trigger the workflow, unauthenticated. Treat it like a password: share it narrowly, and regenerate or remove it if it leaks.

Node types

The palette groups nodes by what they do: call the AI, read data, perform an action, or control flow.

  • Subnomic AI — runs an AI step against a templated prompt. The AI can use the same governed tools (queries, commands, introspection, …) the workflow's credential allows; you can restrict it with an optional tool allowlist and cap its tool-use loop with max iterations.
  • DB query — runs read-only SQL against a target database. Outputs the rows (capped), row_count and timing for downstream steps.
  • Kubernetes GET — a read (GET) against a cluster's API at a path you supply (e.g. /api/v1/pods), with an optional query string.
  • App GET — a read (GET) against an internal app at a path.
  • Server command — runs a shell command on a target server, with an optional timeout. Outputs stdout, stderr and exit_code.
  • Task — enqueues a Docker / Kubernetes action (apply, scale, restart, set image, …) on a target agent, with a JSON payload and optional timeout — the same task pipeline used elsewhere in Subnomic.
  • Create schedule — creates a scheduled task as a step (name, target agent, action, recurrence, timezone), exactly like the Scheduled tasks form.
  • Condition — branches the graph on a boolean expression (see below).
  • Manual approval — pauses the run until a person approves or rejects it, with an optional message to the approver.
  • Delay — pauses the run for a number of seconds (up to 900) before continuing.
  • Sub-workflow — calls another workflow as a step, passing optional JSON input.

Passing data between steps

Each step records its output, and later steps can reference it. Text fields (SQL, commands, prompts, paths) support templating: reference an earlier step with {{ .steps.<node_id>.<field> }} and the trigger payload with {{ .trigger.input.<name> }}. A few helpers are available: default, toJson, upper, lower, trim.

SQL (db.query):        SELECT * FROM orders WHERE user_id = {{ .trigger.input.user_id }}
Prompt (ai.agent):     Summarize these rows: {{ toJson .steps.recent_orders.rows }}
Command (server.exec): systemctl restart {{ .steps.find_service.name }}
References are strict: a typo that points at a step or field that doesn't exist fails that node rather than silently inserting an empty value — so broken wiring surfaces immediately in the run trace.

Conditions & branching

A Condition node evaluates a sandboxed expression and splits the graph into a true and a false branch — wire the next step onto whichever handle you need. Expressions are written in a safe, side-effect-free language and read step outputs directly (no template braces), for example:

len(steps.recent_orders.rows) > 0
steps.health_check.exit_code == 0

Steps on the branch that wasn't taken are skipped — they don't run and have no side effects.

Error handling

Each node (except the trigger) can be tuned in the inspector:

  • Retries — 0–5 extra attempts (with a short backoff) if the step fails.
  • On errorFail the run (default) halts the whole workflow, while Continue records the error on that step and proceeds downstream — useful for non-critical steps.

Manual approval & resume

A Manual approval node pauses the run and waits for a human. The run shows as Awaiting approval in its trace, where an approver clicks Approve (the run resumes past the node) or Reject (the run fails). Use it as a gate before a deployment or a destructive change.

Workflows are checkpointed: every step that succeeds is persisted as it completes. If a run pauses for approval — or a worker crashes mid-run — it resumes from where it left off, restoring completed steps' outputs rather than re-running them. Side effects (a command, a task, an API call) are never executed twice.

Runs & history

Every run is recorded under the workflow's Runs view: its trigger, start time, duration and status (pending / running / succeeded / failed / canceled / awaiting approval). Open a run to see the live trace — the graph colored by step status, plus each step's resolved input, output, error and linked task — which auto-refreshes while the run is in flight.

  • Run now — start a run immediately, regardless of trigger.
  • Cancel — stop an in-progress run.
  • Enable / disable — pause a scheduled or webhook workflow without deleting it.
The run engine is highly available: each pending run is claimed with a database lock, so it executes exactly once even across several backend replicas. The schedule loop runs the same way — a due workflow fires once, not once per replica.

Permissions

workflow.read workflow.write workflow.run

read covers viewing workflows and run history; write covers create / update / delete and enable / disable (including webhook setup); run covers Run now, cancel, and approving or rejecting a paused run. Beyond these, each step is additionally bound by the agent credential the workflow runs as — so the workflow can only reach targets and actions that credential is scoped for.