Ollama Provider: Local and Cloud Model Integration

Learn how to run OpenClaw with Ollama using local models, cloud models, or both. Covers native API setup, avoiding /v1 issues, and provider configuration.

Read this when

  • You want to run OpenClaw with cloud or local models via Ollama
  • You need Ollama setup and configuration guidance
  • You want Ollama vision models for image understanding

OpenClaw communicates with Ollama through its native API (/api/chat) rather than the OpenAI-compatible /v1 endpoint. There are three operating modes:

ModeWhat it uses
Cloud + LocalA reachable Ollama host, serving local models and (if signed in) :cloud models
Cloud onlyhttps://ollama.com directly, no local daemon
Local onlyA reachable Ollama host, local models only

For a cloud-only deployment using the dedicated ollama-cloud provider id, refer to Ollama Cloud. When you want cloud routing kept distinct from a local ollama provider, use ollama-cloud/<model> refs.

Warning

Avoid the /v1 OpenAI-compatible URL (http://host:11434/v1). It disrupts tool calling, and models may output raw tool-call JSON as plain text. Stick with the native URL: baseUrl: "http://host:11434" (no /v1).

The standard config key is baseUrl. baseURL is also recognized for OpenAI-SDK-style examples, though new configs should rely on baseUrl.

Auth rules

Local and LAN hosts

Ollama URLs on loopback, private networks, .local, and bare hostnames do not require a genuine bearer token. OpenClaw substitutes the ollama-local marker in these cases.

Remote and Ollama Cloud hosts

Public remote hosts and https://ollama.com demand a real credential: OLLAMA_API_KEY, an auth profile, or the provider's apiKey. For direct hosted usage, the ollama-cloud provider is the recommended choice.

Custom provider ids

A custom provider using api: "ollama" adheres to the same guidelines. As an example, an ollama-remote provider targeting a private LAN host can employ apiKey: "ollama-local"; sub-agents resolve that marker via the Ollama provider hook instead of seeing it as a missing credential. memory.search.provider can also reference a custom provider id, letting embeddings use that Ollama endpoint.

Auth profiles

SQLite auth stores hold the credential for a provider id; endpoint settings (baseUrl, api, models, headers, timeouts) belong in models.providers.<id>. Older flat auth-profiles.json files like { "ollama-windows": { "apiKey": "ollama-local" } } are not a runtime format; openclaw doctor --fix imports them into SQLite as a canonical ollama-windows:default API-key profile with a backup. A baseUrl value in that legacy file is irrelevant and should be relocated to provider config.

Memory embedding scope

Bearer auth for Ollama memory embeddings is limited to the host it was declared for:

  • A provider-level key is sent only to that provider's host.
  • memory.search.remote.apiKey and per-agent overrides are sent only to their remote embedding host.
  • A pure OLLAMA_API_KEY env value is treated as the Ollama Cloud convention and is not sent to local/self-hosted hosts by default.

Getting started

Onboarding (recommended)

Run onboarding

openclaw onboard

Pick Ollama, then choose a mode: Cloud + Local, Cloud only, or Local only.

In a fresh guided setup, OpenClaw first examines the default or configured Ollama host. Automatic discovery only considers models already loaded in memory, as reported by /api/ps, with tool support and at least 16K of context confirmed by /api/show. An eligible model on disk but not loaded is not an automatic candidate. The selected route still requires a real completion before OpenClaw saves it; discovery never pulls or loads an idle model.

To use an installed but idle model in desktop Model Setup, select Choose connection on the Ollama card, then Local only. This explicit setup path can prepare an eligible installed model for the live check without requiring it to be loaded already.

Select a model

Cloud only prompts for OLLAMA_API_KEY and suggests hosted cloud defaults. Cloud + Local and Local only prompt for an Ollama base URL and inspect installed models. If no tools-capable model is found, setup can ask permission to pull a recommended model. An installed :latest tag such as gemma4:latest is shown once instead of duplicating gemma4. Cloud + Local also checks whether the host is signed in for cloud access.

Verify

openclaw models list --provider ollama

Non-interactive:

openclaw onboard --non-interactive --accept-risk --skip-health \
  --auth-choice ollama \
  --custom-base-url "http://ollama-host:11434" \
  --custom-model-id "qwen3.5:27b"

--custom-base-url and --custom-model-id are not required; leaving them out defaults to the local host address and the gemma4 suggested model.

Manual setup

Install and start Ollama

Download it from ollama.com/download, then fetch a model:

ollama pull gemma4

To enable hybrid cloud access, execute ollama signin on the same machine.

Set a credential

export OLLAMA_API_KEY="ollama-local"    # local/LAN host, any value works
export OLLAMA_API_KEY="your-real-key"   # https://ollama.com only

Alternatively, specify it in the config: openclaw config set models.providers.ollama.apiKey "OLLAMA_API_KEY".

Select the model

openclaw models list
openclaw models set ollama/gemma4

Or through config:

{
  agents: {
    defaults: {
      model: { primary: "ollama/gemma4" },
    },
  },
}

Cloud models through a local host

Cloud + Local directs both local and :cloud models to a single accessible Ollama host, which represents Ollama's hybrid approach and the option selected during installation when both types are desired.

OpenClaw asks for the base URL, identifies local models, and verifies ollama signin status. Once authenticated, it proposes hosted defaults (kimi-k2.5:cloud, minimax-m2.7:cloud, glm-5.1:cloud, glm-5.2:cloud). If authentication is absent, setup remains local-only until ollama signin is executed.

For cloud-only access without a local daemon, opt for openclaw onboard --auth-choice ollama-cloud and refer to Ollama Cloud, a route that avoids the need for ollama signin or an active server:

openclaw onboard --auth-choice ollama-cloud
openclaw models set ollama-cloud/kimi-k2.5:cloud

The cloud model list presented during openclaw onboard is fetched in real time from https://ollama.com/api/tags, limited to 500 entries, ensuring the picker shows the current hosted offerings. If ollama.com is inaccessible or yields no models during setup, OpenClaw resorts to its built-in suggested list so configuration can proceed.

Model discovery (implicit provider)

When OLLAMA_API_KEY (or an auth profile) is configured and neither models.providers.ollama nor another custom provider with api: "ollama" is present, OpenClaw obtains models from http://127.0.0.1:11434:

BehaviorDetail
Catalog query/api/tags
Capability detectionBest-effort /api/show examines contextWindow, num_ctx Modelfile parameters, and capabilities (vision/tools/thinking)
Vision modelsA vision capability from /api/show designates the model as image-capable (input: ["text", "image"])
Reasoning detectionRelies on the thinking capability from /api/show when present; otherwise uses a name-based heuristic (r1, reason, reasoning, think) when Ollama does not report capabilities. glm-5.2:cloud and deepseek-v4-flash|pro:cloud are always classified as reasoning irrespective of reported capabilities.
Token limitsmaxTokens uses OpenClaw's Ollama max-token cap as its default
CostsEvery cost is 0
ollama list
openclaw models list

A nonempty models.providers.ollama.models list picks manual models and bypasses discovery. When Ollama falls within the agent's model scope, an explicit self-hosted endpoint with models: [] stays eligible for discovery; models.providers.ollama.apiKey by itself does not choose that provider for Gateway model browsing.

Hosted https://ollama.com entries skip discovery since Ollama Cloud models are managed by the provider. In the absence of an explicit Ollama endpoint, a custom provider with api: "ollama" and a non-loopback baseUrl blocks ambient localhost discovery; list that custom provider's models manually (see Configuration). Loopback custom providers such as http://127.0.0.2:11434 keep ambient local discovery active.

You can pass a complete ref like ollama/<pulled-model>:latest without adding a hand-written models.json entry; OpenClaw performs live resolution. On signed-in hosts, picking an unlisted ollama/<model>:cloud ref checks that exact model against /api/show and, only when Ollama confirms the metadata, registers it in the runtime catalog. Misspellings still come back as unknown models.

Smoke tests

For a lightweight text check that avoids the full agent tool stack:

OLLAMA_API_KEY=ollama-local \
  openclaw infer model run \
    --local \
    --model ollama/llama3.2:latest \
    --prompt "Reply with exactly: pong" \
    --json

Pair --file with an image to run a minimal vision-model probe (PNG, JPEG, and WebP are accepted; anything else is rejected before Ollama gets called, so use openclaw infer audio transcribe for audio):

OLLAMA_API_KEY=ollama-local \
  openclaw infer model run \
    --local \
    --model ollama/qwen2.5vl:7b \
    --prompt "Describe this image in one sentence." \
    --file ./photo.jpg \
    --json

Neither route loads chat tools, memory, or session context. If this path works while normal agent replies do not, the model's tool or agent capability is the likely culprit, not the endpoint.

Choosing a model through /model ollama/<model> is an explicit user decision: when the configured baseUrl cannot be reached, the next reply surfaces the provider error rather than quietly switching to another configured model.

Isolated cron jobs add one local safety check before the agent turn starts: if the selected model maps to a local, private-network, or .local Ollama provider and /api/tags is down, OpenClaw marks that run as skipped and includes the model in the error message. This endpoint check is cached per host for 5 minutes, so repeated cron jobs hitting a stopped daemon do not all fire off failing requests.

Live verification:

OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_OLLAMA=1 OPENCLAW_LIVE_OLLAMA_WEB_SEARCH=0 \
  pnpm test:live -- extensions/ollama/ollama.live.test.ts

For Ollama Cloud, run the same live test against the hosted endpoint (embeddings are skipped by default; force them with OPENCLAW_LIVE_OLLAMA_EMBEDDINGS=1 because a cloud key may lack permission for /api/embed):

export OLLAMA_API_KEY='<your-ollama-cloud-api-key>'
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_OLLAMA=1 \
OPENCLAW_LIVE_OLLAMA_BASE_URL=https://ollama.com \
OPENCLAW_LIVE_OLLAMA_MODEL=glm-5.1:cloud \
OPENCLAW_LIVE_OLLAMA_WEB_SEARCH=1 \
pnpm test:live -- extensions/ollama/ollama.live.test.ts

To add a model, pull it and it gets discovered on its own:

ollama pull mistral

Node-local inference

Agents can hand a short task to an Ollama model running on a paired desktop or server node. The prompt and response travel over the existing authenticated Gateway/node connection; execution happens on the node's own loopback Ollama endpoint (http://127.0.0.1:11434).

Start Ollama on the node

ollama pull qwen3:0.6b
ollama list

Connect the node host

openclaw node run \
  --host <gateway-host> \
  --port 18789 \
  --display-name "Local inference"

Approve the device and its node commands on the Gateway host, then confirm:

openclaw devices list
openclaw devices approve <deviceRequestId>
openclaw nodes pending
openclaw nodes approve <nodeRequestId>
openclaw nodes status --connected

A first connection, or an upgrade that introduces Ollama commands, may prompt node-command approval. If the node connects without advertising ollama.models and ollama.chat, re-check openclaw nodes pending.

Use it from an agent

The bundled Ollama plugin ships the node_inference tool. Agents call action: "discover" first, then action: "run" with a node and model taken from that result (run can leave the node out when exactly one capable node is connected). Example: "Discover the Ollama models on my nodes, then use the fastest loaded model to summarize this text."

Discovery reads /api/tags, inspects /api/show capabilities, and relies on /api/ps when present to rank already-loaded models ahead of others. Only local models Ollama reports as chat-capable (the completion capability) are returned; Ollama Cloud rows and embedding-only models are left out. Each run turns off model thinking and caps output at 512 tokens (hard limit 8192) unless the tool call asks for a different maxTokens; some models, GPT-OSS among them, cannot disable thinking and may still produce reasoning tokens.

To keep Ollama running on a node without exposing it to agents:

openclaw config set plugins.entries.ollama.config.nodeInference.enabled false

Restart the node (openclaw node restart, or stop and rerun openclaw node run for a foreground session). The node stops advertising ollama.models and ollama.chat; Ollama itself and the Gateway's Ollama provider are untouched. Set the value back to true and restart to re-enable; a changed command surface may need openclaw nodes pending approval again after reconnect.

Check the node commands directly, without an agent turn:

openclaw nodes invoke \
  --node "Local inference" \
  --command ollama.models \
  --params '{}' \
  --invoke-timeout 90000 \
  --timeout 100000

openclaw nodes invoke \
  --node "Local inference" \
  --command ollama.chat \
  --params '{"model":"qwen3:0.6b","prompt":"Reply with exactly: pong","maxTokens":32,"timeoutMs":120000}' \
  --invoke-timeout 130000 \
  --timeout 140000

--invoke-timeout limits how long the node gets to run the command; --timeout bounds the overall Gateway call and should be set higher.

Node-local inference always hits the node's own loopback endpoint, never a configured remote or cloud models.providers.ollama.baseUrl. The node commands are enabled by default on macOS, Linux, and Windows node hosts and still fall under normal node pairing and command policy.

Vision and image description

The bundled Ollama plugin registers Ollama as an image-capable media-understanding provider, letting OpenClaw send explicit image-description requests and configured image-model defaults through local or hosted Ollama vision models.

ollama pull qwen2.5vl:7b
export OLLAMA_API_KEY="ollama-local"
openclaw infer image describe --file ./photo.jpg --model ollama/qwen2.5vl:7b --json

--model must be a full <provider/model> ref; when it is set, infer image describe tries that model first instead of skipping description for models that already handle native vision. If the call fails, OpenClaw can move on through agents.defaults.imageModel.fallbacks; file and URL preparation errors stop the flow before fallback is attempted. Use infer image describe for OpenClaw's image-understanding flow and configured imageModel; use infer model run --file for a raw multimodal probe with a custom prompt.

To set Ollama as the default image-understanding provider for inbound media:

{
  agents: {
    defaults: {
      imageModel: {
        primary: "ollama/qwen2.5vl:7b",
      },
    },
  },
}

Prefer the full ollama/<model> reference. A bare imageModel reference such as qwen2.5vl:7b only resolves to ollama/qwen2.5vl:7b when that exact model appears in models.providers.ollama.models with input: ["text", "image"], and no other configured image provider exposes the same bare identifier; otherwise, include the provider prefix explicitly.

Local vision models that run slowly may demand a longer image-understanding timeout than cloud-based ones, and on constrained hardware they can crash if Ollama attempts to allocate the model's full advertised vision context. Configure a capability timeout and limit num_ctx:

{
  models: {
    providers: {
      ollama: {
        models: [
          {
            id: "qwen2.5vl:7b",
            name: "qwen2.5vl:7b",
            input: ["text", "image"],
            params: { num_ctx: 2048, keep_alive: "1m" },
          },
        ],
      },
    },
  },
  tools: {
    media: {
      models: [
        {
          provider: "ollama",
          model: "qwen2.5vl:7b",
          timeoutSeconds: 300,
          capabilities: ["image"],
        },
      ],
      image: {
        timeoutSeconds: 180,
      },
    },
  },
}

This timeout governs inbound image understanding and the explicit view_image tool. The models.providers.ollama.timeoutSeconds setting still manages the underlying Ollama HTTP request guard for standard model calls.

Live verification:

OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_OLLAMA_IMAGE=1 \
  pnpm test:live -- src/agents/tools/image-tool.ollama.live.test.ts

If you set models.providers.ollama.models manually, flag vision models explicitly:

{
  id: "qwen2.5vl:7b",
  name: "qwen2.5vl:7b",
  input: ["text", "image"],
  contextWindow: 128000,
  maxTokens: 8192,
}

OpenClaw rejects image-description requests for models not marked image-capable. With implicit discovery, this comes from /api/show's vision capability.

Configuration

Basic (implicit discovery)

export OLLAMA_API_KEY="ollama-local"

Tip

When OLLAMA_API_KEY is configured, you can leave apiKey out of the provider entry; OpenClaw populates it for availability checks.

Explicit (manual models)

Explicit configuration suits hosted cloud setups, a non-default host/port, forced context windows, or fully manual model lists:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "https://ollama.com",
        apiKey: "OLLAMA_API_KEY",
        api: "ollama",
        models: [
          {
            id: "kimi-k2.5:cloud",
            name: "kimi-k2.5:cloud",
            reasoning: false,
            input: ["text", "image"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 128000,
            maxTokens: 8192
          }
        ]
      }
    }
  }
}

