n4nAI

LangChain ChatOpenAI with a custom base_url for gateway routing

Learn how to point LangChain ChatOpenAI at a custom base_url gateway for model routing, fallback, and unified API access with runnable Python code.

n4n Team4 min read813 words

Audio narration

Coming soon — every post will get a voice note here.

Most teams hit the wall when they need to swap LLM providers without rewriting their LangChain calls. Pointing LangChain ChatOpenAI at a custom base_url gateway lets you route requests to any OpenAI-compatible backend, unify model access, and add fallback logic in one place. This guide shows the exact steps to wire up langchain chatopenai base_url gateway routing with runnable code and verification.

Step 1: Install the LangChain OpenAI integration

Use the isolated langchain-openai package rather than the deprecated langchain umbrella import. The ChatOpenAI class delegates to the openai Python SDK, so its base_url handling matches the official client exactly.

pip install langchain-openai==0.1.7 openai==1.30.0

Pin versions in production. Breaking changes in the OpenAI SDK surface directly in LangChain, and a floating version will eventually break your gateway routing silently.

Step 2: Stand up or select an OpenAI-compatible gateway

A gateway translates a single OpenAI-style API surface to multiple upstream providers. You can run your own with LiteLLM or a custom proxy, or use a hosted service. For example, n4n.ai exposes one OpenAI-compatible endpoint that addresses 240+ models and automatically falls back when a provider is rate-limited, but the client code in this article is identical regardless of which backend you point at.

The only contract you need: the gateway must accept POST /v1/chat/completions with the same JSON shape as OpenAI, and return the same streaming or non-streaming format. If you run your own, export the URL and a key (the key can be a dummy if the gateway trusts your network):

export GATEWAY_BASE_URL="https://gateway.internal/v1"
export GATEWAY_API_KEY="sk-gateway-dummy"

Step 3: Initialize ChatOpenAI with the custom base_url

The critical move is passing base_url to ChatOpenAI. LangChain forwards this to the underlying SDK. Use a model name your gateway recognizes.

from langchain_openai import ChatOpenAI
import os

llm = ChatOpenAI(
    model="gpt-4o-mini",  # gateway maps this to an upstream
    temperature=0.2,
    base_url=os.environ["GATEWAY_BASE_URL"],
    api_key=os.environ["GATEWAY_API_KEY"],
    max_retries=2,
)

That is the minimal langchain chatopenai base_url gateway setup. Every request from this instance now hits your gateway instead of api.openai.com.

Watch the trailing slash

The openai SDK joins base_url with the endpoint path. If you set base_url="https://gateway.internal/v1/" (with slash), the SDK may produce https://gateway.internal/v1//chat/completions. Most gateways tolerate this, but strip the trailing slash to avoid ambiguous routing logs and double-slash redirects.

Step 4: Route models with headers or model aliases

Gateways commonly let you specify provider or route via headers. ChatOpenAI accepts default_headers:

llm_anthropic = ChatOpenAI(
    model="claude-3-sonnet",
    base_url=os.environ["GATEWAY_BASE_URL"],
    api_key=os.environ["GATEWAY_API_KEY"],
    default_headers={"x-provider": "anthropic"},
)

If your gateway uses model prefix routing (e.g., anthropic/claude-3-sonnet), just pass that as model. Test both approaches; gateways differ in precedence. Some gateways honor client routing directives and forward provider cache-control hints, so you can pass {"x-cache-control": "max-age=3600"} to reuse upstream prompt caches.

Passing gateway-specific params

Gateways often accept extra body fields. LangChain forwards unknown kwargs via extra_body:

response = llm.invoke(
    "Summarize this log",
    extra_body={"route": "cheap", "fallback": ["gpt-3.5-turbo"]},
)

Check your gateway docs for exact keys. Don’t assume OpenAI-only fields; the gateway may ignore them or reject the request.

Step 5: Add fallback and degradation handling

Provider outages are routine. If your gateway doesn’t auto-fallback, implement a thin wrapper:

from langchain_core.exceptions import LangChainException

def safe_call(llm, prompt):
    try:
        return llm.invoke(prompt)
    except LangChainException as e:
        # swap to a backup gateway or model
        backup = ChatOpenAI(
            model="mistral-small",
            base_url=os.environ["BACKUP_URL"],
            api_key=os.environ["BACKUP_API_KEY"],
        )
        return backup.invoke(prompt)

If you use a gateway that already performs automatic fallback when a provider is degraded, you can rely on its 200 responses and keep max_retries=2 for transient network errors only. Don’t build client-side provider selection on top of a gateway that already does it—you’ll double-retry and inflate latency.

Step 6: Stream tokens through the gateway

Streaming works unchanged. Set streaming=True:

llm_stream = ChatOpenAI(
    model="gpt-4o-mini",
    base_url=os.environ["GATEWAY_BASE_URL"],
    api_key=os.environ["GATEWAY_API_KEY"],
    streaming=True,
)

for chunk in llm_stream.stream("Write a haiku about TCP retransmits"):
    print(chunk.content, end="", flush=True)

The gateway must support SSE at the same path. Most OpenAI-compatible proxies do. If you see truncated streams, check whether the gateway buffers responses—some cheap proxies don’t flush per token.

Step 7: Verify the integration end to end

Don’t trust silent success. Run a raw POST to confirm the gateway shape, then run the LangChain call and inspect metadata.

import requests, os

def verify_gateway():
    r = requests.post(
        f"{os.environ['GATEWAY_BASE_URL']}/chat/completions",
        headers={"Authorization": f"Bearer {os.environ['GATEWAY_API_KEY']}"},
        json={"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "ping"}]},
    )
    assert r.status_code == 200, r.text
    data = r.json()
    assert "choices" in data and data["choices"][0]["message"]["content"]
    print("Gateway OK, model used:", data.get("model"))

verify_gateway()

Then inspect LangChain’s response metadata:

resp = llm.invoke("Hello")
print(resp.response_metadata)

If you see usage tokens and a valid id, the langchain chatopenai base_url gateway path is functioning. For per-token metering, cross-check the usage block with your gateway’s dashboard.

Step 8: Drop the gateway LLM into a LangChain chain

Higher-level LangChain abstractions don’t care about the base URL. Bind the gateway-backed model into a prompt chain:

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a terse ops assistant."),
    ("user", "{input}")
])
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"input": "Why is my p99 latency spiking?"}))

This proves the langchain chatopenai base_url gateway integration doesn’t break Runnable composition, streaming, or output parsing. You can swap the gateway URL to change providers without touching chain code.

Common pitfalls

  • TLS verification: Internal gateways with self-signed certs need verify=False in the SDK. Pass a custom httpx.Client via client= or set OPENAI_VERIFY_SSL=False.
  • Model name mismatch: Gateways don’t proxy every OpenAI model name. Map explicitly; gpt-4 may need to become openai/gpt-4.
  • Timeout: Default SDK timeout is 600s. Set timeout=30 for interactive apps to fail fast.
  • Port in URL: If the gateway runs on :8080, include it: http://localhost:8080/v1.
  • Header casing: Some gateways read X-Provider, others x-provider. Match their docs exactly; HTTP headers are case-insensitive in theory but buggy proxies exist.

Closing checklist

You now have a ChatOpenAI instance bound to a custom base_url, routing logic via headers or model strings, streaming, fallback, and a verification step. The entire payoff of the langchain chatopenai base_url gateway pattern is one client, many models, zero code changes when providers rotate. Run the verification script in CI against a stub gateway to catch regressions before they hit production.

Tagslangchainchatopenaibase-urlrouting

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All langchain + openai-compatible gateway integration posts →