the path · 01
Hello world — the smallest COMPLETE Nika workflow.
run itnika try 01-hello
01-hello.nika.yaml
# SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## 01 · Hello world — the smallest COMPLETE Nika workflow.## Four questions, four answers, and nothing else: what does it run on, what# may it touch, what does it do, what does it hand back. A file that skips# one of the four still executes — it just stops being a contract.## Demonstrates ·# - the envelope · `nika: v1` (the contract version) + `workflow.id`# - `model:` · one local model · no API key, nothing leaves the machine# - `permits: {}` · the DECLARED zero · this workflow may touch nothing# - one task · the `infer:` verb, bounded by `max_tokens:`# - `outputs:` · the value a caller gets back## Needs · ollama with the model pulled · `ollama pull qwen3.5:4b`.# No ollama? The dry twin runs anywhere, zero setup ·# `nika run examples/01-hello.nika.yaml --model mock/echo`## Run · nika run examples/01-hello.nika.yamlnika: v1workflow: id: hellomodel: ollama/qwen3.5:4b # local · zero key · swap for any provider in the catalog# The declared zero. `permits:` is default-deny once present, so an empty# block is a statement, not a formality: this workflow opens no file, reaches# no host, runs no program. Leaving the block out says something different —# that no boundary was declared — and both forms refuse an effecting tool at# run, with different verdicts: an absent block reports NIKA-AUTH-006 (no# boundary to judge against), `permits: {}` reports NIKA-SEC-004 (outside the# boundary you drew). Declaring the zero is what puts the checker's PERMITS# and TRIFECTA judges on duty — under-declaring quietly stands them down.permits: {}tasks: greet: infer: prompt: "Say hello in French, in one short sentence." # The ceiling. On a priced model this is what turns the cost report from # UNBOUNDED into a hard worst-case number. # # 2048 for two words looks absurd until you measure it. `max_tokens` caps # think + answer, and qwen3.5 is a reasoning model that deliberates before # it speaks — on this exact prompt: 64 → "", 256 → "", 512 → "", 1024 → # "Bonjour.", 2048 → "Bonjour !". Under the threshold the run is GREEN and # the output is EMPTY, because the budget ran out mid-thought. Size the # cap for the thinking, or pick a non-thinking model (llama3.2:3b) when # you want a tight one. max_tokens: 2048# The return value. It does NOT appear on the live run — that surface shows# progress. `--output json` is the export contract: the typed `outputs:` as# ONE JSON object on stdout, which is how a caller reads a workflow's result# (`exec: nika run sub.nika.yaml --output json` + `capture: stdout`).## nika run examples/01-hello.nika.yaml --output json# → {"greeting":"Bonjour !"}outputs: greeting: ${{ tasks.greet.output }}nika-spec@6ac29351a · sha256 f857a9ec2910dd47…