返回 CodeWhale
WORKFLOW_AUTHORING.md
根目录 / docs / WORKFLOW_AUTHORING.md
1 # Workflow Authoring
2
3 > **Ordinary multi-agent work does not require this file.** In Operate, send
4 > normal messages; Codewhale can work directly or prefer background workers
5 > when parallelism, isolation, or duration makes delegation useful. Use Workflow
6 > when ordered phases, gates, shared budgets, replay, or deterministic fan-in
7 > matter; Act/Agent may also use optional soft-auto launch. See
8 > [Automatic Workflows](AUTOMATIC_WORKFLOWS.md).
9
10 Workflow has one runtime boundary: authored source lowers to typed
11 Rust `WorkflowSpec`, Rust validates the IR, and the scheduler/headless worker
12 runtime executes leaves. Authoring languages do not get hidden authority to own
13 files, shell, network, providers, cancellation, or TUI state.
14
15 Compatibility launch paths on the `workflow` tool:
16
17 | Input | When to use |
18 |-------|-------------|
19 | `plan` | Structured goal / phases / children (preferred agent path) |
20 | `script` | Short inline JS the model owns |
21 | `source_path` | Checked-in `.workflow.js` / `.workflow.ts` in the workspace |
22
23 For a guided walkthrough from Fleet task specs to Workflow authoring and
24 monitoring, see [Fleet + Workflow Tutorial](FLEET_WORKFLOW_TUTORIAL.md).
25
26
27 ## Access model
28
29 The Workflow script is a **coordinator only**. It has no filesystem or shell of
30 its own. Real work happens in sub-agents the script launches.
31
32 | Layer | What it can access |
33 |-------|--------------------|
34 | Workflow script (JS VM) | Script variables, branching/loops, `task()` / `parallel()` / `pipeline()`, `phase` / `log`, `budget` / `args`. **No** direct FS, shell, network, env, imports, clock, or randomness. |
35 | Workflow-spawned sub-agents | Normal tool surface (read/search/edit/write, shell, web, MCP) subject to role posture, allowlists, and parent policy. File edits for write-capable roles auto-accept under Workflow; shell / web / MCP still require parent auto-approve or fail closed. |
36 | Parent session | Working directory, configured tools/MCP, permission mode, sandbox/network rules. |
37
38 ### Scale
39
40 - Up to **16 concurrent** live agents in one run (additional spawns wait for a slot).
41 - Up to **1_000 agents per run** (VM lifetime spawn cap).
42 - Soft auto-launch still uses a lower child soft-cap (`auto_start_child_limit`).
43
44 See the Workflow JS sandbox tests for the fail-closed host surface inventory.
45
46 ## Language Choice
47
48 | Surface | Strength | Tradeoff | v0.8.60 stance |
49 |---|---|---|---|
50 | YAML / JSON IR | Simple, reviewable, no runtime | Verbose for generated workflows | Keep as interchange/debug format |
51 | JavaScript | Familiar object syntax and easy agent generation | Unsafe if executed as a general runtime | First-class authoring through declarative compile-only subset |
52 | TypeScript | Best editor/types story for workflow SDK | Needs stripping/typechecking if full TS is supported | Same compile-only subset for now; richer SDK later |
53
54 The default high-capability path is TypeScript/JavaScript authoring, but only as
55 a compile step. The compiler accepts a JSON-compatible object inside
56 `workflow({...})` from `.workflow.js` or `.workflow.ts`, lowers it to
57 `WorkflowSpec`, and runs the Rust validation gate. (Starlark authoring was a
58 bootstrap reference and has been removed; Workflow authoring is JS-only.)
59
60 ## Contract
61
62 Accepted source shape:
63
64 ```js
65 export default workflow({
66 "id": "issue-audit-js",
67 "goal": "Audit an issue fix with parallel agents",
68 "nodes": [
69 {
70 "branch": {
71 "id": "parallel-audit",
72 "children": [
73 { "agent": { "id": "code-audit", "prompt": "Review code", "agent_type": "review" } },
74 { "agent": { "id": "test-audit", "prompt": "Review tests", "agent_type": "verifier" } }
75 ]
76 }
77 },
78 { "reduce": { "id": "summary", "inputs": ["code-audit", "test-audit"], "prompt": "Summarize" } }
79 ]
80 });
81 ```
82
83 Supported node wrappers: `agent`, `branch`, `sequence`, `reduce`,
84 `teacher_review`, `loop_until`, `cond`, and `expand`. Raw `WorkflowNode` JSON IR
85 with `kind` / `spec` also remains valid.
86
87 An `agent` node may declare `"profile": "reviewer"` to run as a named Fleet
88 roster profile. The name is trimmed and lowercased at compile time and must be
89 a single token (no whitespace, quotes, or `=`); the saved roster is resolved at
90 dispatch time, and explicit fields on the agent override profile defaults.
91
92 The runtime `task()` surface also accepts `cwd` for an existing repository-
93 relative working directory. This is required when a workflow is launched from
94 a multi-repository workspace and the child needs shell or file access. `cwd`
95 is validated by the host, does not grant mutation authority, and should be
96 paired with `worktree: true` when the child needs an isolated checkout.
97
98 The compiler rejects effectful constructs such as `import`, `require`, `fetch`,
99 `process`, `Deno`, `Bun`, `child_process`, file reads/writes, `eval`, `async`,
100 and `await`. This is intentionally stricter than JavaScript: workflow source is
101 a familiar declaration format, not a second execution runtime.
102
103 ## Verification
104
105 - `cargo test -p codewhale-workflow --locked javascript`
106
107 Current example: `workflows/issue_audit.workflow.js`.
108
109 ## Agent-Written Fleet Workflows
110
111 The primary product flow is not "ask the user to write a script." The main
112 agent should decide when a task deserves workflow orchestration, draft the
113 Workflow source, show the plan for the current permission mode, and then let
114 the runtime compile and monitor it.
115
116 Workflow owns the plan: phases, branches, loops, reducers, and intermediate
117 results. Fleet owns the durable sub-agent configuration: slots, profiles,
118 models, tool posture, launch concurrency, leases, heartbeats, logs, receipts,
119 and resume/stop/restart controls. In other words, a workflow can choose and
120 monitor Fleet slots, but it must not become a second executor with its own shell
121 or filesystem authority.
122
123 Fleet launch validation applies a conservative default shape before any
124 Workflow IR is lowered to workers:
125
126 - up to 1,000 total worker agents per Workflow run;
127 - up to 16 live worker agents at once; larger populations queue (block) on the
128 host's per-run concurrency gate until a live slot frees, then route through
129 Fleet;
130 - up to 5 recursive Fleet rings (the default user configuration is 2);
131 - loops require `max_iterations`;
132 - dynamic `expand` nodes require `max_children` and a template.
133
134 Those limits distinguish population from instantaneous launch concurrency. A
135 valid 1,000-agent Workflow can still drain through a smaller Fleet
136 worker pool. Model selection stays per slot: a DeepSeek preset can suggest
137 `deepseek-v4-pro` for the orchestrator and `deepseek-v4-flash` for nearby
138 workers, but users and agents may override any slot when the task calls for it.
139
140 ## Experimental search is a Workflow option
141
142 Experimental search generalizes the existing best-of-N recipe without adding a
143 new product mode, scheduler, or sub-agent API. A provider-neutral
144 `WorkflowSearchSpec` freezes the objective, baseline, model request and resolved
145 version, public evidence, evaluator hash, hard gates, scoring rule, budgets,
146 write scope, rounds, and review-only integration policy before admission.
147
148 The current JS starter supports structured generation and read-only review with
149 `strategy: "search"`. Runtime-owned command gates, hidden evaluation, benchmark
150 scoring, and clean-baseline replay are an explicit host seam still to wire; a
151 candidate's self-verdict must never be promoted into evaluator truth. See
152 [Workflow Experimental Search](WORKFLOW_EXPERIMENTAL_SEARCH.md).
153
153 lines MARKDOWN