301 lines
13 KiB
Markdown
301 lines
13 KiB
Markdown
# Draft Workspaces Reference
|
|
|
|
Use draft workspaces for iterative workflow authoring. They are mutable and
|
|
revisioned; artifacts are immutable and versioned.
|
|
|
|
Before writing or patching a draft, inspect the current public shape:
|
|
|
|
wf schema draft
|
|
wf schema DraftUseStep
|
|
|
|
## Draft Shape
|
|
|
|
A draft has:
|
|
|
|
- `name`
|
|
- `input_schema`
|
|
- `state_schema`
|
|
- `output_schema`
|
|
- `start`
|
|
- `steps`
|
|
- `routes`
|
|
- optional top-level `output`
|
|
|
|
`steps` are keyed by stable ids. `routes` map outcomes to another step id or
|
|
`__end__`.
|
|
|
|
## Mapping Rules
|
|
|
|
Step input bindings read graph values into node-local input:
|
|
|
|
```json
|
|
{
|
|
"target": "text",
|
|
"path": "input.text"
|
|
}
|
|
```
|
|
|
|
Step output bindings write node-local output into workflow state:
|
|
|
|
```json
|
|
{
|
|
"source": "echoed",
|
|
"target": "state.echoed"
|
|
}
|
|
```
|
|
|
|
Top-level workflow output uses `path` / `target`, not step-level
|
|
`source` / `target`:
|
|
|
|
```json
|
|
{
|
|
"path": "state.echoed",
|
|
"target": "echoed"
|
|
}
|
|
```
|
|
|
|
## Workspace Flow
|
|
|
|
1. Create workspace from capability.
|
|
2. Get workspace with `include_draft=true` before patching.
|
|
3. Patch with current `revision`.
|
|
4. Validate workspace.
|
|
5. Save artifact or wrapper from workspace.
|
|
|
|
Capability-backed creation auto-binds required capability inputs only. Optional
|
|
inputs remain declared by the capability but are omitted from the initial step
|
|
input map. Add one deliberately when the workflow should expose it:
|
|
|
|
```bash
|
|
wf draft bind report_ws --revision 2 --step call --from input.path --to local.path
|
|
```
|
|
|
|
If a patch returns `revision_conflict`, fetch the workspace again and retry
|
|
against the latest revision.
|
|
|
|
Forward routes in drafts are allowed as invalid intermediate state. If
|
|
`wf draft add capability --route ok=collect` returns `status: invalid`, add the
|
|
missing `collect` step next, then run `wf draft validate`. Do not save or
|
|
compile until validation is valid.
|
|
|
|
## Focused Helpers
|
|
|
|
Prefer focused helpers over JSON Patch for common edits:
|
|
|
|
- `set_draft_name`
|
|
- `set_draft_route`
|
|
- `set_step_input_map`
|
|
- `set_step_output_bindings`
|
|
- `set_step_output_map`
|
|
- `set_workflow_output_bindings`
|
|
- `set_workflow_output_map` (compatibility-only map adapter)
|
|
- `bind_draft`
|
|
- `add_step`
|
|
- `add_step_from_capability`
|
|
- `update_capability_step`
|
|
- `branch_draft`
|
|
- `handle_draft`
|
|
- `compile_draft_workspace`
|
|
|
|
CLI equivalents:
|
|
|
|
```bash
|
|
wf draft set-name <workspace_id> --revision <n> --name <name>
|
|
wf draft set-route <workspace_id> --revision <n> --step <step_id> --outcome ok --to <target>
|
|
wf draft set-input <workspace_id> --revision <n> --step <step_id> --map input.title=report.title
|
|
wf draft set-input <workspace_id> --revision <n> --step <step_id> --value request.format='"markdown"'
|
|
wf draft set-input <workspace_id> --revision <n> --step <step_id> --bindings-file bindings.json
|
|
wf draft set-input <workspace_id> --revision <n> --step <step_id> --clear
|
|
wf draft set-input <workspace_id> --revision <n> --step <step_id> --merge --map input.other=other
|
|
wf draft set-output <workspace_id> --revision <n> --step <step_id> --map text=state.text
|
|
wf draft set-output <workspace_id> --revision <n> --step <step_id> --bindings-file bindings.json
|
|
wf draft set-output <workspace_id> --revision <n> --step <step_id> --clear
|
|
wf draft set-output <workspace_id> --revision <n> --step <step_id> --merge --map other=state.other
|
|
wf draft set-workflow-output <workspace_id> --revision <n> \
|
|
--map state.value=result --value format='"markdown"'
|
|
wf draft set-workflow-output <workspace_id> --revision <n> \
|
|
--bindings-file output-bindings.json
|
|
wf draft set-workflow-output <workspace_id> --revision <n> --clear
|
|
wf draft set-workflow-output <workspace_id> --revision <n> \
|
|
--merge --map state.other=other
|
|
wf draft branch <workspace_id> --revision <n> --step <step_id> --route ok=__end__ --route error=fail
|
|
wf draft handle <workspace_id> --revision <n> --to fail --branch lookup:error --branch transform:error
|
|
wf draft compile <workspace_id>
|
|
wf draft bind <workspace_id> --revision <n> --step <step_id> --from local.document.markdown --to state.document.markdown
|
|
wf draft bind <workspace_id> --revision <n> --step <step_id> --from input.title --to local.document.title
|
|
wf draft add capability <workspace_id> --revision <n> --step <step_id> --capability <qualified_name> --from-step <prev> --from-outcome ok --route ok=__end__ --route error=fail --input input.title=report.title --bind-output result=state.result
|
|
wf draft add interrupt <workspace_id> --revision <n> --step review --kind issue_review --request-schema-file request.schema.json --resume-schema-file resume.schema.json --outcome submitted --outcome cancelled --route submitted=next --route cancelled=revise
|
|
wf draft add when <workspace_id> --revision <n> --step decide --condition-file condition.json --then next --otherwise revise
|
|
```
|
|
|
|
`set-workflow-output` replaces the complete ordered top-level
|
|
`WorkflowDraft.output` binding list. It accepts graph source paths
|
|
(`input.*`, `state.*`, or `context.*`) and literal values; `set-output` edits
|
|
one step's local-to-state bindings. Nested `input.*` and `state.*` sources can
|
|
project missing output-schema fields from their declared source schemas.
|
|
Literal values and `context.*` paths require declared output targets, and
|
|
literal values are validated against those targets rather than inferred.
|
|
|
|
`set-input` direction: `input.title=document.title` means graph source
|
|
`input.title` maps to node-local target `local.document.title`. Targets are
|
|
rootless node-local paths; never prefix the target with `local.`. Existing
|
|
single-field targets such as `input.text=text` remain valid. Repeated graph
|
|
sources are allowed and preserve fan-out to distinct local targets.
|
|
|
|
Canonical replacement can mix ordered path and literal bindings:
|
|
|
|
```bash
|
|
wf draft inspect WS --include-draft |
|
|
jq '.draft.steps.publish.input' > bindings.json
|
|
|
|
wf draft set-input WS --revision 4 --step publish \
|
|
--map state.report.title=request.title \
|
|
--map state.report.markdown=request.body \
|
|
--value request.format='"markdown"'
|
|
|
|
wf draft set-input WS --revision 5 --step publish \
|
|
--bindings-file bindings.json
|
|
|
|
wf draft set-input WS --revision 6 --step publish --clear
|
|
```
|
|
|
|
Replacement is the default and `--bindings-file` is the canonical lossless
|
|
form. `--merge` is retained only for compatibility map-only edits. Do not use
|
|
it to add literals or when canonical ordering or repeated-source fan-out must
|
|
survive. Existing literal bindings are retained during a map-only merge.
|
|
|
|
`set-output` direction: `text=state.text` means node-local source `local.text`
|
|
maps to graph target `state.text`.
|
|
|
|
Without `--merge`, `set-input` replaces the whole ordered binding list;
|
|
`set-output` replaces its complete ordered canonical binding list. Repeated
|
|
sources are valid fan-out when their state targets differ. Use the canonical
|
|
file form for a lossless round-trip, or `--clear` to replace the list with no
|
|
bindings:
|
|
|
|
```bash
|
|
wf draft set-output WS --revision 4 --step analyze \
|
|
--map report.title=state.report.title \
|
|
--map report.title=state.audit.title
|
|
|
|
wf draft inspect WS --include-draft |
|
|
jq '.draft.steps.analyze.output' > output-bindings.json
|
|
|
|
wf draft set-output WS --revision 5 --step analyze \
|
|
--bindings-file output-bindings.json
|
|
|
|
wf draft set-output WS --revision 6 --step analyze --clear
|
|
```
|
|
|
|
`--clear` replaces the list with `[]` and restores the implicit same-name state
|
|
fallback. `--merge --map` is compatibility-only and may collapse existing
|
|
fan-out; it cannot preserve literals or canonical ordering. Use it only when a
|
|
lossy map edit is acceptable.
|
|
|
|
`bind input.title -> local.document.title` is schema-aware and idempotent when
|
|
`input.title` is already declared. Bind names both rooted endpoints explicitly.
|
|
Use it for repair hints or schema projection. Use
|
|
`set-input --merge --map input.title=document.title` when you only need to update
|
|
a compatibility step input map; that command already implies the local side.
|
|
|
|
- `bind_draft`
|
|
|
|
Declares a workflow input/state/output schema field from a capability local
|
|
input/output schema and merges the matching step binding. Use `input/state ->
|
|
local` for step inputs and `local -> state/output` for step outputs. Prefer
|
|
this over manual JSON Patch when validation says a target schema field is
|
|
missing. The selected step must have `use` so the helper can find the
|
|
capability schema. It intentionally rejects non-capability/control steps
|
|
instead of guessing. A `local.x -> output.y` bind is atomic: it projects the
|
|
capability field schema into both workflow state and output schemas, writes
|
|
`local.x -> state.y` on the step, and publishes `state.y -> output.y` at the
|
|
workflow boundary.
|
|
|
|
```bash
|
|
wf draft bind <workspace_id> --revision <n> --step <step_id> --from local.document.markdown --to state.document.markdown
|
|
wf draft bind <workspace_id> --revision <n> --step <step_id> --from input.title --to local.document.title
|
|
wf draft bind <workspace_id> --revision <n> --step <step_id> --from local.document.markdown --to output.document.markdown
|
|
wf draft validate <workspace_id>
|
|
```
|
|
|
|
- `add_step_from_capability`
|
|
|
|
Adds a new capability-backed step with explicit route, input bindings, and
|
|
output-to-state schema/binding wiring in one revision. It can set the incoming
|
|
edge, outgoing edges, canonical path/literal inputs, metadata, and
|
|
output-to-state schema/binding. Use
|
|
`--route OUTCOME=TARGET` for each outcome; when omitted and the capability
|
|
declares a single outcome, that outcome routes to `__end__`. Multi-outcome
|
|
capabilities require exact route coverage; missing or unknown outcomes are
|
|
rejected before mutation. When `wf draft add capability --route` rejects an
|
|
outcome, the
|
|
error reports declared outcomes and direct add/remove repair guidance. Remove
|
|
unknown route entries and add one route for each missing declared outcome. It
|
|
still requires explicit choices; if you do not
|
|
know a map, inspect the capability or run validation rather than guessing.
|
|
Explicit `--input input.title=report.title` and
|
|
`--input state.title=report.title` mappings project the corresponding
|
|
workflow input/state schema paths from the nested capability input schema.
|
|
|
|
```bash
|
|
wf draft add capability <workspace_id> --revision <n> --step <step_id> --capability <qualified_name> --description "Publish report" --retry 2 --timeout-seconds 30 --from-step <prev> --from-outcome ok --route ok=__end__ --route error=fail --input input.text=text --value format='"markdown"' --bind-output result=state.result
|
|
wf draft update capability <workspace_id> --revision <n> --step <step_id> --clear-description --retry 0 --clear-timeout
|
|
wf draft validate <workspace_id>
|
|
```
|
|
|
|
Repeat `--input`, `--value`, and `--bind-output` once per binding. Use
|
|
`--bindings-file` for exact canonical path/value ordering. On update, omitted
|
|
fields are preserved and `--clear-*` removes the selected metadata; input
|
|
flags replace the complete input list. The update preserves capability
|
|
selection, routes, and outputs. Do not write
|
|
`--bind-output title=state.title summary=state.summary`; the second mapping is
|
|
an unexpected extra argument because it is not attached to its own flag.
|
|
|
|
- `add_step`
|
|
|
|
Adds any typed `DraftStep` with optional incoming and outgoing route wiring in
|
|
one revision. The CLI exposes one command per kind under `wf draft add`:
|
|
`interrupt`, `foreach`, `join`, `end`, `when`, `choose`, `match`, and
|
|
`subgraph`. Decision targets are embedded and reject `--route`. Interrupts
|
|
and subgraphs preserve JSON Schema boundary contracts. Invalid intermediate
|
|
drafts remain saveable in the workspace but must pass `wf draft validate`
|
|
before compile or artifact save.
|
|
|
|
- `branch_draft`
|
|
|
|
Updates routes for an existing step in one revision without rewriting the
|
|
full routes object. Supply `--route OUTCOME=TARGET` for each outcome to
|
|
set or update.
|
|
|
|
- `handle_draft`
|
|
|
|
Routes multiple source step outcomes to a common target. Supply
|
|
`--branch STEP:OUTCOME` for each source outcome and `--to TARGET` for the
|
|
shared destination.
|
|
|
|
- `compile_draft_workspace`
|
|
|
|
API/RPC/MCP returns the compiled raw plan plus required capabilities without
|
|
mutating or saving the draft workspace. The CLI prints only the raw plan JSON
|
|
on success. On invalid draft status, it returns structured diagnostics without
|
|
a `compiled_plan`.
|
|
|
|
Validation repair hints are product guidance. If a diagnostic suggests
|
|
`wf draft bind`, run that exact focused command before hand-editing schemas or
|
|
step bindings, then validate the new revision.
|
|
|
|
Remove commands are for recovery. They do not delete schema fields and
|
|
`remove-step` does not remove inbound routes. Validate after removal and repair
|
|
the resulting diagnostics explicitly.
|
|
|
|
Use JSON Patch for structural edits the helpers do not cover.
|
|
|
|
For larger patches, write a JSON Patch array to a file and pass it with
|
|
`--input-file`:
|
|
|
|
```bash
|
|
wf draft patch <workspace_id> --revision <n> --input-file draft-patch.json
|
|
```
|
|
|
|
The patch file must be an RFC 6902 JSON Patch array, not a full draft object.
|