Answer the OpenAI-shaped calls from wherever the deployment says - #13
Merged
davidmckayv merged 2 commits intoAug 19, 2026
Merged
Conversation
OpenBot already runs on your own machine, in your own PostgreSQL, with a model key you supply. The one thing it could not do was decide where that key is spent: `agent-bot` constructed its client with a key and no base URL, `agent-langgraph` did the same through `ChatOpenAI`, and compose handed neither of them a way to be told otherwise. A deployment that had put a gateway or a proxy in front of its models, or that runs the model on hardware it controls, had to fork two files to use it. `OPENAI_BASE_URL` is that decision, and the API server already honoured it: `resolveModel` in the pinned runtime reads it for every `openai/*` model, so the package built-in agents have always been movable. This gives the two shipped Bots the same variable and hands it to both containers, so one line moves the whole deployment rather than the half of it that happens to run outside Docker. It is a base URL rather than another `BOT_PROVIDER` branch because the API is the contract. `anthropic` and `google` are different APIs, not different URLs for this one, and they are untouched. Model names travel verbatim in `BOT_MODEL` and in the tenant package's `default_model`, because an endpoint names its own catalogue. Verified against a live OpenAI-compatible gateway: both Bots stream AG-UI and emit tool calls, which is what a Bot needs to drive its computer.
knowhycodata
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso and
tylerslaton
as code owners
August 19, 2026 19:59
The OpenAI half of this landed the right idea and stopped one provider short. A deployment that fronts Anthropic or Google the same way, or runs either on its own hardware, had the same silent split this change set out to remove: the API server would follow and agent-langgraph would not. Both use the names the API server already reads, so one line still moves the built-in agents and the Bot together. agent-bot is untouched. It speaks the OpenAI API directly by construction, so there is no Anthropic or Google call in it to redirect.
Contributor
|
Nice PR. Thank you. |
davidmckayv
approved these changes
Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #12.
OPENAI_BASE_URLdecides where an OpenAI-shaped request is answered. Unset, that is OpenAI. Set, it is any endpoint speaking the same API: a gateway in front of several providers, a proxy, or a model on hardware you control.The API server already honoured it —
resolveModelin the pinned@copilotkit/runtime@1.67.1readsprocess.env.OPENAI_BASE_URLfor everyopenai/*model, so package built-in agents have always been movable, just undocumented. The two shipped Bots did not follow, and compose handed neither of them anything that could carry one. This closes that split: one line now moves the whole deployment rather than the half of it that happens to run outside Docker.Changes
agent-bot/src/index.tsbaseURLto the OpenAI client.agent-langgraph/src/index.tsconfiguration.baseURLtoChatOpenAI.docker-compose.ymlOPENAI_BASE_URLto both Bot services..env.example,docs/configuration.md,README.mdtests/compose.test.tsA base URL rather than another
BOT_PROVIDERbranch, because the API is the contract.BOT_PROVIDER=anthropicandBOT_PROVIDER=googleare different APIs, not different URLs for this one, and are untouched. Model names travel verbatim inBOT_MODELand in the tenant package'sdefault_model, since an endpoint names its own catalogue.The docs carry the two caveats that bite in practice: not every catalogue entry accepts tools, and a Bot without tool calling cannot drive its computer; and
BOT_RESPONSES_API=trueneeds an endpoint implementing the Responses API, not only chat completions.Verification
Both Bots were run against a live OpenAI-compatible gateway —
OPENAI_BASE_URL=https://llmtr.com/v1, whose catalogue is public atGET /v1/modelsand needs no key — and both streamed AG-UI end to end with a real tool call, which is what a Bot needs to drive its computer:The server path was verified by reading
resolveModelin the pinned runtime rather than run, since that needs Intelligence credentials. It splits on the first/only, so a namespaceddefault_model: openai/gpt-4obecomesopenai/openai/gpt-4oand reaches the endpoint asopenai/gpt-4o. The exact pin makes that stable.bun run format:check,bun run lintandbun run typecheckpass.bun testpasses except for the PostgreSQL integration tests and the symlink tests, which fail identically on an unmodified checkout on this machine — no database, and Windows symlinks need elevation. The new compose test passes.