AGPL-3.0-or-later · forever.

the deterministic authoring path

human-gated-ship

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
    human-gated-ship.nika.yaml
    # SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## TEMPLATE · human-gated-ship: gates in parallel, a human signs,# the action ships, evidence always lands.# The default shape for anything irreversible (deploys · sends · publishes).## Instantiate · copy → fill `# SLOT:` → `nika check` → repair → re-check.# The contract (patterns 6 + 9) ·#   nothing irreversible happens before nika:prompt returns true#   the assert makes a RED gate terminal · the act fails LOUDLY (default#   capture) · a terminal `when: true` task records EVERY outcome#   (acted · refused · failed): the always-patternnika: v1workflow: human-gated-ship-template  # SLOT: kebab-case workflow iddescription: "verify in parallel · human GO · act · record"   # SLOTpermits:                            # SLOT: the blast radius · default-deny once present  exec: ["echo"]                    # SLOT: ONLY the programs the gates + act run (argv form)  tools: ["nika:assert", "nika:prompt", "nika:notify"]  net: { http: ["hooks.slack.com"] }   # SLOT: the webhook host · nothing else may leavesecrets:  webhook:    source: env    key: TEAM_WEBHOOK_URL           # SLOT: where the record lands    egress:      - to: "nika:notify"        host_from_self: true        # the secret value IS the destination URLtasks:  # ── the verification wave · all checks run in parallel ──  - id: check_a    exec:      command: ["echo", "ok"]        # SLOT: gate 1 (argv form · injection-safe)      capture: structured  - id: check_b    exec:      command: ["echo", "ok"]        # SLOT: gate 2      capture: structured  - id: gates    depends_on: [check_a, check_b]    invoke:      tool: "nika:assert"      args:        condition: "${{ tasks.check_a.output.exit_code == 0 && tasks.check_b.output.exit_code == 0 }}"        message: "A gate is RED: refusing to proceed"   # SLOT  - id: human    depends_on: [gates]    invoke:      tool: "nika:prompt"      args:        message: "All gates GREEN. Proceed?"   # SLOT: the decision, fully informed        default: false  - id: act    depends_on: [human]    when: ${{ tasks.human.output == true }}    exec:      command: ["echo", "shipped"]   # SLOT: the irreversible action (argv · program must be in permits.exec)      # default capture · a failing ship fails LOUDLY (NIKA-EXEC-001):      # never `capture: structured` on the irreversible step (exit codes      # would become data and a red ship would read as success)  - id: record    depends_on: [act]    when: true                      # the always-pattern · runs on success, failure, OR refusal    invoke:      tool: "nika:notify"      args:        channel: webhook        target: "${{ secrets.webhook }}"        message: "Run finished · act=${{ tasks.act.status }}"   # SLOT · success | failure | skipped        severity: infooutputs:  acted: ${{ tasks.act.status }}

    sha256 24b29fb8ced2e7b0… · conformance-gated upstream · source

  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

    open the skeleton →

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 →