Triggo Documentation
Workflow Builder

Activation and Versioning

How draft workflows become live, and how to roll back to a previous version.

Activation and Versioning

A workflow moves through a small, predictable set of states. This page explains what each state means, how to promote a draft into production, and how to roll back when you need to.

The lifecycle at a glance

Under the hood, every workflow has one of five statuses:

StatusWhat users seeMeaning
blueprintDraftNever activated. You're still building it on the canvas.
active_waitingLiveActivated and waiting for its trigger to fire.
active_runningRunningCurrently executing at least one run.
stoppedStoppedActivated previously, then deactivated. Trigger is no longer listening.
errorErrorAuto-stopped after repeated failures (see error handling).

Allowed transitions:

  • blueprintactive_waiting (first activation)
  • active_waitingactive_running (the executor flips this as runs start and finish)
  • active_waiting / active_runningstopped or error
  • stopped / erroractive_waiting (re-activation)

You'll hear the states called "draft", "live", and "stopped" in the UI. The underlying enum values are what you'll see in API responses and logs.

Publishing (activation)

The canvas edits the draft; a single trigger-aware primary action button handles every publish path. What that button reads depends on whether you've picked a trigger and, if so, which kind.

No trigger yet. A fresh canvas shows Add trigger. You pick a trigger before anything else happens — there's no path forward without one.

Event-driven workflows (inbound webhook, schedule, polling connectors like Telegram or Gmail) publish by clicking Activate. The button is disabled while the draft has any validation errors — the toolbar shows an error badge with the count. Clicking it deploys the draft as a new immutable version AND wires the trigger up to the outside world (webhook subscriptions go active, Telegram webhooks are set, polling triggers get a BullMQ repeatable job). Once the workflow is live, the same primary button becomes Stop, which reverses the external wiring: webhooks are unregistered (onDisable), schedule jobs are removed, subscriptions marked inactive. You can re-activate a stopped workflow — including one that auto-stopped after repeated failures — by clicking Activate again.

Callable workflows (system manual trigger, used for AI-agent actions and workflows published as actions) follow a two-step path:

  • On the very first deploy the primary button is Activate. The initial-deploy mechanics are the same as for event-driven workflows (snapshot the draft, bump the version, validate the DAG), but there's no external wiring to register — callable workflows are invoked on demand by agents, not by external events.
  • After that first deploy the primary button becomes Publish Action. Publishing snapshots the current draft as a new version and makes it visible to list_actions so agents can call it. Publish Action is enabled only when the workflow has a Return Output node, so agents have a defined response shape. A secondary Run manually button lives next to Publish Action for one-off testing while you iterate.

Validation errors block the primary button in every path. The service checks:

  • Complexity limits — node count, edge count, depth.
  • Type-specific shapecallable workflows must have exactly one Action Input node and at least one Return Output. event_driven workflows must have a valid trigger node.

If validation fails the deploy is refused and the toolbar surfaces the error count.

The older Launch button and the workflow-card Launch/Stop controls have been removed — the canvas toolbar now owns the primary action end-to-end. Mid-flight draft edits on a live event-driven workflow still surface Apply changes / Discard changes buttons next to the primary action; those let you publish a draft on top of an already-running version without stopping it.

How activation reaches the outside world. For event-driven workflows, Activate does more than snapshot a version — it calls activateTrigger(), which registers webhooks, marks inbound webhook subscriptions active, and schedules polling jobs via BullMQ. Only after the external side succeeds does the workflow move to active_waiting. Stop reverses all of this.

What gets versioned

Versioning covers the workflow definition only — the nodes, edges, and per-node configuration that make up the DAG. Each deploy produces a workflow_versions row with status: "deployed", previous deployed/draft rows are marked archived, and a fresh status: "draft" row is created on your next edit.

Credentials are not snapshotted. A node that references an AmoCRM or Google connection resolves those credentials at run time from the connections table. This has a deliberate consequence:

  • Rotating a connection's credentials takes effect immediately on the currently active version — no re-deploy needed.
  • Rolling a workflow back to an older version does not roll back the credentials it uses. If that connection has since been disconnected or re-authorized, the restored version picks up the current state.

Schedules, webhook subscriptions, and run history are also kept outside the version snapshot.

Version history and revert

You can view prior versions from the canvas toolbar's version dropdown. Selecting an older version loads it into the canvas in read-only preview mode and shows a banner at the top: "Restore this version". Clicking that button calls the workflow.restoreVersion tRPC mutation, which copies the chosen version's definition into a new draft. From there you deploy it like any other change — the restored draft goes through the same validation and becomes the newest deployed version.

There's also a workflow.revert endpoint used for some AI-driven flows, and workflow.archiveVersion for housekeeping. Restore is the path most users take.

Reverts don't delete history. The old deployed version stays in the table as archived and remains visible in the dropdown.

Stopping and deactivating

When an event-driven workflow is active_waiting or active_running, the canvas toolbar's primary action is Stop. Clicking it calls the tRPC workflow.pause endpoint, which moves the status to stopped and invokes deactivateWebhooks() — each trigger's onDisable runs, polling jobs are removed, and subscriptions are marked inactive.

Once stopped, the trigger is no longer listening. Inbound webhook events for a stopped workflow are dropped by the webhook router — they are not queued for later replay. Scheduled triggers simply don't fire while stopped.

To restart, click Activate — the same primary button flips back once the status is stopped (or error). Triggo re-registers the external webhook or re-schedules the polling job before flipping the status back to active_waiting.

Auto-stop on repeated failures

Triggo will stop a workflow on your behalf if it fails three consecutive runs. When that happens the status moves to stopped (tracked via Redis key autopause:{workflowId}:failures), and you'll see it in the workflow list with an error context. See error handling for the full auto-pause mechanics and how to recover.

On this page