On this page
On this page
Providers
vLLM
vLLM serves open-source (and some custom) models through an OpenAI-compatible HTTP API. OpenClaw connects using the openai-completions API and can auto-discover models when you opt in with VLLM_API_KEY.
| Property | Value |
|---|---|
| Provider ID | vllm |
| API | openai-completions (OpenAI-compatible) |
| Auth | VLLM_API_KEY environment variable |
| Default base URL | http://127.0.0.1:8000/v1 |
| Streaming usage | Supported (stream_options.include_usage) |
Getting started
Start vLLM with an OpenAI-compatible server
Your base URL must expose /v1 endpoints (/v1/models, /v1/chat/completions). Start the server with the model you want to serve:
See the vLLM online serving docs for flags. vLLM commonly runs on:
Set the API key environment variable
Any non-empty value works if your server does not enforce auth:
Select a model
Replace with one of your vLLM model IDs:
Verify the model is available
Model discovery (implicit provider)
When VLLM_API_KEY is set (or an auth profile exists) and models.providers.vllm is not defined, OpenClaw queries GET http://127.0.0.1:8000/v1/models and converts the returned IDs into model entries.
Explicit configuration
Configure explicitly when vLLM runs on a different host or port, you want to pin contextWindow/maxTokens, your server requires a real API key, or you connect to a trusted loopback, LAN, or Tailscale endpoint:
To keep the provider dynamic without listing every model, add a wildcard to the visible model catalog:
Advanced configuration
Prioritize interactive requests
When interactive and background work share one vLLM engine, enable native priority scheduling on the server:
Then opt in for that model in OpenClaw:
priorityScheduling is an optional boolean, disabled by default. It applies
only to the selected vllm/* model's params; agent-specific model params can
override it. Global or agent-wide params do not enable it. Other providers and
fallback models do not inherit the opt-in.
| Request | Native priority |
|---|---|
Interactive user turn or manual /compact |
-100 |
| Delegated or unclassified work | 0 |
| Cron, heartbeat, memory, or simple helper completion | 100 |
Run-triggered compaction inherits the originating urgency. Independent automatic compaction uses background priority. Simple helper completions include utility summaries and tool-side model calls, even when a user is waiting for their result.
Lower numbers are scheduled first under contention; arrival order breaks ties. OpenClaw sends the native field and does not maintain another queue, reserve capacity, or isolate model memory. See the vLLM scheduler reference.
When enabled, dynamic priority takes precedence over an explicit
extraBody.priority or extra_body.priority. When disabled, OpenClaw adds no
scheduling field and preserves existing literal priority overrides, including
zero. Numeric priority: 0 never enables scheduling.
The vLLM request contract requires priority scheduling for nonzero priorities.
Before switching the server back to FCFS, disable priorityScheduling and remove
any explicit nonzero priority overrides. This new optional field needs no Doctor
migration.
Proxy-style behavior
vLLM is treated as a proxy-style OpenAI-compatible /v1 backend, not a native OpenAI endpoint:
| Behavior | Applied? |
|---|---|
| Native OpenAI request shaping | No |
service_tier |
Not sent |
Responses store |
Not sent |
| Prompt-cache hints | Not sent |
| OpenAI reasoning-compat payload shaping | Not applied |
| Hidden OpenClaw attribution headers | Not injected on custom base URLs |
Qwen thinking controls
For Qwen models, set compat.thinkingFormat: "qwen-chat-template" on the model row when the server expects Qwen chat-template kwargs. These models expose a binary /think profile (off, on) because Qwen chat-template thinking is an on/off flag, not an OpenAI-style effort ladder.
OpenClaw maps /think off to:
Non-off thinking levels send enable_thinking: true. If your endpoint expects DashScope-style top-level flags instead, use compat.thinkingFormat: "qwen" to send enable_thinking at the request root.
If your served template accepts effort levels, declare them in compat.supportedReasoningEfforts, for example ["low", "medium", "xhigh"]. OpenClaw then exposes those /think choices plus off. The shared reasoning resolver maps the selected level to the declared wire value. With qwen-chat-template, that value goes in chat_template_kwargs.reasoning_effort; with qwen, it goes in root reasoning_effort.
Provider-native values are case-sensitive. Use compat.reasoningEffortMap, such as { low: "LOW", high: "HIGH" }, to map logical choices to a declared native list such as ["LOW", "HIGH"]. Unmapped native labels are not advertised as effort choices. Missing, empty, or unusable lists keep binary thinking, as does compat.supportsReasoningEffort: false.
The plugin prepares these mappings as model capabilities before session setup, so advanced choices such as xhigh and max also survive session-level clamping when their native wire labels differ.
The default remains off, including after upgrading an existing configured model. An explicit enabled level now sends its declared effort instead of silently using the template's default. Ordinary binary Qwen models keep their existing request shape. Per-model params.extra_body remains the final request-body override.
DeepSeek V4 thinking controls
For vLLM model IDs containing deepseek-v4 or deepseek_v4, configure reasoning: true. OpenClaw sends the selected effort through chat_template_kwargs.reasoning_effort, with both thinking and enable_thinking set to true. Declared efforts and reasoningEffortMap use the same shared resolver as other OpenAI-compatible models.
/think off sends both template flags as false, because vLLM enables DeepSeek thinking when either flag is true. Hosted DeepSeek's root thinking object and root reasoning_effort are removed. Existing explicit template kwargs and the final params.extra_body override remain authoritative. Explicit Qwen thinking formats take precedence over the model-name match.
This request shaping does not enable reasoning for catalog rows marked reasoning: false or change discovery heuristics. Configure the model explicitly if discovery does not recognize its reasoning capability.
Nemotron 3 thinking controls
For vllm/nemotron-3-* models with thinking off, the bundled plugin sends:
To customize these values, set chat_template_kwargs under the model params. If you also set params.extra_body.chat_template_kwargs, that value wins because extra_body is the last request-body override.
Qwen tool calls appear as text
First confirm vLLM was started with the right tool-call parser and chat template for the model. vLLM documents hermes for Qwen2.5 models and qwen3_xml for Qwen3-Coder models.
Symptoms: skills/tools never run, the assistant prints raw JSON/XML such as {"name":"read","arguments":...}, or vLLM returns an empty tool_calls array when OpenClaw sends tool_choice: "auto".
Some Qwen/vLLM combinations return structured tool calls only when the request uses tool_choice: "required". Force it per model with params.extra_body:
Replace the model id with the exact id from openclaw models list --provider vllm, or apply the same override from the CLI:
This is an opt-in workaround: it forces every turn with tools to make a tool call, so use it only for a dedicated model entry where that is acceptable. Do not set it as a global default for all vLLM models, and do not pair it with a proxy that converts arbitrary assistant text into executable tool calls.
Custom base URL
If your vLLM server runs on a non-default host or port, set baseUrl in the explicit provider config:
Troubleshooting
Slow first response or remote server timeout
For large local models, remote LAN hosts, or tailnet links, set a provider-scoped request timeout:
timeoutSeconds applies to vLLM model HTTP requests only: connection setup, response headers, body streaming, and the total guarded-fetch abort. It also raises the LLM idle/stream watchdog ceiling above the implicit ~120s default for this provider. Prefer this over increasing agents.defaults.timeoutSeconds, which controls each model attempt's execution budget. A lower agent or run-specific timeout still caps the attempt; each configured fallback gets a fresh budget.
Server not reachable
Check that the vLLM server is running and accessible:
If you see a connection error, verify the host, port, and that vLLM started in OpenAI-compatible server mode. OpenClaw trusts the exact configured models.providers.vllm.baseUrl origin for guarded model requests on loopback, LAN, and Tailscale endpoints. Metadata, link-local, and local-use NAT64 (64:ff9b:1::/48) origins remain blocked without explicit opt-in. Set models.providers.vllm.request.allowPrivateNetwork: true only when vLLM requests must reach another private origin, or false to opt out of exact-origin trust.
Auth errors on requests
If requests fail with auth errors, set a real VLLM_API_KEY that matches your server configuration, or configure the provider explicitly under models.providers.vllm.
No models discovered
Auto-discovery requires VLLM_API_KEY to be set. If you have defined models.providers.vllm, OpenClaw uses only your declared models unless agents.defaults.models includes "vllm/*": {}.
Tools render as raw text
If a Qwen model prints JSON/XML tool syntax instead of executing a skill:
- Start vLLM with the correct parser/template for that model.
- Confirm the exact model id with
openclaw models list --provider vllm. - Add a dedicated per-model
params.extra_body.tool_choice: "required"override only iftool_choice: "auto"still returns empty or text-only tool calls.