Flow-driven CLI runtime for Codex agent sessions.
Project description
flow
flow runs agents through flowchart-like workflows in the background. You can watch them and help if they need it. An simple flow:
flow:
name: agi-watcher
mode: read-only
args:
site:
help: news site to monitor
check-news:
start: true
thinking: low
prompt: Check {{site}} to see if there's a story about AGI being achieved
transitions:
- if: there is news that AGI has been acheived
go: investigate
- if: there are no stories about AGI being achieved
wait: 60m
go: check-news
investigate:
thinking: xhigh
prompt: |
Read the article, comments and any sources you can find.
Decide whether AGI really has been achieved or if this is just hype.
transitions:
- if: AGI really has been acheived
go: its-over
- if: AGI has probably not been achieved
go: check-news
its-over:
mode: yolo
prompt: |
Use pushover to send the user a short summary of the situation.
Then send another reminding them to go outside, lie on the grass and enjoy the sun.
end: true
Use it like this:
$ flow start agi-watcher.yaml --site news.ycombinator.com
Monitor the situation:
$ flow list
$ flow list --top
Runtime active | uptime 00:18:01 | active agents 3 | total agents 4 | cumulative agent time 00:11:18
agi-watcher
check-news
#6 waiting 00:42:32 ~/work/agent-flows site=news.ycombinator.com
#7 waiting 00:42:43 ~/work/agent-flows site=reddit.com/r/locallama
#8 working 00:00:19 ~/work/agent-flows site=https://karpathy.github.io
Check what a specific agent has been up to:
$ flow show 6
$ flow show 6 --top
agi-watcher in ~/work/agent-flows (started 23:57 on Apr 1 | 0h 0m running, 0h 6m waiting)
State check-news | Substate normal | Phase waiting
Status Waiting until 2026-04-01T22:58:16Z
site: news.ycombinator.com
Events
23:57 on Apr 1 (0h 0m): check-news started
23:58 on Apr 1 (0h 0m): check-news -> check-news "Checked the live Hacker News front page and relevant HN search results; no current story claims AGI has been achieved."
23:58 on Apr 1 (0h 0m): check-news wait for 60m until 00:58 on Apr 2
View and interact with any codex session directly in your terminal:
$ flow view 6
View many agents in lots of little windows:
$ flow view --all
You have complete control at all times, including pausing and resuming automation for an agent, interrupting it, moving to another state and more. Read the CLI overview for the details.
The main idea is simple:
- a flow is a graph of named states
- each state can give the agent a prompt
- each state has outgoing transitions
- after a turn, the agent chooses the next transition in JSON
- the runtime moves the agent, waits, pauses, or asks for help as needed
- every agent is running in a tmux session you can attach to and view or interact with if you have to
flow is built for asynchronous work. You start agents, the runtime keeps them moving through a flowchart in the background, and you inspect or intervene only when you want to.
Principles
- Each agent is always in exactly one state.
- Flows are plain YAML, meant to be easy for both humans and agents to read and write.
- Starting an agent snapshots the flow file. Later edits only affect new agents.
- The runtime is persistent. Agent state lives in
~/.flowby default. - Each agent gets its own tmux session and long-lived Codex process.
- Codex uses your normal shared
~/.codexhome, so your usual config, auth, and skills still apply. - Waiting, pausing, interruption, and recovery are first-class runtime concepts.
Requirements
- Python 3.10+
tmux- a working Codex CLI setup
Installation
Install the published package:
python -m pip install flow-like-a-river
This installs the flow CLI command.
Development setup in a fresh virtual environment:
python -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
pytest
Runtime model
The runtime runs as a detached background process.
flow initstarts it if neededflow start ...also starts it automaticallyflow restartgracefully stops it and starts it againflow shutdownlets agents finish their current turn and then stops the runtimeflow shutdown nowkills agents and tmux sessions immediately
State is stored in:
~/.flow/runtime.sqlite3~/.flow/logs/daemon.log
You can override the home directory with FLOW_HOME.
Flow files
A flow file has:
- one top-level
flow:header block - one block per state, e.g.
my-state:
Top-level flow: fields:
name: flow nameversion: of the flow file format (optional, currently always1)path: initial working directory for new agents (optional, defaults to the current working directory whereflow startis run)mode: default Codex permissions mode (optional, defaults toyolo, other options aredanger-full-access,full-auto,workspace-write,read-only)thinking: default flow reasoning effort (optional, defaultxhigh, other options arehigh,mediumandlow)args: named CLI arguments for placeholders (optional)
State fields:
start: true: marks a start state (optional)end: true: marks an end state (optional)wait: default delay before the state runs (optional)prompt: text sent to the agent on entry (optional, state moves directly to transition questions if empty)mode: per-state mode override (optional default set inflow:header)thinking: per-state thinking override (optional, default set inflow:header)transitions: list of outgoing transitions (optional only ifend: true)
Transition fields:
if: natural-language condition, e.g. "the CI tests have all passed"wait: optional delay before entering the target state, e.g. "10m"go: target state name
Placeholders like {{repo}} can appear in strings. They become CLI arguments at flow start time.
Example:
flow:
name: check-ci
path: ~/project
args:
run_url:
help: GitHub Actions run URL
check:
start: true
prompt: |
Inspect the CI run at {{run_url}}.
transitions:
- if: still running
wait: 10m
go: check
- if: passed
go: notify-pass
- if: failed
go: investigate
notify-pass:
prompt: |
Send a success notification.
transitions:
- go: done
investigate:
prompt: |
Investigate the failure and write a short report.
transitions:
- go: done
done:
end: true
How a state runs
When an agent enters a normal state:
- Flow sends the state prompt to Codex (optionally after a wait period).
- Codex works until its turn completes.
- Flow asks Codex to choose one transition in strict JSON.
- Flow follows that transition.
There are also two implicit choices that change the status of an agent without changing its state:
keep_working: stays in the same state and tells Codex to continue workingneeds_help: stops automation for this agent and waits for someone to assist it
If a state has no prompt and exactly one unconditional transition, Flow auto-advances without asking Codex anything. This is useful for pure wait states.
Waiting
wait can appear on:
- a state: default delay when entering that state
- a transition: override delay for that specific entry
Internally, waits become an absolute ready_at timestamp.
Useful patterns:
- poll every 10 minutes by looping back to the same state with
wait: 10m - define a pure wait state with no prompt and one unconditional transition
If you want to cancel a wait early:
flow wake <agent-id>
wake only clears the timer. It does not resume an agent that is paused in interaction or needs_help.
CLI overview
Validate one or more flow files:
flow validate examples/agi-watcher.yaml examples/ci-notify.yaml
Start an agent:
flow start examples/agi-watcher.yaml --site news.ycombinator.com
If the flow has more than one start state:
flow start my-flow.yaml start-state-name --path ~/work/repo
List active and archived agents:
flow list
flow list agi-watcher
flow list --top
Show one agent in detail:
flow show 12
flow show 12 --top
flow show displays:
- flow name and working path
- start time
- total running time
- total waiting time
- Codex thread id when known
- a
codex resume ...hint for finished agents when possible - args
- a timestamped event log
With --top, flow list and flow show clear and redraw the screen every five seconds. Press space to refresh immediately and q to exit.
View live tmux sessions:
flow view 12
flow view 12 15 18
flow view --all
With multiple ids, flow view opens a tiled tmux dashboard with one read-only pane per agent.
Pause, interrupt, and resume automation:
flow pause 12
flow interrupt 12
flow resume 12
flow pause: pause automation without sendingCtrl-C; if Codex is already working on a turn, that turn is allowed to finish naturallyflow interrupt: pause automation and also sendCtrl-Cto the live Codex sessionflow resume: leaveinteractionorneeds_helpand let automation continue
Move or stop an agent:
flow move 12 investigate
flow stop 12
flow stop 12 done
Delete an archived agent entirely:
flow delete 12
Manage the runtime:
flow init
flow restart
flow shutdown
flow shutdown now
Agent states you will see
Normal runtime state:
- the agent is in a flow state and automation is active
Special substates:
interaction: you paused or interrupted the agent, and automation is pausedneeds_help: the agent asked for human help and automation is paused
Other useful runtime phases:
waiting: waiting forready_atworking: Codex is still working on the current promptfinished: the agent reached an end state
Diagnostics
flow list includes runtime diagnostics before the state list when relevant.
It can show:
- daemon crash details if the runtime exited with an error
- new runtime warnings and errors since the last time you ran
flow list - agent-level
errorandneeds_helpevents
This is driven by structured runtime diagnostics, not just raw log scraping.
Example files
examples/agi-watcher.yamlexamples/ci-notify.yaml
The examples cover:
- placeholders
- polling with
wait - success and failure transitions
- push-notification follow-up states
- a simple realistic monitoring flow
A typical session
Validate a flow:
flow validate examples/agi-watcher.yaml
Start an agent:
flow start examples/agi-watcher.yaml --site news.ycombinator.com
Watch progress:
flow list
flow list --top
flow show 1
flow show 1 --top
flow view 1
Intervene if needed:
flow pause 1
flow interrupt 1
flow resume 1
flow wake 1
flow move 1 investigate-failure
Restart the runtime after code changes:
flow restart
Stop everything cleanly:
flow shutdown
Notes
- Reserved state names are
stopped,needs_help, andinteraction. - End states cannot define
wait. - A state can only have one unconditional transition, and it must be last.
- Relative paths and
~inflow.pathare expanded to absolute paths. - Absolute and relative times in
flow showuse your local timezone for display.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flow_like_a_river-0.1.2.tar.gz.
File metadata
- Download URL: flow_like_a_river-0.1.2.tar.gz
- Upload date:
- Size: 58.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cd0b8408314d43cb0bb80a7bc2b522d35dd8778596918bafe877fb08aa9e9e0
|
|
| MD5 |
9feb1e4d6c9d8104a28145731db78b39
|
|
| BLAKE2b-256 |
4fe6215c40f8eb1140e175bcef8c7ec60c0c2d6c9b1b5d5465a6a0fbd5e445b4
|
Provenance
The following attestation bundles were made for flow_like_a_river-0.1.2.tar.gz:
Publisher:
workflow.yml on yieldthought/flow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flow_like_a_river-0.1.2.tar.gz -
Subject digest:
5cd0b8408314d43cb0bb80a7bc2b522d35dd8778596918bafe877fb08aa9e9e0 - Sigstore transparency entry: 1283895064
- Sigstore integration time:
-
Permalink:
yieldthought/flow@2901523a73150793b28062dd489c67a85fee5e2a -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/yieldthought
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@2901523a73150793b28062dd489c67a85fee5e2a -
Trigger Event:
push
-
Statement type:
File details
Details for the file flow_like_a_river-0.1.2-py3-none-any.whl.
File metadata
- Download URL: flow_like_a_river-0.1.2-py3-none-any.whl
- Upload date:
- Size: 45.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ddec9c9d05bebe1eada52af6e762b1a95937a9631e6b68b9c225ebc0ada1869
|
|
| MD5 |
d0d7e429d119ce8ad2f2c04fec07da82
|
|
| BLAKE2b-256 |
3f69108d09fa49bce197faa134e9b23ccf950b515eb876d49389fd49363d58f7
|
Provenance
The following attestation bundles were made for flow_like_a_river-0.1.2-py3-none-any.whl:
Publisher:
workflow.yml on yieldthought/flow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flow_like_a_river-0.1.2-py3-none-any.whl -
Subject digest:
3ddec9c9d05bebe1eada52af6e762b1a95937a9631e6b68b9c225ebc0ada1869 - Sigstore transparency entry: 1283895777
- Sigstore integration time:
-
Permalink:
yieldthought/flow@2901523a73150793b28062dd489c67a85fee5e2a -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/yieldthought
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@2901523a73150793b28062dd489c67a85fee5e2a -
Trigger Event:
push
-
Statement type: