Skip to main content

LLM plugin for models hosted by OpenRouter

Project description

llm-openrouter

PyPI Changelog Tests License

LLM plugin for models hosted by OpenRouter

Installation

First, install the LLM command-line utility.

Now install this plugin in the same environment as LLM.

llm install llm-openrouter

Configuration

You will need an API key from OpenRouter. You can obtain one here.

You can set that as an environment variable called OPENROUTER_KEY, or add it to the llm set of saved keys using:

llm keys set openrouter
Enter key: <paste key here>

Usage

To list available models, run:

llm models list

You should see a list that looks something like this:

OpenRouter: openrouter/openai/gpt-3.5-turbo
OpenRouter: openrouter/anthropic/claude-sonnet-4
OpenRouter: openrouter/meta-llama/llama-2-70b-chat
...

To run a prompt against a model, pass its full model ID to the -m option, like this:

llm -m openrouter/anthropic/claude-sonnet-4 "Five spooky names for a pet tarantula"

You can set a shorter alias for a model using the llm aliases command like so:

llm aliases set claude openrouter/anthropic/claude-sonnet-4

Now you can prompt Claude using:

cat llm_openrouter.py | llm -m claude -s 'write some pytest tests for this'

Images are supported too, for some models:

llm -m openrouter/anthropic/claude-3.5-sonnet 'describe this image' -a https://static.simonwillison.net/static/2024/pelicans.jpg
llm -m openrouter/anthropic/claude-3-haiku 'extract text' -a page.png

Vision models

Some OpenRouter models can accept image attachments. Run this command:

llm models --options -q openrouter

And look for models that list these attachment types:

  Attachment types:
    application/pdf, image/gif, image/jpeg, image/png, image/webp

You can feed these models images as URLs or file paths, for example:

llm -m openrouter/google/gemini-flash-1.5 'describe image' \
  -a https://static.simonwillison.net/static/2025/two-pelicans.jpg

Schemas

LLM includes support for schemas, allowing you to control the JSON structure of the output returned by the model.

Some of the models provided by OpenRouter are compatible with this feature, see their full list of structured output models for details.

llm-openrouter currently enables schema support for the models in that list. Models have varying levels of quality in their schema support, so test carefully rather than assuming all models will correctly work the same.

llm -m openrouter/google/gemini-flash-1.5 'invent 3 cool capybaras' \
  --schema-multi 'name,bio'

Output:

{
  "items": [
    {
      "bio": "Chill vibes only.  Spends most days floating on lily pads, occasionally accepting head scratches from passing frogs.",
      "name": "Professor Fluffernutter"
    },
    {
      "bio": "A thrill-seeker!  Capybara extraordinaire known for her daring escapes from the local zoo and impromptu skateboarding sessions.",
      "name": "Capybara-bara the Bold"
    },
    {
      "bio": "A renowned artist, creating masterpieces using mud, leaves, and her own surprisingly dexterous paws.",
      "name": "Michelangelo Capybara"
    }
  ]
}

Tools

Most OpenRouter models support tool calls. You can try that out like so:

llm -m openrouter/openai/gpt-5 \
  -T llm_version -T llm_time \
  "What version of LLM and what time is it?" \
  --tools-debug

Example output:

Tool call: llm_version({})
  0.27.1


Tool call: llm_time({})
  {
    "utc_time": "2025-09-20 23:35:53 UTC",
    "utc_time_iso": "2025-09-20T23:35:53.205247+00:00",
    "local_timezone": "PDT",
    "local_time": "2025-09-20 16:35:53",
    "timezone_offset": "UTC-7:00",
    "is_dst": true
  }

LLM version: 0.27.1
Current time: 2025-09-20 16:35:53 PDT (2025-09-20 23:35:53 UTC)

Reasoning

Some OpenRouter models such as GPT-5 support options for controlling reasoning:

  • -o reasoning_effort low|medium|high - control reasoning effort
  • -o reasoning_max_tokens 2048 - an alternative way of specifying effort for some models
  • -o reasoning_enabled true - use this to enable reasoning without setting an effort via one of the other two options

For example:

llm -m openrouter/openai/gpt-5 \
   'prove dogs exist' \
   -o reasoning_effort high

Provider routing

OpenRouter offers comprehensive options for controlling which underlying provider your request is routed to.

You can specify these using the OpenRouter JSON format, then pass that to LLM using the -o provider '{JSON goes here} option:

llm -m openrouter/meta-llama/llama-3.1-8b-instruct hi \
  -o provider '{"quantizations": ["fp8"]}'

This specifies that you would like only providers that support fp8 quantization for that model.

