> ## 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.

# Providers catalog

> Every LLM provider Nika knows about: the canonical 14 of stdlib v0.1 (5 local · 8 cloud · 1 mock), API dialects, and environment variables.

export const CANON = {
  schemaVersion: 1,
  verbs: 4,
  verbNames: ["infer", "exec", "invoke", "agent"],
  namespaces: 5,
  namespaceNames: ["vars", "with", "tasks", "env", "secrets"],
  builtins: 23,
  builtinNames: ["assert", "compose", "convert", "date", "done", "edit", "emit", "fetch", "glob", "grep", "hash", "inspect", "jq", "json_diff", "json_merge_patch", "log", "notify", "prompt", "read", "uuid", "validate", "wait", "write"],
  providers: 14,
  providersCloud: 8,
  providersLocal: 5,
  providersTest: 1,
  providerIdsCloud: ["mistral", "anthropic", "openai", "gemini", "deepseek", "xai", "groq", "openrouter"],
  providerIdsLocal: ["ollama", "lmstudio", "llamacpp", "localai", "vllm"],
  providerIdsTest: ["mock"],
  extractModes: 9,
  extractModeNames: ["article", "feed", "jq", "links", "markdown", "metadata", "selector", "sitemap", "text"],
  errorNamespaces: 14,
  errorNamespaceNames: ["NIKA-AGENT", "NIKA-BUILTIN", "NIKA-CANCEL", "NIKA-DAG", "NIKA-EXEC", "NIKA-IMPL", "NIKA-INFER", "NIKA-INVOKE", "NIKA-MCP", "NIKA-PARSE", "NIKA-PROVIDER", "NIKA-SEC", "NIKA-TIMEOUT", "NIKA-VAR"],
  errorCategories: 12,
  errorCodes: 50,
  pillars: 5
};

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"
};

Nika's stdlib v0.1 ships **{CANON.providers} canonical providers**:
{CANON.providersLocal} local / self-hosted runners, {CANON.providersCloud}
cloud APIs, and {CANON.providersTest} deterministic mock. You select one with
a single `model: <provider>/<name>` field. **Local first** · nothing leaves
your machine unless a cloud provider is explicitly selected.

