Skip to content

Add Router One to Copilot for Obsidian as a custom OpenAI-compatible provider

Copilot for Obsidian (logancyang/obsidian-copilot, listed as Copilot in Community Plugins) connects to Router One through Settings → Copilot → BYOK (bring your own key) → Add a provider → Add a custom provider: Base URL https://api.router.one/v1, a Router One key, exact catalog model IDs such as anthropic/claude-sonnet-5, and Enable CORS left off so Quick Chat streams. Router One then serves the model requests from Quick Chat, Quick Ask, Copilot Commands and opencode Agent Chat, while Copilot keeps your notes, context, agent tools, permissions and Miyo search. This guide was checked against Copilot 4.0.13, released 2026-10-02, which installs OpenCode 2.0.22 for Agent Chat (Copilot 4.0.12 and later no longer run OpenCode 1, per the release notes); the Claude and Codex backends never use BYOK keys.

Before you start: which Copilot features use the provider

Install or update Copilot from Community Plugins and check that the installed version is 4.0.13 or later; this guide was checked against 4.0.13. Copilot 4 requires Obsidian 1.11.4 or newer, its minimum app version, which is also what the Obsidian Keychain that holds BYOK keys needs. Only the first four rows below use the provider; the other features run on their own accounts or services and never use this key.

Before you start: which Copilot features use the provider
Copilot surfaceUses the Router One provider?Where the request comes from
Quick Chat (desktop and mobile)Yes, when a Router One model is selectedObsidian itself: POST /v1/chat/completions
Quick AskYes, when its model is a Router One model; it starts on the Default quick command model under CommandObsidian itself: POST /v1/chat/completions
Copilot Commands and Trigger quick commandYes, when the model the command names, or the Default quick command model it falls back to, is a Router One modelObsidian itself: POST /v1/chat/completions
Agent Chat with opencode (desktop only)Yes, once opencode is installed and the model is enabled for itThe local opencode process: POST /v1/chat/completions
Agent Chat with Claude or CodexNo; they never use BYOK keysThe Claude Code or Codex CLI, with its own login and configuration, not this BYOK key
Copilot-hosted models, hosted Copilot Plus toolsNo; they need a Copilot license and run on Brevilabs servicesNot Router One
Miyo semantic search, Relevant NotesNo; Miyo keeps its own indexNot Router One

Configure Copilot for Obsidian to use the Router One base URL

Open Settings → Copilot → BYOK, select Add a provider, then select Add a custom provider at the bottom of the dialog. Use this entry instead of changing the URL of the OpenAI entry: the listed vendor entries stay tied to that vendor's model metadata and to opencode's built-in provider for it, while a custom provider reaches opencode as a generic OpenAI-compatible provider at your Base URL. In Configure Custom OpenAI-compatible, set Display name to Router One and paste a dedicated key into API key; the field is marked optional because some custom endpoints run without authentication, but Router One requires the key. Enter https://api.router.one/v1 as Base URL. Copilot appends /models for Test and model discovery, and its chat client appends /chat/completions, so a pasted full endpoint doubles the path. Leave Enable CORS off, its default. With it off, Quick Chat, Quick Ask and Commands send their chat requests with the browser's native fetch, so replies stream and Stop can cancel a request (per Copilot's 4.0.13 source); since 2026-10-02 api.router.one answers the CORS preflight these requests trigger (see Enable CORS: leave it off below). Turn it on only if Test passes but Quick Chat still cannot send; replies then arrive whole instead of streaming. Select Test: Verified means GET /v1/models accepted the key, and the returned IDs appear under Search available models. Check one or two chat models, or type an exact ID in Model ID and select Add. The placeholder shows a bare name, gpt-5.5, but copy the full catalog ID from /models, prefix included where it has one, as in anthropic/claude-sonnet-5 or openai/gpt-5.5. Select Save. New chat models are enabled for Quick Chat and opencode automatically; choose a Default model under Basic → Agents → Quick Chat (on mobile: Basic → Quick Chat models), a Default quick command model under Command for Quick Ask, Quick Command and saved commands, and a Default model under Basic → Agents → opencode once opencode is installed:

Base URL
https://api.router.one/v1
copilot-byok-custom-provider
# Settings → Copilot → BYOK → Add a provider → Add a custom provider
Display name:  Router One
API key:       sk-your-router-one-key       # saved in this device's Obsidian Keychain
Base URL:      https://api.router.one/v1    # not .../chat/completions
Enable CORS:   Off                          # default; replies stream and Stop cancels
Model ID:      anthropic/claude-sonnet-5    # full catalog ID, then Add
               openai/gpt-5.5
# Test → check chat models only → Save

# Basic → Agents → Quick Chat → Default model   (mobile: Basic → Quick Chat models)
# Command → Default quick command model   (Quick Ask, Quick Command, saved commands)
# Basic → Agents → opencode → Default model   (desktop; install opencode first)
# Each chat turn: POST https://api.router.one/v1/chat/completions

Enable CORS: leave it off

