Tested on VS Code 1.140 (Stable) and VS Code Insiders 1.141, October 2026.
I wanted to use OpenRouter models in the VS Code Agent without signing in to GitHub Copilot. VS Code can do this with custom language model providers, but on my machine it only worked in VS Code Insiders. This post shows the setup, how to tell whether you need Insiders, and an nginx reverse proxy for networks where OpenRouter is not reachable.
TL;DR
- Try the regular VS Code first. If you see the symptoms described below, switch to VS Code Insiders.
- Create
chatLanguageModels.jsonwith an OpenRouter provider (vendor: "customendpoint") and your models. Use the exact model ID from openrouter.ai. - Set the API key with Manage Models → Update API Key. Don’t leave the raw key in the JSON: it didn’t work for me.
- Select the model in Models and switch to Agent.
- If OpenRouter is blocked in your country, see the proxy section below.
Prerequisites
- An OpenRouter account with an API key and some credit. Free models come and go (see Troubleshooting).
- A model that supports tool calling. Agent mode needs it.
- VS Code Insiders, if the regular VS Code doesn’t work for you (see the next section).
Do you need VS Code Insiders?
Maybe not, so try the regular VS Code first. On my machine (Stable 1.140), it didn’t work:
- With an empty
chatLanguageModels.jsonthere was no Manage Models button and no Chat: Manage Language Models command. - After I added a provider to the file by hand and restarted, the button and the command appeared, but the Language Models dialog showed only Copilot’s own models. My OpenRouter models were nowhere to be found, and I couldn’t select them in the chat.
- Add Models → OpenRouter accepted an API key and wrote a group to
chatLanguageModels.json, but the group never showed up in the dialog or in the model picker, even after a restart.
I didn’t dig into why. The official docs currently list the Custom endpoint provider as an Insiders feature, and in Insiders everything below worked. So if you see the same symptoms, install VS Code Insiders. It installs side by side with the regular VS Code and keeps its own settings.
Where is chatLanguageModels.json
The file lives in the user data folder of VS Code Insiders, which is separate from the regular VS Code (Code - Insiders, not Code):
- Windows: press
Win + R, enter%APPDATA%\Code - Insiders\Userand press Enter. - macOS: in Finder press
Cmd + Shift + Gand go to~/Library/Application Support/Code - Insiders/User. - Linux: go to
~/.config/Code - Insiders/User.
Note: the regular VS Code uses
Codeinstead ofCode - Insidersin these paths. You can edit the file there, but if the regular VS Code doesn’t show your models, editing it won’t help. Edit the Insiders copy.
Create the provider in chatLanguageModels.json
I didn’t add the provider through the Manage Models dialog. I wrote it in chatLanguageModels.json by hand and VS Code picked it up. This is the file I use:
[
{
"name": "OpenRouter",
"vendor": "customendpoint",
"apiKey": "${input:chat.lm.secret.-32b9a01a}",
"apiType": "chat-completions",
"models": [
{
"id": "qwen/qwen3.8-27b",
"name": "Qwen3.8 27B",
"url": "https://openrouter.ai/api/",
"toolCalling": true,
"vision": true,
"maxInputTokens": 262000,
"maxOutputTokens": 16000
},
{
"id": "deepseek/deepseek-r1",
"name": "DeepSeek R1",
"url": "https://openrouter.ai/api/",
"toolCalling": true,
"vision": false,
"maxInputTokens": 64000,
"maxOutputTokens": 16000
}
]
}
]
The apiKey value is what VS Code writes after the next step. Until then, don’t worry about it.
What the fields mean:
vendor: "customendpoint"marks this as a custom model provider.apiType: "chat-completions"makes VS Code use the Chat Completions API.idis the model ID on OpenRouter. Copy it from the model’s page.urlis the base URL. VS Code builds the Chat Completions request from it (the request ends up at/v1/chat/completions), which is why it is.../api/and not the full endpoint.toolCallingenables tool calling. Without it the Agent can’t work.visionsays whether the model accepts images.maxInputTokensandmaxOutputTokensare the limits VS Code uses.
Choosing values for a model
Take toolCalling and vision from the model’s page on OpenRouter. For example, Qwen3.8 27B is a vision-language model that accepts tools, while DeepSeek R1 is text-only, so vision is false there.
Limits are less clear-cut. The context size can differ between providers and sources: for R1 I’ve seen 64K on the model page and 131K-164K elsewhere, and for Qwen3.8 27B 262K and 1M. I use the smaller figure, which is safe with any provider. Don’t set maxOutputTokens too low for reasoning models, because reasoning tokens count as output. 4096 is too small, since answers get cut off.
If you want a Claude model, the same block works with the slug from its OpenRouter page (for Sonnet 5 it is anthropic/claude-sonnet-5, with vision: true and toolCalling: true).
Set the API key (this step is not optional)
It might seem natural to write your OpenRouter key directly into apiKey:
"apiKey": "sk-or-v1-..."
That is what I did first, and it didn’t work. OpenRouter rejected every request with a 403. I checked the nginx log and found that the Authorization header contained just Bearer, with no token after it.
What fixed it: in Manage Models I selected the OpenRouter provider and chose Update API Key, then entered the key there. VS Code replaced the value in the file with a reference to a secret it stores itself:
"apiKey": "${input:chat.lm.secret.-32b9a01a}"
After that the header was passed correctly and requests went through. As a bonus, the key no longer sits in a file. The reference only works on the machine where you ran Update API Key, so don’t copy it to another machine. Run Update API Key there too.
VS Code replaced the raw key in the file with that reference on its own, so nothing else needs cleaning up.
Using the model
Go back to the Chat view, click Models, pick the OpenRouter model and switch to Agent. VS Code stays the interface and the agent, while OpenRouter provides the model, so you can swap models by editing one entry in the JSON.
If OpenRouter is not reachable from your country
If OpenRouter works for you, skip this section. Otherwise, you can route requests through an nginx reverse proxy on a VPS that can reach it:
VS Code → https://example.com/openrouter/api/ → nginx → https://openrouter.ai/api/v1/chat/completions
In the model config, change the URL:
"url": "https://example.com/openrouter/api/"
nginx configuration
This is the configuration that works for me (TLS for example.com is assumed to be configured already):
location /openrouter/api/v1/chat/completions {
proxy_pass https://openrouter.ai/api/v1/chat/completions;
proxy_ssl_server_name on;
proxy_ssl_name openrouter.ai;
proxy_ssl_protocols TLSv1.2 TLSv1.3;
proxy_ssl_session_reuse on;
proxy_set_header Host openrouter.ai;
proxy_set_header Authorization $http_authorization;
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
proxy_send_timeout 300s;
proxy_buffer_size 32k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
}
Your OpenRouter key is passed through from the Authorization header sent by VS Code, so it is never stored on the server. The location covers only the Chat Completions path, so other endpoints, such as /v1/models, are not proxied. That’s fine here because the models are listed manually in the JSON.
Security notes
- The proxy sees your API key and every prompt, including your project’s code. Only run it on a server you control.
- A public proxy can be used by anyone who finds it. Restrict access, for example with
allow/denyfor your IP addresses andlimit_reqfor rate limiting. Basic auth won’t work here, because it uses the sameAuthorizationheader that carries your OpenRouter key. - Check OpenRouter’s terms of service and any regional restrictions that apply to you before routing around network blocks.
Troubleshooting
The model doesn’t appear in the picker. First check that you are in VS Code Insiders and not in the regular VS Code, and that you edited the file in the Code - Insiders folder. Then check that the JSON is valid and that the provider has an API key set.
403, and the Authorization header contains only Bearer. I got this when I wrote the raw key into apiKey. Run Update API Key (see above) so that VS Code stores the key as a secret. If you use the nginx proxy, you can see what actually arrives by temporarily logging $http_authorization in your log format. Remove it afterwards, because it puts your key into the log.
404 — This model is unavailable for free. This is what I got when I tried a :free model:
{"message":"This model is unavailable for free. The paid version is available now - use this slug instead: deepseek/deepseek-r1","code":404}
Free variants of models get removed. The message contains the paid slug, so put it into id. The error also tells you that the request reached OpenRouter and the key was accepted, so the config and the proxy are fine.
401. The API key is missing or wrong. Run Update API Key again.
The Agent ignores tools or fails. The model, or the specific provider OpenRouter routes you to, may not support tool calling. Check the model’s page and try another model.
Responses hang or arrive all at once (when using the proxy). This is usually buffering. Make sure proxy_buffering off; is set.
A note on privacy
In Agent mode, parts of your project are sent to the model provider as prompts. OpenRouter forwards them to the provider that serves the model, so check the data policy of the models you use, especially the free ones.