AGPL-3.0-or-later · forever.

the deterministic authoring path

docker-report

Agents do not invent structure — they instantiate it. Each skeleton below is a complete, valid workflow with # SLOT: markers at every decision point: route your intent, copy, fill the slots, nika check, done. Machines read the same pack at /templates/catalog.json; the originals live in the spec, conformance- gated on every push.

  • 10skeletonsroute · copy · fill
  • 94slot markersthe only blanks
  • validevery fileconformance-gated
  • sha256every copypinned, re-proven
  1. take data, produce words, save them

    chain9 slotschain.nika.yaml
    • deterministic gather
    • one model job
    • explicit persist

    open the skeleton →

  2. watch X, act when Y

    gate-and-act8 slotsgate-and-act.nika.yaml
    • jq extraction
    • CEL skip-gate
    • often zero model calls

    open the skeleton →

  3. do this for EVERY item

    fanout9 slotsfanout.nika.yaml
    • runtime collection
    • the full leash (max_parallel
    • fail_fast
    • retry)

    open the skeleton →

  4. only what changed since last run · survive bad input

    etl-state6 slotsetl-state.nika.yaml
    • state read→diff→write
    • `on_error: recover:` quarantine

    open the skeleton →

  5. research / review / open-ended

    agent-loop7 slotsagent-loop.nika.yaml
    • plan-then-execute
    • default-deny tools
    • budgets
    • typed final message

    open the skeleton →

  6. anything irreversible (deploy · send · publish)

    human-gated-ship10 slotshuman-gated-ship.nika.yaml
    • parallel gates
    • assert
    • `nika:prompt` GO
    • `on_finally` record

    open the skeleton →

  7. understand a site (domain · theme · assets) from a URL

    website-brief10 slotswebsite-brief.nika.yaml
    • fetch `traverse:` crawl
    • one typed infer
    • explicit persist
    • zero exec

    open the skeleton →

  8. generate image/audio assets from a brief

    media-asset-pack10 slotsmedia-asset-pack.nika.yaml
    • `nika:image_generate`
    • `nika:jq` manifest
    • local/mock provider first

    open the skeleton →

  9. call a product API: upload a file, then create from it

    api-upload-and-create15 slotsapi-upload-and-create.nika.yaml
    • fetch `multipart:` upload
    • masked secrets header
    • mode/jq extraction

    open the skeleton →

  10. read a system's state (docker · kubectl · gh), explain it, keep the report

    docker-report10 slotsdocker-report.nika.yaml
    • argv-array exec (provable allowlist)
    • parallel reads
    • exec ledger
    • one artifact
    docker-report.nika.yaml
    # SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## TEMPLATE · docker-report: read a system's real state via a pinned CLI,# have a model explain it, keep the report as a file. The audited-ops# shape: argv-array exec (a provable `permits.exec` allowlist — a shell# string can smuggle any program through a pipe, so the checker refuses# to bless one), reads fan out in parallel, one model call, one artifact.# Swap `docker` for any product CLI (kubectl · gh · terraform · psql).## Instantiate · copy → fill `# SLOT:` → `nika check` → repair → re-check.## EXEC LEDGER · (the native-first law: every surviving exec names why)# | task | command          | why no native path               | unlock that removes it |# | ps   | docker ps        | product CLI · no MCP surface yet | a docker MCP server    |# | df   | docker system df | same                             | same                   |nika: v1workflow: docker-report-template    # SLOT: kebab-case workflow iddescription: "read the daemon's state · explain it · keep the report"   # SLOTmodel: ollama/qwen3.5:4b            # SLOT: local-first · mock/echo for offline rehearsalpermits:  exec:    - "docker"                      # SLOT: the ONE program the reads may launch  tools:    - "nika:write"  fs:    write:      - "./docker-health.md"        # SLOT: where the report lands (must match `keep`)tasks:  # The reads run IN PARALLEL (no depends_on between them) — the  # scheduler proves it from the DAG, nobody orders it.  - id: ps    exec:      # SLOT: argv ARRAY form — one program, exactly these arguments      command: ["docker", "ps", "--all", "--format", "{{.Names}}\t{{.Status}}\t{{.Image}}"]  - id: df    exec:      command: ["docker", "system", "df"]   # SLOT: the second read (drop the task if one suffices)  - id: diagnose    depends_on: [ps, df]    infer:      # SLOT: what should the model DO with the readings?      prompt: |        You are reading a Docker host's state. Containers (name·status·image):        ${{ tasks.ps.output }}        Disk usage:        ${{ tasks.df.output }}        Write a short health report: what is running, what exited, what        looks unhealthy (restart loops · old exits), and whether disk        usage needs attention. Plain prose, no preamble.      max_tokens: 600               # SLOT: the spend ceiling for this call  - id: keep    depends_on: [diagnose]    invoke:      tool: "nika:write"      args:        path: "./docker-health.md"  # SLOT: same path as permits.fs.write        content: "${{ tasks.diagnose.output }}"outputs:  report: ${{ tasks.keep.output }}

    sha256 a72ad242a22698e5… · conformance-gated upstream · source

The protocol is mechanical: route with the phrases above, instantiate, fill the slots, then nika check teaches anything you missed before anything runs. Try one in the playground, or install and start from a real file. Read the spec →