AGPL-3.0-or-later · forever.

the workflow library

invoice-chaser

finds the overdue, drafts reminders, waits for your yes. A pack showcase file, shown whole to read; nika run invoice-chaser.nika.yaml is the honest affordance. This site never fabricates a replay for it.

  • 6tasksthe plan below walks them
  • 6wavesrun together when they can
  • invoke · inferverbsthe whole grammar it speaks
  • browseread, then runno fabricated replay

the plan

derived from the file, never drawn by hand
ledgerinvoke
rowsinvoke
overdueinvoke
draftsinfer
approveinvoke
saveinvoke

the file, whole

invoice-chaser.nika.yaml
invoice-chaser.nika.yaml
nika: v1workflow:  id: invoice-chaser  description: "Ledger CSV → overdue filter → drafted reminders → human gate → drafts file"model: ollama/qwen3.5:4b   # local · zero key · swap for groq/llama-3.3-70b (drafting is a fast-model job)const:  ledger_csv: "examples/fixtures/invoices.csv"permits:  tools: ["nika:convert", "nika:jq", "nika:prompt", "nika:read", "nika:write"]  fs:    # Two files, both spelled out — `const.ledger_csv` in, the drafts file    # out. A const is baked in and a run cannot move it, so the boundary is    # exact: no glob, and nothing else on disk is reachable either way.    read: ["examples/fixtures/invoices.csv"]    write: ["out/reminders-to-send.md"]tasks:  ledger:    invoke:      tool: "nika:read"      args: { path: "${{ const.ledger_csv }}" }  rows:    with:      csv: ${{ tasks.ledger.output }}    invoke:      tool: "nika:convert"      args:        input: "${{ with.csv }}"        from: csv        to: json        has_header: true  overdue:    with:      rows: ${{ tasks.rows.output }}    invoke:      tool: "nika:jq"      args:        input: "${{ with.rows }}"        expression: 'map(select(.status == "overdue"))'  drafts:    with:      overdue: ${{ tasks.overdue.output }}    when: ${{ size(with.overdue) > 0 }}    infer:      max_tokens: 900       # a ceiling makes the cost report a number, not UNBOUNDED      prompt: |        Draft one short, polite payment reminder per overdue invoice ·        ${{ with.overdue }}        Markdown · one section per client · firm but warm.  approve:    with:      drafts: ${{ tasks.drafts.output }}    when: ${{ with.drafts != null }}   # nothing drafted · nothing to approve    invoke:      tool: "nika:prompt"      args:        message: "Save the reminder drafts for sending?"        default: false  save:    with:      drafts: ${{ tasks.drafts.output }}      approved: ${{ tasks.approve.output }}    when: ${{ with.drafts != null && with.approved == true }}   # zero overdue → drafts skipped (null) · don't write nothing    invoke:      tool: "nika:write"      args:        path: out/reminders-to-send.md        create_dirs: true        content: "${{ with.drafts }}"outputs:  overdue:    value: ${{ tasks.overdue.output }}    description: "The overdue rows the reminders were drafted for"

lines 5664: invoke: a human yes sits before anything is saved. Source: the spec pack · open it in the playground →

Watch the recorded one replay on the home page, walk the showcase gallery, or install and run the file yourself.