
# Frameworks

Every framework on this page has an OpenAI-compatible client, so
LowRouter plugs in with a base URL, a key and a model ID. The code
snippets below are re-run every week against the versions named in
each section.

All of them read the key from the environment:

```bash
export LOWROUTER_API_KEY=sk-lr-...
```

## LangChain (Python)

Verified with `langchain-openai` **1.6.6**.

```bash
pip install langchain-openai
```

`ChatOpenAI` takes the base URL directly. Tool binding works as it
does against OpenAI:

<!-- verify: frameworks-langchain -->
```python
import os
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool

llm = ChatOpenAI(
    model="auto/mistralai/mistral-large-2512",
    base_url="https://api.lowrouter.ai/v1",
    api_key=os.environ["LOWROUTER_API_KEY"],
)

@tool
def get_weather(city: str) -> str:
    """Return the current weather for a city."""
    return f"Sunny in {city}"

msg = llm.bind_tools([get_weather]).invoke("What is the weather in Lyon?")
print(msg.tool_calls)
```

This sends Chat Completions requests. LangChain switches to the
Responses API when you set `use_responses_api=True` or use a feature
that needs it; LowRouter serves both endpoints.

`lowrouter_metadata` is **not** reachable through `msg.response_metadata`:
`langchain-openai` copies a fixed set of keys off the response and drops
unknown top-level ones. To read the per-request record (route, region,
energy, carbon), take `msg.id` (the completion id) and fetch
`GET /v1/generation/{id}` with the same key; see
[per-request metadata](../models/per-request-metadata).

## LlamaIndex

Verified with `llama-index-llms-openai-like` **0.8.0**.

```bash
pip install llama-index-llms-openai-like
```

Use `OpenAILike`. LlamaIndex's plain `OpenAI` class checks model
names against OpenAI's own list and rejects LowRouter IDs.

<!-- verify: frameworks-llamaindex -->
```python
import os
from llama_index.llms.openai_like import OpenAILike

llm = OpenAILike(
    model="auto/mistralai/mistral-large-2512",
    api_base="https://api.lowrouter.ai/v1",
    api_key=os.environ["LOWROUTER_API_KEY"],
    is_chat_model=True,
    is_function_calling_model=True,
    context_window=256000,
)

print(llm.complete("In one sentence, what is a vector database?"))
```

`OpenAILike` knows nothing about the model, so tell it.
`is_chat_model` defaults to false, which sends requests to the legacy
`/completions` endpoint; set it to true for Chat Completions.
`is_function_calling_model=True` lets agents use tools.
`context_window` defaults to 3,900 tokens; set the model's real
window from the [model browser](/models).

## CrewAI

Verified with `crewai` **1.15.23**.

```bash
pip install crewai
```

<!-- verify: frameworks-crewai -->
```python
import os
from crewai import LLM

llm = LLM(
    model="openai/auto/mistralai/mistral-large-2512",
    base_url="https://api.lowrouter.ai/v1",
    api_key=os.environ["LOWROUTER_API_KEY"],
)

print(llm.call("In one sentence, what is a vector database?"))
```

The `openai/` prefix selects CrewAI's OpenAI-compatible client, which
strips it and sends the rest of the ID unchanged. Without the prefix
CrewAI reads `auto` as a provider name, falls back to LiteLLM and
fails unless LiteLLM is installed. Pass the `LLM` to each `Agent` with
`llm=llm`.

## Vercel AI SDK

Verified with `ai` **7.0.122** and `@ai-sdk/openai-compatible`
**3.0.59**.

```bash
npm install ai @ai-sdk/openai-compatible
```

<!-- verify: frameworks-ai-sdk -->
```ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText } from "ai";

const lowrouter = createOpenAICompatible({
  name: "lowrouter",
  baseURL: "https://api.lowrouter.ai/v1",
  apiKey: process.env.LOWROUTER_API_KEY,
});

const { text } = await generateText({
  model: lowrouter("auto/mistralai/mistral-large-2512"),
  prompt: "In one sentence, what is a vector database?",
});
console.log(text);
```

This uses `@ai-sdk/openai-compatible`, which calls Chat Completions
with whatever model ID you give it. The `@ai-sdk/openai` provider
sends requests to the Responses API by default; LowRouter serves that
endpoint too, but the compatible provider is the one checked weekly.

The compatible provider keeps unknown top-level response fields under
`providerMetadata`, keyed by the `name` you passed to
`createOpenAICompatible`. With `name: "lowrouter"` as above,
`lowrouter_metadata` is at `providerMetadata.lowrouter.lowrouter_metadata`
on the `generateText` result (and on the final `finish` part of
`streamText`).

## n8n

n8n's OpenAI credential has a **Base URL** field. Create an OpenAI
credential with Base URL `https://api.lowrouter.ai/v1` and your
`sk-lr-...` key, then use it in an **OpenAI Chat Model** node and
pick or type a LowRouter model ID. The node loads its model list from
LowRouter.

Recent versions of the node call the Responses API by default (the
**Use Responses API** option). LowRouter serves both endpoints; turn
the option off to use Chat Completions. n8n is a GUI, so this section
is not re-run by the weekly check.

## Picking a model

Any LowRouter model ID works in these snippets. For agents and tool
use, pick one with the *function-calling* tag; [the model browser
filtered to them](/models?function_calling=yes) lists every one.
