Workflows and routing
A factory can define several named workflows, each with its own pipeline, finally list, and optional limits.
A factory can define several named workflows, each with its own pipeline, finally list, and optional limits. When a task is added, Kusaw picks one workflow:
--workflowor front matterworkflow:- the first matching
routing.rulesentry - a classify call, when
routing.classify.provideris notoffand there are two or more workflows default_workflow, only when classify isoff(or there is a single workflow)- otherwise the run stays
queuedwithwaiting_for: workflow
A file with a top-level pipeline and no workflows: map still has one workflow named default. You cannot set both a top-level pipeline and mapping-form workflows.
Config
workflows:
feature:
description: "New behaviour described in a spec"
pipeline:
- spec-check
- loop: { name: build-review, max_iterations: 3, steps: [build, review-standards, verify] }
- deliver
finally: [retro]
log-bug:
description: "An error reported by a log store, to reproduce, test and fix"
pipeline: [spec-check, reproduce, build, review-standards, verify, deliver]
limits: { run_minutes: 60 }
default_workflow: feature
routing:
rules:
- { match: { source: "connector:demo-logs", labels: [critical] }, workflow: log-bug }
- { match: { type: bug }, workflow: log-bug }
classify:
provider: agent # agent (default) | command | off
threshold: 0.80 # 0.50 to 1.00- Workflow names match
^[a-z][a-z0-9-]{0,31}$. At most 20 workflows and 50 rules. descriptionis 1 to 300 characters. The classifier andkusaw workflowsshow it.- Steps stay one shared
stepsmap. Each workflow lists step ids. intakeis one list for every workflow; it runs before routing.- Fanout and candidates still resolve named pipelines from the same
workflows:map (list-form entries are sub-pipelines, not routing targets).
A complete two-workflow file is examples/workflows/two-workflows.yaml in the Kusaw source tree. The example pipeline shapes also ship as workflows.<shape> under examples/pipelines/.
The routing item
The router sees source, type, labels, title, body, and repos.
sourceisadd,intake,requeue,schedule:<name>,inbox:<name>,triage:<batch>, orconnector:<name>.- Spec front matter may set
workflow,type(^[a-z][a-z0-9-]{0,31}$), andlabels(up to 20). - Intake from triage uses
source: triage:<batch>and labelrole:<role>. - Rule
sourceis an exact match, or a prefix ending in*(connector:*).typeis exact.labelsandreposmust all be present on the item.
Routing happens once per task. Requeue keeps the workflow unless --workflow is given.
Classify
routing.classify.provider is agent (default), command, or off. This is not the built-in classify step (size buckets / when: booleans). Routing classify is not a pipeline step.
- agent: one read-only call (read-only preset, no repo access, budget
config.max_cost_usddefault 0.05, timeout 2 minutes). The answer is structured<output>JSON matching the classify-workflow schema. Title and body frominbox,connector:<name>, ortriage:<batch>are fenced as outside text. A local spec is not fenced. - command: protocol v2
mode: "classify"through the existing step/command path and that step's declared secrets.run_idis null.context.classifyis{item, workflows}. The resultoutputs(workflow,confidence,rationale) are checked against the same schema.
Confidence is the agent's own estimate, not a calibrated probability. The default threshold is 0.80 (range 0.50 to 1.00). Below it, or on classify failure, the task waits even if default_workflow is set.
The factory has no outside classify provider. A tested example of a user's own command classifier is Outside classify (example).
Waiting and picking
A waiting run stays queued with workflow null. The worker skips it. kusaw status and the API show waiting_for: workflow and the classifier's suggestion when there is one.
Pick with:
kusaw route <task> <workflow>POST /api/f/{factory}/tasks/{task}/routewith{ "workflow": "feature" }- MCP
route_task
kusaw route <task> with no name runs classify again and prints the result without setting anything. Interactive kusaw add and kusaw intake ask in a terminal; --no-input skips the question.
The Dashboard does not have a workflow picker. Use the CLI, the API, or MCP.
Runs
Each run records its workflow name (kusaw status <run> and the run API show it). The run's config snapshot holds that workflow's pipeline, finally, and limits, so later edits to kusaw.yaml do not change a running run.
Custom steps see context.workflow: {name, routed_by, confidence} and KUSAW_WORKFLOW.
A step may fail with reason wrong_workflow and output suggested_workflow. The run ends needs_attention; Kusaw never auto-switches or auto-requeues. Requeue with --workflow.
CLI
kusaw workflows— names, descriptions, step counts, default, ruleskusaw add --workflow,kusaw requeue --workflowkusaw route <task> [<workflow>]kusaw routing test <spec-file> [--source] [--type] [--label]... [--classify]kusaw validatesuccess line includes<n> workflowskusaw statusandkusaw runsshow the workflow name