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.

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 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.

  • 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 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_usd default 0.05, timeout 2 minutes). The answer is structured <output> JSON matching the classify-workflow schema. Title and body from inbox, connector:<name>, or triage:<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_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.

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, 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