Custom base URL

This example carries a nonempty manual model list, so discovery is skipped:

{
  models: {
    providers: {
      ollama: {
        apiKey: "ollama-local",
        baseUrl: "http://ollama-host:11434", // No /v1 - native Ollama API URL
        api: "ollama", // Explicit: guarantees native tool-calling behavior
        timeoutSeconds: 300, // Optional: longer connect/stream budget for cold local models
        models: [
          {
            id: "qwen3:32b",
            name: "qwen3:32b",
            params: {
              keep_alive: "15m", // Optional: keep the model loaded between turns
            },
          },
        ],
      },
    },
  },
}

Warning

Avoid adding /v1. That path selects OpenAI-compatible mode, where tool calling is unreliable.

Common recipes

Swap model IDs for exact names from ollama list or openclaw models list --provider ollama.

Local model with auto-discovery

Ollama on the same machine as the Gateway, discovered automatically:

ollama serve
ollama pull gemma4
export OLLAMA_API_KEY="ollama-local"
openclaw models list --provider ollama
openclaw models set ollama/gemma4

Keep models.providers.ollama unset to use the default local endpoint, or set a self-hosted endpoint with models: [] to remain discovery-eligible.

LAN Ollama host with manual models

{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://gpu-box.local:11434",
        apiKey: "ollama-local",
        api: "ollama",
        timeoutSeconds: 300,
        maxTokens: 8192,
        models: [
          {
            id: "qwen3.5:9b",
            name: "qwen3.5:9b",
            reasoning: true,
            input: ["text"],
            contextTokens: 32768,
            params: {
              num_ctx: 32768,
              thinking: false,
              keep_alive: "15m",
            },
          },
        ],
      },
    },
  },
  agents: {
    defaults: {
      model: { primary: "ollama/qwen3.5:9b" },
    },
  },
}

