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

# Workflows

> Build an automation on a canvas: one trigger, conditions, and steps that act, with every firing recorded step by step in run history.

A workflow reacts to an Alforse event by evaluating conditions and running actions. Examples include notifying an account manager after a sales-order assignment, creating an issue when a job is put on hold, or calling an external service after shipment posting. Build the workflow under **Automate → Workflows** by connecting one trigger to condition and action cards, then select **"Publish"**. A trigger can fan out into multiple branches. Alforse records each execution in [runs and history](#runs-and-history).

Alforse screenshot**The workflow builder canvas under Automate → Workflows: a trigger card wired to condition and action steps, with the palette and the Publish button**

One trigger, fanning out into branches that each end differently.

## What starts a workflow

Every workflow has exactly one **Trigger** step, and it works one of two ways. The **"Trigger type"** toggle picks between **"Event"** and **"Schedule"**; choosing one clears the other.

**Events.** An event is a specific change to a specific record:

| Shape | Example | What you get |
| - | - | - |
| Created | `job.created` | The new record |
| Deleted | `purchaseOrder.deleted` | The record as it was |
| A column changed | `customer.assignee.changed` | The record, plus its `before` and `after` values |

NOTE

**There is no generic “updated” event**

You pick the exact field you care about. Ten record types can be watched — purchase orders, sales orders, jobs, items, receipts, shipments, quotes, suppliers, customers, and issues — each with its own short list of watched fields. A change to a field nobody watches starts nothing at all.

**Business moments.** Below the per-record events, the picker has one group headed **"Business moments"**: the nine points in Alforse's own flows where something meaningful finished: a job released or put on hold, a job operation completed, a quote sent or accepted, a receipt or shipment posted, a sales or purchase invoice posted. A business moment hands your workflow the *identity* of each record, not a copy of its fields; add a **Find** step when you need to read something the moment didn't name.

**Schedules.** In **"Schedule"** mode you pick a **"Frequency"** of Daily, Weekly, or Monthly, the days it applies to, a **"Time of day"**, and a **"Timezone"**; the builder shows a live **"Next fires at:"** line as you change it.

HEADS UP

**Schedules never catch up**

Alforse stores the wall-clock time and time zone separately, so 09:00 remains 09:00 across daylight-saving changes. A monthly schedule on day 31 **skips** months without that date. After an outage, Alforse resumes at the next due time and records runs more than one hour late as skipped. A fixed offset of up to five minutes spreads load, so a 09:00 schedule runs between 09:00 and 09:05.

**"Triggered by".** Event triggers also choose *who* caused the change: **"People"**, **"Workflows"**, or **"Both"**. A new trigger starts at **"People"**, which is the safe answer: it stops a workflow from reacting to edits made by workflows, including its own. Switch it to **"Both"** deliberately, when you want one automation to feed another.

## The steps you can add

Six kinds, in palette order:

| Step | What it does |
| - | - |
| **Trigger** | Starts the workflow. One per workflow, and nothing can connect into it. |
| **Condition** | Sends the run down one path. Each path is a set of clauses, with an optional **"Otherwise"**. |
| **Action** | Does the work — notifies, creates, updates, or calls out. Has separate **Success** and **Failure** handles. |
| **Compute** | Works out a number from a record, such as an order total or a scrap percentage. Read-only. |
| **Find** | Looks a record up so later steps can use it. |
| **Filter** | Keeps only the items in a list that match your rules. |

**Actions** come in three families. Four create records (a job, an issue, a purchase order, or a sales order), each through the same service Alforse's own screens use, so sequences, defaults, and required fields behave identically. Ten update an existing record, one per watched record type. The last two are **"Notify someone"** and **"Call an outside URL"**.

NOTE

**Updates are deliberately narrow**

An update step can only set the fields Alforse lists for that record: an assignee, a due date, a reference, a priority. Statuses are not writable from a workflow, and there is no delete action of any kind. What a workflow can *watch* and what it can *write* are two different lists.

## Filling in a step

Most fields take either a value you type or a value from an earlier step. Type `{` in a text field and a menu opens listing the steps above this one, their outputs, and up to two levels of properties. Only steps *guaranteed* to have run before this one are offered — a value from the other side of a condition is not on the menu, and referring to one is rejected at publish.

**Repeating steps.** Connecting a list to a single-value field runs the step once per item, up to 100 items. The form displays this behavior. Connecting two lists to one step causes a publish-time error because the loop source is ambiguous.

## Calling an outside URL

The **"Call an outside URL"** action sends an HTTP request, a webhook, so another system can react to something in Alforse.

FieldType

<details>
  <summary>**URL**required`text`</summary>

  The `https` address to call. Variables are allowed, so the address can include a record's id.
</details>

<details>
  <summary>**Method**required`choice`</summary>

  `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. A new step starts at `GET`.
</details>

<details>
  <summary>**Headers**`name/value rows`</summary>

  Extra information sent with the request, such as an authorization key. Values can contain variables, and every header *value* is masked in run history.
</details>

<details>
  <summary>**Body**`text`</summary>

  The request payload, with variables substituted. Only shown and sent for `POST`, `PUT`, and `PATCH`.
</details>

HEADS UP

**What the webhook step refuses to do**

Plain `http` is rejected, and so is any address resolving to a private or link-local network, `localhost` and cloud metadata endpoints included. Redirects are not followed, the call gives up after ten seconds, and any answer that isn't a success status fails the step. Eight headers are set by Alforse and cannot be overridden. Alforse does not sign the request — if the receiving system needs to verify the caller, give it a shared secret in a header.

## Saving, publishing, and versions

There is no Save button: the builder saves as you work and reports **"Saving…"**, **"Saved"**, or **"Could not save"** next to the title. A half-finished draft saves happily; nothing is checked until you publish.

**"Publish"** is all-or-nothing. Alforse validates the whole workflow — a trigger exists, no step loops back, every required field is filled, every variable resolves and comes from upstream — and if anything is wrong, nothing is written; the problems appear in a panel and clicking one pans the canvas to the offending step. Publishing is also the only on/off switch: whichever version you publish is the one that runs, and **"Unpublish"** stops the workflow entirely. Nothing is deleted, so publishing again starts it back up. A workflow with nothing published reads as **Draft**.

Publishing freezes that version. To keep working, use the version menu to create a new version, which copies the published one and numbers it one higher. A run already in flight keeps using the version it started with even if you publish another mid-run. The trigger card also has a **"Test run"** button (owner only): it executes for real, but the result is never written to run history.

## Who can do what

Workflows have their own permission module: **View** opens the list, builder, and run history; **Create** adds workflows and versions; **Update** edits, publishes, and test-runs; **Delete** removes a workflow with its versions and history. Every route also requires an employee account.

NOTE

**A workflow runs as its owner, not as whoever triggered it**

Every step reads and writes with the owner's permissions, re-checked at each step. If the owner's access is revoked the run stops with a plain message naming the area. Nothing a workflow does can reach outside the company it belongs to — and run history is read-only in the database itself, so no user, however privileged, can edit or forge a run log.

## Runs and history

Every firing is recorded as a workflow run: one row for the run and one per step, with the values in, the values out, and why it ended the way it did. Open **Automate → Runs** for the list: status, workflow, trigger, the record it started from (shown by its name or number, and linked so you can open it), duration, owner, and a **Chain** cell reading **"Hop 2"** when the run was caused by another run. Rows update live while anything is queued or running.

Alforse screenshot**The Run Details drawer from Automate → Runs: outcome sentence, step list in workflow order with a skipped branch greyed out, and one step expanded showing Input and Output**

The outcome sentence is the fastest way to understand a run.

<details>
  <summary>**Queued**</summary>

  Accepted and waiting for a worker to pick it up.
</details>

<details>
  <summary>**Running**</summary>

  A worker has claimed it and is walking the steps.
</details>

<details open>
  <summary>**Succeeded**</summary>

  Every step that ran finished without error.
</details>

<details>
  <summary>**Failed**</summary>

  At least one step failed, or the run hit the 500-step ceiling.
</details>

<details>
  <summary>**Blocked**</summary>

  A loop guard stopped it before any step ran. The reason is on the run.
</details>

<details>
  <summary>**Skipped**</summary>

  It never started: the workflow was unpublished, or a scheduled run came due too late, or its previous run was still going.
</details>

Clicking a row opens the **"Run Details"** drawer with a one-line plain-English outcome (*"Failed at 'notify the buyer': The address answered 500."*). Below it the steps appear in workflow order rather than execution order, so a step that never ran still holds its place, greyed and marked **"Not reached"** or skipped with its reason. Expand a step for its **Input**, **Output**, and — on conditions — a clause-by-clause **Why** with the path taken marked. A repeating step records each item plus a summary that counts what actually ran (*"Ran 100 of 150; 50 were not used"* means the 100-item cap, not an error).

NOTE

**A run can succeed having done nothing**

If a condition matches none of its paths and has no **"Otherwise"**, that step *succeeded* — it correctly decided not to continue. The run ends successful with most steps never reached, which is why the outcome sentence spells out what happened instead of leaving you to read a green badge. Missing data is likewise a skip, not a failure, and a condition whose values cannot be read does **not** fall through to its **"Otherwise"**: an unknown is not a no.

A failed step stops its branch, not the run: other branches keep going, and a wired **Failure** handle is followed, though the run is marked failed at the end regardless. The one exception is a permission failure, which stops the branch outright even when a failure path exists.

**Chains.** When one workflow's writes trigger another, Alforse links the runs and displays the complete chain. A repeated workflow or a chain deeper than ten hops records a **Blocked** run. Use [**"Triggered by"**](#what-starts-a-workflow) to limit which changes can start a workflow.

HEADS UP

**There is no retry button**

A finished run cannot be re-run from the Runs page. Fix the outside cause and let the next trigger fire, or use the builder's **"Test run"**. A run that crashes mid-flight is retried automatically by the queue, and because each step is claimed before it acts, the retry cannot repeat work that already completed.

**Retention.** A nightly job tidies history in four passes, ignoring runs still in flight: after 24 hours a run still queued or running is closed as failed; after 7 days recorded values are summarised in place; after 30 days step rows are deleted (the run survives); after 90 days the run is deleted entirely. Values whose names look like credentials are stored as `[REDACTED]` and every webhook header value is masked, while ordinary fields that merely sound sensitive (an item key, who authorised something) are left alone: a debugging tool that hides too much is as broken as one that hides too little.

## Related

**Notifications**

Where a workflow's "Notify someone" step lands, and how people mute topics.

[Open](/docs/reference/notifications.md)

**Approvals**

Rule-based gates on documents, the other half of Automation.

[Open](/docs/reference/approvals.md)

**Audit log**

The separate, entity-centric record of who changed what.

[Open](/docs/reference/audit-log.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.