AIREITER

Configuração do LangChain com OpenRouter: URLs base, ferramentas e soluções

Última Atualização: 2026-08-28 03:58:34

Em aplicações novas com LangChain, use ChatOpenRouter. Mantenha ChatOpenAI com https://openrouter.ai/api/v1 em projetos antigos que não podem ser atualizados e use https://openrouter.ai/api apenas no caminho do Anthropic Agent SDK.

Resposta rápida: prefira a integração nativa em projetos novos com LangChain

O OpenRouter fornece o endpoint dos modelos e a camada de roteamento; o LangChain oferece as abstrações de modelos de chat, chains e agentes. Hoje, a combinação nativa é langchain-openrouter com ChatOpenRouter em Python, ou @langchain/openrouter com ChatOpenRouter em JavaScript e TypeScript.

Sua situaçãoCaminho recomendadoPrincipal motivo
Aplicação nova em Python com LangChainlangchain-openrouter + ChatOpenRouterExpõe os controles de roteamento do provedor, metadados, raciocínio, ferramentas e saída estruturada
Aplicação nova em JS/TS com LangChain@langchain/openrouter + ChatOpenRouterMantém as interfaces nativas de mensagens, streaming e ferramentas do LangChain
Aplicação antiga existente com LangChainChatOpenAI + base_url="https://openrouter.ai/api/v1"É a menor mudança para manter a compatibilidade
Aplicação existente usando init_chat_modelLangChain v1 com langchain-openrouterHabilita o caminho de despacho com model_provider="openrouter"
Aplicação com Claude/Anthropic Agent SDKANTHROPIC_BASE_URL="https://openrouter.ai/api"O Agent SDK usa a rota compatível com Anthropic
Aplicação Next.js usando Vercel AI SDK@openrouter/ai-sdk-provider + createOpenRouter()Usa as abstrações streamText() e de ferramentas do AI SDK

O anúncio do pacote oficial do LangChain afirma que o pacote nativo preserva comportamentos específicos do OpenRouter que um wrapper genérico de ChatOpenAI pode perder, como conteúdo de raciocínio, saída estruturada, metadados de roteamento e identidade de tracing. Se esses campos não forem importantes para o projeto, uma configuração de compatibilidade já existente não precisa ser reescrita imediatamente.

Comece pelo mapa de endpoints, não pelo nome do framework

Diferentes SDKs acrescentam caminhos de requisição distintos à URL base. A rota compatível com OpenAI é https://openrouter.ai/api/v1; o guia do OpenRouter para o OpenAI SDK usa esse valor. Já o guia do Anthropic Agent SDK define ANTHROPIC_BASE_URL como https://openrouter.ai/api.

Cliente ou SDKURL base a configurarFamília típica de requisições
OpenAI Python/JS SDKhttps://openrouter.ai/api/v1OpenAI Chat Completions
LangChain legado ChatOpenAIhttps://openrouter.ai/api/v1Chamadas de chat compatíveis com OpenAI
LangChain ChatOpenRouterNormalmente, nenhuma URL base personalizadaIntegração nativa com OpenRouter
Provedor OpenRouter do Vercel AI SDKNormalmente, nenhuma URL base personalizadaO pacote do provedor gerencia o endpoint
Anthropic Agent SDKhttps://openrouter.ai/apiChamadas do Agent SDK compatíveis com Anthropic

Não coloque /chat/completions na URL base de um SDK, a menos que ele peça explicitamente um endpoint completo. Se o erro mostrar um caminho duplicado, como /v1/v1, verifique como o SDK combina a URL base com o caminho do endpoint.

Para um cliente legado do LangChain compatível com OpenAI, o formato mínimo funcional é:

import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="openai/gpt-4o",
    api_key=os.environ["OPENROUTER_API_KEY"],
    base_url="https://openrouter.ai/api/v1",
)

response = llm.invoke("Explain provider routing in one sentence.")
print(response.content)

Use uma chave de API do OpenRouter, não uma chave da OpenAI. O Quickstart do OpenRouter especifica autenticação com token Bearer. HTTP-Referer e X-OpenRouter-Title são cabeçalhos opcionais para atribuição da aplicação, não substitutos de Authorization.

