> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbitrage.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LangChain

> Route + trace LangChain (Python & JS) chat models through Orbitrage.

LangChain's `ChatOpenAI` is OpenAI-compatible — point it at the Orbitrage
gateway and every call is routed and traced. Tools, managed tools, and streaming
all work unchanged.

## Install

<CodeGroup>
  ```bash Python theme={null}
  pip install -U orbitrage langchain langchain-openai
  ```

  ```bash Node.js theme={null}
  npm install orbitrage@latest @langchain/openai @langchain/core
  ```
</CodeGroup>

## Basic chat

Wrapper clients build their own HTTP client, so set the **base URL** and **key**
explicitly, and pass your end-user id via `default_headers`.

<CodeGroup>
  ```python Python theme={null}
  import os, orbitrage
  orbitrage.init(os.environ["ORBITRAGE_API_KEY"], user_id="customer_42")

  from langchain_openai import ChatOpenAI

  llm = ChatOpenAI(
      model="glm-5.2",                       # direct model — or "minimax-m3"; "auto" to route
      base_url="https://api.orbitrage.ai/v1",
      api_key=os.environ["ORBITRAGE_API_KEY"],
      default_headers={"x-orbitrage-end-user-id": "customer_42"},
      max_tokens=512,
  )
  print(llm.invoke("Explain routing in one line.").content)
  ```

  ```typescript Node.js theme={null}
  import { orbitrage } from "orbitrage";
  await orbitrage.init({ apiKey: process.env.ORBITRAGE_API_KEY, userId: "customer_42" });

  import { ChatOpenAI } from "@langchain/openai";

  const llm = new ChatOpenAI({
    model: "glm-5.2",                        // direct model — or "minimax-m3"; "auto" to route
    apiKey: process.env.ORBITRAGE_API_KEY,
    maxTokens: 512,
    configuration: {
      baseURL: "https://api.orbitrage.ai/v1",
      defaultHeaders: { "x-orbitrage-end-user-id": "customer_42" },
    },
  });
  console.log((await llm.invoke("Explain routing in one line.")).content);
  ```
</CodeGroup>

## Managed tools (web search, scrape, calculator — no keys)

Reference a [managed tool](/concepts/tools-gateway) by name and Orbitrage runs it
server-side, then loops the result back to the model.

<CodeGroup>
  ```python Python theme={null}
  # bind passes the managed tool straight through to the API
  out = llm.bind(tools=["calculator_orbitrage"]).invoke(
      "Use the calculator to compute 1234*5678. Only the number."
  )
  print(out.content)   # 7006652
  ```

  ```typescript Node.js theme={null}
  // modelKwargs forwards the managed tool to the API
  const withTool = new ChatOpenAI({
    model: "minimax-m3",
    apiKey: process.env.ORBITRAGE_API_KEY,
    modelKwargs: { tools: ["calculator_orbitrage"] },
    configuration: { baseURL: "https://api.orbitrage.ai/v1" },
  });
  const out = await withTool.invoke("Use the calculator to compute 1234*5678. Only the number.");
  console.log(out.content);   // 7006652
  ```
</CodeGroup>

Your own LangChain tools (`@tool` / `bind_tools`) keep working alongside managed
tools in the same call.

## Streaming

<CodeGroup>
  ```python Python theme={null}
  for chunk in llm.stream("Count from 1 to 5."):
      print(chunk.content, end="", flush=True)
  ```

  ```typescript Node.js theme={null}
  for await (const chunk of await llm.stream("Count from 1 to 5.")) {
    process.stdout.write(String(chunk.content));
  }
  ```
</CodeGroup>

<Tip>
  Pin a **direct model** (`glm-5.2`, `minimax-m3`) for predictable
  behavior. Use `model="auto"` to let Orbitrage pick the cheapest capable model —
  and keep `max_tokens` ≥ 512 so reasoning models aren't truncated.
</Tip>
