Implementation status. The envelope below is the canonical spec
contract (
nika-spec · 01-envelope).
The engine implements it end-to-end today — nika check parses and
audits it, nika run executes it. Live state →Minimal workflow
nika: + workflow:) and a non-empty tasks: — the
whole minimum to be a valid workflow. Fields carry source spans through
Spanned<T> so diagnostics point at the exact byte range.
Why one version marker (not a K8s envelope)
The envelope is one header line ·nika: v1. Earlier drafts explored a
Kubernetes-style apiVersion + kind + metadata + spec envelope, but
the spec rejected it: that is two version-ish fields and ceremony a workflow
file does not need. Modern specs converge on a single version marker —
OpenAPI writes openapi: 3.1.0, Docker Compose dropped its version: field
entirely. Nika takes the proven path: the language name as the key, the
contract version as the value.
- No separate
kind:field — the presence ofworkflow:is itself the document-type discriminator. Future document types (if any ever ship) use their own top-level key. - The engine’s internal canonical URI stays
https://nika.sh/spec/v1for RDF / conformance tooling — but the author never types a URL.
---, parsed into Vec<RawDocument>.
Anatomy of a workflow
The workflow AST (nika-schema::raw::RawWorkflow) models these fields:
| Field | Type | Purpose |
|---|---|---|
schema | SchemaVersion | Locked to v1 today. |
name | String | Workflow identifier (within metadata: in the envelope). |
description | String | Human-readable purpose. |
goal | String (optional) | Agent-driven workflow goal — moving to spec.orchestrate.goal per ADR-021. |
provider / model | String | Defaults applied to every infer / agent task. |
mcp | RawMcpConfig | MCP server aliases usable from invoke / agent. |
context | ContextConfig | Top-level constants available to all tasks. |
include | Vec<IncludeSpec> | Reusable sub-workflows inlined at parse time. |
inputs | Vec<(String, Value)> | Runtime parameters (--input key=value). |
logging | LogConfig | Event verbosity per task kind. |
orchestrate | OrchestrateConfig | Agentic orchestration (depth, concurrency). |
routing | RoutingConfig | Fallback + cost routing. |
schedule | ScheduleConfig | Cron / interval triggers. |
max_duration_secs | u64 | Hard wall-clock ceiling. |
tasks | Vec<RawTask> | The DAG payload. |
Option<Spanned<T>> — source spans survive
all the way into the diagnostic layer (ADR-010 miette bridge).
Execution pipeline
Tasks, dependencies, fan-out
Tasks declare dependencies explicitly throughdepends_on:. Nika builds
the DAG, topologically sorts, and runs tasks in parallel where the graph
allows.
when: is the field (a CEL boolean, or the
literal true for the always-pattern):
retry: is the one shape (and on_error: catches
what retries can’t fix):
Field names are the spec’s:
id: (not name:), when: (not
condition:), retry.max_attempts (not max_retries:). The
JSON Schema rejects the wrong
names at check time.Inputs · vars
Workflow inputs live in vars: (typed or untyped), available in every task
via ${{ vars.<name> }}. Untyped constants and typed, validated inputs use
the same block — the typed form powers schema generation for callable
workflows (nika.run_workflow over MCP).
v1 workflows are single-file — there is no
include: / import:
(static composition is a candidate for a later additive minor · see the
spec’s out-of-scope list). To reuse a sub-DAG today, call it with
invoke: nika:run_workflow.Outputs and events
Every task emits a structuredEvent stream during execution
(nika-kernel::infra::event_sink::Event). Consumers subscribe via
EventSink and receive one JSON object per line (NDJSON on stdout by
default). See Events for the event model and
Bindings for how the DAG propagates values.
The workflow grammar is locked and implemented: the
nika-schema
crate ships the envelope, the analyzer and semantic validation
(type-checked bindings, secret-flow audit, cycle detection) — that is
exactly what nika check runs on your file today.Read next
Bindings
Template expressions —
${{ }} syntax, scopes, filters, taint.Events
The typed event stream every run emits.
Verbs
The 4 verbs each task picks from.
YAML reference
Full schema specification (generated from AST).