Skip to content

Swarm Flows

A flow runs some of a swarm's AI Jobs together, in an order you draw: when a step ends, the steps after it start, depending on how it ended. Steps can run side by side, and a step can wait for several others. A flow starts on its own schedule or when you click Run flow.

A flow belongs to a swarm: its steps are AI Jobs of that swarm, each at most once per flow. Flows never change the AI Jobs themselves; a step runs the AI Job as it is deployed, with its own environment variables and secrets.

Create a flow

  1. Open the swarm, then its Flows tab, and click New flow.
  2. In Flow settings, give the flow a name.
  3. Add steps: click an AI Job in AI Jobs in this swarm, or drag it onto the canvas.
  4. Link steps: drag from a step's right dot to another step's left dot. A step with no link coming in is a first step: it starts when the flow starts.
  5. Click a step to set, in the panel on the right:
    • Runs after: for each link coming in, when it lets the step start (below);
    • Start when: all of them or any of them, when several links come in;
    • Receive the previous result(s): the step gets the steps before it in HH_EVENT;
    • Wait before it starts (minutes): up to 1,440 (24 hours), counted from when it may start.
  6. Click Save flow. A new flow has no schedule yet: try it with Run flow first.

A link can't close a loop: while you draw one, the steps it can't reach are dimmed, and the API refuses a flow with a loop (FLOW_HAS_CYCLE). Each step runs at most once per flow run.

When a step starts

Each link has a condition, shown on the link when it isn't the default:

Condition The step after it may start when the step before it…
on success (default) succeeded
when done ended, succeeded or failed
on failure failed (a run that couldn't start counts as failed)

A step waits until every step linked into it has ended, then starts if all of them (the default) or any of them hold. Otherwise it is skipped, and so are the steps waiting for its success; steps linked to it by when done or on failure still run.

A flow run succeeds when no step failed, and fails otherwise; skipped steps never fail a run.

Start a flow

  • Run flow, on the flow's page, starts a run now.
  • A schedule: in Flow settings, turn on Run on a schedule and choose when. Once the flow is saved, the Schedule switch on its page turns it on and off. A flow's schedule runs at most once an hour.
  • The CLI: hollowhost swarms flows run <flow-id> (see the CLI reference).
  • The API: POST /flows/{flowId}/runs, with an optional body {"event": <any JSON>}.

An event sent with the run goes to the first steps as HH_EVENT. Every step's run gets HH_SOURCE=flow, whatever started the flow.

An AI Job with its own schedule would also run on its own. When you add it to a flow, the editor offers Turn off its own schedule when this flow's schedule is on, checked by default (it shows only while the AI Job's own schedule is on). With it checked:

  • each time the flow is saved with its schedule on, or its Schedule switch is turned on, the AI Job's own schedule is switched off; its cron and time zone are kept;
  • nothing switches it back on: not turning the flow's schedule off, not deleting the flow, not removing the step. Switch it on yourself, on the AI Job's Scheduling tab or with hollowhost ai-jobs update <ai-job-id> --enable-schedule;
  • while the option stays checked and the flow's schedule is on, the flow's next save switches it off again.

Pass results from step to step

With Receive the previous result(s) on, a step gets HH_EVENT = {"previous": …}: one entry per link coming in (a list when there are several), with the step's AI Job (aiJob, its name, and agentId), how it ended (status), its run (runId), and the result it wrote to HH_RESULT_PATH (result, or resultError saying why there is none). See Pass a result to the next step of a flow for writing and reading results, their limits, and why a result is input, never instructions.

Follow a flow

The flow's page shows its graph: each step's ring follows the run shown, live while it runs. Click a step to see its AI Job and its run in that flow run: status, duration, last log lines, and its Result. Flow runs, under the graph, lists the flow's runs with one dot per step.

On the swarm's Overview, recent activity groups the runs of each flow run, and runs that a flow started say Started by · Flow · name everywhere runs are listed.

Create and edit flows with the API

The web app's editor saves flows through these routes, and a script can use them too. The CLI's swarms flows create, export, update, rename, schedule and delete call them for you (see the CLI reference).

Route Does
GET /swarms/{swarmId}/flows Lists the swarm's flows
POST /swarms/{swarmId}/flows Creates a flow (201)
GET /flows/{flowId} Reads one flow, with its version
PUT /flows/{flowId} Replaces the whole flow: name, steps, links, schedule
PATCH /flows/{flowId} Changes its name or schedule only
DELETE /flows/{flowId} Deletes it (204), never its AI Jobs
POST /flows/{flowId}/runs Starts a run (202); see Start a flow