LangChain + OpenRouter: configuração atual

Python: langchain-openrouter

Instale a integração e mantenha a chave fora do arquivo-fonte:

pip install -U langchain-openrouter
export OPENROUTER_API_KEY="sk-or-..."

Depois, instancie o modelo de chat nativo. A integração do LangChain para Python documenta model, temperature, max_tokens e max_retries neste formato:

from langchain_openrouter import ChatOpenRouter

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4.5",
    temperature=0,
    max_tokens=1024,
    max_retries=2,
)

response = model.invoke([
    ("system", "You are a concise technical assistant."),
    ("human", "What does OpenRouter add to a LangChain application?"),
])

print(response.content)

Os nomes dos modelos no OpenRouter geralmente seguem o formato provider/model, como anthropic/claude-sonnet-4.5, openai/gpt-4o ou deepseek/deepseek-r1. Consulte a API de Modelos do OpenRouter antes de colocar a aplicação em produção, porque IDs de modelos, aliases, variantes, disponibilidade e parâmetros compatíveis podem mudar.

JavaScript e TypeScript: @langchain/openrouter

Instale a integração e o LangChain core:

npm install @langchain/openrouter @langchain/core

O construtor baseado em objeto da integração JavaScript do LangChain deixa a configuração explícita e facilita a comparação com o exemplo em Python:

import { ChatOpenRouter } from "@langchain/openrouter";

const model = new ChatOpenRouter({
  model: "anthropic/claude-sonnet-4.5",
  temperature: 0,
  maxTokens: 1024,
});

const response = await model.invoke([
  { role: "system", content: "You are a concise technical assistant." },
  { role: "user", content: "Explain the provider/model format." },
]);

console.log(response.content);

Em Python, o parâmetro é max_tokens; no exemplo de JavaScript, ele aparece como maxTokens. As duas integrações leem OPENROUTER_API_KEY por padrão. Se um modelo aparece no catálogo, mas falha no código, confira o slug exato, o sufixo da variante e os parâmetros aceitos pela requisição.

init_chat_model e a armadilha das versões

Um erro comum é:

ValueError: Unsupported model_provider='openrouter'.

Uma discussão de troubleshooting no fórum do LangChain atribui esse caso ao uso de uma instalação do LangChain anterior à v1 com uma documentação voltada à v1. A recomendação é atualizar o framework e o pacote do provedor juntos:

pip install -U "langchain>=1" langchain-openrouter

Depois, use o inicializador genérico:

import os
from langchain.chat_models import init_chat_model

os.environ["OPENROUTER_API_KEY"] = "sk-or-..."

model = init_chat_model(
    "anthropic/claude-sonnet-4.5",
    model_provider="openrouter",
)

print(model.invoke("Say hello in one sentence.").content)

Se o projeto não puder migrar para o LangChain v1, instale langchain-openrouter e construa diretamente um ChatOpenRouter. Assim, você contorna o registro genérico de provedores e deixa a dependência do OpenRouter explícita.

Migre de ChatOpenAI para ChatOpenRouter

A alteração no código é pequena, mas a fronteira de integração muda de um adaptador genérico da OpenAI para uma classe específica do provedor:

# Antes: solução compatível com OpenAI
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="anthropic/claude-sonnet-4.5",
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

# Depois: integração nativa com OpenRouter
from langchain_openrouter import ChatOpenRouter

model = ChatOpenRouter(model="anthropic/claude-sonnet-4.5")

Primeiro, mantenha os mesmos prompts e pontos de chamada das chains. Só adicione roteamento de provedores, raciocínio, saída estruturada ou tratamento de metadados depois que a chamada nativa básica estiver funcionando.

Streaming, callbacks, ferramentas e saída estruturada no LangChain

model.stream() produz fragmentos de mensagem para um consumo simples de texto. Já stream_events(..., version="v3") expõe eventos do ciclo de vida mais adequados para logs baseados em callbacks, estado da interface e tracing; as duas interfaces estão documentadas na integração do LangChain para Python.

model = ChatOpenRouter(model="openai/gpt-4o")

for event in model.stream_events(
    "Explain why OpenRouter has provider fallbacks.",
    version="v3",
):
    if event["event"] == "on_chat_model_stream":
        chunk = event["data"]["chunk"]
        print(chunk.text, end="", flush=True)

