Workflows

Workflow Studio

A full development lifecycle for automation workflows — draft, validate, publish, and finalize immutable versions — plus an AI-assisted code editor and a line-by-line debugger for the languages Versus runs. Every run records exactly which version it executed.

The Workflow Builder is where you draw a workflow. Workflow Studio is everything around it that turns a drawing into a dependable, production-grade automation: a development lifecycle (draft → published → final), static validation that catches broken graphs before they run, an AI-assisted code editor for the script steps, and a line-by-line debugger that pauses a real run so you can step through it.

It exists to answer three questions every automation platform eventually has to: Which version of this workflow actually ran? Is this workflow safe to run before I run it? And when a step's code fails, why — and how do I fix it?

Introducing. Workflow Studio ships alongside the existing builder and is inert until enabled — with its features turned off, workflows behave exactly as they do today. Rollout is staged (see Safety & rollout), and every read-only capability (validation, dry-trace, the SDK reference) never touches a device.

The Versus Workflows workspace: a searchable, categorized list of built-in and custom workflows with per-card Run and Edit canvas actions and a Recent Runs panel — the surface Workflow Studio builds on with versioning, validation, and debugging.


Why it exists

Before Workflow Studio, a workflow was a single, mutable graph. Editing it changed the definition immediately — including for runs already in flight and for the history of past runs, which read the same live graph. There was no way to say "publish this version and leave it alone," no check that a graph was even runnable until a step failed mid-run, and when a Python or HTTP Request step raised, you saw the exception type and message but not the line, the traceback, or what the code was actually doing.

Workflow Studio closes each of those gaps:

GapBeforeWith Workflow Studio
Which version ran?Runs read the live graph; edits rewrote historyRuns pin to an immutable version snapshot
Is it runnable?Discovered at runtime, as a failed stepValidated before publish, with a hard gate
Why did the code fail?Exception type + message onlyFull traceback, stdout, and a versus.* call trace
How do I fix it?Read the docs, guess, re-runAsk AI to fix — a grounded diff — or set a breakpoint and step through
Safe to change a production workflow?An edit was a production changeDraft freely; publish and finalize deliberately; roll back

The lifecycle: Draft → Published → Final

Every workflow now has three states, mirroring how you'd release any piece of software:

  • Draft — the live, editable graph. This is what you change in the builder. Drafts are never what production pins to.
  • Published — an immutable snapshot of the draft at a point in time, with a version number and an optional label. Publishing freezes the graph, its inputs, and its validation result so it can never drift.
  • Final — the one published version that production runs pin to. Promoting a version to Final archives the previous Final.

Workflow Studio versions page for the demo workflow, listing published version v1 with its state, label, publish time and run count, each row offering Set as Final and Restore to draft, above a Compare panel that diffs any two versions or the working draft.

The Versions page (opened from the Versions button in the editor) lists every published snapshot with its state, label, publish time, and how many runs pinned to it. From here you can promote any version to Set as Final, or Restore to draft to pull an old snapshot back onto the canvas as your new working draft — a one-click rollback.

Comparing versions

The Compare panel diffs any two versions — or a version against the current working draft — and reports exactly what changed as a structured node diff: N added · N removed · N changed, with the specific nodes listed. Before you promote a version, you can see precisely how it differs from what's live today.

The Compare panel on the Versions page set to v1 (published) → Working draft, summarizing the difference as 0 added · 0 removed · 1 changed and listing the one changed node — the Buggy Python Step, with its config marked as the change.

In the comparison above, the working draft has one edited step since v1 was published — the diff pinpoints exactly that node (Buggy Python Step, config changed) rather than leaving you to eyeball two graphs.

Run pinning

Because a run records the exact snapshot it executed, "which graph ran?" is always answerable. A run launched against a finalized workflow carries that version's frozen graph — editing the draft afterward has no effect on it, and re-opening a historical run shows the graph as it was, not as it is now.


Validate before you ship