contextTokens caps OpenClaw's active-input budget; params.num_ctx sets Ollama's request context. Align them when hardware cannot run the model's full advertised context.

Ollama Cloud only

No local daemon, hosted models directly:

export OLLAMA_API_KEY="your-ollama-api-key"
{
  models: {
    providers: {
      ollama: {
        baseUrl: "https://ollama.com",
        apiKey: "OLLAMA_API_KEY",
        api: "ollama",
        models: [
          {
            id: "kimi-k2.5:cloud",
            name: "kimi-k2.5:cloud",
            reasoning: false,
            input: ["text", "image"],
            contextWindow: 128000,
            maxTokens: 8192,
          },
        ],
      },
    },
  },
  agents: {
    defaults: {
      model: { primary: "ollama/kimi-k2.5:cloud" },
    },
  },
}

For the dedicated ollama-cloud provider id instead of this shape, see Ollama Cloud.

Cloud plus local through a signed-in daemon

ollama signin
ollama pull gemma4
{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://127.0.0.1:11434",
        apiKey: "ollama-local",
        api: "ollama",
        timeoutSeconds: 300,
        models: [
          { id: "gemma4", name: "gemma4", input: ["text"] },
          { id: "kimi-k2.5:cloud", name: "kimi-k2.5:cloud", input: ["text", "image"] },
        ],
      },
    },
  },
  agents: {
    defaults: {
      model: {
        primary: "ollama/gemma4",
        fallbacks: ["ollama/kimi-k2.5:cloud"],
      },
    },
  },
}