Use um callback quando a aplicação precisar de notificações de início, token, conclusão ou erro. Use stream() quando ela precisar apenas dos fragmentos do modelo. Leia o uso e os metadados da resposta concluída ou do resultado agregado do stream, como mostra a documentação da integração, em vez de buscá-los em um fragmento inicial qualquer.

Chamadas de ferramentas e roteamento de provedores

O OpenRouter documenta um fluxo normalizado de chamadas de ferramentas: o modelo propõe uma chamada, a aplicação a executa e envia o resultado de volta ao modelo. ChatOpenRouter.bind_tools() aceita ferramentas do LangChain, funções Python, classes Pydantic e schemas em dicionários.

from pydantic import BaseModel, Field

class GetWeather(BaseModel):
    """Get current weather for a city."""

    location: str = Field(
        description="City and state, for example San Francisco, CA"
    )

model_with_tools = model.bind_tools(
    [GetWeather],
    strict=True,
)

result = model_with_tools.invoke("What is the weather in San Francisco?")
print(result.tool_calls)

A primeira chamada retorna apenas as chamadas de ferramentas propostas pelo modelo. Em um ciclo manual completo, crie uma ToolMessage para cada chamada antes de pedir ao modelo a resposta final:

from langchain_core.messages import HumanMessage, ToolMessage
from langchain_core.tools import tool

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

model_with_tools = model.bind_tools([get_weather])
messages = [HumanMessage("What is the weather in San Francisco?")]
ai_msg = model_with_tools.invoke(messages)
messages.append(ai_msg)

for call in ai_msg.tool_calls:
    tool_output = get_weather.invoke(call["args"])
    messages.append(
        ToolMessage(
            content=tool_output,
            tool_call_id=call["id"],
        )
    )

final_msg = model_with_tools.invoke(messages)
print(final_msg.content)

O roteamento de provedores deve ser definido na configuração específica do OpenRouter, descrita na integração do LangChain e no guia de seleção de provedores do OpenRouter:

routed_model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4.5",
    openrouter_provider={
        "order": ["Anthropic", "Google"],
        "allow_fallbacks": True,
        "require_parameters": True,
        "data_collection": "deny",
    },
)

order define a preferência. only restringe os provedores elegíveis, enquanto ignore exclui provedores. allow_fallbacks=True pode enviar uma requisição para além da ordem preferencial. require_parameters=True impede que a requisição seja encaminhada a provedores que não aceitem todos os parâmetros do payload. Essas configurações equilibram disponibilidade e controle sobre o provedor.

Em clientes antigos baseados em ChatOpenAI, os campos específicos do OpenRouter talvez precisem ser enviados por extra_body ou model_kwargs, dependendo da versão do cliente. Um usuário perguntou em uma discussão sobre LangChain/OpenRouter no Reddit:

“Wondering, doesn't openrouter support the openai API spec such that the openai client works?” — u/tuxedo0.

O pacote dedicado torna explícita a fronteira de integração com o OpenRouter, sem exigir que um wrapper genérico da OpenAI exponha todos os campos específicos de cada provedor.

Saída estruturada: confira o endpoint, não apenas o nome do modelo

A integração nativa oferece saída tipada por meio de with_structured_output(). A documentação do LangChain para Python mostra o método nativo com JSON Schema:

from pydantic import BaseModel, Field

class Movie(BaseModel):
    title: str
    year: int
    director: str
    rating: float = Field(description="Rating from 0 to 10")

structured_model = ChatOpenRouter(
    model="openai/gpt-5.5",
).with_structured_output(
    Movie,
    method="json_schema",
    strict=True,
)

movie = structured_model.invoke("Give details about the movie Inception.")
print(movie)

A integração também documenta function_calling; strict não é compatível com json_mode. O comportamento da saída estruturada do OpenRouter pode variar de acordo com o endpoint que atende à requisição, portanto o nome do modelo, sozinho, não é garantia. O guia de saída estruturada do OpenRouter explica por que verificações de capacidade do provedor, require_parameters e validação no cliente são importantes.

Vercel AI SDK + OpenRouter

Em uma aplicação Next.js ou TypeScript que usa o AI SDK da Vercel, instale o provedor do OpenRouter:

npm install @openrouter/ai-sdk-provider ai zod

Este exemplo compacto cobre streaming de texto e uma ferramenta local com Zod. O guia do OpenRouter para o Vercel AI SDK usa o mesmo padrão com createOpenRouter() e openrouter("provider/model").

import { createOpenRouter } from "@openrouter/ai-sdk-provider";
import { isStepCount, streamText, tool } from "ai";
import { z } from "zod";

const openrouter = createOpenRouter({
  apiKey: process.env.OPENROUTER_API_KEY,
});

const result = streamText({
  model: openrouter("openai/gpt-4o"),
  tools: {
    getWeather: tool({
      description: "Get the current weather in a location",
      inputSchema: z.object({
        location: z.string().describe("City and state"),
      }),
      execute: async ({ location }) => ({
        location,
        temperature: 18,
        unit: "celsius",
      }),
    }),
  },
  stopWhen: isStepCount(3),
  prompt: "What is the weather in San Francisco?",
});

for await (const textPart of result.textStream) {
  process.stdout.write(textPart);
}

textStream expõe os deltas de texto. Use fullStream quando a aplicação precisar de raciocínio, chamadas de ferramentas, resultados de ferramentas, limites entre etapas ou eventos de conclusão; a referência de streamText() do AI SDK documenta essas interfaces de resultado. O executor de clima acima é um mock, não uma chamada a uma API real.

Uma issue pública do provedor OpenRouter relatou buffering percebido em um fluxo de chamadas de ferramentas com vários fragmentos usando @openrouter/ai-sdk-provider 2.2.3, AI SDK 6.0.81, Node.js 24 e openai/gpt-5.2. O relato descreveu a ausência do evento tool-input-end. Trate isso como um problema específico de versão, não como um comportamento universal. Se o problema se reproduzir, a issue relata esta solução alternativa:

import { createOpenAI } from "@ai-sdk/openai";

const openrouter = createOpenAI({
  apiKey: process.env.OPENROUTER_API_KEY,
  baseURL: "https://openrouter.ai/api/v1",
});

const model = openrouter.chat("openai/gpt-5.2");

Instale @ai-sdk/openai separadamente e fixe as versões testadas. Essa solução muda o adaptador do provedor, então confirme quais opções específicas do OpenRouter continuam disponíveis.

Anthropic Agent SDK + OpenRouter

O Anthropic Agent SDK representa uma fronteira de integração separada. O guia oficial do Agent SDK do OpenRouter informa que o SDK usa o Claude Code como runtime e aceita esta configuração de ambiente:

export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"
export ANTHROPIC_API_KEY=""

Deixar ANTHROPIC_API_KEY vazio é intencional. A chave do OpenRouter deve ficar em ANTHROPIC_AUTH_TOKEN, e o caminho /api não deve ser trocado pelo caminho compatível com OpenAI, /api/v1, nessa configuração do Agent SDK.

O formato em TypeScript mostrado no guia é:

npm install @anthropic-ai/claude-agent-sdk
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Find and explain the bug in auth.py.",
  options: {
    allowedTools: ["Read"],
  },
})) {
  if (message.type === "assistant") {
    console.log(message.message.content);
  }
}

O OpenRouter fornece o endpoint do modelo; o Agent SDK mantém o loop do agente e o runtime das ferramentas. Teste ferramentas, streaming, comportamento de contexto e opções específicas do modelo na rota exata que será usada em produção, porque a paridade automática com os recursos nativos da Anthropic não é garantida.

401, 404 e o clássico “funciona no curl, mas não no SDK”

Identifique a camada que está falhando antes de trocar de modelo. Autenticação, montagem da URL, busca do modelo, filtros de provedor e validação de parâmetros exigem correções diferentes.