Copilot uses two transports, per its 4.0.13 source (checked 2026-10-03). Test, model discovery and the provider checks that run whenever you open BYOK go through Obsidian's requestUrl API, which browser CORS rules do not apply to. With Enable CORS off, Quick Chat, Quick Ask and Copilot Commands send from the Obsidian window with native fetch: the reply streams, and Stop aborts the request, because Copilot passes its abort signal to the streaming call. These requests carry an Authorization header, a JSON body and the OpenAI SDK's own X-Stainless-* headers, so the browser first sends a CORS preflight. Since 2026-10-02, api.router.one answers preflights with Access-Control-Allow-Origin: * and allows the request headers the preflight lists, X-Stainless-* included, so the chat request goes out and the reply streams; before that date it did not allow those headers, which is why this guide used to say to turn Enable CORS on. Stop closes the connection, and Router One records the request as HTTP 499 client_cancelled and bills only the usage the upstream reported (see LLM streaming). With Enable CORS on, the chat requests go through requestUrl instead: the reply appears only once it is complete, as Copilot's own setting tooltip says, and the 4.0.13 source passes no abort signal on this path, so Stop does not cancel the request: it runs to the end and is billed like any completed request. Copilot's Model Sources page (checked 2026-10-03) recommends turning it on when Test succeeds but Quick Chat cannot send, so reserve it for that case, for example a network proxy that strips CORS headers. The switch does not change opencode Agent Chat, which runs as a separate local process and streams either way. It is saved per provider and changed under More actions → Edit key; a provider migrated from Copilot 3 keeps the CORS choice it had. If you turned Enable CORS on while following an earlier version of this guide, turn it off under More actions → Edit key to get streaming replies and a Stop that cancels the request.

Count Quick Chat requests: messages, titles and retries

With a Router One model selected, each Quick Chat message is one POST /v1/chat/completions with stream set to true. A new chat includes the active note as context by default, so a long note adds input tokens to every turn. Per the 4.0.13 source, Copilot sends no temperature, top_p or output limit for custom-provider models, and it does not request stream usage, so Quick Chat's token counter usually stays hidden for these models; use Dashboard → Logs for tokens and cost. Autosave Chat as Markdown is on by default, and the first time it saves a conversation note Copilot asks the same model for a short title, which is at least one more small request. The client retries a failed request up to three more times, so one message can be sent up to four times; per the @langchain/core 1.2.8 source that Copilot 4.0.13 bundles, a 500 is retried and a 400 is not. One naming rule also matters: Quick Chat switches model names that begin with gpt-5 to the Responses API. The catalog IDs for GPT models carry a prefix, as in openai/gpt-5.5, so they do not match this rule and stay on Chat Completions. A bare name typed from the placeholder, such as gpt-5.5, is sent to POST /v1/responses instead, which Router One serves natively for the GPT family.

Agent Chat: opencode builds its own requests

Agent Chat on opencode does not reuse the Quick Chat client. Per the 4.0.13 source, when Copilot starts opencode it passes a generated configuration that registers your custom provider as an @ai-sdk/openai-compatible provider with the same Base URL and key, lists each model enabled for opencode under its full catalog ID, and declares text input only for custom-provider models it has no metadata for. opencode then builds its own requests to POST /v1/chat/completions and adds tools, tool_choice and other parameters of its own, so a model that answers in Quick Chat can still return an error here; read which parameter the error names. For images, use Quick Chat, which per the same source does not block them for these models and sends them as image_url content, with a model whose page lists image input. After you change the provider, key or enabled models, an open chat shows a config has changed notice; choose Reload to restart opencode with the new values.

Search and embeddings stay outside the gateway

Copilot 4.0.6 and later have no embedding-model setting to point at Router One: that release retired Vault QA and removed the plugin's own index, and meaning-based search and Relevant Notes now come from Miyo, a separate local-first app connected under Settings → Copilot → Miyo, which keeps its own index. Router One serves no embeddings endpoint and takes no part in that indexing. Excerpts found by Miyo or by an agent's file tools become part of the prompt sent to your selected model, so they count as input tokens in Logs. Copilot-hosted models and hosted Copilot Plus tools run on Brevilabs services under a Copilot license; this guide covers Quick Chat's Chat mode, which needs no Copilot license (Router One still bills each request), and opencode Agent Chat.

Which model ID should Copilot for Obsidian send?

Copy the exact model ID from /models, preserving case, hyphens, and version suffixes; do not substitute a display name. Open its detail page and match the supported API endpoints, context window, and capabilities such as tool calling to the provider and features selected in Copilot for Obsidian. A catalog listing does not mean the client can use every feature of that model. Give each client or application a dedicated API key with a maxSpend cap.

Which API protocol is Copilot for Obsidian using?

OpenAI-compatible describes an interface format; it does not make Chat Completions (/v1/chat/completions), Responses (/v1/responses), and Anthropic Messages (/v1/messages) interchangeable. Check the installed client version, provider configuration, and actual request path against the model detail page and API compatibility fact sheet. A successful plain-text chat does not establish support for hosted tools, conversation state, or file-editing features.