Workflow Studio statically analyzes a graph and reports problems before a run — as you edit (soft, advisory) and again as a hard gate on publish (a graph with errors can't be published).

The Workflow Studio Demo open in the builder after validation, showing a clean Start → Buggy Python Step → End graph and a green "valid" pill next to the lifecycle bar's Validate, Publish version, Debug and Versions buttons.

Click Validate in the lifecycle bar and the result appears as a pill — valid, or a count of errors and warnings. Open the issues panel and each finding is clickable: selecting it highlights the offending node on the canvas. Nodes with a problem also carry a small badge (a red ring for an error, amber for a warning) so you can spot them at a glance.

Validation catches the classes of defect that otherwise surface only at runtime:

CheckSeverityWhat it means
No Start / multiple StartErrorA workflow needs exactly one entry point
Unknown stepErrorA node references a step key that isn't installed
Missing required configErrorA step is missing a value it can't run without
Dangling edgeErrorAn edge points at a node that isn't there
Unreachable nodeErrorNothing connects to this node — it can never run
Unbound decision branchErrorA Decision's yes/no path isn't wired
Dead endWarningA path that doesn't reach an End node
CycleWarningThe graph loops back on itself

Publishing and finalizing

When a draft validates, Publish version freezes it into a new immutable snapshot. Publishing runs the full validation as a hard gate — if the graph has errors, publishing is blocked and the errors are shown, so a broken graph can never become a version.

Once you've published, Set vN as Final promotes that snapshot to the version production pins to. A finalized workflow shows a Finalized badge in the lifecycle bar; if you then edit the draft, the badge notes "draft has unpublished edits," so it's always obvious when what you're looking at differs from what's live. On production workflows, finalizing is where an approval step belongs — publish is the developer action, finalize is the release.

Rolling back is the same machinery in reverse: Restore to draft on an earlier version, re-publish, and finalize — or simply set an earlier published version as Final again.


The code editor

Four step types run code you write — Python Script and HTTP Request (Python), Ansible Playbook (YAML), and structured payloads for Terraform, Rundeck, AS3, and Webhook steps. Workflow Studio gives all of them a proper editor, and gives the Python steps an AI collaborator and a debugger.

The Workflow Studio Demo in the builder: the step palette on the left (Structure, Custom, and vendor step libraries), a Start → Buggy Python Step → End graph on the canvas, and the Python Script node's properties panel on the right with an AI Assist button, an SDK Reference link, and a Monaco code editor showing the script with a breakpoint dot in the gutter.

Select a script step and its panel opens on the right with a full Monaco editor (the same engine as VS Code): syntax highlighting, multi-cursor, find-and-replace. The panel is resizable — drag its left edge to give the code as much room as you need, and the width persists. Two tools sit above the code:

  • AI Assist — describe what you want in plain language and the assistant writes, completes, explains, or refactors the script. Every suggestion comes back as a diff you review and Accept or Reject, never as a silent whole-buffer replacement.
  • SDK Reference — a live, always-current reference for the versus SDK available inside a Python step. It's generated by introspecting the actual SDK at runtime, so it never drifts from the code — every method the platform exposes is listed with its signature. That includes native per-vendor troubleshooting — versus.probe(device_id, kind), versus.available_probes(device_id), and versus.vendor_family(device_id) call the same read-only drivers Diagnostics AutoPilot uses (NetScaler, PAN-OS, FortiGate, Check Point, Cisco ACI/ASA/IOS-XE/NX-OS, Arista, AVI, Kemp, Alteon, NSX-T, Infoblox, Cloudflare, AWS/Azure LB, and more), so a workflow can pull HA state, virtual-server health, or config objects from any supported device in one call.

The AI editor is grounded in two things at once: the live SDK reference (so it only calls methods that exist) and, when you invoke it from a failed run, that run's traceback (so a fix is aimed at the actual error). Under the hood it uses the platform's standard, governed LLM path — the same one the rest of Versus uses.

Autocomplete. As you type versus. in a Python step, the editor suggests every method on the SDK — name, signature, and documentation inline — drawn from that same live reference, so the completions never drift from the real SDK. Typing versus.integrations. narrows to the integration providers (Slack, Jira, ServiceNow, vSphere, IPAM, SIEM, SCM, Rundeck, AWX, …). Press Ctrl+Space to invoke it manually.


Passing data between steps

A workflow is a graph, not an event bus — there is no publish/subscribe or event-emitter in the SDK. Steps hand results forward through a run-scoped context: a shared key/value store that lives for the length of one run.

  • Produce — in the step that computes something, call versus.set_output("key", value). (In an HTTP Request step it's http.set_output(...).)
  • Consume — in any later step, read it back with versus.get_input("key", default); the default is returned only if nothing upstream set that key.
  • Branch on it — a Decision node routes down its green yes / red no path based on a boolean flag in that same context, so an upstream step can steer the rest of the workflow by setting a flag.

Because the context is snapshotted per step, the debugger's Locals panel and each step's recorded context show exactly what that step saw coming in and what it produced.

"Events" in the SDK. There is no event-subscription model — the graph is the control flow, and steps pass data with the outputs above. The one place the word appears is a vendor probe kind: versus.probe(device_id, "events") fetches recent events/logs from a device that supports it — a read, not a subscription. (Workflows are triggered by schedules or webhooks, but that's a workflow-level trigger, not something a step's code subscribes to.)


Debugging a run

When a script step fails, the run view tells you everything about why, not just that it failed.

A failed Workflow Studio Demo run titled "Nightly reachability check": the Buggy Python Step is marked failed with Mark Complete and Redo step actions, the step log shows the run's output followed by a Python traceback pointing at the workflow script, a red TRACEBACK panel with an "Ask AI to fix" button, and a versus.* call trace listing the SDK calls the script made.

Every failed script step captures:

  • The full traceback, rewritten so line numbers refer to your script (<workflow-script>, line N) rather than the platform's internals — the traceback points straight at the line you wrote.
  • Everything the script printed (stdout/stderr), interleaved into the step log with timestamps.
  • A versus.* call trace — every SDK call the script made, in order, with mutating calls, read-only calls, and errors marked. It's how you see what the code actually did before it broke.

The step keeps the operational actions it always had — Mark Complete (accept it and move on), Redo step (retry it), and Back-Out on the run — so debugging and running are the same view.

Ask AI to fix

Press Ask AI to fix on a failed step and Workflow Studio sends the AI editor the step's code and the captured traceback, and asks for a corrected version.

The same failed run after pressing Ask AI to fix: a "Suggested fix (diff)" panel shows the AI's corrected script as a colored diff, with a "Copy fixed code" button and a note to review the diff, copy the fixed code, and paste it into the step's code panel in the editor.

The suggestion appears right under the traceback as a diff — the fix in context, not a wall of new code. Review it, click Copy fixed code, and paste it into the step's code panel back in the editor. Because the fix is grounded in the real traceback and the live SDK, it targets the actual failure rather than guessing.

Stepping through the code

For anything a traceback alone won't explain, set a breakpoint and step through a real run. There are two kinds, and they work together:

  • Step breakpoints — on any node. Select the node and tick Breakpoint at the top of Node Properties; a red dot appears on the canvas node. This works for every step, including catalogue steps (a Check Point upgrade check, an F5 UCS save) whose code is fixed: a Debug run pauses right before the step runs, so you can inspect the run context — every variable earlier steps produced — and decide what happens next.
  • Line breakpoints — inside a Python Script step. In the step's code editor, click the thin margin immediately to the left of the line numbers (the glyph gutter) beside any line — a red dot marks the breakpoint (click it again to remove). The run pauses on that line with the script's locals visible.

Then press Debug in the lifecycle bar. With no breakpoints of either kind set, Debug pauses before every step instead, so you can walk the whole workflow one step at a time.

When a run is paused before a step, the run view shows the step as paused, the run context in a card at the top, and three controls: Continue (run on to the next breakpoint, or the end), Step (run just this step, then pause before the next one) and Cancel.

A paused Workflow Studio Demo debug run: the Buggy Python Step is paused, the run view shows the whole script with the current line highlighted and a marker in the margin, a Locals panel listing the in-scope variables and their values, and Step, Continue and Stop controls.

When the run hits a breakpoint it pauses and the run view shows:

  • The whole script, with the line it's paused on highlighted and marked in the margin, so you always see where you are in context.
  • Locals — every in-scope variable and its current value, redacted for secrets.
  • Step Into, Step Over, Continue, and Stop — advance one line (entering any function you defined in the script), run the current line's calls to completion and pause at the next line at this level, run to the next breakpoint (or the end), or abort.

The debugger drives a genuine execution — the same code, the same SDK, the same data a normal run sees — so what you observe is exactly what runs. Resume commands are delivered through the database, so stepping works even though the run executes on a different worker than the one you're clicking in.


Test modes

A run doesn't have to touch production. Workflow Studio adds run modes alongside the normal live run:

  • Dry-run — walks the graph and resolves every target and step without executing the side effects. Steps that would change a device are recorded as simulated instead of run, so you can preview the whole path a workflow would take.
  • Lab — a real execution deliberately aimed at a non-production device group, for exercising a workflow end-to-end before it ever sees production.

Both are recorded distinctly on the run, so a dry-run or lab run is never mistaken for a production one.


Safety & rollout

Workflow Studio is built to be adopted gradually and to be invisible until you want it:

  • Inert by default. The lifecycle, the code IDE, and the isolated code runner are each behind their own feature flag. With them off, workflows behave exactly as they do today — the same builder, the same runs.
  • Read-only where it counts. Validation, dry-trace, the SDK reference, and version diffing never touch a device.
  • Publishing is gated. A graph with validation errors cannot be published, so a broken workflow can't become a version at all.
  • Runs are interruptible. A Stop on a running or hung script actually interrupts it, and an optional isolated subprocess runner executes step code in a separate, killable, resource-limited process — so a runaway script can be stopped hard rather than left to spin.
  • Nothing is lost. Publishing never deletes a draft; finalizing archives the prior Final rather than discarding it; restoring an old version to draft leaves every published snapshot intact.

Quick reference

ActionHow
Validate a workflowValidate in the lifecycle bar; issues panel highlights the offending node
Freeze the current draftPublish version (blocked if validation fails)
Make production use a versionSet vN as Final
See every version + diffVersions → Compare any two versions or the draft
Roll backRestore to draft on an earlier version, or set it as Final again
Get AI help writing a stepAI Assist in a Python/HTTP step → review the diff → Accept
Look up the SDKSDK Reference in a Python step (always current)
Autocomplete the SDKType versus. (or versus.integrations.) in a Python step; Ctrl+Space to invoke
Pass data to a later stepversus.set_output("k", v) upstream → versus.get_input("k") downstream
Understand a failureOpen the failed run → traceback, stdout, and versus.* call trace
Fix failing codeAsk AI to fix → review the diff → Copy fixed code
Pause before any stepSelect the node → tick Breakpoint → Debug → Continue / Step / Cancel (nothing set = pause before every step)
Step through codeClick the margin left of the line numbers in a Python step to set a line breakpoint → Debug → Step Into / Step Over / Continue / Stop
Preview without side effectsRun in dry-run mode

Related