A workflow definition is one JSON document:
{
"name": "My Workflow", // required; unique enough to find by name
"description": "What it does", // shown in ccw_list — write it for the agent choosing
"tags": ["ops"], // optional
"folder": "ops/deploys", // optional; '/'-separated, first segment is the package
"inputSchema": { // optional JSON Schema for instance input
"type": "object",
"properties": { "target": { "type": "string" } },
"required": ["target"]
},
"steps": [ … ],
"transitions": [ … ]
}id, version, status and timestamps are managed by the server. Never send them on create.
Step shape
{
"id": "step_scan", // you choose it; unique within the workflow
"name": "Scan Repository", // unique, human-readable — see the naming rules
"type": "instruction", // one of the fourteen types
"config": { … }, // type-specific
"position": { "x": 250, "y": 0 } // optional — designer canvas coordinates
}Naming rules
A step's result is stored under variables.steps["<step name>"] and referenced in templates as {{steps.<step name>.output}}. Template paths split on ., so:
- Step names must be unique within the workflow. A duplicate silently overwrites the earlier result.
- Step names must not contain dots. Spaces are fine —
{{steps.Scan Repository.output}}works.
Neither rule is caught at publish. Both fail quietly at runtime, downstream, when a template resolves to the wrong thing or to nothing.
Positions
Optional; omit them. The designer lays out workflows whose steps have no positions and saves the result. Nothing functional depends on coordinates.