Multiple Ollama hosts

Custom provider IDs when running more than one Ollama server; each gets its own host, models, auth, and timeout.

{
  models: {
    providers: {
      "ollama-fast": {
        baseUrl: "http://mini.local:11434",
        apiKey: "ollama-local",
        api: "ollama",
        models: [
          { id: "gemma4", name: "gemma4", input: ["text"], contextTokens: 32768 },
        ],
      },
      "ollama-large": {
        baseUrl: "http://gpu-box.local:11434",
        apiKey: "ollama-local",
        api: "ollama",
        timeoutSeconds: 420,
        maxTokens: 16384,
        models: [
          { id: "qwen3.5:27b", name: "qwen3.5:27b", input: ["text"], contextTokens: 131072 },
        ],
      },
    },
  },
  agents: {
    defaults: {
      model: {
        primary: "ollama-fast/gemma4",
        fallbacks: ["ollama-large/qwen3.5:27b"],
      },
    },
  },
}

OpenClaw strips the active provider prefix (falling back to a bare ollama/ prefix) before calling Ollama, so ollama-large/qwen3.5:27b reaches Ollama as qwen3.5:27b.

Lean local model profile

Some local models handle simple prompts but struggle with the full agent tool surface. Limit tools and context before adjusting global runtime settings:

{
  agents: {
    entries: {
      local: {
        default: true,
        experimental: {
          localModelLean: true,
        },
        model: { primary: "ollama/gemma4" },
      },
    },
  },
  models: {
    providers: {
      ollama: {
        baseUrl: "http://127.0.0.1:11434",
        apiKey: "ollama-local",
        api: "ollama",
        models: [
          {
            id: "gemma4",
            name: "gemma4",
            input: ["text"],
            contextTokens: 32768,
            params: { num_ctx: 32768 },
            compat: { supportsTools: false },
          },
        ],
      },
    },
  },
}

Use compat.supportsTools: false only when the model or server reliably fails on tool schemas; it trades agent capability for stability. localModelLean removes heavyweight browser, cron, message, media-generation, voice, and PDF tools from the direct agent surface unless explicitly required, and places larger catalogs behind Tool Search. It does not alter Ollama's runtime context or thinking mode. Pair it with params.num_ctx and params.thinking: false for small Qwen-style thinking models that loop or spend their budget on hidden reasoning.

Model selection

{
  agents: {
    defaults: {
      model: {
        primary: "ollama/gpt-oss:20b",
        fallbacks: ["ollama/llama3.3", "ollama/qwen2.5-coder:32b"],
      },
    },
  },
}

Custom provider ids work the same way: for a ref using the active provider prefix, such as ollama-spark/qwen3:32b, OpenClaw strips that prefix before calling Ollama, sending qwen3:32b.

For slow local models, prefer provider-scoped tuning before raising the whole agent runtime timeout:

