agentflow is a small Node runner. A workflow is an .mjs file; each agent()
call spawns one non-interactive CLI session of the harness you pick, under a
bounded concurrency pool, and every settled result is journaled so a run can be
resumed. The plan lives in the script, not in a model's context window. This is
the same idea as Claude Code's dynamic workflows,
delivered as a portable subprocess runner.
agentflow social card: the mark, wordmark and an illustrative run ledger
The image is a design proposal with illustrative log lines, not a capture. TODO: replace with a real terminal recording of
agentflow tailon a live run (needs paid or free-tier model calls, so it was not recorded here).
Install
Requires Node 20 or newer. From a clone:
git clone https://github.com/duketopceo/agentflow
cd agentflow
bin/agentflow doctor # which harness CLIs are on PATH
There is no npm package yet ("private": true; see ROADMAP U5).
npm install is only needed for the OpenCode plugin.
As an agent plugin
const results = await parallel(files.map((f) => () =>
agent(Review ${f}, { label: review:${f}, model: "cheap" })
));
const good = results.filter(Boolean);
Globals inside a script: `agent()`, `parallel()`, `pipeline()`, `batch()`,
`phase()`, `log()`, `args`. `batch()` fans out through the harness's async
surface — one OR Batch job on `--harness openrouter` (~40–60% cheaper),
one Devin Cloud session per item on `--harness devin` (`swe-2` models are
free), one async sonar request per item on `--harness perplexity`
(grounded, cited answers — the research surface), or first-party batch APIs
on `--harness openai`/`--harness anthropic` (~50% off, 24h window). Results
align to input order; resumable mid-poll.
## Watching a run
`agentflow watch [run-id]` renders a live per-lane view from the run journal —
spinning in-flight lanes, batch poll progress, per-call token counts, orphan
detection — on an alternate screen. Piped output falls back to `tail`-style
event lines; `status <id>` prints the same totals for scripts. Token usage
is journaled per call on harnesses that report it (devin, via `--export`)
and summed in `status`/`watch`.
## Install as an agent plugin
The repo carries a manifest for each harness; all resolve to the shared
`skills/agentflow/` directory.
| Harness | Install |
|---|---|
| Devin | `devin plugins install -y duketopceo/agentflow` (or `--local /path/to/agentflow`) — reads `.devin-plugin/`; auto-installs the compound-engineering plugin via `requiredPlugins` |
| Claude Code | `claude plugin marketplace add duketopceo/agentflow` then `claude plugin install agentflow@agentflow` → `.claude-plugin/` (live-verified) — though inside Claude, prefer the native Workflow tool |
| Codex | `codex plugin marketplace add duketopceo/agentflow` then `codex plugin add agentflow@agentflow` → `.codex-plugin/` (live-verified) |
| OpenCode | v1 `1.18.29+`: `opencode plugin github:duketopceo/agentflow` → `plugins/agentflow/v1.mjs` (live-verified). v2: `opencode plugin github:duketopceo/agentflow#main::path:plugins/agentflow` → `v2.mjs` (no v2 CLI published yet). Both expose `agentflow_run`/`agentflow_doctor`. See `.opencode/INSTALL.md` |
| Factory Droid | `droid plugin marketplace add duketopceo/agentflow` — `.factory-plugin/` native (`.claude-plugin/` also auto-translates); ships the `worker` droid |
| Copilot CLI | `copilot plugin install duketopceo/agentflow` (verified: skill installs); MCP via `copilot mcp add agentflow -- agentflow mcp` |
| Cursor | `.cursor-plugin/` native; submit listing via cursor.directory or cursor.com/marketplace/publish — root `plugin.json` also covers the open standard |
| Gemini CLI | `gemini extensions install https://github.com/duketopceo/agentflow` — verified live: `gemini mcp list` shows `agentflow` connected |
| Any MCP client | `agentflow mcp` — the `.mcp.json` at repo root wires it (Crush, Claude Desktop, Zed, Roo, Kiro…). Tools: `agentflow_run`/`doctor`/`status`/`tail`/`stop` |
| Ori/OpenRouter/Perplexity | no plugin surface — run `agentflow` CLI directly with `--harness ori` / `--harness openrouter` / `--harness perplexity` or `--via ori` |
<sub>Devin, OpenCode v1, Claude Code, Codex, Gemini (extension + MCP server), the universal
skills registry, and Copilot rows are live-verified; Factory/Cursor rows are
manifest-verified (GUI/no-binary installs). agentflow is not published to npm — the plugin manifests above
(or a clone + `npm link`) are the install path.</sub>
## Quick start
No model calls, no cost:
```bash
bin/agentflow run examples/parallel-audit.mjs --harness echo
Real harness, cheap model (see docs/smoke-matrix.md for tested combinations):
bin/agentflow run workflows/deep-research.mjs --harness devin -- "your question"
bin/agentflow run workflows/deep-research.mjs --harness openrouter --cache -- "your question" # needs OPENROUTER_API_KEY
bin/agentflow run my-workflow.mjs --harness claude --via ori -- args # claude workers billed through OpenRouter
A workflow script has top-level await and these globals: agent, parallel,
pipeline, phase, log, args.
export const meta = { name: "audit", description: "review every file", phases: ["fan-out"] };
phase("fan-out");
const results = await parallel(files.map((f) => () =>
agent(`Review ${f}`, { label: `review:${f}`, model: "cheap" })
));
const good = results.filter(Boolean); // a failed call is null, not an exception
Commands: run, status <run-id>, tail <run-id>, list, doctor.
Useful flags: --harness, --concurrency, --via ori, --cache, --resume <run-id>,
--retries, --max-agents, --strict, --detach.
How it works
flowchart LR
S[workflow script .mjs] --> R[runtime: pool + journal]
R -->|agent#40;#41; x N| P{adapter}
P --> D[devin -p]
P --> C[claude -p]
P --> X[codex exec]
P --> O[opencode run]
P --> I[ori code]
P --> H[openrouter HTTP]
P -.->|--via ori| W[ori wraps the CLI]
R --> J[(.agentflow/runs/id.jsonl)]
J -->|--resume| R
- Cross-harness means: one script, and a thin adapter per CLI that builds
argv, spawns the process, classifies failure (timeout, permission denial) and
parses output into
{text, json}. Sessions, tools and context are not shared; workers share only the filesystem. - Journal: each settled call is one line in
.agentflow/runs/<run-id>.jsonl.--resumereplays settled calls by call order, so keepagent()call order stable.--cachememoises by content (prompt, model, schema, ...) instead. - Limits you should know: no sandbox beyond what each CLI enforces, no
usage/cost numbers in the journal, schema output is validated by prompt and
extraction only (native on codex), and
--resumedoes not yet check that a prompt is unchanged (ROADMAP U3).
Ops
bin/agentflow run w.mjs --detach # background; journal keeps the record
bin/agentflow status <run-id> # progress; 'orphaned' if the pid died
bin/agentflow stop <run-id> # SIGTERM the journaled pid (resumable)
bin/agentflow clean [--all] # reclaim worktrees of non-live runs (force!)
node scripts/smoke-harnesses.mjs # reproducible live-adapter matrix
Ops commands are cwd-rooted — run them from the directory you ran run
from. clean force-removes worktrees (ended and orphaned runs): harvest
agent work first.
agent(p, {worktree: 'auto'}) runs the call in its own git worktree under
.agentflow/worktrees/ — isolates file-mutating agents from the main
checkout; clean reclaims them after the run ends.
Docs
skills/agentflow/SKILL.md— agent-facing guidance (installed per harness)docs/plans/— design history and the program roadmapdocs/smoke-matrix.md— live per-adapter verification results (scripts/smoke-harnesses.mjsreproduces)docs/research/— cross-harness landscape + orchestration economics; start with2026-10-10-landscape.mddocs/publish-matrix.md— per-harness distribution surfaces and publish pathsDESIGN.mdandassets/brand/— design direction and logo proposal
Status
Early development, v0.2. Plans and priorities are in ROADMAP.md.
Contributing
Run node --test. Keep changes small and add a test for adapter behaviour; see
docs/solutions/agent-orchestration/ for the invariants (notably that every
spawnAgent override must call applyVia). Open a PR; the default branch is
protected.
License
AGPL-3.0. Free to use and modify, including privately. If you host or distribute a modified version, you must publish your source under the same license. See LICENSE.
Versions of this repository before the AGPL-3.0 change were published under the MIT License, and those copies remain available under MIT.