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¶
- Open the swarm, then its Flows tab, and click New flow.
- In Flow settings, give the flow a name.
- Add steps: click an AI Job in AI Jobs in this swarm, or drag it onto the canvas.
- 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.
- 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.
- 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 nodeId1 to 40 letters, digits, -or_; unique in the flowRequired — agentIdAn AI Job of the swarm, at most once per flow Required The step's AI Job joinalloranyallStart when passPrevioustrueorfalsefalseReceive the previous result(s) waitMinutes0 to 1440 0Wait before it starts (minutes) turnOffOwnScheduletrueorfalsefalse(the editor checks it)Turn off its own schedule… x,yIntegers from -100000 to 100000 0The step's place on the canvas -
edges, the links (can be left out):fromandtoarenodeIds, andcondissucceeds(on success, the default),finishes(when done) orfails(on failure). schedule:nullfor none, orcronExpression(5 fields, at most once an hour),timezone(IANA,UTCby default) andenabled(falseby 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.