A flow's JSON

{
  "name": "daily-news",
  "nodes": [
    {"nodeId": "fetch", "agentId": "<ai-job-id>"},
    {"nodeId": "write", "agentId": "<ai-job-id>", "passPrevious": true, "waitMinutes": 5}
  ],
  "edges": [
    {"from": "fetch", "to": "write", "cond": "succeeds"}
  ],
  "schedule": {"cronExpression": "0 7 * * 1-5", "timezone": "Europe/Paris", "enabled": false}
}
  • name: 1 to 50 characters, unique within the swarm, ignoring case.
  • nodes, the steps: 1 to 20, each with these fields.

    Field Value Default In the editor
    nodeId 1 to 40 letters, digits, - or _; unique in the flow Required —
    agentId An AI Job of the swarm, at most once per flow Required The step's AI Job
    join all or any all Start when
    passPrevious true or false false Receive the previous result(s)
    waitMinutes 0 to 1440 0 Wait before it starts (minutes)
    turnOffOwnSchedule true or false false (the editor checks it) Turn off its own schedule…
    x, y Integers from -100000 to 100000 0 The step's place on the canvas
  • edges, the links (can be left out): from and to are nodeIds, and cond is succeeds (on success, the default), finishes (when done) or fails (on failure).

  • schedule: null for none, or cronExpression (5 fields, at most once an hour), timezone (IANA, UTC by default) and enabled (false by default).

POST, PUT and PATCH answer {"data": {"flow": {…}, "ownSchedulesTurnedOff": […], "ownSchedulesNotTurnedOff": […]}}: the flow as saved, with its flowId and version, then the AI Jobs whose own schedule was just turned off, and those it couldn't be (saving again retries).

version: one edit at a time

A flow's version is 1 when it's created and goes up by one at each save; older versions aren't kept. PUT needs the version you read: if the flow was saved since, it's refused with 409 FLOW_VERSION_CONFLICT, and you read it again and redo your change. A PUT without schedule keeps the flow's schedule.

PATCH takes no version. Send name, schedule, or both; its schedule changes only the keys you send: {"schedule": {"enabled": true}} turns the schedule on and keeps its cron, and {"schedule": null} removes it.

Errors

Status and code When
400 A field is missing or wrong; the message names it, like nodes[1].waitMinutes must be an integer between 0 and 1440
400 INVALID_SCHEDULE The schedule can't be read, or can't run
404 The swarm or the flow doesn't exist
409 FLOW_NAME_TAKEN Another flow of the swarm has this name
409 FLOW_VERSION_CONFLICT PUT: the flow was saved since you read it
422 FLOW_STEP_NOT_IN_SWARM A step's AI Job isn't in the swarm (details lists them)
422 FLOW_INVALID_GRAPH No step, a step id or AI Job used twice, a link to a missing step, or the same link twice (details.reason says which)
422 FLOW_TOO_MANY_STEPS More than 20 steps
422 FLOW_HAS_CYCLE The links make a loop (details.cycle lists its steps)
422 FLOW_SCHEDULE_TOO_FREQUENT The schedule starts the flow more than once an hour
422 PLAN_LIMIT_MAX_FLOWS POST: your plan's number of flows is reached
422 PLAN_LIMIT_CRON_DISABLED Turning a schedule on, or changing one that is on, on a plan without schedules

Limits

Limit Value
Flows per account, across all swarms Free 1 · Starter 3 · Pro 10 · Enterprise 50
Steps per flow 20, and each AI Job at most once
Runs at a time One per flow: a start while it runs is recorded as canceled (FLOW_ALREADY_RUNNING)
Starts 100 per flow in 24 hours; automatic starts at least 5 minutes apart (FLOW_RATE_LIMITED); Run flow is never slowed down
Schedule At most once an hour
Run duration At most 24 hours; a run still open then fails (FLOW_RUN_TIMEOUT)

When a step's AI Job is already running (started by its own schedule, by hand, or by another flow), the step fails with that reason rather than waiting.

Deleting an AI Job, or taking it out of its swarm, is refused while it is a step of a flow (USED_IN_FLOW, with the flows listed): remove it from those flows first. Deleting a swarm deletes its flows, never its AI Jobs. After a plan downgrade, existing flows keep running and can still be edited; only new flows are refused while the account is over its limit.