#11637·langchainjs

streamUsage default diverges from Python: setting a custom baseURL disables it in langchain-openai but not in @langchain/openai

Author: xizhuomengcontinCreated Sep 14, 2026Updated Sep 14, 2026

Summary

Setting a custom base URL changes the stream_usage default in Python but not in JS. The Python package documents the reasoning; the JS package neither matches the behaviour nor mentions it. Same conceptual setting, two different outcomes.

Measured

Python (langchain-openai):

python
ChatOpenAI(model="gpt-4o-mini", api_key="sk-test")                                  # stream_usage = True
ChatOpenAI(model="gpt-4o-mini", api_key="sk-test", base_url="http://127.0.0.1:9/v1")# stream_usage = None

JS (@langchain/openai):

javascript
new ChatOpenAI({ model: "gpt-4o-mini", apiKey: "sk-test" })                                        // streamUsage = true
new ChatOpenAI({ model: "gpt-4o-mini", apiKey: "sk-test", configuration: { baseURL: "http://…" } })// streamUsage = true

Both with OPENAI_BASE_URL and OPENAI_API_BASE unset, so the constructor argument is the only variable.

Why Python does it

From chat_models/base.py, the ChatOpenAI docstring:

OPENAI_BASE_URL is also inspected by LangChain only to decide whether to default-enable stream_usage — when set, the default is left off because many non-OpenAI endpoints do not support streaming token usage.

and the init logic guards on self.openai_api_base is None and "OPENAI_BASE_URL" not in os.environ.

That reasoning is sound and applies equally to JS: a gateway, vLLM, or an OpenAI-compatible server that does not implement stream_options.include_usage gets sent the flag anyway, and depending on the server either ignores it or rejects the request. The JS user has no way to know this is happening, because nothing in the typings or docs mentions that streamUsage interacts with the base URL at all — streamUsage: boolean in chat_models/base.d.ts is the whole of it.

What I think should happen

Either direction is defensible, but they should not silently differ:

  1. Match Python — leave streamUsage unset when a custom baseURL (or OPENAI_BASE_URL / OPENAI_API_BASE) is in play, with the same one-line rationale in the typings.
  2. Keep JS as-is and document it — state in the streamUsage doc comment that it stays on against custom endpoints, and that servers which do not implement stream_options.include_usage may need it disabled explicitly.

Option 1 is the smaller surprise for anyone running both languages against the same gateway, which is the case that produced this report.

Related

Same area as #11635 (the OPENAI_API_BASEOPENAI_BASE_URL resolution order being documented in Python but not JS). Filing separately because that one is a docs fix and this one is a behavioural difference; happy to have them merged if you would rather track "what changes when you set a base URL" as one item.

Environment

@langchain/openai and langchain-openai as resolved on 2026-09-14; Node 22.23.2 and Python 3.12 on Windows. No network calls involved — both checks read the constructed object.

Source: langchain-ai/langchainjs