A flow is Python
A flow is a directory holding Python that takes the agents and the task, and whoever writes one is a weaver. Most are ordinary functions: a loop, a subprocess call, a file read between two turns, a condition on what the last answer said. An atlas makes a different bargain: its deliberately narrow body is read before it runs and compiled into a typed graph called a prophecy.
Both are Python, discovered the same way and driven by the same run. A weaver reaches for an ordinary flow when the shape should remain free, and for an atlas when it must be checked, compared or resumed node by node before any agent starts.
A session of its own each round: the agent starts from the task and the repository with nothing of the last round in context. The repository is the memory.
What makes a function a flow
A mark on it, and nothing else. Which of a file's functions is the flow is the file's own to say rather than a name to guess at, because a flow is read by running its file and a file may leave several functions behind.
What the mark carries is what a command line cannot otherwise know:
- How many agents it drives — the length of the tuple it declares. A run started with the wrong number fails before its first turn rather than partway through a loop.
- What it calls each of them. Declared as a named tuple, a flow says
actorandreviewerrather than "the first one" and "the second one" — and those names are what a trace groups each agent's sessions under. - What it needs of them. A flow that runs an agent under a goal says so beside the place, and an agent whose backend has no goal feature is refused before the first turn.
- Where its turns may land. A place may be pointed at another machine, or fixed to a container of an image the flow itself names and configurable by nobody.
- Whether it can be picked up where its last run left off.
- One file, several flows. Three phases of one thing are one thing to write and three to run, each asking only for the agents it drives and only for the settings it takes.
A flow may also declare settings of its own as a pydantic model, which become fields on the sheet where it is set up and lines in a file a scripted run can hand it.
Ordinary flows are loaded as code
There is no static description of an ordinary flow to run instead, and none is cached. A flow rewritten between two runs — by hand, or by an agent that flow is itself driving — runs as it is now. That is what makes a flow, and the skills it brings, a thing a run can improve.
The static checker can inspect a flow's source without importing it. An atlas goes further: its body is the description, so compiling it produces a prophecy without executing that body — but its node functions and the rest of its module remain ordinary Python.
Its own directory is importable while it runs and only while, since what a flow imports is not something the rest of the process should be able to. All of which is why a flowverse is trusted the way a repository of code is trusted rather than read as data, and why Security is a page rather than a paragraph.
The shapes a loop takes
The diagram above is the whole vocabulary, and each shape is a few lines:
- A conversation. The flow waits for the next thing to say, says it, and waits again. Between two turns it is a Python function sitting on a call that has not returned.
- Ralph. A session of its own each round: the agent starts from the task and the repository with nothing of the last round in context. The repository is the memory.
- Stateful ralph. One session, opened once and held, re-sent the task every round. The conversation is what the flow is — and is the one thing a run picked up again cannot have back.
- An actor and a reviewer. One works; the other is asked, in a session of its own, for an answer in a shape, so the loop reads a field rather than a paragraph.
- A fan-out. One agent, a session per file, all of them going at once.
A flow that calls a flow
A loop worth having is a loop another loop can reach for. A flow may ask for another by the same name a command line takes, hand it agents it already holds, and take back whatever it answers with — awaited, where the inner flow is a coroutine.
A name nothing answers to is refused where it is asked for rather than where the answer is called, so a flow that asks for the wrong one says so at once instead of an hour into a loop. The inner flow's agents are not renamed: they belong to the run that was started, and a name changed under them would change what has already been written down. Both ends of the call go into the run's own record — a run is what it did as well as what it was started as.
Everything a flow needs lives inside it
So that it can be copied, forked and edited whole: a flow whose parts are elsewhere has a hole in it wherever it lands.
- Its own skills are the
skills/directory inside it, undeclared: they are in it, and looking is what finds them. - A skill maintained elsewhere is named as a git URL where the flow is declared, cloned under humanize's own home and fetched again the next time a run asks for it — so it keeps up, and goes on working when the network is down.
- The flow's own wins a name a repository also uses, because a fork that edited a skill meant the edited one.
- A repository that cannot be fetched at all stops the run where the flow is got ready, not at the first turn. A flow that works by a skill it has not got is not one to start and find out about an hour in.
Where flows come from
A flowverse is a git repository with a flows/ directory in it, offered under its own name, and only that directory is read — a repository is a README, a pyproject and a test suite as well, and reading a flow means running it.
Nearest wins: this project's flows, then yours, then whatever there is to run, so a project may mean its own chat by chat. A name qualified by a flowverse is that flowverse's and is never stood in for.
One is always listed — official, the package's own chat plus humanize's repository of the rest, listed whether or not it has been fetched. A list that only mentioned it once somebody had thought to add it would be a list that hid what there is to run.
Where the detail is
- Writing a flow · Loops · Testing a flow
- An atlas · Checking a flow · Python becomes a prophecy
- Settings of its own · A flow that calls a flow · Flowverses
- Flows reference — the contract, in full