What happens
OpenBot runs on your own machine, in your own PostgreSQL, with a model key you supply. Where that key is spent is the one part that is not yours to set: a deployment that puts a gateway or a proxy in front of its models, or that runs a model on hardware it controls, cannot tell the shipped Bots about it.
Concretely:
agent-bot/src/index.ts constructs new OpenAI({ apiKey: process.env.OPENAI_API_KEY }) with no baseURL.
agent-langgraph/src/index.ts constructs ChatOpenAI without configuration.baseURL.
docker-compose.yml passes neither Bot anything that could carry one, so even setting a variable in .env would not reach the containers.
What is already true
The API server does not have this problem. builtInAgentConfiguration in server/src/copilot.ts hands `${provider}/${defaultModel}` to BuiltInAgent, and resolveModel in the pinned @copilotkit/runtime@1.67.1 builds its OpenAI client as:
createOpenAI({
apiKey: apiKey || process.env.OPENAI_API_KEY,
baseURL: process.env.OPENAI_BASE_URL,
})(model)
So package built-in agents have always been movable by setting OPENAI_BASE_URL. It is undocumented, and the two shipped Bots do not follow.
That split is the part worth fixing. A deployment that moves its models and finds the built-in coworkers on the new endpoint while both Bots still call api.openai.com has nothing in the configuration to tell it so.
Proposed fix
Have both Bots read OPENAI_BASE_URL, pass it to both services in docker-compose.yml, and document it in .env.example and docs/configuration.md.
A base URL rather than another BOT_PROVIDER value, because the API is the contract: anthropic and google are different APIs, not different URLs for this one, and would be untouched. Model names would travel verbatim in BOT_MODEL and in the tenant package's default_model, since an endpoint names its own catalogue.
Two caveats belong in the docs alongside it: not every catalogue entry accepts tools, and a Bot without tool calling cannot drive its computer; and BOT_RESPONSES_API=true needs an endpoint that implements the Responses API, not only chat completions.
Happy to open the PR — the change is small and I have it working against a live OpenAI-compatible gateway, with both Bots streaming AG-UI and emitting tool calls.
What happens
OpenBot runs on your own machine, in your own PostgreSQL, with a model key you supply. Where that key is spent is the one part that is not yours to set: a deployment that puts a gateway or a proxy in front of its models, or that runs a model on hardware it controls, cannot tell the shipped Bots about it.
Concretely:
agent-bot/src/index.tsconstructsnew OpenAI({ apiKey: process.env.OPENAI_API_KEY })with nobaseURL.agent-langgraph/src/index.tsconstructsChatOpenAIwithoutconfiguration.baseURL.docker-compose.ymlpasses neither Bot anything that could carry one, so even setting a variable in.envwould not reach the containers.What is already true
The API server does not have this problem.
builtInAgentConfigurationinserver/src/copilot.tshands`${provider}/${defaultModel}`toBuiltInAgent, andresolveModelin the pinned@copilotkit/runtime@1.67.1builds its OpenAI client as:So package built-in agents have always been movable by setting
OPENAI_BASE_URL. It is undocumented, and the two shipped Bots do not follow.That split is the part worth fixing. A deployment that moves its models and finds the built-in coworkers on the new endpoint while both Bots still call
api.openai.comhas nothing in the configuration to tell it so.Proposed fix
Have both Bots read
OPENAI_BASE_URL, pass it to both services indocker-compose.yml, and document it in.env.exampleanddocs/configuration.md.A base URL rather than another
BOT_PROVIDERvalue, because the API is the contract:anthropicandgoogleare different APIs, not different URLs for this one, and would be untouched. Model names would travel verbatim inBOT_MODELand in the tenant package'sdefault_model, since an endpoint names its own catalogue.Two caveats belong in the docs alongside it: not every catalogue entry accepts tools, and a Bot without tool calling cannot drive its computer; and
BOT_RESPONSES_API=trueneeds an endpoint that implements the Responses API, not only chat completions.Happy to open the PR — the change is small and I have it working against a live OpenAI-compatible gateway, with both Bots streaming AG-UI and emitting tool calls.