n4nAI

Competitor comparisons

How-to

Moving your OpenCode setup from OpenRouter to n4n

A practical walkthrough to move OpenCode from OpenRouter to n4n: rewrite config, remap model IDs, test requests, and verify usage metering and fallback.

n4n Team4 min read959 words

Audio narration

Coming soon — every post will get a voice note here.

If you’re running OpenCode against OpenRouter and want to move OpenCode from OpenRouter to n4n, the migration is mostly a base-URL and model-name swap. OpenCode speaks the OpenAI chat completions protocol, and n4n.ai exposes a single OpenAI-compatible endpoint that fronts 240+ models, so the client code doesn’t change—only the configuration does. This guide walks through the exact file edits, environment changes, and verification steps to cut over without losing your session history.

Step 1: Locate your current OpenRouter configuration

OpenCode loads provider settings from a JSON file. For a global install it’s usually ~/.config/opencode/opencode.json; for a project-scoped setup it’s ./opencode.json in the repo root. Find it:

find ~ -name "opencode.json" 2>/dev/null
find . -name "opencode.json" 2>/dev/null

A typical OpenRouter-backed config looks like this:

{
  "providers": {
    "openrouter": {
      "base_url": "https://openrouter.ai/api/v1",
      "api_key": "sk-or-v1-xxxxxxxx",
      "models": ["openai/gpt-4o", "anthropic/claude-3.5-sonnet"]
    }
  },
  "agents": {
    "default": { "provider": "openrouter", "model": "openai/gpt-4o" },
    "review": { "provider": "openrouter", "model": "anthropic/claude-3.5-sonnet" }
  }
}

When you move OpenCode from OpenRouter to n4n, this file is the only artifact you must edit. Your conversation transcripts, tool definitions, and agent prompts stay intact because they reference provider names, not URLs.

Step 2: Back up the existing configuration

Before mutating anything, copy the file with a timestamp:

cp ~/.config/opencode/opencode.json \
   ~/.config/opencode/opencode.json.bak-$(date +%s)

Verify the backup is valid JSON:

jq empty ~/.config/opencode/opencode.json.bak-* 2>/dev/null && echo "backup OK"

If something goes wrong during the cutover, mv the backup back into place. Keep it for at least a week of real usage.

Step 3: Swap the provider base URL and API key

The core of the move OpenCode from OpenRouter to n4n is replacing the base_url and pointing the API key at your n4n credential. Store the key in an environment variable to avoid plaintext secrets in the config:

{
  "providers": {
    "n4n": {
      "base_url": "https://api.n4n.ai/v1",
      "api_key_env": "N4N_API_KEY",
      "models": ["openai/gpt-4o", "anthropic/claude-3.5-sonnet"]
    }
  },
  "agents": {
    "default": { "provider": "n4n", "model": "openai/gpt-4o" },
    "review": { "provider": "n4n", "model": "anthropic/claude-3.5-sonnet" }
  }
}

Export the key in your shell profile (~/.bashrc or ~/.zshrc):

export N4N_API_KEY="sk-n4n-xxxxxxxx"

If your OpenCode build doesn’t support api_key_env, use "api_key": "${N4N_API_KEY}" and run the config through envsubst before launch, or use the opencode secret set command if available. The important change is that every agent now points at the n4n provider block.

Step 4: Remap model identifiers

OpenRouter prefixes model IDs with the vendor (openai/, anthropic/). n4n passes model strings through to upstream providers, so the same IDs usually work. But verify against the live model list to avoid 404s:

curl -s https://api.n4n.ai/v1/models \
  -H "Authorization: Bearer $N4N_API_KEY" | jq -r '.data[].id' | grep -E "gpt-4o|claude-3.5"

If a slug differs (e.g. claude-3.5-sonnet vs anthropic/claude-3.5-sonnet-20240620), update both the models array and each agent’s model field. A small Python script can rewrite all agent references in one pass:

import json, os
path = os.path.expanduser("~/.config/opencode/opencode.json")
cfg = json.load(open(path))
# rename provider block
cfg["providers"]["n4n"] = cfg["providers"].pop("openrouter")
cfg["providers"]["n4n"]["base_url"] = "https://api.n4n.ai/v1"
cfg["providers"]["n4n"]["api_key_env"] = "N4N_API_KEY"
# point every agent at the new provider
for agent in cfg.get("agents", {}).values():
    if agent.get("provider") == "openrouter":
        agent["provider"] = "n4n"
json.dump(cfg, open(path, "w"), indent=2)
print("rewritten")

Run this only after you’ve manually confirmed the correct model IDs from the curl output above.