<Info>
  **Canonical source:** [`stdlib/providers-v0.1.md`](https://github.com/supernovae-st/nika-spec/blob/main/stdlib/providers-v0.1.md)
  in the spec (counts from `canon.yaml`). The engine additionally carries an
  extended catalog of {STATUS.providers} TOML records
  ([`crates/nika-catalog/data/llm-providers.toml`](https://github.com/supernovae-st/nika/blob/main/crates/nika-catalog/data/llm-providers.toml))
  used for capability metadata. Anything outside the canonical 14 routes
  through the `openai` + `base_url` escape hatch, not its own prefix.
</Info>

## Overview

<CardGroup cols={3}>
  <Card title="Providers" icon="server">
    **{CANON.providers}** canonical: {CANON.providersLocal} local · {CANON.providersCloud} cloud · {CANON.providersTest} mock
  </Card>

  <Card title="API dialects" icon="plug">
    **3**: openai-chat (the 5 local + most cloud) · anthropic · gemini
  </Card>

  <Card title="Capability rules" icon="grid">
    **{STATUS.capabilityRules}** in `model-capabilities.toml`
  </Card>
</CardGroup>

## How to pick a provider

<Steps>
  <Step title="Pick your trust model">
    Local / self-hosted (Ollama / LM Studio / llama.cpp / LocalAI / vLLM): zero key, zero egress, sovereign by default. EU cloud (Mistral). US frontier (Anthropic / OpenAI / Google). Aggregator (OpenRouter). Each has different residency and compliance trade-offs.
  </Step>

  <Step title="Check the `api_dialect`">
    All 5 local providers + most cloud providers speak `openai-chat`: same request shape, differing base URL. `anthropic` and `gemini` have native dialects.
  </Step>

  <Step title="Verify the backend is reachable">
    Local providers need their server running (e.g. the Ollama daemon on `localhost:11434`) and no key. Cloud providers declare an `env_var` (e.g., `MISTRAL_API_KEY`). `nika doctor` checks provider readiness before run.
  </Step>

  <Step title="Pick default vs cheap model">
    Every provider declares both. `default_model` is the capable tier; `cheap_model` is the cost-optimized tier. Capability rules in `model-capabilities.toml` determine which models support vision / tools / streaming / structured output.
  </Step>
</Steps>

## By category

<Tabs>
  <Tab title="Local / self-hosted (5)">
    | ID         | Name                                           | Dialect       | Env var  | Example model                 |
    | ---------- | ---------------------------------------------- | ------------- | -------- | ----------------------------- |
    | `ollama`   | Ollama daemon (`localhost:11434`)              | `openai-chat` | `(none)` | `llama3.1`                    |
    | `lmstudio` | LM Studio (`localhost:1234/v1`)                | `openai-chat` | `(none)` | `qwen2.5-14b-instruct`        |
    | `llamacpp` | llama.cpp `llama-server` (`localhost:8080/v1`) | `openai-chat` | `(none)` | `qwen2.5-7b-instruct`         |
    | `localai`  | LocalAI (`localhost:8080/v1`)                  | `openai-chat` | `(none)` | `llama-3.1-8b-instruct`       |
    | `vllm`     | vLLM OpenAI server (`localhost:8000/v1`)       | `openai-chat` | `(none)` | `meta-llama-3.1-70b-instruct` |

    <Tip>
      **The sovereign default.** No API key, no cloud egress:
      `model: ollama/llama3.2:3b` runs offline / air-gapped. Any other
      OpenAI-compatible local server (Jan · llamafile · KoboldCpp) routes
      through the `openai` + `base_url` escape hatch.
    </Tip>
  </Tab>

  <Tab title="Cloud (8)">
    | ID           | Name                                | Dialect       | Env var              | Default model                 |
    | ------------ | ----------------------------------- | ------------- | -------------------- | ----------------------------- |
    | `mistral`    | Mistral AI (EU · sovereign-leaning) | `openai-chat` | `MISTRAL_API_KEY`    | `mistral-large-latest`        |
    | `anthropic`  | Anthropic Claude                    | `anthropic`   | `ANTHROPIC_API_KEY`  | `claude-sonnet-4-6`           |
    | `openai`     | OpenAI                              | `openai-chat` | `OPENAI_API_KEY`     | `gpt-4o`                      |
    | `openrouter` | OpenRouter gateway                  | `openai-chat` | `OPENROUTER_API_KEY` | `anthropic/claude-sonnet-4-6` |
    | `groq`       | Groq (fastest open-weight)          | `openai-chat` | `GROQ_API_KEY`       | `llama-3.3-70b-versatile`     |
    | `deepseek`   | DeepSeek                            | `openai-chat` | `DEEPSEEK_API_KEY`   | `deepseek-chat`               |
    | `gemini`     | Google Gemini                       | `gemini`      | `GEMINI_API_KEY`     | `gemini-2.5-flash`            |
    | `xai`        | xAI Grok                            | `openai-chat` | `XAI_API_KEY`        | `grok-3`                      |

    <Tip>
      Keys live in `${{ secrets.* }}` / env vars, never inline in the
      workflow. OpenRouter aggregates \~200 models under one key
      (`openrouter/<vendor>/<model>`). Use it to experiment across vendors
      without per-vendor keys.
    </Tip>
  </Tab>

  <Tab title="Test (1)">
    | ID     | Name          | Dialect | Env var  | Default model          |
    | ------ | ------------- | ------- | -------- | ---------------------- |
    | `mock` | Mock provider | custom  | `(none)` | `echo` (deterministic) |

    <Note>
      **Mock** ships with every install for deterministic tests:
      `model: mock/echo` returns the prompt verbatim, zero network, zero
      entropy. The canonical examples + CI rely on it.
    </Note>
  </Tab>
</Tabs>

## Full alphabetical list

<AccordionGroup>
  <Accordion title={`The ${CANON.providers} canonical spec v0.1 IDs (sorted)`} icon="list">
    `anthropic` · `deepseek` · `gemini` · `groq` · `llamacpp` · `lmstudio` ·
    `localai` · `mistral` · `mock` · `ollama` · `openai` · `openrouter` ·
    `vllm` · `xai`

    {CANON.providers} total: {CANON.providersLocal} local · {CANON.providersCloud} cloud ·
    {CANON.providersTest} test · matches `canon.yaml` in the spec repo. The
    engine's extended capability catalog ({STATUS.providers} TOML records)
    is an implementation detail: extended IDs are reached via the
    `openai` + `base_url` escape hatch, never their own prefix.
  </Accordion>
</AccordionGroup>

## Example: invoke a provider

<CodeGroup>
  ```yaml workflow.nika.yaml theme={"system"}
  nika: v1
  workflow: multi-provider

  tasks:
    - id: primary
      on_error: { skip: true }   # a dead provider skips (error preserved) · the gate below reads it
      infer:
        model: ollama/llama3.2:3b              # local · zero key
        prompt: "Explain linear algebra in one sentence."

    - id: fallback
      depends_on: [primary]
      when: "${{ tasks.primary.error != null }}"   # skip preserves the error · the fallback reads it
      infer:
        model: mistral/mistral-large
        prompt: "Explain linear algebra in one sentence."
  ```

  ```bash Required env theme={"system"}
  ollama pull llama3.2:3b         # local primary · no key
  export MISTRAL_API_KEY=...      # cloud fallback only
  nika run workflow.nika.yaml
  ```
</CodeGroup>

<Info>
  `infer:` is live in v{STATUS.version}. Run `nika doctor` first to see
  which provider keys or local servers are available without printing secrets.
</Info>

## See also

<CardGroup cols={2}>
  <Card title="Capability rules" icon="grid" href="/reference/capabilities">
    The {STATUS.capabilityRules} rules that govern which models support which features.
  </Card>

  <Card title="Concepts · Providers" icon="server" href="/concepts/providers">
    How provider routing works at runtime.
  </Card>

  <Card title="Error codes" icon="triangle-exclamation" href="/reference/error-codes">
    `NIKA-1xx` provider errors.
  </Card>

  <Card title="Schema" icon="file-code" href="/reference/schema">
    Workflow envelope, `.nika.yaml` top-level keys.
  </Card>
</CardGroup>
