Workflows and routing
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:
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. The GF-109 pipeline shapes also ship as workflows.<shape> in 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 GF-36 classify step (size buckets / when: booleans). Routing classify is not a pipeline step.
- agent: one read-only call (
PresetReadOnly, no repo access, budgetconfig.max_cost_usddefault 0.05, timeout 2 minutes). The answer is GF-100<output>JSON matchingclassify-workflow.schema.json. Title and body frominbox,connector:<name>, ortriage:<batch>are fenced as outside text (GF-93). 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.
There is no Dashboard workflow picker in this batch.
Runs
runs.workflow holds the name. 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
Example pipelines
The built-in pipeline (implement, review, verify, deliver) is one shape. These four examples are complete factories built only from custom command steps, `kusaw agent-args`, `kusaw extract`, and effects. They show that the factory is neutral: you copy a shape, you do not have to keep the defaults.
Outside classify (example)
This page is a stub. The factory has no outside classify provider and makes no network call for routing. `routing.classify.provider` stays `agent`, `command`, or `off`. A user who accepts an outside typed-decision service writes their own [command](workflows.md) classifier; the factory ships the pattern, not the path.