OpenRouter
OpenRouter is a gateway to hundreds of AI models, from Anthropic, Google, DeepSeek, Meta, Mistral and others, through one API key and one prepaid account. It is GrillMyCode's only supported provider, and the default, so ai_provider can be left out. The model is chosen with ai_model.
To create an account and key, see Get started: Set up an OpenRouter key. To choose a model and understand the cost, see Choosing a model and managing cost.
OpenRouter can't be reached with the built-in GITHUB_TOKEN. Every workflow must supply api_key, and the action fails immediately with a setup message if it is missing.
Upgrading a workflow that used GitHub Models? See Upgrade notes.
Inputs
| Input | Value |
|---|---|
api_key | ${{ secrets.OPENROUTER_API_KEY }}. Required |
ai_model | Any OpenRouter model ID, in provider/model-name format. Defaults to google/gemini-3.5-flash-lite. May end with a routing variant, such as :nitro |
ai_provider | openrouter, the default. May be left out |
ai_temperature | Randomness of the output, from 0.0 to 1.0. Default 0.5 |
ai_retry_max_attempts | Total attempts per request, including the first. Default 5 |
Model IDs must match OpenRouter's catalogue exactly; see openrouter.ai/models. For example: anthropic/claude-sonnet-5, openai/gpt-5-mini, meta-llama/llama-3.1-70b-instruct.
Recommended models
These have been tested with GrillMyCode and usually cost under one cent per assessment. They are the options pre-loaded in the Workflow Wizard.
| Model | ai_model |
|---|---|
| Google Gemini 3.5 Flash Lite (default) | google/gemini-3.5-flash-lite |
| DeepSeek V4 Flash | deepseek/deepseek-v4-flash |
| Minimax M2.7 | minimax/minimax-m2.7 |
| StepFun Step 3.7 Flash | stepfun/step-3.7-flash |
| Tencent Hy3 | tencent/hy3 |
| Xiaomi MiMo V2.5 Pro | xiaomi/mimo-v2.5-pro |
Of those tested, the default writes the most effective multiple-choice distractors, which is why it is the default. See Choosing a model and managing cost for notes on each. Any other model works too; check its price at openrouter.ai/models first, because costs vary by orders of magnitude.
Model routing variants
Most models on OpenRouter are served by several providers, which differ in speed and price for the same model. By default OpenRouter chooses among them for you, weighing price and recent reliability.
Appending a routing variant to the model ID tells it what to prioritize instead. The variant is part of the ai_model value — there is no separate input:
ai_model value | Effect | Reach for it when |
|---|---|---|
google/gemini-3.5-flash-lite | OpenRouter's default choice of provider | Almost always. Speed and cost are both reasonable |
google/gemini-3.5-flash-lite:nitro | Sorts providers by throughput (tokens per second) and allows their paid priority tier endpoints | The model's questions are good but assessments take an unreasonably long time to arrive. Review the model's pricing first — the fastest endpoints can cost more |
google/gemini-3.5-flash-lite:floor | Sorts providers by price and allows their discounted flex tier endpoints | Cost matters more than turnaround. Flex endpoints can be slower, or queue when busy |
- uses: NSCC-ITC-Assessment/GrillMyCode@v0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
api_key: ${{ secrets.OPENROUTER_API_KEY }}
ai_model: 'google/gemini-3.5-flash-lite:nitro'
Things worth knowing before you use one:
- The model does not change. A variant only changes which provider runs it, so the questions are generated by the same model and their quality is unaffected.
- Fallbacks still apply. If the first provider is unavailable, OpenRouter moves to the next one in the sorted order.
- Check pricing before using
:nitro. Billing follows the provider that actually served the request, so a priority-tier endpoint is billed at its own, higher rate — and the fastest provider is rarely the cheapest. Per-provider prices are on each model's page at openrouter.ai/models. The same applies in reverse to:floor: a request served on a flex tier is billed at the flex rate. - Try a different model before reaching for
:nitro. If assessments are slow and the questions are mediocre, another model is the better fix — see Recommended models.:nitrois for when the model is right and only the wait is wrong. - Models with a single provider are unaffected, because there is nothing to sort.
- One variant at a time.
:nitroand:floorare opposites; OpenRouter lets the last one in the ID win, but a workflow file should carry only one.
Variants are an OpenRouter feature. They live in the model ID rather than in a separate action input, so nothing changes for any other provider GrillMyCode might support later.
In the Workflow Wizard this is the Model routing setting on the AI step, which appends the suffix to the model you picked.
:::note Other suffixes
OpenRouter also has suffixes that select a different model entry rather than a different provider, such as :free. Those are outside what the Wizard offers, but ai_model accepts any model string OpenRouter does. See OpenRouter's model variants documentation.
:::
Retries and rate limits
A request is retried on 429 (rate limit), 500, 502, 503 and 504 responses, and on network failures, up to ai_retry_max_attempts attempts in total. The wait between attempts grows each time, and a Retry-After header on a 429 is honoured. No single wait is longer than 30 seconds.
Rate limits apply to the API key, so a whole class submitting at once shares one budget. Accounts with no credit are limited far more strictly than funded ones. If 429 errors persist, check the account's balance, raise ai_retry_max_attempts, or try a less busy model.
For the 404 "No endpoints available matching your guardrail restrictions and data policy" error, see Troubleshooting.
Example
- uses: NSCC-ITC-Assessment/GrillMyCode@v0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
api_key: ${{ secrets.OPENROUTER_API_KEY }}
ai_model: 'google/gemini-3.5-flash-lite'
Setting ai_provider: 'openrouter' explicitly is harmless but unnecessary.