{
  models: {
    providers: {
      ollama: {
        timeoutSeconds: 300,
        models: [
          {
            id: "gemma4:26b",
            name: "gemma4:26b",
            params: { keep_alive: "15m" },
          },
        ],
      },
    },
  },
}

timeoutSeconds covers the model HTTP request: connection setup, headers, body streaming, and the total guarded-fetch abort. params.keep_alive is forwarded as top-level keep_alive on native /api/chat requests; set it per model when first-turn load time is the bottleneck.

Quick verification

# Ollama daemon visible to this machine
curl http://127.0.0.1:11434/api/tags

# OpenClaw catalog and selected model
openclaw models list --provider ollama
openclaw models status

# Direct model smoke
openclaw infer model run \
  --model ollama/gemma4 \
  --prompt "Reply with exactly: ok"

When connecting to a remote host, swap 127.0.0.1 for the baseUrl host. If curl succeeds but OpenClaw fails, confirm whether the Gateway is located on a separate machine, container, or service account.

OpenClaw ships Ollama Web Search as a web_search provider.

PropertyDetail
Hostmodels.providers.ollama.baseUrl if configured, otherwise http://127.0.0.1:11434; https://ollama.com targets the hosted API directly
AuthNo key needed for a signed-in local host; OLLAMA_API_KEY or configured provider auth applies to direct https://ollama.com search or hosts requiring auth
RequirementLocal/self-hosted hosts must be active and signed in with ollama signin; direct hosted search demands baseUrl: "https://ollama.com" plus a valid API key

Pick it during openclaw onboard or openclaw configure --section web, or configure:

{
  tools: {
    web: {
      search: {
        provider: "ollama",
      },
    },
  },
}

For direct hosted search via Ollama Cloud:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "https://ollama.com",
        apiKey: "OLLAMA_API_KEY",
        api: "ollama",
        models: [{ id: "kimi-k2.5:cloud", name: "kimi-k2.5:cloud", input: ["text"] }],
      },
    },
  },
  tools: {
    web: {
      search: { provider: "ollama" },
    },
  },
}

With a self-hosted host, OpenClaw attempts the local /api/experimental/web_search proxy first, then switches to the hosted /api/web_search route on that host; a signed-in local daemon typically responds through the local proxy. Direct https://ollama.com calls always hit the hosted /api/web_search endpoint.

Note

Refer to Ollama Web Search for complete setup and behavior details.

Advanced configuration

Legacy OpenAI-compatible mode

Warning

Tool calling is unreliable in this mode. Only use it when a proxy demands OpenAI format and you do not rely on native tool calling.

Set api: "openai-completions" explicitly for a proxy sitting behind /v1/chat/completions:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://ollama-host:11434/v1",
        api: "openai-completions",
        injectNumCtxForOpenAICompat: true, // default: true
        apiKey: "ollama-local",
        models: [...]
      }
    }
  }
}

Streaming and tool calling might not work together in this mode; you may need to enable params: { streaming: false } on the model.

OpenClaw adds options.num_ctx by default in this mode to prevent Ollama from quietly dropping to a 4096-token context. If your proxy rejects unrecognized options fields, turn it off:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://ollama-host:11434/v1",
        api: "openai-completions",
        injectNumCtxForOpenAICompat: false,
        apiKey: "ollama-local",
        models: [...]
      }
    }
  }
}

Context windows

For models found automatically, OpenClaw relies on the context window /api/show provides, including larger PARAMETER num_ctx values from custom Modelfiles; otherwise it defaults to OpenClaw's standard Ollama context window.

