Skip to content

Models

Netclaw assigns LLMs to three roles in the Models section of ~/.netclaw/config/netclaw.json: Main, Fallback, and Compaction. Only Main is required. The other two route to Main when unset.

Before assigning models, you need at least one provider configured. See Managed Providers or Self-Hosted Providers.

For CLI commands that manage models interactively, see netclaw model.

RolePurposeRequired?
MainPrimary model for all interactionsYes — defaults to qwen3:30b on local-ollama
FallbackAutomatic failover when Main is unavailableNo — routes to Main when unset
CompactionCheaper/faster model for context summarizationNo — routes to Main when unset

Model Manager TUI showing role assignments

Models has two halves. Definitions describe models; Roles name which definition fills each job:

{
"Models": {
"Definitions": {
"qwen-main": {
"Provider": "remote-gpu",
"ModelId": "qwen3:30b",
"ContextWindow": 32768
}
},
"Roles": {
"Main": "qwen-main"
}
}
}

The split is what makes role changes non-destructive. Point Main at a different definition and the old one keeps its context window and modality overrides — switch back and it’s exactly as you left it.

Definition names are yours. netclaw model set generates <provider>-<model-id> (remote-gpu-qwen3-30b), but nothing depends on that shape — rename them to whatever reads well and update the roles to match. Names match case-insensitively and must be unique.

Each definition takes these fields:

FieldTypeDefaultDescription
Providerstring"local-ollama"Key into the Providers dictionary
ModelIdstring"qwen3:30b"Model identifier as used by the provider API
ContextWindowint?nullClamps the runtime context window in tokens; takes precedence over provider-reported value
Provenanceenum?nullRead-only. Set by the CLI: "Live" (discovered from provider), "Defaults" (curated defaults), or "Manual" (model set)
InputModalitiesflags enum?nullOverride input modalities, e.g. "Text, Image". Values: Text, Image, Audio, Video
OutputModalitiesflags enum?nullOverride output modalities (same values, e.g. "Text")

And Roles takes exactly three keys — Main, Fallback, Compaction — each naming a definition. Main is required.

An omitted optional field means “detect it at runtime.” Netclaw writes no placeholder or sentinel to mean “cleared” — if ContextWindow isn’t there, detection resolves it.

With Ollama running locally and qwen3:30b pulled, this is all you need. The Provider value must match a key you’ve defined under Providers in the same config file.

{
"Models": {
"Definitions": {
"qwen-main": {
"Provider": "local-ollama",
"ModelId": "qwen3:30b"
}
},
"Roles": {
"Main": "qwen-main"
}
}
}

Context window is auto-detected from Ollama.

A more realistic setup: 30B for Main, 8B for Fallback (resilience if the big model goes down), and the same 8B definition reused for Compaction, because summarization doesn’t need a big model. Two definitions, three roles:

{
"Models": {
"Definitions": {
"qwen-main": {
"Provider": "remote-gpu",
"ModelId": "qwen3:30b",
"ContextWindow": 32768
},
"qwen-small": {
"Provider": "remote-gpu",
"ModelId": "qwen3:8b",
"ContextWindow": 32768
}
},
"Roles": {
"Main": "qwen-main",
"Fallback": "qwen-small",
"Compaction": "qwen-small"
}
}
}

Two roles sharing one definition is normal — Fallback and Compaction both resolve to qwen-small here, and editing that definition moves both.

Config takes precedence over anything the provider reports:

  1. ContextWindow value in config (highest priority)
  2. Provider-detected value (via /api/show, /v1/models, etc.)
  3. Default: 32,768 tokens

Any role-bound definition with an explicit ContextWindow must set it to at least 4,096 tokens. Definitions no role points at aren’t validated.

Set Main’s ContextWindow higher than the provider reports and netclaw logs a warning and uses your number anyway. It doesn’t refuse to boot — a detected context window is a guess, and taking down every session over a number netclaw can’t trust is worse than trying. If the number really is too big, the provider rejects the oversized request and the session compacts and retries.

