using-openrouter
Helper for calling OpenRouter models with strict JSON enforcement, cost accounting, and model pinning.
Install
mkdir -p .claude/skills/using-openrouter && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/19062" && unzip -o skill.zip -d .claude/skills/using-openrouter && rm skill.zipInstalls to .claude/skills/using-openrouter
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
How to call OpenRouter correctly from this CV app (Python, OpenAI SDK) — strict JSON-schema generation, provider pinning, reasoning control, cost accounting, and the verified model slugs. Use this skill WHENEVER you call OpenRouter here: generating CVs, judging JD coverage, or clustering jobs via qwen3-235b, qwen3.7-max, deepseek-v4-pro, or gpt-5.1; whenever you need guaranteed strict JSON, temperature-0 determinism, reasoning/thinking control, or per-call cost on OpenRouter; and for the model-migration / A-B work. Trigger even if the user just says "use OpenRouter", "call qwen/deepseek", "route via openrouter", or mentions OPENROUTER_API_KEY — don't hand-roll the request, use the helper here.Key capabilities
- →Generate strict JSON responses from OpenRouter models
- →Control model provider routing for specific parameters
- →Manage cost accounting for OpenRouter API calls
- →Disable reasoning for JSON generation calls
- →Repair malformed JSON syntax in responses
- →Handle model-specific quirks like temperature rejection
How it works
The skill uses a helper script to call OpenRouter via the OpenAI SDK, enforcing parameter pinning, disabling reasoning, and enabling response healing for JSON output.
Inputs & outputs
When to use using-openrouter
- →Generating JSON responses
- →Switching between AI models
- →Tracking API usage costs
About this skill
Using OpenRouter (for this CV app)
OpenRouter gives one prepaid balance + one OpenAI-compatible key for ~every model.
You call it with the official openai SDK by swapping base_url. The whole reason
this skill exists is that one default behavior will silently break us, plus a few
model-specific quirks. Internalize the four rules below and use the bundled helper.
scripts/or_client.py encodes all of this — import it, don't re-derive it.
references/openrouter-reference.md has the exhaustive, sourced facts + per-provider
tables. Read it when a detail here isn't enough or when slugs/providers need re-verifying.
The four rules that matter
-
Always pin
require_parametersfor any JSON call. By default OpenRouter may route your request to a provider that doesn't supportresponse_formatand will silently ignore your schema — you get HTTP 200 with free-form prose, no error. The fix isextra_body={"provider": {"require_parameters": True}}, which routes only to providers that honor every parameter you sent. This is non-negotiable fordeepseek-v4-pro(its cheapest/default endpoint, DeepSeek's own, does not enforce strict schema). -
gpt-5.1rejects a customtemperature. Same quirk as on OpenAI direct (the GPT-5 family). Sendtemperatureonly to Qwen/DeepSeek; forgpt-5.1rely on schema + seed. -
Turn reasoning OFF for JSON/judging calls.
qwen3.7-maxanddeepseek-v4-proare reasoning-capable. Thinking tokens are billed as output, add latency/nondeterminism, and some providers drop or leak them underjson_schema. Sendextra_body={"reasoning": {"enabled": False, "exclude": True}}.qwen3-235b-a22b-2507is the non-thinking Instruct variant — cleanest for deterministic temp-0 judging. -
Non-streaming + Response Healing for reliability. Use
stream=Falseso OpenRouter's freeplugins:[{"id":"response-healing"}]can repair malformed JSON syntax (Qwen/DeepSeek emit invalid JSON a few % of the time; healing takes Qwen3-235B ~88% → ~99.98% valid). Healing fixes syntax, not schema adherence — always still validate the parsed dict and fail closed.
Verified model slugs (2026-06-17 — re-verify before long-term reliance)
| Purpose | Slug | Notes |
|---|---|---|
| CV gen (incumbent / quality bar) | openai/gpt-5.1 | native strict SO; no temperature; $1.25/$10 |
| CV gen (cheap flagship) | qwen/qwen3.7-max | $1.25/$3.75; single provider (alibaba) = no failover; reasoning-capable |
| CV gen (cheapest flagship) | deepseek/deepseek-v4-pro | ~$0.44/$0.87; native endpoint not strict — pinning mandatory |
| group + match (judge) | qwen/qwen3-235b-a22b-2507 | ~$0.09/$0.10; non-thinking; accepts temp=0 + seed |
Slugs/providers drift. Confirm with strict_providers(slug) (in the helper) or
GET /api/v1/models/{slug}/endpoints before trusting a provider list.
The canonical call (use the helper)
from scripts.or_client import or_client, chat_json, MODELS, STRICT_PROVIDERS
client = or_client() # OpenAI SDK pointed at OpenRouter, key from .env
# Strict CV generation (reasoning off, provider pinned, healing on, cost returned):
cv, meta = chat_json(
client, MODELS["deepseek-v4-pro"],
messages=[{"role": "system", "content": system_prompt},
{"role": "user", "content": jobs_xml}],
schema=cv_schema, schema_name="tailored_cv",
pin_providers=STRICT_PROVIDERS["deepseek/deepseek-v4-pro"], # belt-and-suspenders
)
print(meta["served_by"], meta["cost_usd"])
# Deterministic temp-0 judge (non-thinking model, temp honored):
verdict, meta = chat_json(
client, MODELS["qwen3-235b"],
messages=judge_msgs, schema=judge_schema, schema_name="coverage",
temperature=0, seed=7,
)
chat_json already: sets require_parameters, disables reasoning, enables healing, omits
temperature for gpt-5.*, strips stray ```json fences, json.loads (raises on
bad output — fail closed), and pulls cost/tokens from resp.model_dump()["usage"].
Strict-schema requirements (our build_cv_schema already complies)
Strict mode = every object has additionalProperties: false, every property is in
required, optional fields are nullable unions ({"type": ["array", "null"]}), and
constraint keywords (pattern, min/maxLength, format, default, …) are stripped/ignored.
server/cv_schema.py:build_cv_schema already follows this exactly — reuse it, don't rewrite.
Cost, credits, errors (details in the reference)
- Cost is auto-returned:
resp.model_dump()["usage"]["cost"](USD; the typed.usage.costmay be absent). Ground truth:GET /api/v1/generation?id=<id>(retry on 404 — written async). - Check balance before a batch:
check_key()in the helper (GET /api/v1/key). - Retry
408/429/502/503/504; never retry402(no credits) or403(guardrail).require_parameters+ too many filters →503(no eligible provider) — loosen a filter.
When to read the reference
references/openrouter-reference.md — per-provider strict-SO tables for each model, the full
reasoning/billing model, prompt-caching specifics, privacy/data controls, the complete error
table, and every source URL. Go there before changing provider pins or debugging a routing/
schema/temperature surprise.
When not to use it
- →When not calling OpenRouter
- →When not needing guaranteed strict JSON
- →When not needing per-call cost on OpenRouter
Prerequisites
Limitations
- →The `gpt-5.1` model rejects a custom `temperature` parameter.
- →Response healing fixes JSON syntax, not schema adherence.
- →Some providers may drop or leak thinking tokens under `json_schema`.
How it compares
This workflow prevents silent schema breakage and handles model-specific quirks, unlike a direct, unmanaged OpenRouter API call.
Compared to similar skills
using-openrouter side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| using-openrouter (this skill) | 0 | 17d | Review | Intermediate |
| openai-knowledge | 5 | 4mo | No flags | Intermediate |
| openrouter-function-calling | 5 | 10d | Review | Intermediate |
| openrouter-hello-world | 7 | 10d | Caution | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
openai-knowledge
openai
Use when working with the OpenAI API (Responses API) or OpenAI platform features (tools, streaming, Realtime API, auth, models, rate limits, MCP) and you need authoritative, up-to-date documentation (schemas, examples, limits, edge cases). Prefer the OpenAI Developer Documentation MCP server tools when available; otherwise guide the user to enable `openaiDeveloperDocs`.
openrouter-function-calling
jeremylongshore
Implement function/tool calling with OpenRouter models. Use when building agents or structured outputs. Trigger with phrases like 'openrouter functions', 'openrouter tools', 'openrouter agent', 'function calling'.
openrouter-hello-world
jeremylongshore
Create your first OpenRouter API request with a simple example. Use when learning OpenRouter or testing your setup. Trigger with phrases like 'openrouter hello world', 'openrouter first request', 'openrouter quickstart', 'test openrouter'.
openrouter-openai-compat
jeremylongshore
Configure OpenRouter as an OpenAI API drop-in replacement. Use when migrating from OpenAI or using OpenAI-compatible libraries. Trigger with phrases like 'openrouter openai', 'openrouter drop-in', 'openrouter compatibility', 'migrate to openrouter'.
gemini-openai-api
Project-N-E-K-O
Gemini 模型通过 OpenAI 兼容 API 接入指南。包含:(1) 辅助 API 配置(summary/correction/emotion/vision),(2) extra_body 格式用于控制 thinking,(3) 响应格式处理(markdown 代码块)。当需要将 Gemini 作为辅助模型接入、配置 thinking 参数、或处理 Gemini API 返回格式时使用。
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.