Per-model contextWindow specifies native window metadata, while per-model contextTokens limits active input. Provider-level maxTokens serves as an output-token default; a model entry can override it. Native /api/chat requests pull options.num_ctx from a positive params.num_ctx first, then from the effective model contextTokens if present. Local discovery usually restricts contextTokens to 32,768 (or the model's smaller native window), letting OpenClaw override a smaller Modelfile context even without an explicit params.num_ctx. Invalid, zero, negative, or non-finite params.num_ctx values get ignored. Only when neither value exists does Ollama pick its own model, Modelfile, OLLAMA_CONTEXT_LENGTH, or VRAM-based default; the native adapter does not directly fall back to the advertised contextWindow. After upgrading an older configuration, execute openclaw doctor --fix. Use params.num_ctx to explicitly override the native request context. The OpenAI-compatible adapter still injects options.num_ctx by default from params.num_ctx, then the matching model entry's contextTokens or contextWindow; disable with injectNumCtxForOpenAICompat: false if the upstream rejects options.

Native model entries can also take standard Ollama runtime settings through
params, which get passed along as native /api/chat options: num_keep, seed,
num_predict, top_k, top_p, min_p, typical_p, repeat_last_n,
temperature, repeat_penalty, presence_penalty, frequency_penalty,
stop, num_batch, num_gpu, main_gpu, use_mmap, and num_thread.
Certain keys (format, keep_alive, truncate, shift) are sent as
top-level request fields rather than inside options. OpenClaw forwards only these Ollama request keys, so runtime-only parameters like
streaming are never transmitted to Ollama. To set the top-level think, use params.think (or
params.thinking); false turns off API-level
thinking for Qwen-style thinking models.

{
  models: {
    providers: {
      ollama: {
        models: [
          {
            id: "llama3.3",
            contextWindow: 131072,
            contextTokens: 32768,
            maxTokens: 65536,
            params: {
              num_ctx: 32768,
              temperature: 0.7,
              top_p: 0.9,
              thinking: false,
            },
          }
        ]
      }
    }
  }
}

Per-model agents.defaults.models["ollama/<model>"].params.num_ctx also functions; if both are specified, the explicit provider model entry takes precedence.

Thinking control

OpenClaw passes thinking to Ollama in its expected format: top-level think, not
options.think. Auto-discovered models where /api/show indicates a
thinking capability provide /think low, /think medium, /think high,
and /think max; models without thinking expose only /think off.

openclaw agent --model ollama/gemma4 --thinking off
openclaw agent --model ollama/gemma4 --thinking low

Alternatively, define a model default:

{
  agents: {
    defaults: {
      models: {
        "ollama/gemma4": {
          params: { thinking: "low" },
        },
      },
    },
  },
}

Per-model params.think/params.thinking can either disable or force API
thinking for a given model. OpenClaw keeps that explicit configuration when the active run has only the implicit off default; a runtime command that is not off, such as /think medium, still takes precedence. A truthy
thinking request is never sent to a model explicitly marked
reasoning: false; a think: false request is always transmitted regardless.

Reasoning models

Models named deepseek-r1, reasoning, reason, or think are treated
as reasoning-capable by default, requiring no extra setup:

ollama pull deepseek-r1:32b

Model costs

Because Ollama runs locally and at no cost, all model costs are 0 for both
auto-discovered and manually defined models.

Memory embeddings

The Ollama provider that ships with OpenClaw adds an embedding provider for memory search. It relies on the configured Ollama base URL and API key, invokes /api/embed, and combines multiple memory chunks into a single input call when feasible.

When proxy.enabled=true, embedding requests aimed at the exact host-local loopback origin derived from the configured baseUrl take OpenClaw's guarded direct path rather than the managed forward proxy. The configured hostname must be localhost itself or a loopback IP literal; DNS names that only resolve to loopback still go through the managed proxy. LAN, tailnet, private-network, and public Ollama hosts always use the managed proxy path, and redirects to a different host/port do not inherit trust. proxy.loopbackMode: "proxy" sends loopback traffic through the proxy regardless; proxy.loopbackMode: "block" blocks it before any connection is made, see Managed proxy.

PropertyValue
Default modelnomic-embed-text
Auto-pullYes, if not present locally
Embedding concurrencyProvider-owned; no memory-search tuning key is required

For query-time embeddings, retrieval prefixes are applied to models that need or suggest them: nomic-embed-text, qwen3-embedding, and mxbai-embed-large. Document batches remain unchanged, so existing indexes require no format migration.

The Ollama memory provider controls embedding concurrency and batching. For a remote embedding host, use the supported remote.baseUrl and remote.apiKey fields to keep auth scoped to that host:

{
  memory: {
    search: {
      provider: "ollama",
      model: "nomic-embed-text",
      remote: {
        baseUrl: "http://gpu-box.local:11434",
        apiKey: "ollama-local",
      },
    },
  },
}

Streaming configuration

By default, Ollama uses the native API (/api/chat), which handles streaming and tool calling together without any extra setup.

For native requests, thinking control passes through directly: /think off and openclaw agent --thinking off send top-level think: false unless an explicit params.think/params.thinking is set; /think low|medium|high send the matching effort string. Verified full-effort Ollama Cloud families like GLM 5.2 and DeepSeek V4 also send native think: "max" for /think max; other models and local servers keep the compatible think: "high" mapping.

Tip

For the OpenAI-compatible endpoint instead, see "Legacy OpenAI-compatible mode" above, streaming and tool calling may not work together there.

Troubleshooting

WSL2 crash loop (repeated reboots)

On WSL2 with NVIDIA/CUDA, the official Ollama Linux installer sets up an ollama.service systemd unit with Restart=always. If that service autostarts and loads a GPU-backed model during WSL2 boot, Ollama can pin host memory while loading; Hyper-V memory reclaim cannot always reclaim those pages, so Windows can terminate the WSL2 VM, systemd restarts Ollama, and the loop repeats.

Evidence: repeated WSL2 reboots/terminations, high CPU in app.slice or ollama.service right after WSL2 startup, and SIGTERM from systemd rather than the Linux OOM killer.

OpenClaw logs a startup warning when it detects WSL2, ollama.service enabled with Restart=always, and visible CUDA markers.

Mitigation:

sudo systemctl disable ollama

On the Windows side, add this to %USERPROFILE%\.wslconfig, then run wsl --shutdown:

[experimental]
autoMemoryReclaim=disabled

Or shorten keep-alive / start Ollama manually only when needed:

export OLLAMA_KEEP_ALIVE=5m
ollama serve

See ollama/ollama#11317.

Ollama not detected

Confirm Ollama is running and is in the agent's model scope. For ambient localhost discovery, set OLLAMA_API_KEY (or an auth profile). A nonempty manual model list skips discovery; an explicit self-hosted endpoint with models: [] does not:

ollama serve
curl http://localhost:11434/api/tags

No models available

Pull the model locally, or define it explicitly in models.providers.ollama:

ollama list  # See what's installed
ollama pull gemma4
ollama pull gpt-oss:20b
ollama pull llama3.3     # Or another model

Connection refused

# Check if Ollama is running
ps aux | grep ollama

# Or restart Ollama
ollama serve

Remote host works with curl but not OpenClaw

Verify from the same machine and runtime that runs the Gateway:

openclaw gateway status --deep
curl http://ollama-host:11434/api/tags

Common causes:

  • baseUrl points at localhost, but the Gateway runs in Docker or on another host.
  • The URL uses /v1, selecting OpenAI-compatible behavior instead of native Ollama.
  • The remote host needs firewall or LAN binding changes.
  • The model is on your laptop's daemon but not the remote one.

Model outputs tool JSON as text

Usually the provider is in OpenAI-compatible mode, or the model cannot handle tool schemas. Prefer native mode:

{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://ollama-host:11434",
        api: "ollama",
      },
    },
  },
}

