PineRouterDocs
GuidesModelsAPI referenceApps
SDKs and frameworks

LangChain

Use LangChain's ChatOpenAI in Python and TypeScript with this API.

LangChain reaches this API through ChatOpenAI from its OpenAI package. Set the base URL to https://pinerouter.ai/v1 and use your key. Chains, agents and LangGraph then run on any text model on Models.

Install

pip install -U langchain-openai
uv add langchain-openai
npm install @langchain/openai @langchain/core zod
pnpm add @langchain/openai @langchain/core zod
bun add @langchain/openai @langchain/core zod

Configure API keys

.env
API_KEY=sk-...

Load it into the environment before you run the code (for example with python-dotenv, or node --env-file=.env). Keep the key out of your code.

Run

Text

import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-6-luna", base_url="https://pinerouter.ai/v1", api_key=os.environ["API_KEY"])

print(llm.invoke("Name three rivers in Europe.").content)
import { ChatOpenAI } from "@langchain/openai";

const llm = new ChatOpenAI({
  model: "gpt-6-luna",
  configuration: { baseURL: "https://pinerouter.ai/v1", apiKey: process.env.API_KEY },
});

const res = await llm.invoke("Name three rivers in Europe.");
console.log(res.content);

Stream

for chunk in llm.stream("Write a haiku about rivers."):
    print(chunk.content, end="", flush=True)
for await (const chunk of await llm.stream("Write a haiku about rivers.")) {
  process.stdout.write(String(chunk.content));
}

Tool calling

bind_tools / bindTools sends your tools in OpenAI's format. The answer's tool_calls lists what the model wants to run.

from pydantic import BaseModel, Field

class GetWeather(BaseModel):
    """Current weather for a city"""
    city: str = Field(description="City name, for example Paris")

ai_msg = llm.bind_tools([GetWeather]).invoke("What is the weather in Paris?")
print(ai_msg.tool_calls)
import { tool } from "@langchain/core/tools";
import * as z from "zod";

const getWeather = tool(({ city }) => `Sunny, 21 C in ${city}`, {
  name: "get_weather",
  description: "Current weather for a city",
  schema: z.object({ city: z.string() }),
});

const aiMsg = await llm.bindTools([getWeather]).invoke("What is the weather in Paris?");
console.log(aiMsg.tool_calls);

Specifics

  • ChatOpenAI reads only fields in OpenAI's standard format, so model-specific extras in answers (such as a separate reasoning field) are dropped.
  • In Python you can set the base URL with OPENAI_API_BASE or OPENAI_BASE_URL instead of base_url. With OPENAI_BASE_URL set, LangChain leaves streaming usage off by default; pass stream_usage=True to get token counts on streams.
  • In TypeScript, configuration takes any option of the OpenAI SDK client, such as baseURL and apiKey.
  • LangChain's chat models are for text. For images, video and other media call Jobs with the HTTP helper, for example inside a LangChain tool.
  • Tool calling depends on the model. Test with the model you plan to use.

Next