Open Dynamic Workflows
Dynamic workflow orchestration for Cursor, Grok Bot (via Cursor CLI), Grok Build, ZCode, Antigravity, and Copilot — fan a deterministic
JavaScript script out across many CLI subagents through a native workflow tool and authoring skill.
A dynamic workflow is a plain-JS script that orchestrates subagents at scale. The model
writes the script for the task; the plugin's bundled runtime executes it, fanning each
agent() call out to a real cursor-agent, grok, claude, codex, or zcode subprocess.
Harness policy (2026-09-11)
Claude harnesses use native ultracode; Codex/ChatGPT harnesses use native ultra mode. Advise the mode without changing the selected model; do not activate ODW on those hosts.
Cursor and Grok Bot use ODW with Cursor CLI workers, not Cursor multitask
or persistent Bot-to-Bot delegation. Set ODW_HOST=grok-bot explicitly in the
Bot VM; omitted executor then selects cursor, not Grok Build. Grok Build,
ZCode, Antigravity and Copilot retain their corresponding ODW executors.
Installation and live-run gaps remain explicit. Legacy Claude/Codex executors
remain available to standalone SDK callers, not their native-only host packages.
Worktree safety
Use isolation: 'worktree' for workers that mutate files concurrently, not for
every read-only task. The first isolated worker pins the caller HEAD for the whole
run, including nested workflows. Staged/unstaged caller edits are not copied or
discarded; commit required shared inputs before an isolated run. A caller inside
a repository subdirectory stays in that subdirectory inside each worker checkout.
Only successful pristine worktrees at their original commit are removed, without
force. New commits, changed/untracked/ignored files, failed or cancelled workers,
and uncertain cleanup retain the checkout. Use worktreeNotes and the agent
trace cwd to inspect and integrate the result; no changes are auto-merged into
the caller. Retained commits remain reachable through their worktree. Worktrees
are Git isolation, not a security sandbox: native permission checks remain in force.
Install (Cursor CLI)
Cursor CLI (agent, from cursor.com/install) does not yet install plugins from a marketplace the way Grok/Codex do. Use the repo installer — one copy-paste, then a new agent session has the workflow tool and the authoring skill. Omitted executor is cursor.
git clone --depth 1 https://github.com/atebites-hub/open-dynamic-workflows-plugin.git
node open-dynamic-workflows-plugin/scripts/install-cursor-cli.mjs
That writes an absolute MCP command into ~/.cursor/mcp.json (CLI user/project mcp.json does not expand ${PLUGIN_ROOT}), links the plugin into ~/.cursor/plugins/local/open-dynamic-workflows, and copies the skill to ~/.cursor/skills/open-dynamic-workflows. Then:
agent mcp enable open-dynamic-workflows
agent mcp list
Headless check: agent -p --force --trust --workspace . --output-format json --approve-mcps. Developers iterating on a checkout can skip the home install and load the dual-format plugin (Cursor Plugin + Agent Plugin) with agent --plugin-dir /path/to/open-dynamic-workflows-plugin.
Cursor IDE
cursor-agent plugin marketplace add atebites-hub/open-dynamic-workflows-plugin only registers the marketplace. Install open-dynamic-workflows from Customize, or copy/symlink the plugin into ~/.cursor/plugins/local. Plugin mcp.json still uses ${PLUGIN_ROOT} for that loader.
Omitted executor runs on cursor (agent / cursor-agent / CURSOR_BIN). Nested Cursor leaves set ODW_CURSOR_LEAF=1 and must not reload this plugin's workflow tool.
Cursor team marketplace
This repository is the team marketplace catalog (.cursor-plugin/marketplace.json, name atebites-cursor-plugins). In Dashboard → Plugins → Import from Repo, import:
https://github.com/atebites-hub/open-dynamic-workflows-plugin
Then in Customize, install:
- open-dynamic-workflows — this repo (
plugins/open-dynamic-workflows) - ponytail — https://github.com/atebites-hub/ponytail
- sol-advisor — https://github.com/atebites-hub/sol-advisor
Remote source values are GitHub URLs, which the official marketplace schema allows. Plugin entries only use name, source, and description. If Import from Repo only indexes in-repo paths, add the ponytail and sol-advisor GitHub repos as additional marketplaces — this catalog does not vendor those trees.
CLI install for open-dynamic-workflows is still node scripts/install-cursor-cli.mjs above.
Install (Grok Build)
grok plugin marketplace add atebites-hub/open-dynamic-workflows-plugin
grok plugin install open-dynamic-workflows --trust
Open a new Grok session (or press r in the Plugins tab). Omitted executor runs on grok.
The plugin is self-contained; no project-local ODW checkout or build is needed.
Claude and Codex: native mode only
Use Claude ultracode or Codex/ChatGPT ultra mode. These plugin manifests now provide only native-mode guidance, not an ODW MCP server. The server also rejects stale Claude/Codex host configurations with an actionable mode recommendation.
Install (Antigravity CLI)
After cloning/building this repository:
node scripts/install-antigravity-cli.mjs
The native CLI registers an absolute MCP command and imports the authoring skill.
No undocumented plugin-root substitution is used. Keep the checkout in place and
start a fresh session. Desktop/IDE seating requires its own live verification.
Use ANTIGRAVITY_BIN (or AGY_BIN) for an explicit CLI path. New worker sessions
use --new-project at their worktree cwd. Headless write permission must be
authorized for those paths; SUCCESS with denied_actions is treated as failure.
Install (Copilot)
copilot plugin install atebites-hub/open-dynamic-workflows-plugin:plugins/copilot/open-dynamic-workflows
Restart the session after install. COPILOT_BIN selects an explicit CLI binary.
The adapter requires the JSONL interface present in Copilot CLI 1.0.83. It keeps
path verification enabled, does not enable all paths/URLs, and reports quota or
permission errors instead of claiming an empty successful run. Model and effort
remain per-worker selections; unavailable billing quota is not an adapter pass.
Install (ZCode users)
/plugins marketplace add atebites-hub/open-dynamic-workflows-plugin
/plugins install open-dynamic-workflows
Then restart ZCode (or open a new session). That's it — no build step, no node_modules.
The plugin ships a self-contained dist/mcp/server.js.
After install, a session gets:
- a
workflowtool — the model authors a script and callsworkflow({ cwd, script }); it runs to completion and returns the script's value. - the
$open-dynamic-workflowsskill — the authoring guide (when to reach for a workflow, themeta/agent()/pipeline()/parallel()contract, proven shapes). - the
/open-dynamic-workflows:workflowsslash command — list and resume runs in the current project.
How it works
model writes a JS workflow script
└─ calls workflow({ cwd, script })
└─ plugin's MCP server (dist/mcp/server.js)
└─ ODW runtime: runWorkflow({ executors: { cursor, zcode, grok, claude, codex } })
├─ agent({executor:'cursor'}) (or omitted on Cursor) spawns `cursor-agent -p …`
├─ agent({executor:'zcode'}) (or omitted on ZCode) spawns `zcode --prompt …`
├─ agent({executor:'grok'}) (or omitted on Grok Build) spawns `grok -p …`
├─ agent({executor:'claude'}) spawns `claude --print …`
├─ agent({executor:'codex'}) spawns `codex exec --json …`
├─ parallel()/pipeline() orchestrate, journal persists results
└─ returns the script's `return` value + run metadata
Each executor uses the user's installed CLI from PATH (GROK_BIN / ZCODE_BIN / CURSOR_BIN override the
binary). Cursor runs headless agent/cursor-agent -p with --output-format json or stream-json,
--force, and --workspace. Nested cursor leaves do not reload this plugin's MCP (ODW_CURSOR_LEAF=1).
Grok runs headless grok -p with --output-format json or streaming-json,
--always-approve, and --sandbox workspace — never the broken --tools allowlist. Nested
grok leaves do not reload this plugin's MCP. Codex verifies cwd against the active workspace
metadata supplied by the host, then runs with JSONL output and a workspace-write sandbox.
ZCode uses ZCODE_ODW_PROTOCOL=1. Each agent is one real model turn. A Codex model override
defaults to medium reasoning unless the node supplies reasoningEffort. Completed agents
replay from the journal with zero token spend.
A minimal workflow
export const meta = { name: 'demo', description: 'two parallel grok agents' }
const results = await parallel([
() => agent('What is 2+2? Reply with just the number.', { executor: 'grok', label: 'math' }),
() => agent('Name a red planet. One word.', { executor: 'grok', label: 'trivia' }),
])
return { results }
Call workflow({ cwd: "/absolute/project/path", script: "<the above>" }); the tool returns
{ value: { results: [...] }, runId, ok, ... }.
See the $open-dynamic-workflows skill for the full authoring contract (phases, schemas,
the pipeline-vs-parallel decision, adversarial-verify / judge-panel / loop-until-dry shapes).
Repository layout
This repo is the Cursor, Grok, Codex, and ZCode marketplace and the plugin.
├── .cursor-plugin/marketplace.json # Cursor team marketplace catalog (official schema)
├── .cursor-plugin/plugin.json # Cursor plugin manifest
├── plugin.json # Agent Plugins manifest (CLI --plugin-dir)
├── mcp.json # Cursor MCP launch (${PLUGIN_ROOT}; IDE / plugin loader)
├── scripts/install-cursor-cli.mjs # Cursor CLI home install (absolute MCP path)
├── .grok-plugin/marketplace.json # Grok marketplace catalog
├── .grok-plugin/plugin.json # Grok plugin manifest (repo-as-plugin / grok plugin install .)
├── .grok-plugin/mcp.json # Grok MCP launch (GROK_PLUGIN_ROOT, 8h tool timeout)
├── plugins/open-dynamic-workflows/ # Grok marketplace package (catalog source; Grok rejects "./")
├── .agents/plugins/marketplace.json # Codex marketplace manifest
├── .codex-plugin/plugin.json # Codex plugin manifest
├── .codex-mcp.json # Codex MCP launch config
├── marketplace.json # ZCode marketplace manifest
├── .zcode-plugin/plugin.json # ZCode plugin manifest
├── .mcp.json # ZCode stdio MCP server (${ZCODE_PLUGIN_ROOT})
├── .claude-plugin/plugin.json # Claude Code manifest + MCP mirror
├── skills/open-dynamic-workflows/ # authoring skill (vendored from ODW)
├── commands/workflows.md # /workflows slash command
├── src/mcp/server.ts # MCP server source (the `workflow` tool)
├── dist/mcp/server.js # COMMITTED self-contained bundle (what runs)
├── scripts/{build,setup,smoke}.mjs # dev build + smoke pipeline
├── open-dynamic-workflows/ # git submodule (ODW source — dev only)
└── zcode-cli/ # git submodule (dev convenience; not bundled)
For maintainers / contributors
The dist/mcp/server.js that users run is built from the submodules and committed.
Nested remotes, pin policy, and the weekday sync workflow are in UPSTREAM.md.
After cloning:
npm run setup # init submodules + locked installs + build ODW + esbuild → dist/mcp/server.js
npm run smoke # standalone JSON-RPC smoke test of the built server
npm run build # rebuild just the bundle (skips submodule init)
npm run verify # rebuild and run the plugin smoke checks
node scripts/install-cursor-cli.mjs # Cursor CLI: MCP + local plugin + skill
The build (scripts/build.mjs) uses esbuild to inline ODW + its only dep (ajv) into a
single ESM file, matching the android-emulator plugin's pattern. No node_modules ship to
users.
Governed routing (v0.3)
For a run that must use one exact route, pass an immutable policy:
workflow({
cwd: "/absolute/project/path",
routingPolicy: {
executor: "codex",
model: "gpt-5.4",
reasoningEffort: "high",
},
script,
})
The policy is validated by ODW core before the journal or any subprocess is opened. Every
omitted node route inherits it; an explicit executor, model, or reasoning-effort conflict fails
before launch. Nested workflows inherit the same policy. Policy runs cannot combine with
resumeFromRunId or cache replay. The MCP result exposes only the allowlisted policy tuple and
its SHA-256 routingPolicyFingerprint; this is correlation evidence, not proof that a host CLI
accepted the requested model. Inspect the run trace for the authoritative executor/model/effort
and runtime ID when the host provides them.
Without routingPolicy, existing host defaults remain unchanged: omitted executor selects
Cursor, Grok, Claude, Codex, or ZCode from the host launch environment. An explicit executor
still overrides that host default.
Notes / scope (v0.4.3)
- Host-native default worker. Omitted
executoruses cursor on Cursor and Grok Bot, grok on Grok Build, zcode on ZCode, codex on Codex, claude on Claude Code. Name another worker to override. - Host-specific lifecycle. Grok Bot
workflow()returns a durable background job handle; pollworkflow_statusand useworkflow_cancelto stop it. Other hosts keep their synchronousworkflow()behavior. - Local evidence.
.odw/artifacts contain workflow scripts, prompts, and agent responses; newly written run files are owner-only. Keep.odw/gitignored. - No ultracode auto-decide. ODW does not auto-inject a workflow the way Claude ultracode can. The skill and tool descriptions stay passive; the model decides. Claude/Codex host exclusions and the Cursor/Grok Bot ODW route are defined by the harness policy above.
- Telemetry. The
zcode_resultenvelope currently reportscostUsd/inputTokens/outputTokensas null (telemetryAvailable: false). The plugin reports zeros honestly until the zcode launcher fills these in.
See harness policy above.
License: MIT.
Native-only installation roots
Claude and Codex install the small packages under
native/claude/open-dynamic-workflows and native/codex/open-dynamic-workflows.
Do not install the development repository root on those hosts: native auto-
discovery can otherwise load root workflow skills and the ZCode MCP config.
The published advice-only roots contain one native-orchestration skill and no
MCP configuration. Claude external catalogs use the documented git-subdir
source with the reviewed release SHA; Codex's own catalog points at its native
package directory. Other hosts retain the full workflow package.
Grok Bot through Cursor CLI
This is a configured host-to-executor mapping, not native Bot orchestration.
The worker CLI runs inside the Bot VM. Do not use a Mac-side fallback or
substitute the ambiguous agent binary, which may belong to Grok Build.
Before installation, check cursor-agent --version and cursor-agent status
in that VM. Keep credentials out of prompts and logs. A Grok Bot login does not
prove Cursor CLI authentication, model availability, or which allowance pays
for its requests. No model selection or billing setting is changed by this plugin.
For the Cursor CLI MCP configuration in the Bot VM:
node scripts/install-cursor-cli.mjs --host grok-bot
cursor-agent mcp enable open-dynamic-workflows
This installer configures Cursor CLI; it does not install/authenticate that CLI
or certify that the Grok Bot host loads its local MCP configuration. Register
node /absolute/plugin/dist/mcp/server.js with ODW_HOST=grok-bot through the
host's supported MCP mechanism. If that mechanism is unavailable, report an
installation gap rather than calling an alternate host a Grok Bot pass.
Every Grok Bot workflow call must supply its absolute VM project cwd.
Use isolation: 'worktree' for parallel writers. Poll the returned jobId with
workflow_status; accepted/queued is not success. Inspect the final result's
executionContext (configured host/default executor only), per-agent traces
(actual executor), and retained branch/diff receipts. Never infer preserved
files from a resumed chat ID, or runtime/model attestation from a host label.
npm run verify exercises the Grok Bot mapping, missing/relative cwd rejection,
installer idempotence, and two retained writer worktrees through the packaged
server. The model CLIs in those tests are fixtures; live VM qualification is
still a separate requirement.
Grok Bot background jobs (0.4.2)
The host's short MCP deadline must not own a long workflow. workflow now
accepts a job promptly on Grok Bot, while a detached supervisor runs the same
ODW engine. workflow_status({cwd, jobId, waitSeconds: 10}) waits at most 20
seconds per call; poll until terminal. Only state: "completed", ok: true
means success: all nodes must succeed and the journal must be durable.
Pass a stable optional requestId for idempotent start retries. Identical
snapshotted inputs return the same job; changed inputs under that key are
rejected. This is not agent-cache replay. scriptPath is snapshotted at start
and resolves relative to the supplied project cwd. The core runId becomes
available after execution starts and is distinct from the control jobId.
Jobs survive an MCP request ending or the MCP server process disconnecting.
Use workflow_cancel({cwd, jobId}) for explicit cancellation. maxSeconds
bounds the whole job: default 1800, range 1-28800, plus up to 5 seconds for
cooperative abort/receipt flushing before the supervisor kills its owned
runtime process group. Cancellation retains partial CLI traces and worktrees.
On Linux, 0.4.3 also stops job-marked Cursor Shell sessions that detached from
that group. Status exposes cleanup.method and cleanup.complete; terminal
receipts are written after cleanup. Cleanup failure is interrupted, never a
successful run. Non-Linux hosts retain process-group-only cleanup. The marker is
lifecycle ownership, not a security sandbox or protection against hostile workers.
No PID supplied by a client is ever signalled. Unknown/cross-project handles
fail; a dead supervisor without a terminal receipt is interrupted, never a pass.
Private job input, status, result and runner logs live in .odw/.jobs/.
Gitignore that directory as well as workflow run artifacts: they can contain
prompts/results. No credentials or environment snapshot are written by the
job controller. This is POSIX process supervision, not a security sandbox,
VM-restart recovery, or strict Advisor attestation. A lost VM cannot be made
durable by this adapter; preserve/inspect its evidence before a fresh run.
Run npm run verify:long for a packaged >60-second process/worktree fixture.
It uses fake model CLIs; a real Grok Bot run is a separate release acceptance.