Skip to main content
Version: v0 (current)

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.

An API key is required

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​

InputValue
api_key${{ secrets.OPENROUTER_API_KEY }}. Required
ai_modelAny 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_provideropenrouter, the default. May be left out
ai_temperatureRandomness of the output, from 0.0 to 1.0. Default 0.5
ai_retry_max_attemptsTotal 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.

These have been tested with GrillMyCode and usually cost under one cent per assessment. They are the options pre-loaded in the Workflow Wizard.

Modelai_model
Google Gemini 3.5 Flash Lite (default)google/gemini-3.5-flash-lite
DeepSeek V4 Flashdeepseek/deepseek-v4-flash
Minimax M2.7minimax/minimax-m2.7
StepFun Step 3.7 Flashstepfun/step-3.7-flash
Tencent Hy3tencent/hy3
Xiaomi MiMo V2.5 Proxiaomi/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 valueEffectReach for it when
google/gemini-3.5-flash-liteOpenRouter's default choice of providerAlmost always. Speed and cost are both reasonable
google/gemini-3.5-flash-lite:nitroSorts providers by throughput (tokens per second) and allows their paid priority tier endpointsThe 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:floorSorts providers by price and allows their discounted flex tier endpointsCost 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. :nitro is 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. :nitro and :floor are 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.