AGPL-3.0-or-later · forever.

the language

Every word.

The whole language, in one file you can read.

Projected from workflow.schema.json · the same contract your editor validates against. Every word opens its own room. The four verbs keep theirs.

the envelope · mark AND name

hello-ai.nika.yamlsource
# first model call · one local seat, one bounded sentencenika: hello-aimodel: ollama/llama3.2:3b   # local · zero key · swap for any provider in the catalogpermits: {}tasks:  greet:    infer:      prompt: "Say hello in one sentence."      max_tokens: 64outputs:  greeting: ${{ tasks.greet.output }}
  • 59wordsthe whole surface
  • 66declarations10 surfaces
  • 4verbsrooms of their own
  • schemathe sourcenever prose
  • envelopethe file itself
  • taskone step of the plan
  • inferinside infer:
  • execinside exec:
  • invokeinside invoke:
  • agentinside agent:
  • for_eachinside for_each:
  • retryinside retry:
  • on_errorinside on_error:
  • liftinside a lift entry

59 words across 10 blocks, and 6 of them speak in more than one. Point at a word to see its other homes.

A filled corner marks a word the schema requires at that surface; +n counts the other blocks the same word speaks in. Both derive from workflow.schema.json: the served contract, not a second opinion about it.

  1. afterthe wiringtask
    task
    objectThe CONTROL boundary · {producer-task: predicate}. Each entry is one control edge (spec/03-dag.md §after). State, never data — observe outcomes through with:.
  2. task
    the fourth verb: a budgeted tool-calling loop; its room: /verbs/agent
  3. argsinvoke
    invoke
    objectArguments passed to the tool · an object whose shape is the TOOL's own schema, not the language's. Each builtin and each MCP tool declares its own (spec/02-verbs.md §invoke) · `${{ }}` may appear in any leaf value.
  4. backoff_max_msthe failure grammarretry
    retry
    integerCeiling on the computed delay, in milliseconds · default 60000, one minute. Exponential growth stops climbing here.
  5. backoff_msthe failure grammarretry
    retry
    integerInitial delay between attempts, in milliseconds · default 1000. `backoff_strategy` decides how it grows from there.
  6. backoff_strategythe failure grammarretry
    retry
    stringWhich curve the delay follows between attempts · `fixed` · `linear` · `exponential` · default `exponential`. Each attempt waits `backoff_ms` flat, `backoff_ms × attempt`, or `backoff_ms × 2^(attempt-1)` capped at `backoff_max_ms`. fixedlinearexponential
  7. becauseliftrequired in lift
    lift*
    stringThe non-empty justification · recorded in the run receipt with the taint path and the value digest.
  8. exec
    stringWhich stream becomes the task's output · `stdout` (default) · `stderr` · `combined` · `structured` = `{ stdout, stderr, exit_code }`. This is the SOURCE; `decode:` is how that string becomes a value. stdoutstderrcombinedstructured
  9. exec
    arrayargv — the program and its arguments, execve, NO shell. Each element substituted independently (the injection-safe form). Shell features (pipes · redirects · globs) live in `shell:`.
  10. constenvelope
    envelope
    objectNamed constants · `${{ const.X }}` · a fixed value baked into the workflow. Either a bare literal, or a `{ type, value }` typed constant whose `value:` MUST conform to `type:`. The literal half of the dead `vars:` block (R3a · LAW-SURFACE-0201) · everything that is not `required: true` lands here per the E-split total rule.
  11. cwdexec
    exec
    stringWorking directory for the subprocess · default = the engine's own cwd.
  12. decodeexec
    exec
    stringHow the captured string becomes a value · `text` (default) · `json` · `jsonl` · `bytes`. Illegal with `capture: structured`, which already IS an object (NIKA-PARSE-025) · a non-parsing stream settles the task `failure` inside `on_error:` scope (spec 09 §decode). textjsonjsonlbytes
  13. envexec
    exec
    objectOS environment variables for THIS subprocess · a key→value map applied over the composed environment. Nothing is inherited — the ambient environment reaches a task only through `permits.env` (spec/01-envelope.md §permits).
  14. task
    the second verb: run a command, captured and typed; its room: /verbs/exec
  15. task
    objectNamed jq-expression bindings extracted from the verb's raw response · read downstream as `${{ tasks.X.<name> }}`. The field names the OPERATION (run this jq); it does not write `output` — `${{ tasks.X.output }}` stays the raw response (spec/03-dag.md §extract). jq is the single data extraction-and-transform language (the former RFC 9535 JSONPath was dropped · jq is a superset · per spec/04-variables.md §216-225). A binding may not shadow a record projection: output · status · error · started_at · ended_at · duration_ms are forbidden at parse time (spec/04-variables.md §Rules) — enforced via propertyNames.
  16. fail_fastfor_each
    for_each
    booleanWhether the fan-out abandons the batch on the first failure · default true. False finishes every item and yields null at a failed index, so the batch reports what it could.
  17. task
    objectFan this task out over a collection · ONE block, so the concurrency is visible where the fan-out is declared. `max_parallel` and `fail_fast` live here because they have no meaning without it.
  18. fromlift
    lift
    stringREQUIRED for law 'taint', forbidden otherwise · the ONE binding this entry raises (e.g. inputs.p · config.region · tasks.fetch.output) · a dotted value-binding path.
  19. grouptask
    task
    stringFan-in MEMBERSHIP · this task joins the named group, and a consumer folds the whole group with one `${{ group.<name> }}` binding in its `with:` (spec/03-dag.md §group). Membership is DECLARED, never matched: a renamed member leaves its group loudly (NIKA-DAG-008 on the reference), where a glob would shrink the fold in silence. A group exists iff at least one task declares it. An `unwind` task may not join one (NIKA-DAG-009 · cleanup never schedules).
  20. task
    the first verb: call a model; its room: /verbs/infer
  21. inputsenvelope
    envelope
    objectTyped workflow inputs · `${{ inputs.X }}` · the parameters an author declares and a caller supplies. Each entry is a typed declaration whose `type:` speaks the full TypeExpr of 09-types (R3b · LAW-GRAMMAR-0211 · the flat 6-enum is dead · LAW-SURFACE-0211). The typed half of the dead `vars:` block (R3a · LAW-SURFACE-0201) · a `required: true` value lands here per the E-split total rule.
  22. task
    the third verb: call a tool (nika: builtin or mcp: server); its room: /verbs/invoke
  23. itemsfor_eachrequired in for_each
    for_each*
    string | arrayThe collection · a `${{ ... }}` reference OR a literal array. Evaluated EXACTLY ONCE, before the fan-out; no iteration feeds back into it (spec 03 §where this sits).
  24. jitterthe failure grammarretry
    retry
    booleanRandomize the computed delay so tasks retrying the same upstream do not synchronize · default TRUE. Engines SHOULD use a full-jitter or equal-jitter family — the anti-thundering-herd default (spec/05-errors.md §Retry policy).
  25. lawliftrequired in lift
    lift*
    stringWHICH law this entry lifts · 'taint' raises ONE binding from untrusted to trusted (NEP-0004 · LAW-AUTH-0325) · 'data-as-code' declares this task's fetch a code-bearing artifact it will never load or run (NEP-0006 · LAW-AUTH-0327). Neither ever lifts the net boundary or the SSRF floor. taintdata-as-code
  26. lifttask
    task
    arrayThe authored doors · each entry lifts exactly ONE named law, with a mandatory reason, check-visible and receipt-recorded. A lift is NEVER a permit bypass — the value still sits inside the declared boundary, and no law but the named one moves. The law set is CLOSED and normative (a NEP amends it): this is why a new law costs zero language fields (spec/10-authority.md §the authored doors).
  27. max_attemptsthe failure grammarretryrequired in retry
    retry*
    integerTotal attempts, counting the first try · integer ≥ 1 · the one required field of a `retry:` block. Engines honor it strictly and surface the LAST error if every attempt fails (spec/05-errors.md §Retry policy).
  28. max_parallelfor_each
    for_each
    integerCap concurrent iterations · default unbounded · 1 = sequential.
  29. infer
    integer | stringper-call output token cap
  30. agent
    integer | stringCumulative token budget across every turn of the loop · the SPEND ceiling, where `max_turns` is the step ceiling. Default is engine-configurable (spec/02-verbs.md §agent).
  31. agent
    integer | stringthe agent’s loop bound; the worst case is finite
  32. modelenvelopeinferagent
    envelope
    stringDefault model · `<provider>/<name>` (e.g. ollama/qwen3.5:9b · anthropic/claude-sonnet-4-6 · mock/echo).
    infer
    string
    agent
    string
  33. nikaenveloperequired in envelope
    envelope*
    stringThe file's NAME · kebab-case · and the mark that says « this is a nika file ». One word, one meaning across both document types: `nika.yaml` carries the PROJECT name, a `*.nika.yaml` carries the WORKFLOW name. The document TYPE is read from `tasks:` — present means workflow, absent means project — so it survives a blob, a paste or an HTTP body where the filename does not travel. This key held the literal `v1` until the envelope nuke; it carried zero bits as a version (there is no `nika: v2` — ever) and now carries the file's most necessary field instead.
  34. on_codesthe failure grammarretryon_error
    retry
    arrayRetry ONLY on these canonical `NIKA-<NS>-<NNN>` codes · absent, the engine retries anything transient. Codes, never HTTP status numbers · the retry-side mirror of `on_error.on_codes`.
    on_error
    arrayOptional catch-side filter (mirror of retry.on_codes · same regex) · the action applies ONLY when the final error code is listed · unlisted codes fall through to the default fail (spec/05-errors.md §Fields).
  35. on_errorthe failure grammartask
    task
    the catch side: recover with a value, skip, or fail loudly, per error code
  36. outputsenvelope
    envelope
    objectThe workflow's return value · symmetric to inputs. Each entry is a `${{ tasks.X.output }}` reference (untyped form · string) OR a typed declaration { value · type · description }. Powers `nika run` result + the output half of the callable-workflow schema.
  37. permitsthe boundaryenvelope
    envelope
    objectThe declared capability boundary · once present every category is default-deny unless listed (spec/01-envelope.md §permits · NIKA-SEC-004).
  38. promptinferagentrequired in infer · agent
    infer*
    stringthe model job, in words: interpolate ${{ }} references, never paste secrets
    agent*
    stringthe model job, in words: interpolate ${{ }} references, never paste secrets
  39. recoverthe failure grammaron_error
    on_error
    Recovery output · a `${{ }}` ref OR a literal (merges the former fallback/value per spec/05-errors.md).
  40. retrythe failure grammartask
    task
    Retry policy for this task · `{ max_attempts, backoff_ms, backoff_strategy, backoff_max_ms, jitter, on_codes }`. Retries run BEFORE `on_error` sees anything — the catch handles the last error only (spec/05-errors.md §Retry policy).
  41. task
    The task's output contract · the TYPED door, where a verb-level `schema:` is the out-of-core hatch. The two are exclusive on one task (NIKA-TYPE-003 · spec 09-types.md).
  42. runenvelope
    envelope
    objectThe run's entropy and clock declaration · every source of randomness and of time is declared, never ambient. The two dimensions couple: only `ambient × system` (the status quo) and `none | seeded × virtual` (the deterministic states) are legal, and a declared contradiction refuses at parse (NEP-0010).
  43. schemainferagent
    infer
    objectJSON Schema · the structured-output contract the model's reply must satisfy. The out-of-core hatch; the typed door is task-level `returns:` (both on one task is NIKA-TYPE-003).
    agent
    objectJSON Schema · the contract the agent's FINAL message must satisfy. The out-of-core hatch; the typed door is task-level `returns:` (both on one task is NIKA-TYPE-003).
  44. secretsthe boundaryenvelope
    envelope
    objectVault-backed masked references · `${{ secrets.X }}` · never inline literals.
  45. shellexec
    exec
    stringOne shell line, run via /bin/sh -c — the EXPLICIT dangerous door (pipes · redirects · globs). The blocklist applies here; interpolating untrusted values here is on the author. Exactly one of command|shell.
  46. skillsagent
    agent
    arrayAgent Skill (SKILL.md) file paths · explicit static paths only, no globs and no templates. They follow the agentskills.io shape, and are loaded at compose time and injected into the system context.
  47. stdinexec
    exec
    stringData written to the command's standard input · may interpolate `${{ }}`.
  48. systeminferagent
    infer
    stringSystem prompt · the standing instruction, sent ahead of `prompt:` and unchanged by it.
    agent
    stringSystem prompt · the standing instruction, sent ahead of `prompt:` and unchanged by any turn of the loop.
  49. tasksenveloperequired in envelope
    envelope*
    objectThe task map · the KEY is the task's identity (snake_case · CEL-safe). Source order is presentation only — the graph alone schedules.
  50. temperatureinferagent
    infer
    number | stringSampling temperature · 0 is the steadiest the provider offers, 2 the loosest. A number in 0-2, or a `${{ }}` reference.
    agent
    number | stringSampling temperature for every turn of the loop · 0 is the steadiest the provider offers, 2 the loosest. A number in 0-2, or a `${{ }}` reference.
  51. infer
    objectExtended thinking · `{ enabled, budget_tokens }` — reasoning the model may spend before it answers (spec/02-verbs.md §infer).
  52. task
    stringGo-duration string · quoted · e.g. "30s" "5m" "1h30m" "2.5s". Max 24h.
  53. toolinvoke
    invoke
    stringTool reference · nika:<path> (closed v0.1 builtin set) OR mcp:<server>/<tool> (requires the slash). The namespace set is CLOSED at v1 (spec/02-verbs.md) — an x-<vendor>: prefix is RESERVED, not valid (engine-specific tools route through mcp: · spec/06-stdlib-contract.md §Namespace ownership).
  54. toolsagent
    agent
    arrayWhitelist · DEFAULT-DENY (no tools if absent) · gitignore-style globs · `!` negation.
  55. visioninfer
    infer
    arrayImage inputs for the call · each entry `{ source: file | url, path | url }` · the images `prompt:` is allowed to refer to.
  56. whentask
    task
    boolean | stringLOCAL business condition · false skips the task · evaluated POST-gate over {vars · env · with · item · index}. Referring to `tasks.*` is illegal here (NIKA-VAR-021 · hoist it into `with:`) · spec/03-dag.md §when.
  57. withthe wiringtask
    task
    objectTask-level scope injection · `${{ with.X }}`.
  58. workflowinvoke
    invoke
    stringCompose another workflow (spec 14) · a STATIC target: a filesystem path OR registry:owner/name@version (pinned). A templated target is refused at check (NIKA-COMP-001). Exactly one of tool: | workflow: (the invoke tagged union · G21).

the three families

14 of 59 words

Most words carry no family and say nothing about one. These do: the contract declares where each may legally appear, so a surface can colour by MEANING instead of by syntax class. It is the same fact the panel tints and the room states in a sentence.

the blocks around the words

the namespaces · every ${{ … }} reference starts at one

the value types · what a declared shape can be

A key the schema doesn't declare is a nika check finding before anything runs. The language teaches itself. Try it in the playground, walk the four verbs or the standard library. Read the spec →