AGPL-3.0-or-later · forever.

the deterministic authoring path

api-upload-and-create

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
    api-upload-and-create.nika.yaml
    # SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## TEMPLATE · api-upload-and-create · upload a file → create a resource from it.# The shape for « call a product API: multipart upload, then a JSON create ».## Instantiate (agents · deterministic) ·#   1. Copy this file · rename per the job (kebab-case).#   2. Fill every `# SLOT:` line · delete slot comments when filled.#   3. Validate · `nika check <file>` (or conformance/runner.py validate).#   4. Repair using the error's fix line · re-check until valid.# Native-first · the upload is fetch `multipart:` (file parts ride the# permits.fs READ boundary); auth rides a masked secrets header; the# create is fetch JSON; extraction is the mode/jq pairing. Zero exec ·# no upload helper script.nika: v1workflow: api-upload-and-create-template  # SLOT: kebab-case workflow iddescription: "upload → create → result"   # SLOT: one honest sentencemodel: ollama/qwen3.5:4b            # SLOT: provider/model · local · zero keyvars:  api_base: "https://api.example.com"     # SLOT: the product API base  asset_path: "./out/assets/asset-1.png"  # SLOT: the file to uploadsecrets:  API_KEY:    source: env    key: EXAMPLE_API_KEY            # SLOT: the OS env var holding the key    egress:      - to: "nika:fetch"            # the send · default-deny otherwise      - to: "outputs"               # the return value derives from the authed responsetasks:  - id: upload    invoke:      tool: "nika:fetch"      args:        url: "${{ vars.api_base }}/upload"   # SLOT: the upload endpoint        method: POST        headers:          x-api-key: "${{ secrets.API_KEY }}"  # SLOT: the auth header name        multipart:          - { name: file, path: "${{ vars.asset_path }}" }          # SLOT: extra text fields · { name: directory, value: "assets" }        mode: jq        jq: ".url"                  # SLOT: where the response carries the asset URL  - id: create    depends_on: [upload]    invoke:      tool: "nika:fetch"      args:        url: "${{ vars.api_base }}/create"   # SLOT: the create endpoint        method: POST        headers:          x-api-key: "${{ secrets.API_KEY }}"        body:                       # SLOT: the create payload (objects auto-JSON)          asset_url: "${{ tasks.upload.output }}"        mode: jq        jq: "{ id: .id, url: .url }"   # SLOT: the fields downstream needsoutputs:  result: ${{ tasks.create.output }}   # SLOT: the callable contract

    sha256 ca872e2ac9f1dd2f… · conformance-gated upstream · source

  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 →