AGPL-3.0-or-later · forever.

ADR-021

YAML envelope convention: apiVersion + kind + metadata + spec, multi-doc, 9 doc kinds

superseded · 2026-04-16 · L0 L0.5 · cites 6

Superseded by ADR-082. This decision is kept because its successor cites it.

ADR-021: YAML envelope convention #

⚠️ SUPERSEDED 2026-05-25 · The K8s envelope decided here (apiVersion: nika.sh/v1 + kind + metadata + spec) is superseded by the public `nika-spec`, which adopts a single version marker · nika: v1 + workflow: <id> + tasks:. The spec explicitly rejects the apiVersion:/schema: two-field form as Kubernetes-ceremony a workflow file does not need (cf nika-spec spec/01-envelope.md · "Why one field, not apiVersion + schema"). The engine's internal canonical URI stays https://nika.sh/spec/v1 for RDF/conformance tooling, but the author never types it. Decision below preserved as audit trail per cross-source-validation.md §2.7. The kind discriminator + multi-doc rationale (9 doc kinds) is the part that survives — only the version-field shape changed (apiVersion: nika.sh/v1nika: v1).

Context #

Phase D Round 2c-2e shipped a parser for top-level workflow scalars (name, description, goal, provider, model, schema) and tasks: sequence. Background research (4 web-research agents, 2026-04-16) converged unanimously on adopting the K8s envelope pattern (apiVersion + kind + metadata + spec) with multi-document YAML support. Evidence: every workflow DSL with >2 doc types (Argo, Tekton, Flux, Drone-1.x, Helm) ended up with this envelope after flat-form regret migrations.

Nika has 9 user-facing doc kinds at v0.90: Workflow, Skill, Agent, Provider, MCP, Eval, Recipe, Shield, Lints (+ Memory v0.95, Plugin v0.100 reserved). Without an envelope, every kind reimplements identity + version semantics.

Decision #

Adopt the K8s envelope as the canonical shape for every Nika user-facing structured config (YAML and TOML):

yaml
apiVersion: nika.sh/v1kind: Workflow                # closed enum: Workflow|Skill|Agent|Provider|                              #              Mcp|Eval|Recipe|Shield|Lints|                              #              Memory(reserved)|Plugin(reserved)metadata:  name: my-workflow  description: ...  labels: { ... }             # optional  annotations: { ... }        # optionalspec:  defaults: { model: openai/gpt-4o }  tasks: [...]                # for kind: Workflow

Multi-document YAML (--- separator) supported: one file may declare multiple kinds (Workflow + Skill + Agent), parsed into Vec<RawDocument>.

Model identifier: single string provider/model (LiteLLM format), e.g. openai/gpt-4o, anthropic/claude-sonnet-4.5. Drop separate provider: + model: fields.

Drop workflow-level `goal:` — CrewAI agent-specific concept, not a workflow concept (0 of 8 surveyed workflow DSLs have it). If goal-driven agentic workflows need it, place in spec.orchestrate.goal:.

Format support:

  • YAML: workflows (DSL, user-authored)
  • TOML: catalog data, agent presets, lint rules (config-as-data)
  • Markdown + YAML frontmatter: skills/agents (prose-heavy, Cursor/Claude convention)

All three formats use the same envelope keys (apiVersion + kind + metadata + spec).

Consequences #

  • ✅ Single envelope shape across 9 doc kinds = LLM-friendly (Nika-brain generates correct shape on first try)
  • ✅ Forward-compat: adding a kind (e.g., Memory at v0.95) requires only adding a variant to the closed Kind enum
  • ✅ K8s envelope is in 100% of LLM training data — Nika-brain pattern-matches without prompting tax
  • ❌ Diverges from typical "Rust workspace" convention (TOML flat) — but workflow engines diverge from compilers (the relevant comparison set)
  • ❌ Existing nika-schema parser (Round 2c-2e, 38 tests) needs full rewrite in Phase D — explicit cost accepted (v0.1, 0 users, break freely)
  • ⚠️ Hygiene vector 23 (check-workflow-envelope.sh) MUST land in Phase B before any envelope code is written — guards against regression

Alternatives considered #

  • Flat top-level (current Round 2c shape) — dies at ~8 fields per GitLab/Drone/Dify post-mortems
  • Hybrid (Dify-style: version + kind + nested app block) — half-step that loses metadata uniformity
  • URL-path discrimination (apiVersion: nika.sh/v1/Workflow) — breaks YAML editor schema hints
  • Filename convention only — moves truth out of doc, hurts multi-doc

See ~/.claude/.../memory/project_foundation_v081_constellation.md for the 4-agent research synthesis.

read at v0.107.0 · the decision record ships with the engine