返回 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. Small work stays direct; multiple delegated steps use a
5 > compact Workflow plan with dependencies, bounded scopes, and completion
6 > evidence. Fleet manages the same sub-agents and roles. One bounded,
7 > independent task can use a direct agent, with `followup` for continued work.
8 > Act/Agent may also use optional soft-auto launch. See
9 > [Automatic Workflows](AUTOMATIC_WORKFLOWS.md).
10
11 Workflow has one runtime boundary: authored source lowers to typed
12 Rust `WorkflowSpec`, Rust validates the IR, and the scheduler/headless worker
13 runtime executes leaves. Authoring languages do not get hidden authority to own
14 files, shell, network, providers, cancellation, or TUI state.
15
16 Compatibility launch paths on the `workflow` tool:
17
18 | Input | When to use |
19 |-------|-------------|
20 | `plan` | Structured goal / phases / children (preferred agent path) |
21 | `script` | Short inline JS the model owns |
22 | `source_path` | Checked-in `.workflow.js` / `.workflow.ts` in the workspace |
23
24 Use `agent(action="roster")` to inspect the saved Fleet models and roles before
25 assigning children. Native plan children accept `model` for a saved shortlist
26 selector, or `role`/`profile` for a saved assignment. Named Exact Fleets keep
27 their member routes fixed and reject per-step model overrides. Plan children
28 also accept `cwd`, a repository-relative working directory — required in
29 multi-repository workspaces so the child (and worktree isolation) resolves the
30 right repository, mirroring `task({cwd})`.
31
32 For a guided walkthrough from fleet task specs to Workflow authoring and
33 monitoring, see [fleet + Workflow Tutorial](FLEET_WORKFLOW_TUTORIAL.md).
34
35
36 ## Access model
37
38 The Workflow script is a **coordinator only**. It has no filesystem or shell of
39 its own. Real work happens in sub-agents the script launches.
40
41 | Layer | What it can access |
42 |-------|--------------------|
43 | 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. |
44 | 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. |
45 | Parent session | Working directory, configured tools/MCP, permission mode, sandbox/network rules. |
46
47 ### Scale
48
49 - Up to **16 concurrent** live agents in one run (additional spawns wait for a slot).
50 - Up to **1_000 agents per run** (VM lifetime spawn cap).
51 - Configured `max_children` and `max_concurrent` can narrow these limits.
52 - Automatic launch is model-judged on scope; the host enforces only the hard `max_children` / `max_depth` ceilings.
53 - Plan the population the work needs and let the host queue and clamp it.
54 These ceilings are enforcement, not a reason to pre-shrink a valid plan.
55
56 See the Workflow JS sandbox tests for the fail-closed host surface inventory.
57
58 ## Language Choice
59
60 | Surface | Strength | Tradeoff | v0.8.60 stance |
61 |---|---|---|---|
62 | YAML / JSON IR | Simple, reviewable, no runtime | Verbose for generated workflows | Keep as interchange/debug format |
63 | JavaScript | Familiar object syntax and easy agent generation | Unsafe if executed as a general runtime | First-class authoring through declarative compile-only subset |
64 | 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 |
65
66 The default high-capability path is TypeScript/JavaScript authoring, but only as
67 a compile step. The compiler accepts a JSON-compatible object inside
68 `workflow({...})` from `.workflow.js` or `.workflow.ts`, lowers it to
69 `WorkflowSpec`, and runs the Rust validation gate. (Starlark authoring was a
70 bootstrap reference and has been removed; Workflow authoring is JS-only.)
71
72 ## Contract
73
74 Accepted source shape:
75
76 ```js
77 export default workflow({
78 "id": "issue-audit-js",
79 "goal": "Audit an issue fix with parallel agents",
80 "nodes": [
81 {
82 "branch": {
83 "id": "parallel-audit",
84 "children": [
85 { "agent": { "id": "code-audit", "prompt": "Review code", "agent_type": "review" } },
86 { "agent": { "id": "test-audit", "prompt": "Review tests", "agent_type": "verifier" } }
87 ]
88 }
89 },
90 { "reduce": { "id": "summary", "inputs": ["code-audit", "test-audit"], "prompt": "Summarize" } }
91 ]
92 });
93 ```
94
95 Supported node wrappers: `agent`, `branch`, `sequence`, `reduce`,
96 `teacher_review`, `loop_until`, `cond`, and `expand`. Raw `WorkflowNode` JSON IR
97 with `kind` / `spec` also remains valid.
98
99 An `agent` node may declare `"profile": "reviewer"` to run as a named fleet
100 roster profile. The name is trimmed and lowercased at compile time and must be
101 a single token (no whitespace, quotes, or `=`); the saved roster is resolved at
102 dispatch time, and explicit fields on the agent override profile defaults.
103
104 The runtime `task()` surface also accepts `cwd` for an existing repository-
105 relative working directory. This is required when a workflow is launched from
106 a multi-repository workspace and the child needs shell or file access. `cwd`
107 is validated by the host, does not grant mutation authority, and should be
108 paired with `worktree: true` when the child needs an isolated checkout.
109
110 The compiler rejects effectful constructs such as `import`, `require`, `fetch`,
111 `process`, `Deno`, `Bun`, `child_process`, file reads/writes, `eval`, `async`,
112 and `await`. This is intentionally stricter than JavaScript: workflow source is
113 a familiar declaration format, not a second execution runtime. The denied
114 effects are not denied to the run — put them in a child worker, which has
115 the full tool surface, and keep the script to coordination.
116
117 ## Verification
118
119 - `cargo test -p codewhale-workflow --locked javascript`
120
121 Current example: `workflows/issue_audit.workflow.js`.
122
123 ## Agent-Written fleet Workflows
124
125 The primary product flow is not "ask the user to write a script." The main
126 agent should decide when a task deserves workflow orchestration, draft the
127 Workflow source, show the plan for the current permission mode, and then let
128 the runtime compile and monitor it.
129
130 Workflow owns the plan: phases, branches, loops, reducers, and intermediate
131 results. fleet owns the durable roster, member identity, semantic role, and
132 saved provider/model pins or inheritance. Runtime owns tool posture, launch
133 concurrency, leases, heartbeats, logs, receipts, and resume/stop/restart
134 controls. In other words, a workflow selects fleet members and monitors their
135 Runtime runs; it isn't an executor, because the script has no shell or
136 filesystem of its own — effects live in the workers.
137
138 Workflow-to-Runtime launch validation applies a conservative default shape
139 before any Workflow IR is lowered to selected workers:
140
141 - up to 1,000 total worker agents per Workflow run;
142 - up to 16 live worker agents at once; larger populations queue (block) on the
143 host's per-run concurrency gate until a live slot frees, then select through
144 fleet and execute through Runtime;
145 - Workflow IR structural nesting no deeper than 5;
146 - Runtime child delegation defaults to 3 levels and has an opt-in hard ceiling
147 of 8; that execution budget is independent of Workflow IR shape;
148 - loops require `max_iterations`;
149 - dynamic `expand` nodes require `max_children` and a template.
150
151 Those limits distinguish population from instantaneous launch concurrency. A
152 valid 1,000-agent Workflow can still drain through a smaller Runtime worker
153 pool. Model selection stays per member: a DeepSeek preset can suggest
154 `deepseek-v4-pro` for the orchestrator and `deepseek-v4-flash` for nearby
155 workers, but users and agents may override any slot when the task calls for it.
156
157 ## Experimental search is a Workflow option
158
159 Experimental search generalizes the existing best-of-N recipe without adding a
160 new product mode, scheduler, or sub-agent API. A provider-neutral
161 `WorkflowSearchSpec` freezes the objective, baseline, model request and resolved
162 version, public evidence, evaluator hash, hard gates, scoring rule, budgets,
163 write scope, rounds, and review-only integration policy before admission.
164
165 The current JS starter supports structured generation and read-only review with
166 `strategy: "search"`. Runtime-owned command gates, hidden evaluation, benchmark
167 scoring, and clean-baseline replay are an explicit host seam still to wire; a
168 candidate's self-verdict must never be promoted into evaluator truth. See
169 [Workflow Experimental Search](WORKFLOW_EXPERIMENTAL_SEARCH.md).
170
170 lines MARKDOWN