AGPL-3.0-or-later · forever.

the language

system

System prompt · the standing instruction, sent ahead of `prompt:` and unchanged by it. One of 62 words the served contract declares, projected from workflow.schema.json, the same file your editor validates against.

  • 2surfacesinfer · agent
  • optionaleverywherea choice, never a miss
  • stringtypethe declared shape
  • 1skeletonscarry this key

the contract

2 declarations

Descriptions are the schema's own; the deeper invariants (value languages and regexes) ride the same projection. A miss is a nika check finding before anything runs.

infer
stringSystem prompt · the standing instruction, sent ahead of `prompt:` and unchanged by it.inside infer:
agent
stringSystem prompt · the standing instruction, sent ahead of `prompt:` and unchanged by any turn of the loop.inside agent:

in a real file

from the agent-loop skeleton
agent-loop.nika.yaml
  execute:    with:      steps: ${{ tasks.plan.output.steps }}    agent:      # Say what the JOB is. Do NOT describe the output shape.      #      # The engine binds `schema:` to the FINAL answer: a free-text answer      # that does not conform is RE-ASKED with the schema wired, bounded by a      # retry budget. Measured on ollama/qwen3.5:4b — this task, with zero      # shape instruction, returns a clean typed object.      #      # Hand-instructing "reply with the object, then call nika:done" is      # actively harmful: a `nika:done` carrying `result:` is validated      # DIRECTLY and is NEVER re-asked (nika-verb-agent/src/lib.rs · "a miss      # is a verdict, never a re-ask"), so a model that hands its JSON back      # as a *string* dies NIKA-INFER-002 with the budget already spent.      # Measured twice on that exact instruction. Let the engine own shape.      system: "You are a careful analyst. Work the plan step by step and report what you actually found."   # SLOT      prompt: "Plan · ${{ with.steps }}"      tools:                        # SLOT: the MINIMUM grant for the job        # Pure compute — this pair needs no filesystem, so the skeleton runs        # anywhere. Granting the agent a tool here is only HALF a grant: every        # call still crosses the workflow boundary above. Adding `nika:read`        # to this list WITHOUT adding `permits.fs.read` fails at run with        # `NIKA-SEC-004 · agent tool "nika:read" refused by the security        # boundary` — measured, mid-loop, after the turns are paid for.        - "nika:jq"        - "nika:done"               # the early-exit sentinel · loop-owned      max_turns: 15                 # SLOT: the loop bound      max_tokens_total: 80000       # SLOT: the spend bound      schema:                       # SLOT: the typed final-message contract        type: object        additionalProperties: false        required: [findings]        properties:          findings: { type: array, items: { type: string } }

a verbatim slice, real line numbers from agent-loop.nika.yaml, conformance-gated upstream on every spec push. open the full skeleton →

cross-references

The whole grammar in one place: the four verbs · the standard library · the spec. Try it in the playground. Read the reference →