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 handledgerinvoke
rowsinvoke
overdueinvoke
draftsinfer
approveinvoke
saveinvoke
the file, whole
invoice-chaser.nika.yamlinvoice-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 56–64: 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.