> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nika.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Your first workflow

> Five minutes from install to a checked and runnable Nika workflow.

export const STATUS = {
  head: "95962d5cd",
  branch: "main",
  version: "0.91.0",
  cratesWorkspace: 39,
  cratesAdmitted: 39,
  cratesTarget: "42",
  wipCrates: [],
  libTests: 2989,
  clippyWarnings: 0,
  adrs: 62,
  adrsAccepted: 42,
  adrsProposed: 18,
  providers: 32,
  capabilityRules: 49,
  hygieneVectors: 38,
  hygieneGreen: 28,
  hygieneYellow: 3,
  hygieneRed: 0,
  lastUpdated: "2026-06-25"
};

<Info>
  **v{STATUS.version}:** `nika check`, `nika run`, `nika doctor`, `nika lsp`,
  and `nika mcp` ship in the binary. Run `nika init` once per repo for schema
  and agent rules.
</Info>

## Goal

Write a `.nika.yaml` file, run it, get structured output. No setup beyond
`nika` installed. **Your first run needs no API key and no model server.**

## 1. Pick how the AI step runs

Three paths, from zero-setup to production:

**Instant (no model at all)**: the built-in `mock/echo` model returns a
deterministic response, so you can see a workflow's shape right now:

```yaml theme={"system"}
model: mock/echo
```

**Local (free · private)**: have [Ollama](https://ollama.com) running,
no API key, nothing leaves your machine:

```bash theme={"system"}
ollama pull llama3.1
```

**Cloud**: set any provider key:

```bash theme={"system"}
export MISTRAL_API_KEY=...
# or export ANTHROPIC_API_KEY=... · any provider in the catalog
```

At any point, `nika doctor` tells you exactly what's wired and how to fix
what isn't:

```bash theme={"system"}
nika doctor
```

All provider env vars listed in [Providers catalog](/reference/providers-catalog).

## 2. Write the workflow

Create `hello.nika.yaml`:

```yaml hello.nika.yaml theme={"system"}
nika: v1
workflow: hello

tasks:
  - id: greet
    infer:
      model: ollama/llama3.1               # <provider>/<name> · local · swap for any cloud provider
      prompt: "Say hi to the chrysalis. Be brief."
```

Three things to notice:

* **`nika: v1`** declares the workflow language + pins the contract version (a single version marker · `v1` forever).
* **`workflow:`** is a human-readable name (kebab-case · the document-type discriminator).
* **`tasks:`** is a list; each task has an `id` and one verb (here, `infer`).

## 3. Check it, then run it

```bash theme={"system"}
nika check hello.nika.yaml   # the static audit: plan · cost · secrets · types · before a single token is spent
nika run hello.nika.yaml
```

`nika check` catches broken references, missing dependencies and schema
problems before any model is called — and points at the exact fix:

<video autoPlay muted loop playsInline poster="/images/posters/static-check-fix.png" style={{ borderRadius: "0.75rem" }}>
  <source src="https://mintcdn.com/supernovae-acdf3706/vVkJcOKMcsJbQfuN/videos/static-check-fix.webm?fit=max&auto=format&n=vVkJcOKMcsJbQfuN&q=85&s=e9884d59dc50fb58a26e9ded7072c9f9" type="video/webm" data-path="videos/static-check-fix.webm" />

  <source src="https://mintcdn.com/supernovae-acdf3706/vVkJcOKMcsJbQfuN/videos/static-check-fix.mp4?fit=max&auto=format&n=vVkJcOKMcsJbQfuN&q=85&s=e2f468f89c0c070f19ab554c78c68197" type="video/mp4" data-path="videos/static-check-fix.mp4" />
</video>

<Tip>
  No provider handy? Swap the `model:` line for `mock/echo`. Both commands
  work fully offline, and you can wire a real model later.
</Tip>

Example output:

```
▶ greet  infer  → ollama/llama3.1
  ┌─ output ──────────────────
  │ Welcome inside the chrysalis. 🦋
  └───────────────────────────
✓ greet  T+00:00:01.42  OK
```

## 4. Add a second task that depends on the first

```yaml hello.nika.yaml theme={"system"}
nika: v1
workflow: hello

tasks:
  - id: greet
    infer:
      model: ollama/llama3.1               # <provider>/<name> · local · swap for any cloud provider
      prompt: "Say hi to the chrysalis. Be brief."

  - id: critique
    depends_on: [greet]
    infer:
      model: ollama/llama3.1               # <provider>/<name> · local · swap for any cloud provider
      prompt: |
        The greeting was: ${{ tasks.greet.output }}

        Rewrite it shorter and more enigmatic.
```

Notice `${{ tasks.greet.output }}`. That's a [binding](/concepts/bindings).
The engine injects the previous task's output into the prompt at runtime,
with explicit taint tracking and pipe filters.

### The graph you just built

```mermaid theme={"system"}
%%{init: {'theme':'dark','themeVariables':{'background':'transparent','mainBkg':'transparent'}}}%%
flowchart LR
    classDef task fill:#3F7DFF,color:#fff,stroke:#7FE9FF,font-weight:bold
    G["greet<br/>infer"]:::task --> F["critique<br/>infer"]:::task
```

One `depends_on` line and the order falls out of the file. Tasks with no
dependency between them run **in parallel automatically**. You never
schedule anything.

## 5. Get structured output

```yaml hello.nika.yaml theme={"system"}
nika: v1
workflow: hello-structured

tasks:
  - id: names
    infer:
      model: ollama/llama3.1               # <provider>/<name> · local · swap for any cloud provider
      prompt: "Generate three names for a butterfly."
      schema:                          # structured output · JSON Schema
        type: object
        properties:
          names:
            type: array
            items:
              type: string
              minLength: 3
              maxLength: 20
            minItems: 3
            maxItems: 3
        required: [names]
```

Nika takes the JSON Schema, asks the provider for output that conforms
(using each provider's native structured-output API where the [capability
rules](/reference/capabilities) allow it: schema mode, object mode, or
JSON-mode emulation), and validates the result against your schema before
passing it on.

