The protocol
Route — one intent, one template
The templates
are six complete, valid skeletons (conformance-gated on every
push). Match the outer shape of the job:
| Intent sounds like… | Template |
|---|---|
| take data → produce words → save | chain |
| watch X, act when Y | gate-and-act |
| do this for every item | fanout |
| only what changed · survive bad input | etl-state |
| research / review / open-ended | agent-loop |
| anything irreversible | human-gated-ship |
Instantiate — structure is copied, never invented
Copy the template, rename the workflow, fill every
# SLOT: line.
Creativity belongs only in prompts, jq expressions and paths. If
the job needs a construct the template lacks, the
coverage matrix
names the canonical example that exercises it — read it, don’t
guess.Check — never ship unchecked
nika check workflow.nika.yaml (engine) or
python conformance/runner.py validate <file> (spec oracle).
Editors get the same truth live via the
JSON Schema.Repair — the error names its fix
Fix exactly what the code says, nothing else, then re-check:
| Error | The fix |
|---|---|
NIKA-DAG-003 | you referenced ${{ tasks.X }} — add depends_on: [X] |
NIKA-DAG-001 | cycle — remove the back-edge |
NIKA-VAR-001 | undeclared name — declare it in vars:/secrets: or fix the typo |
NIKA-PROVIDER | model: must be <provider>/<name> with a canonical prefix |
NIKA-PARSE (duplicate id) | two tasks share an id — rename one |
The eight hard rules
These catch ~90% of LLM-written errors. The validator enforces all of them; knowing them just saves round-trips:- One verb per task ·
infer,exec,invokeoragent. - snake_case task ids (CEL-safe) · kebab-case
workflow:. - Every
${{ tasks.X }}reference requiresdepends_on: [X]· the DAG has no invisible edges. when:is a${{ }}CEL boolean or the literaltrue/false·${{ vars.count }}is not a condition;${{ vars.count > 0 }}is; a bare string without${{ }}is rejected;when: trueis the always-pattern (run even when an upstream failed).size()is the only CEL function · arithmetic and string functions live in jq, not in${{ }}.nika:writeneedscontent:· a write without it writes nothing.nika:doneonly insideagent.tools· it is the loop sentinel, meaningless elsewhere.- Fan-outs get the leash ·
max_parallel+fail_fast: false+ per-iterationretry/timeout.
After valid: the judgment layer
Validity is the floor. The twelve patterns are the ceiling: deterministic core, typed boundaries, the right gate (when = skip · assert = fail · prompt = human), sovereignty for
sensitive data, budgets on agents, on_finally evidence. Every
pattern links the canonical example that embodies it.
The templates
Six skeletons, every decision point a slot, conformance-gated.
The twelve patterns
The judgment layer: why each locked choice is locked.