Incorporating search results from Exa

OpenRouter have a partnership with Exa where prompts through any supported model can be augmented with relevant search results from the Exa index - a form of RAG.

Enable this feature using the -o online 1 option:

llm -m openrouter/mistralai/mistral-small -o online 1 'key events on march 1st 2025'

Consult the OpenRouter documentation for current pricing.

Listing models

The llm models -q openrouter command will display all available models, or you can use this command to see more detailed JSON:

llm openrouter models

Output starts like this:

- id: latitudegames/wayfarer-large-70b-llama-3.3
  name: LatitueGames: Wayfarer Large 70B Llama 3.3
  context_length: 128,000
  architecture: text->text Llama3
  pricing: prompt $0.7/M, completion $0.7/M

- id: thedrummer/skyfall-36b-v2
  name: TheDrummer: Skyfall 36B V2
  context_length: 64,000
  architecture: text->text Other
  pricing: prompt $0.5/M, completion $0.5/M

- id: microsoft/phi-4-multimodal-instruct
  name: Microsoft: Phi 4 Multimodal Instruct
  context_length: 131,072
  architecture: text+image->text Other
  pricing: prompt $0.07/M, completion $0.14/M, image $0.2476/K

Add --json to get back JSON instead, which looks like this:

[
  {
    "id": "microsoft/phi-4-multimodal-instruct",
    "name": "Microsoft: Phi 4 Multimodal Instruct",
    "created": 1741396284,
    "description": "Phi-4 Multimodal Instruct is a versatile...",
    "context_length": 131072,
    "architecture": {
      "modality": "text+image->text",
      "tokenizer": "Other",
      "instruct_type": null
    },
    "pricing": {
      "prompt": "0.00000007",
      "completion": "0.00000014",
      "image": "0.0002476",
      "request": "0",
      "input_cache_read": "0",
      "input_cache_write": "0",
      "web_search": "0",
      "internal_reasoning": "0"
    },
    "top_provider": {
      "context_length": 131072,
      "max_completion_tokens": null,
      "is_moderated": false
    },
    "per_request_limits": null
  }

Add --free for a list of just the models that are available for free.

llm openrouter models --free

Information about your API key

The llm openrouter key command shows you information about your current API key, including rate limits:

llm openrouter key

Example output:

{
  "label": "sk-or-v1-0fa...240",
  "limit": null,
  "usage": 0.65017511,
  "limit_remaining": null,
  "is_free_tier": false,
  "rate_limit": {
    "requests": 40,
    "interval": "10s"
  }
}

This will default to inspecting the key you have set using llm keys set openrouter or using the OPENROUTER_KEY environment variable.

You can inspect a different key by passing the key itself - or the name of the key in the llm keys list - as the --key option:

llm openrouter key --key sk-xxx

Development

To set up this plugin locally, first checkout the code. Then create a new virtual environment:

cd llm-openrouter
python3 -m venv venv
source venv/bin/activate

Now install the dependencies and test dependencies:

llm install -e '.[test]'

To run the tests:

pytest

To update recordings and snapshots, run:

PYTEST_OPENROUTER_KEY="$(llm keys get openrouter)" \
  pytest --record-mode=rewrite --inline-snapshot=fix

If tests against additional models are added, update tests/models_persister.py to preserve those model ids in the recordings.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llm_openrouter-0.5.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llm_openrouter-0.5-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file llm_openrouter-0.5.tar.gz.

File metadata

  • Download URL: llm_openrouter-0.5.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for llm_openrouter-0.5.tar.gz
Algorithm Hash digest
SHA256 9edc30cb104ab482ab55cd6922715860405a2900e8b51190facf0b7747051a7b
MD5 411870631d41f413fff9d2910b103e3f
BLAKE2b-256 3d36bd3fd40317982b4405a855f236582ca5f7834f8bf42b004b328bb31514bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for llm_openrouter-0.5.tar.gz:

Publisher: publish.yml on simonw/llm-openrouter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file llm_openrouter-0.5-py3-none-any.whl.

File metadata

  • Download URL: llm_openrouter-0.5-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for llm_openrouter-0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 293b74486ccac3763706baeabde82886625503bd1d5f86ba09fda33016eda3c7
MD5 d89f3afe7dd160b2aec0aee67d545c34
BLAKE2b-256 c93c3f4cc507dfb3ef6639b5e25db22aee7a51372c461cfe7d4bccb4d4ac7e92

See more details on using hashes here.

Provenance

The following attestation bundles were made for llm_openrouter-0.5-py3-none-any.whl:

Publisher: publish.yml on simonw/llm-openrouter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page