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

# Workflows

> Run a routine the same way every time. Build it by API, CLI or MCP, check it, turn it on and follow its runs.

A workflow is a routine that runs the same way every time: a start, then steps wired in order. Every Monday at 9, read last week’s Stripe payments, have Hermes write a summary, post it in Slack. A workflow is written as lines of JSON, one per step. You see the same workflow as cards on the canvas at [orgo.ai/workflows](https://www.orgo.ai/workflows), and any change made by API, CLI or MCP shows there the moment it lands.

> [!NOTE]
>
> Workflows are in preview. Where they aren’t open to your account, every Workflows endpoint answers a bare `404` with no body. Don’t retry it; ask Orgo to open Workflows for the account.

## What a workflow is made of

A workflow has exactly one start, then up to the steps it needs. Each step after the start names the steps it follows (`after`), so steps can run side by side and join again.

| Step | What it does |
| - | - |
| App action (`app`) | Reads or writes in an app connected on the workflow’s computer: find Stripe payments, post in Slack, add a row to Sheets, send a Gmail. Any action of any app is a step, by its tool. |
| Agent (`agent`) | Judgment or writing by an agent on the computer: Hermes (`hermes`), Claude Code (`claude-code`) or OpenClaw (`openclaw`). |
| Script (`script`) | Bash or Python run on the computer. What it prints is handed on. |
| Screen (`screen`) | Orgo’s computer agent does the work on the computer’s screen, for a site or app with no action. |
| Check with me (`person`) | The run waits until you say go or stop. |
| Message (`message`) | Hermes messages you on iMessage or Telegram, with set words or a draft you approve. |
| Chart (`chart`) | Draws numbers from earlier steps as an image: a line, bars, or one number with its trend. |

Anything that changes from run to run is a fill-in in braces, like `{report}` or `{first name}`. A fill-in is something an earlier step hands on, something the start carries, or a setting you fill in once.

Here is a complete workflow. Each weekday at 9:00 AM, Hermes writes a report and it is posted in a Slack channel you name once:

```json theme={null}
{"id":"a","kind":"start","title":"9:00 AM","sub":"Weekdays","name":"Morning report"}
{"id":"b","after":["a"],"kind":"agent","agent":"hermes","title":"Write the report","task":"Write a short report on yesterday’s new customers."}
{"id":"c","after":["b"],"kind":"app","app":"slack","title":"Post","where":"{channel}","message":"{report}"}
```

The whole line format, with every field and kind, is at [orgo.ai/workflows.md](https://www.orgo.ai/workflows.md). You don’t have to write lines yourself: send a description in plain words and Orgo drafts them.

### The workflow’s computer

Every workflow runs on one of your computers. Its app steps use the apps connected there (the same ones [Connectors](https://docs.orgo.ai/guides/connectors.md) shows), its agent steps ask the agent installed there, and its screen and script steps run there. Pick the computer once with `PATCH /workflows/{id}` and `{ "computer": "<computer UUID>" }`. A workflow whose steps need a computer can’t run without one.

## How a workflow starts

| Start | How it’s written | When it runs |
| - | - | - |
| A time | `title` is the clock time, `sub` how often: `"Every day"`, `"Weekdays"`, `"Mon, Thu"`, `"Every month"`, `"Every 30 min"`. A cron rule works too. | On schedule, in the workflow’s `time_zone`. |
| An app event | `app` and the event: an email arrives, a meeting is booked, a new order. Any app’s event works, by its trigger. | Each time the event happens. |
| An agent calls it | `"title":"An agent calls it","sub":"Agent"` | When another agent posts to the workflow’s call link with its key. You copy both from the start on the canvas. |

Any workflow can also be run by hand: [Start a run](https://docs.orgo.ai/api-reference/workflows/start-run.md), `orgo workflows run`, or `orgo_run_workflow`.

A new workflow is off. Turning it on (`PATCH` with `{ "on": true }`) sets up its start, and it works only while the workflow can run: if it can’t, the answer is `422` with `code: "not_ready"` and a `to_fix` list in plain words. A later change that leaves it unable to run turns it off, and the answer says `turned_off: true`.

## Check it before it runs

[Validate](https://docs.orgo.ai/api-reference/workflows/validate.md) proves a workflow will work, and sends nothing. It looks at the computer (without waking it), each agent installed there, each app signed in (with a read that proves it), the channels and sheets it names, the secrets its scripts read and your credit. Each step answers `ok`, or `say` (what is in the way) and `fix` (the one thing that fixes it).

```bash theme={null}
curl -X POST https://www.orgo.ai/api/workflows/morning-report/validate \
  -H "Authorization: Bearer $ORGO_API_KEY"
```

```json theme={null}
{
  "ok": false,
  "steps": [
    { "step": "a", "ok": true },
    { "step": "c", "ok": false, "say": "Slack isn’t connected on this computer.", "fix": { "action": "reconnect", "app": "slack", "label": "Connect Slack" } }
  ],
  "to_fix": ["Connect Slack"]
}
```

Validate before you turn a workflow on, and again after you change it.

## Runs

A run goes on in the background. [Start a run](https://docs.orgo.ai/api-reference/workflows/start-run.md) answers `202` at once, and you read it again with [Get a run](https://docs.orgo.ai/api-reference/workflows/get-run.md) or follow it with [Follow a workflow](https://docs.orgo.ai/api-reference/workflows/events.md).

| State | Meaning |
| - | - |
| `running` | A step is being done. |
| `waiting` | It waits at Check with me for you, or for another agent. `waiting.id` is the step. |
| `done` | Every step ran. `output` is what the last step handed on. |
| `stopped` | It stopped. `stop.say` says why in one line and `stop.fix` is the one thing that fixes it. |
| `needs_review` | A send may or may not have gone out, because no answer came. Orgo never sends it again by itself: check the app first. |

A run whose steps use the computer’s agents or screen wakes the computer as it starts, if it is asleep. A timed start wakes it about 3 minutes before. A run that still finds it asleep stops, and its fix wakes the computer and runs it again.

[Stop a run](https://docs.orgo.ai/api-reference/workflows/stop-run.md) ends a run wherever it is: mid-step, between tries, or waiting. What it runs on the computer is ended. Steps that already ran stay done.

A run waiting at Check with me goes on only when you say go, on the canvas or signed in. A key or an agent may stop it with [Answer a waiting run](https://docs.orgo.ai/api-reference/workflows/answer-run.md) and `{ "choice": "stop" }`, but a go from a key answers `403` with `code: "person_required"`. An agent that finds a run waiting should tell you, not answer for you.

## Reliability

* **Each start runs once.** A time is keyed by the time itself, so it starts one run however many times it fires. An app event sent again (twice at once, as a new event, or late) is the run it already started.
* **On time.** A time missed while Orgo was down runs once, late, while less than half its period has passed (6 hours at most). The run says how late it started. Past that it doesn’t run, and it is listed as a stopped run with no steps. A computer asleep is woken about 3 minutes before a timed run that needs it.
* **Retries.** A failure an app says will pass is tried again over minutes. A workflow that sends many keeps each app’s pace on its computer, so the rest wait their turn instead of failing.
* **Retries of your own calls.** Send an `Idempotency-Key` header when you create a workflow or start a run. A retry with the same key answers what the first request did, and never makes a second workflow or a second run.
* **Saved.** Workflows, their settings and their last 20 runs are kept across restarts. A run uses the steps as they were when it started; a later edit never changes a run already going.

## Safety

* **Text from outside gets a turn with no tools.** When an agent step reads something other people wrote (an email, a message, what an app found, what an event or a caller sent), Hermes and Claude Code answer it in a turn with no tools, no MCP servers and no secrets in their environment. OpenClaw has no such turn, so a workflow that hands it outside text is refused before anything runs, and Validate says so on that step.
* **Facts are checked.** Before a send goes out, every number, date and name an agent wrote must be in the data it was handed, or worked out from it. If one isn’t, the agent gets one more turn; then the run waits at Check with me if the workflow has one, or stops and sends nothing.
* **Scripts get only the secrets they name.** A script runs in a clean environment: no `/root/.env` and no `ORGO_API_KEY`. A workspace secret is there only when the script names it, like `$STRIPE_KEY`.
* **You say go.** Only you approve a Check with me step. A send whose words an agent wrote after reading other people’s words needs a Check with me before it when it goes to someone the event named, and Validate says to add one.
* **Who a send reaches never comes from an agent’s answer.** The recipient, channel or sheet is set in the step.

## What a key needs

Workflows have their own permission group, `workflows`: read to list and read workflows and their runs, write to make, change, delete and run them. A key without it answers `403` with `code: "key_permission"`. Two more rules:

* Making a workflow from `describe` also takes AI write, since a model drafts it.
* Picking a workflow’s computer, and validating, turning on or running a workflow whose steps act on its computer, also take Control write and AI write: the same access that controlling the computer takes.

A key with full access has all of these. The groups are described in [API key permissions](https://docs.orgo.ai/api-reference/api-keys/permissions.md).

## A complete example

Make the morning report above, check it, turn it on and run it once. Replace `$COMPUTER_ID` with the UUID of a computer where Hermes is set up and Slack is connected.

> [tab] API
>
> ```bash theme={null}
> A="Authorization: Bearer $ORGO_API_KEY"
> API=https://www.orgo.ai/api/workflows
>
> # 1. Make it from its lines (the three lines above, saved as morning-report.jsonl)
> jq -Rs '{name: "Morning report", lines: .}' morning-report.jsonl |
>   curl -s -X POST "$API" -H "$A" -H "Content-Type: application/json" \
>     -H "Idempotency-Key: $(uuidgen)" -d @-
> # 201 {"id":"morning-report","on":false,"version":1,"lines":"...","to_fix":["Fill in channel", ...]}
>
> # 2. Its computer, time zone and channel
> curl -s -X PATCH "$API/morning-report" -H "$A" -H "Content-Type: application/json" \
>   -d "{\"computer\":\"$COMPUTER_ID\",\"time_zone\":\"America/New_York\",\"settings\":{\"channel\":\"sales\"}}"
>
> # 3. Check it, sending nothing
> curl -s -X POST "$API/morning-report/validate" -H "$A"
>
> # 4. Turn it on (422 not_ready with to_fix until it can run)
> curl -s -X PATCH "$API/morning-report" -H "$A" -H "Content-Type: application/json" -d '{"on":true}'
>
> # 5. Run it now, and read the run
> curl -s -X POST "$API/morning-report/runs" -H "$A" -H "Content-Type: application/json" \
>   -H "Idempotency-Key: $(uuidgen)" -d '{"inputs":{}}'
> # 202 {"run":{"run_id":"...","state":"running",...}}
> curl -s "$API/morning-report/runs/$RUN_ID" -H "$A"
>
> # Stop it, if you need to
> curl -s -X POST "$API/morning-report/runs/$RUN_ID/stop" -H "$A"
> ```
>
> Replace `$RUN_ID` with the `run_id` from step 5. To have Orgo draft the steps instead, send `{"name": "Morning report", "describe": "Every weekday at 9 AM, …"}` in step 1, then read `to_fix` for the settings it asks for. To change the steps, read the workflow, edit its `lines` and send them back with [Replace a workflow’s steps](https://docs.orgo.ai/api-reference/workflows/replace.md) and `If-Match` set to the version you read.

> [tab] CLI
>
> ```bash theme={null}
> orgo workflows create --name "Morning report" \
>   "every weekday at 9 AM, write a short report on yesterday’s new customers and post it in Slack"
> orgo workflows show morning-report        # its steps and what is left to fix
> orgo workflows check morning-report       # proves it will work, sending nothing
> orgo workflows on morning-report
> orgo workflows run morning-report --follow
> orgo workflows stop morning-report <run>
> ```
>
> The workflows commands ship in a CLI release after 2.3.0. The CLI has no command that picks a workflow’s computer, time zone or settings. Set them once on the canvas, or with step 2 of the API tab. The commands are listed in [CLI](https://docs.orgo.ai/guides/cli.md#workflows).

> [tab] MCP
>
> Connect the hosted server once, as described in [MCP](https://docs.orgo.ai/guides/mcp.md#workflows), then ask in plain words:
>
> ```text theme={null}
> Make me an Orgo workflow: every weekday at 9 AM, write a short report on
> yesterday’s new customers and post it in #sales on Slack. Use my computer
> agent-1, check it, and turn it on.
> ```
>
> The agent calls `orgo_create_workflow`, `orgo_list_workflow_computers`, `orgo_update_workflow` (computer, time zone and channel), `orgo_validate_workflow`, then `orgo_update_workflow` with `on: true`. To run it now it calls `orgo_run_workflow` and reads the run with `orgo_get_workflow_run`.

## API reference

| Method | Path | What it does |
| - | - | - |
| `GET` | [`/workflows`](https://docs.orgo.ai/api-reference/workflows/list) | Every workflow, with whether it is on and ready, its last run and its next time. |
| `POST` | [`/workflows`](https://docs.orgo.ai/api-reference/workflows/create) | Makes a workflow from plain words or its lines. |
| `GET` | [`/workflows/{id}`](https://docs.orgo.ai/api-reference/workflows/get) | One workflow: its lines, settings, version and what to fix. |
| `PUT` | [`/workflows/{id}`](https://docs.orgo.ai/api-reference/workflows/replace) | Replaces its steps. |
| `PATCH` | [`/workflows/{id}`](https://docs.orgo.ai/api-reference/workflows/update) | Turns it on or off, renames it, sets its settings, computer or time zone. |
| `DELETE` | [`/workflows/{id}`](https://docs.orgo.ai/api-reference/workflows/delete) | Deletes it and stops its runs. |
| `POST` | [`/workflows/{id}/validate`](https://docs.orgo.ai/api-reference/workflows/validate) | Checks each step will work, sending nothing. |
| `POST` | [`/workflows/{id}/runs`](https://docs.orgo.ai/api-reference/workflows/start-run) | Starts a run now. |
| `GET` | [`/workflows/{id}/runs`](https://docs.orgo.ai/api-reference/workflows/list-runs) | Its last 20 runs. |
| `GET` | [`/workflows/{id}/runs/{runId}`](https://docs.orgo.ai/api-reference/workflows/get-run) | One run. |
| `POST` | [`/workflows/{id}/runs/{runId}/stop`](https://docs.orgo.ai/api-reference/workflows/stop-run) | Stops a run wherever it is. |
| `POST` | [`/workflows/{id}/runs/{runId}/answer`](https://docs.orgo.ai/api-reference/workflows/answer-run) | Stops a run waiting at Check with me. |
| `GET` | [`/workflows/{id}/events`](https://docs.orgo.ai/api-reference/workflows/events) | Its changes and runs as they happen. |

Every error is JSON: `{ "error", "code", "say"?, "next"?, "to_fix"? }`. `say` is the problem in a few words, and `next` names the call that fixes it.


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