Step 5: Set routing directives and cache-control headers

n4n honors client routing directives and forwards provider cache-control hints. If you want to pin a request to a specific upstream region or mark it ephemeral, pass headers at the provider level. OpenCode allows arbitrary headers per provider:

{
  "providers": {
    "n4n": {
      "base_url": "https://api.n4n.ai/v1",
      "api_key_env": "N4N_API_KEY",
      "headers": {
        "Cache-Control": "ephemeral",
        "X-N4N-Route": "aws-us-east-1"
      },
      "models": ["openai/gpt-4o"]
    }
  }
}

This is useful when you need to prevent prompt caching for sensitive diffs or force a specific backbone. The gateway forwards Cache-Control to the backing provider when that provider supports it, so you get the same cache semantics without client-side branching.

Step 6: Test a minimal completion

Don’t launch a full coding session yet. Send a single message through raw HTTP to validate credentials and model routing:

curl -s https://api.n4n.ai/v1/chat/completions \
  -H "Authorization: Bearer $N4N_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Reply with the word OK."}],
    "max_tokens": 5
  }' | jq '.choices[0].message.content'

Expected output: "OK". A 401 means the env var isn’t exported in the shell running the command. A 404 means the model slug is wrong—return to Step 4.

Then exercise OpenCode’s own client:

opencode --provider n4n --model openai/gpt-4o
> summarize the README in one sentence

If the agent returns a summary, the transport and auth are correct.

Step 7: Verify automatic fallback behavior

One reason to move OpenCode from OpenRouter to n4n is the gateway’s automatic fallback when a provider is rate-limited or degraded. You don’t configure this; it’s built into the endpoint. To confirm it’s active, request a model under artificial load or temporarily set a tiny quota in your n4n dashboard. Instead of a hard 429, the endpoint should serve from a secondary upstream if the model family exists there.

Inspect the response header to see which backend served the token:

curl -s -D - https://api.n4n.ai/v1/chat/completions \
  -H "Authorization: Bearer $N4N_API_KEY" \
  -d '{"model":"openai/gpt-4o","messages":[{"role":"user","content":"hi"}]}' \
  -o /dev/null | grep -i "x-n4n-upstream"

If the header shows a fallback region or alternate vendor, the cutover gives you resilience without extra code.

Step 8: Confirm per-token usage metering

After you move OpenCode from OpenRouter to n4n, confirm responses include accurate token counts. The OpenAI-compatible response carries a usage object:

{
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 3,
    "total_tokens": 15
  }
}

n4n meters per token on this basis, so your quotas align with what the model actually processed. In OpenCode, enable debug logging to inspect the raw response:

opencode --debug --provider n4n 2>&1 | grep -A4 '"usage"'

You should see total_tokens populated on every turn. If it’s zero or missing, your OpenCode version may be stripping it—upgrade to a build that passes the full response through.

Step 9: Remove OpenRouter references and verify success

Grep your config and environment for leftover OpenRouter strings:

grep -ri "openrouter" ~/.config/opencode/ 2>/dev/null
env | grep -i "OPENROUTER"

If anything remains, delete or unset it. Then run a real task—edit a file, run a test, apply a patch—inside OpenCode for at least ten minutes. Check that:

  • Model responses are low-latency and correctly formatted.
  • No 429s appear in debug logs.
  • usage.total_tokens increments per request.
  • The backup file is untouched.

That’s the whole cutover. The move OpenCode from OpenRouter to n4n took nine steps, most of which were verification. Your agent now talks to a single endpoint that covers the same model catalog with built-in fallback and token metering.

Migrating multiple agents and teams

If you run OpenCode in CI or across a team, encode the config in a version-controlled opencode.json and inject N4N_API_KEY via your secrets manager. Do not commit the key. For monorepos with per-directory agents, repeat Step 4’s Python rewrite for each nested config:

find . -name "opencode.json" -exec python rewrite_provider.py {} \;

Where rewrite_provider.py contains the logic from Step 4 parameterized by path.

Troubleshooting notes

  • SSL errors: If you use a corporate proxy, set HTTPS_PROXY for the OpenCode process, not just the interactive shell.
  • Model not found: Some vendors require version dates (e.g. claude-3.5-sonnet-20240620). Pull the full list from /v1/models and copy the string verbatim.
  • Header conflicts: OpenCode already sends Authorization. Only add routing or cache keys in the headers block.
  • Latency spikes: Use the X-N4N-Route header from Step 5 to pin a region close to your deployment.

Keep the .bak file for a week, then delete it. You’re done.

Tagsopencodeopenroutermigration

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →