Flows
Rethinking workflows
When building start.chat we realized something, something of a secret:
Apps’ slash commands are skills…
… what if you can just… chain them together?
We wanted some sort of flow system from the start — any intranet needs it, and every platform already implements flows, just usually in their backend.
We knew we wanted to find an 80/20 solution — let your dedicated infrastructure for flows handle the intense stuff, but give you something you can create, test, and edit 10x faster:
- Text-first
- LLM-first
- Easy to read and understand
- Low conceptual burden
- Easy to fit in small space
- Outputs deterministic code
So, we iterated quite a lot until we had Pipedown, a portable plain-text format for pipelines.
Like Markdown adds very very little syntax and then gets out of the way, Pipedown just gives you a few constructs to actions and AI into automated pipelines.
What is a flow?
Kind of like this:
Steps starting with /app action call a specific installed app.
Steps without / are LLM steps — natural language instructions processed by AI
to transform, filter, or summarize data.
There’s 12 special words or symbols on top of that, but that’s it. The rest is determined by the runtime.
Our runtime does some really fun things we’ve figured out that make flows both very powerful, but also very fast, and deterministic. In fact, you can even copy our flows out as plain JavaScript snippets to use anywhere you want.
Richer example
- Runs every day at 9am
- Fetches issues from GitHub
- Uses AI to filter to critical/urgent ones, tagging the result as
#issues - Sends a notification referencing that tagged output
Note that you don’t need to label “issues” in this flow, as steps always return
two things: summary and data, which are passed to the next step, and all
steps in start.chat automatically figure out how to use their summary and data
intelligently when they first run using LLMs, saving the “strategy” — a simple
JS snippet they figure out iteratively — in a cache, in order to run instantly
from then on out.
Step types
| Type | Syntax | Description |
|---|---|---|
| App action | /app action args | calls an installed app’s action |
| LLM step | plain text | AI processes the previous output |
| Conditional | if condition | skips subsequent steps if false |
| Cancel | cancel if condition | stops the flow entirely if true |
| Wait | /wait @person or /wait 2h | pauses for approval or a duration |
| Error handler | ! retry 3, ! ignore, ! fallback | controls error behavior |
| Parallel | * step | runs step in parallel with siblings |
See Writing Flows for the complete syntax reference.
Triggers
Flows support three trigger types:
Manual — click the play button to run on demand. This is the default.
Schedule — run at set intervals:
Event — run when an app emits events:
Or target a specific event:
See When Flows Run for all frequencies and event options.
Creating flows
Write a flow directly in any message. Start detects the flow syntax, creates a flow record, and shows a play button to run it. Multi-line flows work in code blocks too.
Where flows run
Each flow gets its own thread in the Flows channel. When a flow runs, each step executes sequentially and the output is posted to the thread.
| Status | Description |
|---|---|
idle | waiting to start |
running | currently executing steps |
complete | all steps finished successfully |
failed | a step encountered an error |
cancelled | manually stopped or cancelled by a cancel if step |
waiting | paused on a /wait step |