> ## Documentation Index
> Fetch the complete documentation index at: https://docs.os.default.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflows

> Automate what happens when leads come in: route, enrich, notify, and book.

Workflows automate what happens after something occurs in your workspace. A workflow starts
from a **trigger** (a form submission, an incoming webhook, a meeting status change, a new CRM
record, and more) and then runs a series of **steps** that route the lead, enrich it, update
your CRM, send a notification, book a meeting, or call an outside system.

<Note>
  Open **Workflows** to see every workflow in your workspace. Select one to open it in the
  builder, or create a new one.
</Note>

## Triggers and steps

Every workflow has two kinds of building block:

* A **trigger** starts the workflow. Each workflow begins with exactly one. See
  [Triggers](/workflows/triggers) for the full list.
* **Steps** are the actions that run after the trigger fires, laid out on a canvas. A step
  can route a lead, write to your CRM, add someone to a sequence, send a Slack message, show
  a scheduler, branch on a condition, and more.

## The workflows list

Opening **Workflows** shows every workflow in your workspace.

* **Folders**: tabs across the top group your workflows. **All Workflows** shows everything
  and **Unfiled** shows workflows with no folder; folders you create appear alongside them.
  Use the folder menu to rename, reorder, or delete a folder.
* **Filter by**: narrows the list. Under **Status**, choose **Active**, **Draft**, or both.
  Under **Trigger**, choose one or more trigger types to show only workflows that start that
  way.
* **Created by**: a separate dropdown to show workflows from **All creators**,
  **Created by you**, or a specific teammate.

Each workflow's card shows a status badge: **Draft** (never published), **Paused** (published,
but turned off), or **Active** (published and turned on).

## Create a workflow

<Steps>
  <Step title="Open the Workflows app">
    Select **Workflows** to see your list of workflows.
  </Step>

  <Step title="Create a new workflow">
    Select **Create workflow**, give it a name, for example `Inbound demo requests`, and
    confirm. The workflow opens in the builder.
  </Step>

  <Step title="Choose a trigger">
    Add a trigger to define what starts the workflow, then add the steps that follow.
  </Step>
</Steps>

## Add a step

Steps sit on the builder canvas as connected nodes; drag from one step to another to connect
them, or branch a step into more than one path. Select **Add Node** to open the step picker,
then choose a step. Steps are grouped by what they do (routing, CRM, notifications,
enrichment, and so on). Each step you add starts unconfigured; open it to set it up.

## Insert data from earlier in the workflow

