1 · Deterministic core, model at the edges
jq decides; the model explains. Anything that can be computed (filtering, sums, diffs, ranking) happens innika:jq or a data
builtin, deterministically and for free. The model gets the jobs only
a model can do: judgment, language, synthesis.
2 · Parallelism is the default · edges are the only ordering
Tasks with no edge between them run together. Don’t serialize out of habit: awith: binding IS the data edge (data and dependency are one
declaration) and an after: entry is the control edge — the engine
computes the graph from those two doors and schedules the waves. The
DAG has no invisible edges: a tasks.* reference outside the boundary
is NIKA-VAR-021 (the fix is machine-applicable — hoist into with:).
Anti-pattern · a linear chain of tasks that never read each
other’s output. That is wall-clock spent on nothing.
Taught by · Standup digest ·
Social repurpose (the diamond) ·
CEO Monday brief (3-branch gather).
3 · Type the boundaries
Every place data crosses from a model into the deterministic world gets a contract:schema: on infer/agent (the model must return that
shape), nika:validate for second opinions, nika:assert as the hard
gate. Enums kill « kinda-strong » ratings.
Anti-pattern · prose in, prose out, regex in the middle. If a
downstream task indexes into a field, the producer needs a schema.
Taught by · Meeting actions ·
Contract guard (schema + validate + assert,
belt-and-braces) · Support triage (enums).
4 · Fan out with a leash
for_each over a runtime collection is the power move. Bound it with
max_parallel (providers rate-limit, GPUs thrash), make it resilient
with fail_fast: false (collect errors instead of aborting the batch)
and give each iteration its own retry and timeout.
Anti-pattern · an unbounded fan-out against a rate-limited API, or
leaving fail_fast on its default (true) for a batch where one bad
item is normal.
Taught by · Competitor radar ·
Localization factory ·
Resume screener.
5 · Plan, then execute
For open-ended work: a fast model writes a typed plan, anagent:
executes it under budgets, a thinking model synthesizes. Three stages,
three cost profiles, every intermediate auditable on disk.
Anti-pattern · one giant agent loop with no plan, no budget and no
typed output. Nothing about it can be audited or bounded.
Taught by · Deep research brief ·
Corpus digest.
5b · Context folding · fresh windows over a folded corpus
The corpus-scale variant of « plan, then execute »: when the input is too big for one window, never let any window hold it. A fast pass plans a focus per unit from identifiers alone (paths, titles, ids · never contents), afor_each wave processes each unit in its own fresh
window (one slice, one focus, zero history), jq merges and ranks the
typed results deterministically, and the synthesis reads only that
deck. The corpus lives in the dataflow; window size stops scaling with
corpus size, and the deck in outputs: is an audit surface: everything
the synthesis saw, nothing it didn’t.
Two disciplines make the fold sovereign. The discovered collection is
the spine · model assignments join it by key, so a hallucinated
identifier drives nothing. And the per-unit schema carries no
identifier · transpose re-attaches identity, so a model cannot
misfile its own result.
Anti-pattern · concatenating the corpus into one prompt and asking
for a summary. Past a few documents you pay more for worse recall, and
nothing in the middle was actually read.
Taught by · Corpus digest ·
Localization factory (the mechanical
fold · no plan stage).
6 · Three gates, three meanings
when:· the skip gate. Routing, not failure (skipped ≠failed).nika:assert· the fail-fast gate. The run is wrong, stop loudly.nika:prompt· the human gate. Blocks until a person decides.
prompt gate, or claims success without an assert, is
promising more than it checks.
Anti-pattern · a tasks.* status test inside when: as a plain
success gate. That form is illegal since W2 (NIKA-VAR-021): the gate
lives on the edges — a value edge already admits on {success, skipped},
and after: { a: success } is the strict form. when: decides
business conditions on local values, post-gate.
Taught by · Invoice chaser (human gate) ·
Incident war room (assert refuses
optimistic postmortems) · Release train
(all three in one file).
7 · Sovereignty is a model: line
Sensitive data (contracts, CVs, medical, financial) runs on a local
provider, ollama/… or lmstudio/…. Same file shape, zero cloud. The
canonical providers make this a one-line decision,
not an architecture meeting.
Taught by · Contract guard ·
Resume screener.
8 · Agents get budgets, tools get grants
agent: is default-deny: no tools: means no tools at all. Grant the
minimum (nika:read + nika:done makes a read-only reviewer), cap
the loop (max_turns · max_tokens_total), and let nika:done end
it cleanly.
Anti-pattern · tools: ["nika:*", "mcp:*/*"] on an agent that
only needed to read. Least privilege costs one line less.
Taught by · PR review fan-out (the
read-only swarm) · Code review
(foundation).
9 · Evidence always lands · on_finally
Two tools, one rule. on_finally: is per-task cleanup: it fires
when that task ran (success, failure, timeout, mid-flight cancel).
A terminal after: {…: terminal} task is the always-pattern: it
runs once its producers settle, whatever happened — terminal admits
every terminal state (success · failure · skipped · cancelled). Pair it
with a .status observation in with: when the body branches on the
outcome. Cleanup belongs to the task; the record that must land at 3am
belongs to a terminal task.
Taught by · Incident war room ·
Release train (the departure record is an
after: { live: terminal } task: it lands even when the train aborts).
10 · One data language · jq, once
output: bindings, nika:jq, the fan-in zip (transpose), the
state diff: all of it is the same jq. Don’t invent per-task string
parsing and don’t ask the model to reshape JSON. One transform
language is already there.
Taught by · Localization factory
(the transpose zip) · ETL quarantine
(group_by accounting).
11 · Workflows are callable · type the outputs:
A workflow with typed outputs: is a building block: another workflow
(or a human, or CI) consumes a contract, not a log. Name what comes
out, type it, describe it.
Taught by · Deep research brief
({brief, sources}) · Schema retry
(foundation · the typed-outputs shape).
12 · Mock-first · runnable with zero keys
model: mock/echo makes a workflow CI-runnable and demo-safe. Write
it mock-first and swap the provider when it ships. Every example in
this documentation that can run without keys does.
Anti-pattern · a workflow you can’t validate without spending real
tokens. The conformance gate runs every example on every push, and
yours should pass the same way.
Taught by · the whole examples pack, and the
state-file pattern makes even stateful
workflows replayable.
The shape of a well-written file
the shape · a skeleton, not a runnable file
Four recipes the patterns compose into
The 12 patterns are the values; these are the moves you reach for when a real integration pushes back. Each is canonical in the spec: linked, not improvised.Poll until ready
retry: fires on errors, never on values, so make « not ready » an error
inside the task. A jq-mode fetch whose program errors on the pending shape
turns polling into typed, bounded retry:
retry_when:, retrying on a value
condition directly, is reserved for a future minor.)
Diamond join
Two exclusivewhen: branches, one consumer. A skipped branch’s output is
defined null (never an error), so the join is one jq filter:
Fan-out that survives partial failure
A failed iteration contributesnull at its index: positions stay aligned
with the input. Recover per-iteration when a placeholder is acceptable,
filter downstream. The same on_error: recover: mechanism also degrades a
single task to a declared fallback — the run completes and the output says
what it is:
Matrix expansion
A matrix is precomputed data, not control flow. Build the product with jq, fan out over it:See every pattern live
The examples gallery: real jobs, every construct taught,
every file conformance-validated.