Skip to Content
kusaw docsv1.0.0

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:

  1. --workflow or front matter workflow:
  2. the first matching routing.rules entry
  3. a classify call, when routing.classify.provider is not off and there are two or more workflows
  4. default_workflow, only when classify is off (or there is a single workflow)
  5. otherwise the run stays queued with waiting_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

YAML
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.
  • description is 1 to 300 characters. The classifier and kusaw workflows show it.
  • Steps stay one shared steps map. Each workflow lists step ids.
  • intake is 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.

  • source is add, intake, requeue, schedule:<name>, inbox:<name>, triage:<batch>, or connector:<name>.
  • Spec front matter may set workflow, type (^[a-z][a-z0-9-]{0,31}$), and labels (up to 20).
  • Intake from triage uses source: triage:<batch> and label role:<role>.
  • Rule source is an exact match, or a prefix ending in * (connector:*). type is exact. labels and repos must 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, budget config.max_cost_usd default 0.05, timeout 2 minutes). The answer is GF-100 <output> JSON matching classify-workflow.schema.json. Title and body from inbox, connector:<name>, or triage:<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_id is null. context.classify is {item, workflows}. The result outputs (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}/route with { "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, rules
  • kusaw add --workflow, kusaw requeue --workflow
  • kusaw route <task> [<workflow>]
  • kusaw routing test <spec-file> [--source] [--type] [--label]... [--classify]
  • kusaw validate success line includes <n> workflows
  • kusaw status and kusaw runs show the workflow name

On this page