SintomaCamada provávelPrimeira verificação
401 Missing Authentication headerCabeçalho ou carregamento do ambienteConfirme Authorization: Bearer ...; teste /api/v1/key
401 Unauthorized com uma chave presenteChave incorreta, revogada ou vaziaConfirme se o processo enxerga OPENROUTER_API_KEY; use uma chave do OpenRouter
404 com caminho malformadoMontagem da URL baseClientes compatíveis com OpenAI usam /api/v1; o Agent SDK usa /api; procure por /v1 duplicado
404 Invalid model ou model_not_foundIdentificador do modeloConsulte /api/v1/models e use o id retornado ou um alias documentado
404 No allowed providers are availableFiltros de provedores ou disponibilidade do endpointInspecione only, ignore, max_price, require_parameters e as configurações de política de dados
400 para top_k, min_p, ferramentas ou JSON SchemaIncompatibilidade de capacidadesConfira supported_parameters; exija provedores compatíveis durante o roteamento
curl funciona, mas o código do framework falhaCaminho do SDK, capitalização, serialização ou cabeçalhos descartadosCompare a URL final, o cabeçalho de autenticação, o ID do modelo e o corpo JSON

O OpenRouter documenta GET /api/v1/key como uma verificação autenticada da chave de API. Execute esse teste antes de investigar o LangChain:

curl -sS https://openrouter.ai/api/v1/key \
  -H "Authorization: Bearer $OPENROUTER_API_KEY"

Em seguida, confirme a descoberta de modelos:

curl -sS https://openrouter.ai/api/v1/models \
  -H "Authorization: Bearer $OPENROUTER_API_KEY"

A API de Modelos permite filtrar modelos compatíveis com ferramentas antes de adicioná-las:

curl -sS \
  "https://openrouter.ai/api/v1/models?supported_parameters=tools" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY"

Um 404 também pode significar que o modelo existe, mas nenhum provedor elegível restou depois da aplicação dos filtros da requisição. Para inspecionar as decisões de roteamento, habilite o cabeçalho opcional X-OpenRouter-Metadata: enabled; a documentação de Router Metadata descreve o objeto openrouter_metadata resultante e seu comportamento em caso de erro.

Durante o desenvolvimento, compare a requisição gerada depois de ocultar a chave: URL base, caminho final, presença de Authorization, ID exato do modelo e campos específicos do provedor no corpo. Para uma investigação específica de autenticação, consulte o guia da AIReiter para erros de chave de API inválida e problemas 401/403.

Checklist de migração para produção

  1. Alinhe as gerações dos pacotes. Mantenha versões compatíveis de langchain, langchain-core e langchain-openrouter ou @langchain/openrouter, em vez de copiar versões de um tutorial antigo.
  2. Resolva os IDs canônicos dos modelos. Use /api/v1/models ou o catálogo de modelos do OpenRouter; trate aliases como uma mudança de comportamento intencional.
  3. Defina a fronteira do fallback. O fallback de provedor melhora a disponibilidade. O fallback de modelo pode alterar qualidade, latência, capacidades e custo. Registre o model final retornado pelo OpenRouter.
  4. Exija as capacidades quando elas forem importantes. Use filtros de capacidade do provedor em requisições com ferramentas e saída estruturada; não trate suporte a ferramentas como prova de compatibilidade com JSON Schema estrito.
  5. Valide as saídas da aplicação. Pydantic, Zod ou outro validador deve conferir os argumentos das ferramentas e as respostas estruturadas antes que o código seguinte aja sobre elas.
  6. Registre metadados úteis. Preserve ID da requisição, modelo, uso, motivo de conclusão e informações sobre o provedor que atendeu à requisição, quando a política de privacidade permitir. A integração do LangChain também documenta session_id para agrupar requisições e trace para metadados por requisição.
  7. Teste os dois modos de streaming. Uma chamada sem streaming bem-sucedida não prova que os fragmentos de chamadas de ferramentas ou o streaming da interface funcionarão corretamente.
  8. Exercite as restrições de provedores. Se usar only, ignore, filtros de coleta de dados ou um teto de preço, teste o caminho de erro sem provedores elegíveis.
  9. Mantenha as credenciais no servidor. Armazene OPENROUTER_API_KEY no ambiente do servidor ou em um gerenciador de segredos, nunca em um bundle do navegador ou em um arquivo .env versionado.

A sequência mais confiável é: valide a chave, confirme o ID do modelo, faça uma chamada simples de texto e só então adicione roteamento, ferramentas, saída estruturada e streaming em múltiplas etapas.