Most fields accept values pulled from the trigger or from an earlier step, so a CRM field, a
Slack message, or a webhook body can carry the lead's real data. Type `{{` in a field to open
the data picker (or select the **{ }** button in the field's toolbar). It groups values under
**CRM**, **Enrichment**, **AI**, **Slack**, **Default Objects** (the person and company details
every trigger provides), and **Workflow** (scheduling and meeting details, the trigger data,
and any values earlier steps produced).

In a Slack message field, type `@` instead (or select the **@** toolbar button) to open a
separate picker for mentioning people: mapped Slack recipients, user groups, and upstream
references, such as an account owner, that resolve to a real Slack user when the message
sends. Outside Slack message fields, `@` has no special meaning; use `{{` there.

## The Enabled switch

Each workflow has an **Enabled** switch, in the builder toolbar and in the workflow's details
panel. Turn it on to let the published version run for live traffic; turn it off to pause the
workflow without deleting anything. The switch stays off until the workflow has been published
at least once.

## Test a workflow

Select **Test** to open the **Test Workflow** panel, choose the trigger to fire, edit its
sample payload, then select **Run Test**.

For a workflow that starts from a CRM record trigger, the payload opens as a record already
listing its identifying field (for example, email or domain) and any fields your trigger's
condition checks. Every listed field starts blank; fill in real values before you run the
test. Testing isn't available yet for workflows that start from a **Meeting Status** trigger.

<Warning>
  A test performs real actions: it can create or update CRM records, and it sends any
  configured messages or webhooks for real. Use test data you are comfortable sending through.
</Warning>

## Publish a workflow

Your edits save to a **draft** automatically. The draft does not run for live traffic until
you publish it.

* Select **Publish** to make the current draft live. Once published, the button reads
  **Publish changes** when you have unpublished edits, and **Up to date** when the live
  version matches your draft.
* Each publish creates a new version, so you can see what was live and when.

Each workflow has one draft, shared by everyone in your workspace. Publishing takes the whole
draft live, including any unpublished changes your teammates made.

While you edit, a banner shows whether you are editing the draft or viewing a published
version, with a count of unpublished changes.

### If more than one person is editing

Everyone works on the same draft, so there is no separate copy per person and nothing to merge.

* Publishing publishes everything in the draft, yours and your teammates'. If someone is still
  part-way through a change, publishing takes that unfinished change live too. Agree on who
  publishes, and publish once you are both finished.
* Editing different steps is safe: both sets of changes land. If you both edit the **same** step,
  each save writes that step's whole configuration, so the last save replaces the earlier one.
  Split the work by step to avoid this.
* The builder does not show who else is in the workflow with you, and it does not update live as
  they work. Reload the page to pick up their latest changes before you publish.
* The workflow's details panel shows **Modified**: who changed the workflow last, and when.

### Version history

Open the workflow's details panel and select **Version history** to see every published version,
newest first, with who published it and when. **Current Version** at the top is the draft you are
editing.

* Select a version to view it on the canvas. Past versions are read-only, and a banner offers
  **Back to draft**.
* Select **Restore to draft** to bring a version back for editing. Use this to undo an unwanted
  publish, or to recover a change captured in an earlier published version. Version history holds
  published versions only, so a draft edit that was overwritten before anyone published it was
  never captured and cannot be restored.
* Restoring replaces the whole draft with that version, so any unpublished changes in the draft
  are discarded, including your teammates'. Check with them first.
* Restoring does not publish anything and does not change the **Enabled** switch. Review the
  restored draft, then publish it when you are ready.

## Review past runs

Open a workflow's **Logs** tab to see every past run: the version that ran, the record it
processed, the trigger, and whether it succeeded. See [Run logs](/workflows/run-logs) for a
full walkthrough.

## Step references

* [Actions](/workflows/steps-actions): Send to Webhook, Redirect, Date Transformer, Create
  Variable
* [CRM](/workflows/steps-crm): create, match, and update records and activities, create
  associations, and convert a Salesforce lead
* [Sequencing](/workflows/steps-sequencing): add people to Apollo, Outreach, Salesloft,
  Amplemarket, Gong, HubSpot, and Smartlead
* [Notifications](/workflows/steps-notifications): Slack messages and channels, internal email
* [Enrichment](/workflows/steps-enrichment): enrich people and companies, geolocation
* [Routing and scheduling](/workflows/steps-routing-scheduling): round-robin assignment, show
  a scheduler
* [Logic and timing](/workflows/steps-logic-timing): branch on conditions, split traffic for
  an experiment, and add a delay
* [AI](/workflows/steps-ai): prompt a model and use its response in later steps

{/* TODO screenshot: the Workflows builder canvas with a trigger and a few steps */}

{/* TODO screenshot: the {{ data picker and the @ Slack mention picker side by side */}

{/* shared-draft, multi-editor, and Version history sections verified against product (origin/main as of 2026-07-29):
   one shared draft per workflow = all workflow_nodes / workflow_edges / triggers rows at version_number 0, keyed by
   workflow with no per-user column
     → packages/core-db/src/schema/{workflowVersions,workflows}/index.ts
   publish snapshots every v0 row into a new immutable version (max(version) + 1) in one transaction, and does not
   touch is_enabled
     → apps/default-api/src/server/modules/workflows/mutations.ts (publishWorkflow)
   same-step last-write-wins: updateNode is an unconditional UPDATE on (id, version_number 0) with no optimistic
   concurrency or updated_at guard, and it writes the whole config_bindings object; an open config panel also prefers
   its local draft over incoming server state, so the overwriting editor sees no conflict
     → mutations.ts (updateNode), apps/default-fe/.../@workflows/workflows/_hooks/useNodeConfig.ts
   no presence / locking / live collaboration anywhere (no CRDT, yjs, websocket, and no locked_by or editing_by
   columns); teammate changes surface only on refetch (30s staleTime + refetch on window focus), after which syncNodes
   replaces canvas node data with server state while keeping local positions and selection
     → apps/default-fe/src/trpc/utils/query-client.ts, .../@workflows/workflows/_store/store.ts (syncNodes)
   Version history entry point + labels: "Version history" menu item in the details panel Manage Workflow section,
   sidebar titled "Version History", entries "Current Version" (the draft, timestamped workflow.updated_at with the
   last editor) then published versions newest-first with their publisher, then "Initial Draft"; footer button
   "Restore to draft"
     → .../workflow-canvas/{Header.tsx,VersionHistorySidebar.tsx},
       packages/ui/src/composed/workflows/workflow-details-floating/workflow-details-floating-dropdown.tsx
       (Manage Workflow section, General Info rows labeled "Created" and "Modified"),
       apps/default-api/.../workflows/queries.ts (getWorkflowVersionHistory kinds + desc ordering)
   past versions are read-only with a "Back to draft" banner action
     → WorkflowCanvas.tsx (readonly: isViewingHistoricalVersion), WorkflowDraftStateBanner.tsx
   restore replaces the entire draft: deletes all v0 nodes, edges, and triggers, re-inserts the chosen published
   version's rows at v0, resets the denormalized publish flags, and leaves published rows and is_enabled untouched
     → mutations.ts (restoreWorkflowVersionToDraft)
   RECOVERY LIMIT (added 2026-08-01 in answer to the Greptile review on PR 3131): the only snapshots that exist are
   the ones publish creates, so restore can only recover a state that was published. The same-step overwrite
   described above happens at v0, where updateNode writes in place and nothing is snapshotted, so the earlier draft
   edit is gone with no way back. The bullet says "captured in an earlier published version" deliberately; do not
   shorten it to "a change that was overwritten", which is the wording the review flagged
     → getWorkflowVersionHistory returns published rows plus a synthesized "Current Version" entry for the draft
       itself, not a history of draft saves (queries.ts); updateNode has no snapshot step (mutations.ts) */}
