Model providers
Which model providers ocra can use, what each needs, and how to use your own endpoint.
ocra runs its reviewers through OpenCode, so the providers in OpenCode's catalog work, apart from the few that need code from npm. Name a model as provider/model in the model chains (Configuration). The runtime receives only the credentials of the providers your chains name.
Providers in OpenCode's catalog
| Provider | Example model | What to set | Tested live |
|---|---|---|---|
| Gemini API | google/gemini-3.5-flash | GEMINI_API_KEY (or GOOGLE_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY) | Yes |
| Vertex AI | google-vertex/gemini-3.5-flash | GOOGLE_VERTEX_PROJECT, GOOGLE_VERTEX_LOCATION=global, and application default credentials or GOOGLE_APPLICATION_CREDENTIALS | Yes, also keyless from GitHub Actions through workload identity federation |
| Anthropic | anthropic/<model> | ANTHROPIC_API_KEY | No |
| OpenAI | openai/<model> | OPENAI_API_KEY | No |
| Amazon Bedrock | amazon-bedrock/<model> | AWS_REGION and AWS credentials: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (with AWS_SESSION_TOKEN), AWS_PROFILE, or AWS_BEARER_TOKEN_BEDROCK | No |
| Azure OpenAI | azure/<deployment> | AZURE_API_KEY, AZURE_RESOURCE_NAME | No |
| DeepSeek, OpenRouter, Groq, Mistral, xAI and the rest of the catalog | deepseek/<model> | The provider's key, such as DEEPSEEK_API_KEY; for an id ocra does not know, every variable starting with it, such as GROQ_ | No |
"No" means that ocra passes the provider its variables and OpenCode does the rest, but no review has run through that provider yet. If one fails, open an issue. Model ids come from OpenCode's catalog, models.dev.
Providers that need code from npm
OpenCode ships the code for talking to almost every provider in its catalog. For a few it would download that code from npm the first time a model is used, and ocra does not let anything be downloaded during a review. In the catalog of 2026-09-29 these are aihubmix, cloudflare-ai-gateway, merge-gateway, qvac, salad-cloud, sap-ai-core and watsonx. Their models fail at once with "Failed to initialize provider". If such a service offers an endpoint that speaks the OpenAI API, declare it as your own endpoint.
Your own endpoint
A self-hosted server (vLLM, Ollama, LM Studio) or a company gateway that speaks the OpenAI API is declared in .ocra/config.json:
{
"models": {
"standard": "gateway/qwen3-coder",
"light": "gateway/qwen3-small",
"top": "gateway/qwen3-max"
},
"providers": {
"gateway": {
"type": "openai-compatible",
"baseUrl": "https://llm.example.com/v1",
"apiKeyEnv": "GATEWAY_API_KEY",
"models": {
"qwen3-coder": { "input": 0.5, "output": 2, "cachedInput": 0.1 },
"qwen3-small": { "input": 0.1, "output": 0.4 },
"qwen3-max": { "input": 2, "output": 8 }
}
}
}
}- The id (
gateway) is yours: lowercase letters, digits and hyphens. Pick one OpenCode's catalog does not use, since a declared provider replaces a known one of the same id for the run. baseUrlmust behttps, or plainhttpon this machine:localhost,127.0.0.1or::1. For Ollama, for example,http://127.0.0.1:11434/v1. It may not contain{or}, which OpenCode would replace with a variable or a file's content.apiKeyEnvis the name of the variable that holds the key. The key never goes in the file, and only this variable reaches the runtime. Names of platform tokens and cloud credentials (starting withGITHUB_,GITLAB_,CI_,AWS_,AZURE_and similar) are refused. Leave it out for a server without keys.effort(optional) says how the endpoint takes a reasoning effort from thedirectruntime:openaisendsreasoning_effort(the default, which OpenAI, the Gemini API's OpenAI-compatible endpoint and OpenRouter accept),openroutersendsreasoning: { effort }.- Every model has a price in US dollars per million tokens:
input,output, and optionallycachedInput. ocra uses them for the reported cost and for--max-cost-usd. A price of 0 is allowed, for a server on your own hardware; the run then warns that the model is unpriced and that the spend limit does not count it. - A shared configuration named by
extendsmay declare providers too, but only when it is pinned with#sha256=: unpinned, whoever serves the file could send your code to an endpoint of their choosing. ocra ignores an unpinned file that declares providers, with a warning that gives the pin to add once you have checked the file. The repository's declaration of the same id wins. In pull and merge requests, providers come from the base commit, like the rest of the configuration.
This has been tested in CI against a fake OpenAI-compatible server with the real OpenCode binary: the key goes where it should, the price is counted, and nothing else on the network is needed. Against a live server it has run on OpenRouter (the free model below, 2026-10-02): the key reached it, tool calls worked, and the price of 0 was reported.
Free models through OpenRouter
A model offered at no charge, such as a stealth preview on OpenRouter, is used like any OpenAI-compatible endpoint: declare the endpoint with a price of 0 for the model, under the id OpenRouter lists it by, and name it as <endpoint id>/<model id>:
{
"models": {
"top": "router/stealth/space-bunny-alpha",
"standard": "router/stealth/space-bunny-alpha",
"light": "router/stealth/space-bunny-alpha"
},
"providers": {
"router": {
"type": "openai-compatible",
"baseUrl": "https://openrouter.ai/api/v1",
"apiKeyEnv": "OPENROUTER_API_KEY",
"models": { "stealth/space-bunny-alpha": { "input": 0, "output": 0 } }
}
}
}- A price of 0 is taken literally: the run warns that the model's tokens are not counted by
--max-cost-usd, and reports a cost of $0, which is what the preview costs; tokens are still reported. - Keep the file outside the reviewed repository and pass it with
--configwhen the review runs with--no-repo-config, as the evaluation harness does. - The evaluation's judge can use the same endpoint:
JUDGE_API_KEY,JUDGE_BASE_URL=https://openrouter.ai/api/v1andJUDGE_MODEL=stealth/space-bunny-alpha. - A preview is a preview: the model, its limits and its price can change without notice, and an anonymous model says nothing about what it keeps. Use it to evaluate, not on code you must keep private.
The model id is the one OpenRouter's API example showed on 2026-10-02 (stealth/space-bunny-alpha); check the model's page, since a preview can move. The declared-endpoint path works without OpenCode's pricing catalog; the catalog form, openrouter/<model>, needs the catalog reachable and the model in it, and fails at once otherwise. Reviews have run through OpenRouter this way since 2026-10-02.
Choosing the runtime
Two runtimes can run the reviewers; runtime in the configuration picks one:
| Runtime | Reaches | Use it when |
|---|---|---|
opencode (default) | Every provider in OpenCode's catalog and your declared endpoints, plus the pricing catalog models.opencode.ai | Your models are Gemini, Vertex AI, Anthropic, Bedrock or another catalog provider |
direct | Only the endpoints declared under providers; nothing else on the network | Every model in your chains is on a declared endpoint, and you want nothing but that endpoint reached |
Both run the same review: the same tools, the same step cap, the same failback over the chain, the same prices. The direct runtime refuses a chain that names a provider you did not declare, and says so before any request. Behind a proxy it reads HTTP_PROXY, HTTPS_PROXY and NO_PROXY like the rest of ocra. The quality numbers on the quality page were measured through opencode; the direct runtime passes the same conformance tests but has not been evaluated on the golden set yet.
The opencode runtime is an optional dependency of the CLI, installed by default. With direct, you can install ocra without it, about 165 MB less: see Without OpenCode, and the input opencode: false in the GitHub Action.
What else reaches the network
Besides the model providers, OpenCode fetches its pricing catalog from models.opencode.ai when it starts. It also tries to install its own plugin package from npm then, and the code for a provider it does not ship when a model needs it; ocra sends both installs to a registry on your machine that refuses them at once. With every address but a declared endpoint refused, a review works (tested). Where outside access is blocked, the catalog fetch fails, OpenCode uses the catalog it ships with, and a model missing from that catalog has no price: the run then warns that its calls are not counted.