Verify the Copilot for Obsidian call in your request trace

Send a simple text request from Copilot for Obsidian, then match its trace in Dashboard → Logs by time, model, and request_id: tokens, cost, latency, and status. Next, test streaming, tool calls, and multi-turn history separately. For failures, retain the actual request path, full error message, and request_id. If there is no matching log, either the request never reached the gateway (client configuration or connectivity) or the gateway refused it before calling a model — a 401 for the key, a 402 for funds, a 429 from your key's or account's limits, or a 400 or 404 for the model ID or endpoint; a streamed request that failed before any output may have no log either. The status and error message the client received tell which, so check them before attributing the error to the gateway or upstream.

FAQ

Test shows Verified, but Quick Chat cannot send a message. What should I change?

Test and its badge only prove that GET /v1/models accepted the key through Obsidian's requestUrl; Quick Chat sends through a different transport. First open BYOK, choose More actions → Edit key on the Router One provider and check that Base URL is exactly https://api.router.one/v1 and that the model ID matches the catalog. If Quick Chat returns an HTTP status with a message, the transport works: read the message, and check that you did not enable an image-generation ID from the discovered list. If the request never shows up in Dashboard → Logs, something between Obsidian and Router One may be blocking the browser request: since 2026-10-02, api.router.one's preflight response allows the headers Quick Chat sends. In that case turn Enable CORS on, the fix Copilot's Model Sources page gives for this symptom (checked 2026-10-03); replies then arrive whole instead of streaming, and Stop no longer cancels the request. A Verified provider also does not prove that every model answers.

I set up Router One in Copilot 3 as a 3rd party (openai-format) model. Do I need to redo it?

Usually not. Copilot 4 has no Model tab. On first load it runs a one-time migration that copies each enabled 3rd party (openai-format) model with a base URL, together with its key and CORS choice, into a BYOK provider named OpenAI Format, one per distinct base URL, key and CORS setting, and enables it for Quick Chat and opencode. Disabled and embedding models are skipped, and the old settings are left in place. Open BYOK, confirm that the provider's Base URL is https://api.router.one/v1 and that its models are exact catalog IDs, then rename it and remove any ID that is no longer in /models. If the migrated provider has Enable CORS on, turn it off under More actions → Edit key to get streaming replies. If it shows No key, edit it and paste the key again.

Why is the Router One key missing on my phone or another computer?

Copilot stores BYOK keys in each device's Obsidian Keychain, not in the vault's data.json, so syncing the vault does not carry the key. On that device, open Settings → Copilot → BYOK and re-enter the key through More actions → Edit key, or add the provider there if it is not listed. The Keychain requires Obsidian 1.11.4 or newer; on older versions Advanced → API Key Storage shows Unavailable. On iOS and Android, Quick Chat, Quick Ask and Copilot Commands run (Agent Chat is desktop-only), and their model list is under Basic → Quick Chat models; those requests are sent from the device itself.

Quick Chat works with a model, but Agent Chat on opencode returns 400. Why?

They are different clients. Quick Chat sends model, messages and stream, while opencode builds its own requests and adds tools, tool_choice and other parameters of its own. Read which parameter or feature the error names. For tool errors, choose a model whose page on /models lists tool calling. An image-generation ID from the discovered list is not a chat model, so it fails in opencode: every chat model in the catalog is served on /v1/chat/completions, the only path opencode's generic provider uses.

Which models can Copilot for Obsidian use through the gateway?

Choose a current catalog model that supports both the endpoint and the features Copilot for Obsidian uses. Check /models and the model detail page for the exact ID, current rates, and capabilities; a family name such as GPT or Claude is not a compatibility guarantee. A client that lists a model has only read the ID, from its own configuration or from GET /v1/models; verify an actual request too.

Models are listed, but requests fail with 400 or 404. What should I check?

Record the actual request path and error message, then check the exact model ID. A 400 can indicate invalid parameters, unsupported tools, or a model/endpoint mismatch; a 404 can indicate an incorrect path or missing resource, so it does not by itself establish that a model was retired. If the error says must be called via, use the named endpoint or select a model supported on the current endpoint. Do not add or remove /v1 or /chat/completions across all clients indiscriminately.

Does this work from Mainland China?

Yes. The gateway is reachable from Mainland China without a VPN, and the configuration is identical to the global setup.

How do I debug a 401/402/403/429?

Start from what your client received: the status, the error body and the X-Request-ID header. A 401 (missing, unknown, revoked or expired key), a 402 (wallet balance, or the key's maxSpend cap) and a 429 from your key's or account's rate limits are refused before any model is called, so they never appear in Dashboard → Logs — nor does a 400 or 404 for a wrong model ID or endpoint. For 401, check that the full key is sent and still active in Dashboard → API Keys; for 402, top up or raise the key's maxSpend; for a 403, keep the full error body. For 429, back off and retry later; a 429 that does show up in Logs came back from upstream after the gateway's retries. Keep the request_id and follow the error-codes reference.