If a small local model still fails on tool schemas, set compat.supportsTools: false on that model entry and retest.

Kimi or GLM returns garbled symbols

Hosted Kimi/GLM responses that are long, non-linguistic symbol runs are treated as a failed provider call rather than a successful reply, so normal retry/fallback/error handling takes over instead of persisting corrupted text into the session.

When the issue shows up again, write down the model name, the session file in use, and whether the run was executed with Cloud + Local or Cloud only. Then start over with a new session and pick a fallback model:

openclaw infer model run --model ollama/kimi-k2.5:cloud --prompt "Reply with exactly: ok" --json
openclaw models set ollama/gemma4

Cold local model times out

Big local models often take a while on their initial load. Set the timeout only for the Ollama provider, and if you want the model to stay warm between turns, enable that option as well:

{
  models: {
    providers: {
      ollama: {
        timeoutSeconds: 300,
        models: [
          {
            id: "gemma4:26b",
            name: "gemma4:26b",
            params: { keep_alive: "15m" },
          },
        ],
      },
    },
  },
}

If the host takes time before it accepts connections, timeoutSeconds widens the guarded connect timeout for this provider too.

Large-context model is too slow or runs out of memory

Plenty of models claim context sizes that your hardware cannot actually handle. Native requests forward whatever contextTokens is in effect, unless params.num_ctx changes it. To get steady first-token latency, limit both OpenClaw's budget and the request context Ollama uses:

{
  models: {
    providers: {
      ollama: {
        maxTokens: 8192,
        models: [
          {
            id: "qwen3.5:9b",
            name: "qwen3.5:9b",
            contextTokens: 32768,
            params: { num_ctx: 32768, thinking: false },
          },
        ],
      },
    },
  },
}

When OpenClaw sends too much prompt, bring down the model entry's contextTokens. If Ollama's runtime context exceeds what the machine can handle, reduce params.num_ctx. And if generation drags on, cut maxTokens.

Note

Additional resources: Troubleshooting and FAQ.

  • Ollama Cloud, Cloud-only configuration that relies on the dedicated ollama-cloud provider.

  • Model providers, Covers every provider, model references, and how failover works.

  • Model selection, Guidance on picking and setting up models.

  • Ollama Web Search, Complete setup and behavior notes for web search powered by Ollama.

  • Configuration, The full configuration reference.

5,364 words · updated Sep 1, 2026