Modalities follow the same precedence as the context window: an explicit value wins, then whatever’s already stored, then detection. Clearing a value with netclaw model set --clear-context-window or --clear-modalities hands that field back to detection — it doesn’t restore the value you cleared.

Netclaw auto-detects what a model supports (context window, modalities) by walking this list until something answers:

  1. Built-in static catalog (covers well-known models with zero network cost)
  2. Ollama /api/show — only when the provider type is ollama
  3. OpenAI-compatible /v1/models metadata — only when the provider type is openai-compatible
  4. OpenRouter public catalog
  5. HuggingFace capability resolver
  6. Text-only defaults (32,768 token context window)

If your provider misreports capabilities (say, an Ollama model supports vision but detection shows text-only), override detection on that definition — either by hand or with netclaw model set:

Terminal window
netclaw model set main remote-gpu qwen3-vl:32b --input-modalities "Text, Image"

The override sticks to the definition, so it survives role reassignment.

When Fallback is configured, netclaw wraps both models in a failover layer. If Main throws after exhausting retries, the request goes to Fallback automatically.

Retries happen first: 3 attempts with exponential backoff (1s base, 30s max, ±25% jitter). Retried errors: network failures, HTTP 408/429/5xx, TaskCanceledException, TimeoutException. Only after all retries fail does failover kick in.

There’s a catch with streaming. Failover only applies if Main fails before the first chunk reaches the caller. Once a chunk has been emitted, failures propagate directly. Splicing two model responses together mid-stream would produce garbage, so netclaw doesn’t try.

EventAlert Level
Main fails, Fallback takes overprovider.failover — Warning
Both Main and Fallback failprovider.unreachable — Critical

If Fallback is not configured, failed retries on Main surface the error directly.

Compaction is for background LLM work: summarizing conversation context when it grows too long, generating session titles, extracting memories. These don’t need your best model. An 8B handles them fine and saves compute for actual conversations.

Compaction fires when context reaches 75% of the context window. Tune it with Session.CompactionThreshold.

Override any model field with NETCLAW_ environment variables. Double underscores separate path segments, following the .NET configuration convention. Definitions and roles nest the same way as the file:

Terminal window
export NETCLAW_Models__Definitions__claude__Provider="openrouter"
export NETCLAW_Models__Definitions__claude__ModelId="anthropic/claude-sonnet-4"
export NETCLAW_Models__Roles__Main="claude"

These take highest priority, overriding anything in netclaw.json. On Linux, variable names are case-sensitive.

ConditionResult
Main Provider or ModelId is emptyDaemon boots degraded — every turn returns the No valid model configuration detected. banner
Fallback or Compaction is incompleteStartup fails
ContextWindow < 4,096 on a role-bound definitionStartup fails
Main ContextWindow exceeds provider-reported valueWarning; netclaw uses your value
Unknown role name in RolesConfig schema rejects it
Provider key doesn’t exist in Providersnetclaw model set rejects it; lists configured providers
A role names a definition that doesn’t existStartup fails: Models:Roles:Main references unknown definition 'x'.
Definitions present without Roles, or vice versaRejected — the canonical shape needs both
Definitions is emptyRejected — needs at least one definition
Two definitions whose names differ only by caseRejected as duplicates
Legacy inline roles mixed with Definitions/RolesRejected — pick one shape

An unresolved role reference is the one worth watching for, since it’s easy to introduce by renaming a definition and forgetting a role. It stops the daemon at startup, and netclaw model list and netclaw doctor both name the offending reference (Models:Roles:Main references unknown definition '...'). The fix is manual — compare Roles against Definitions and make them agree.

All model config changes require a daemon restart. There’s no daemon restart subcommand — stop and start it:

Terminal window
netclaw daemon stop && netclaw daemon start

Under systemd, restart the unit instead:

Terminal window
systemctl --user restart netclaw

In Docker, restart the container: docker restart netclaw.

Verify models are picked up:

Terminal window
netclaw model list # reads the config file
netclaw status # shows what the running daemon is using
  1. Configure a provider (Managed Providers or Self-Hosted Providers)
  2. Assign models to roles (this page, or netclaw model set)
  3. Restart the daemon
  4. Verify with netclaw status