```bash theme={"system"}
nika run hello.nika.yaml
# Output is guaranteed to be { "names": ["...", "...", "..."] }
```

## What you just built

* Workflows are YAML files: `.nika.yaml`.
* Tasks are units of work, identified by `id`.
* Four verbs (`infer`, `exec`, `invoke`, `agent`) define what each task does (HTTP fetch is the `nika:fetch` builtin under `invoke`).
* `depends_on:` builds a DAG.
* `${{ tasks.X.output }}` bindings flow data between tasks, with taint tracking.
* `schema:` enforces JSON schemas on AI output.

## Next checks

<Steps>
  <Step title="Check before running">
    `nika check hello.nika.yaml`: static audit before any token or effect.
  </Step>

  <Step title="Inspect the DAG">
    `nika inspect hello.nika.yaml` or `nika graph hello.nika.yaml --format mermaid`.
  </Step>

  <Step title="Wire your agent">
    Run `nika wire cursor` or `nika wire all` for explicit MCP setup, or use
    the editor extension's agent setup.
  </Step>
</Steps>

## Read next

<CardGroup cols={2}>
  <Card title="Examples · real jobs" icon="rocket" href="/examples/overview">
    Climb the ladder: starter chains to multi-agent swarms, every file
    conformance-validated.
  </Card>

  <Card title="How to write Nika" icon="compass-drafting" href="/guides/patterns">
    The twelve patterns: where the determinism lives, where the model
    is allowed to think.
  </Card>

  <Card title="The 4 verbs" icon="play" href="/concepts/verbs">
    Deep dive on `infer`, `exec`, `invoke`, `agent`.
  </Card>

  <Card title="Bindings" icon="link" href="/concepts/bindings">
    How data flows between tasks with taint tracking.
  </Card>

  <Card title="Providers" icon="server" href="/concepts/providers">
    Why one `InferRequest` works across {CANON.providers} providers.
  </Card>

  <Card title="Live state" icon="gauge" href="/reference/status">
    Which verbs are admitted today.
  </Card>
</CardGroup>
