Integration guides ยท 2026-08-29

Running OpenBot on LLMTR: one base URL, two agent runtimes

How to move an OpenBot deployment onto LLMTR: which components read OPENAI_BASE_URL, why the model name is written out in full in the tenant package as well, and what the tool calling and Responses API constraints mean for model choice.

LLMTR routing diagram showing a single base URL from an OpenBot environment file reaching the API server and two distinct agent runtimes.

The integration is an environment value, not code

OpenBot is an open source system you run on your own infrastructure, able to give every agent a computer of its own. Connecting it to LLMTR required no provider class: the change sits on the openai-compatible-base-url branch of the knowhycodata/openbot repository and touches three files, the environment example, the repository readme and the configuration document. That branch was not taken into OpenBot's own release.

The value it adds is OPENAI_BASE_URL. Left unset, requests go to OpenAI. Set, they go to any endpoint speaking the same chat completions API: a gateway fronting several providers, a proxy, or a model on hardware you control.

What makes it matter is that it moves the whole deployment rather than one Bot. In the words of the configuration document, this design makes it impossible for half of a deployment to end up pointed somewhere else.

Which component reads which value

Three readers make the OpenAI-shaped calls: the API server for the tenant package's built-in agents, agent-bot for the client it constructs, and agent-langgraph when its provider value is openai. All three read the same base URL, so one line redirects them together.

Anthropic and Google have separate names not because they are different URLs but because they are different APIs. That is why ANTHROPIC_BASE_URL and GOOGLE_GENERATIVE_AI_BASE_URL live on their own, and both are names the API server already reads.

The table below lists the values the branch adds and touches, together with the component that reads each. The other entries in the environment file, such as the computer and supervisor secrets, have nothing to do with model selection.

Model-related values in an OpenBot deployment, their defaults, and the component reading each
VariableDefaultRead by
OPENAI_API_KEYunsetAPI server, agent-bot, agent-langgraph
OPENAI_BASE_URLunset, meaning OpenAIThe same three readers at once
BOT_PROVIDERopenaiagent-langgraph only
ANTHROPIC_API_KEYunsetagent-langgraph when the provider is anthropic
ANTHROPIC_BASE_URLunsetThe path speaking the Anthropic API
GOOGLE_API_KEYunsetagent-langgraph when the provider is google
GOOGLE_GENERATIVE_AI_BASE_URLunsetThe path speaking the Google API
BOT_MODELThe provider default in the Bot codeThe two shipped Bots
BOT_RESPONSES_APIfalseagent-langgraph only

The model name is written in full, in two places

Model names travel verbatim. An endpoint that namespaces its catalogue wants both halves of the name, and LLMTR identifiers take the provider/model form, so you write openai/gpt-4o rather than gpt-4o. The same rule applies twice over: to BOT_MODEL in the environment file and to the default model field in the tenant package.

In the tenant package the provider field stays openai, because what it selects is the API being spoken, not the address the request goes to. The credential field is a reference to a stored credential rather than a credential value. Together these two rules mean that changing the base URL leaves the rest of the package alone.

There is an easy way to check the names before writing them: the model list endpoint is readable without a key, so you can see what is actually published without starting the deployment at all.

The model block in a tenant package; the default model name is passed through as written

model:
  provider: openai
  credential_secret_ref: openai-api-key
  default_model: openai/gpt-4o

Two runtimes, two different degrees of freedom

The two shipped Bots read the same base URL but are not equally flexible. The proof-of-concept Bot speaks the OpenAI API by construction; because it speaks that API directly, it has no notion of provider selection at all. The framework side, agent-langgraph, reads the provider value and can be openai, anthropic or google.

That second runtime has one strict rule: it reads the selected provider's own key and refuses to start without it. A deployment running on Anthropic therefore never needs an OpenAI key for it.

The practical consequence is that pointing the base URL at LLMTR moves both runtimes in one move, but switching the provider value to anthropic or google takes that runtime off the OpenAI-shaped path and onto the base URL name belonging to that API.

  • The proof-of-concept Bot speaks only the OpenAI API and ignores the provider value.
  • agent-langgraph speaks one of three APIs depending on the provider value.
  • Without the selected provider's key, that runtime does not start.
  • For built-in agents the OpenAI-shaped call is made by the API server, not by a Bot.

Turning on the Responses API makes the binding matter

The configuration document raises two things worth knowing before pointing a deployment at any gateway, and this is the first: with the Responses API flag on, the endpoint has to implement the Responses API and not only chat completions.

On the LLMTR side that means looking at a model's binding. A chat completions request works when the model has either a chat binding or a Responses binding. A Responses request works only for models with a Responses binding, because there is no bridge in that direction. Turning the flag on and leaving everything else alone will therefore fail for a model that carries only a chat binding.

The three names used in the environment example are all live in the catalog today: openai/gpt-4o, llmtr/gemma-4 and anthropic/claude-sonnet-4.5. All three carry a chat binding, so they work with the flag off. If you intend to turn it on, a name carrying both bindings, such as google/gemini-3.7-flash, is a safer starting point.

Values copied from the environment example; the key is a placeholder

OPENAI_BASE_URL=https://llmtr.com/v1
OPENAI_API_KEY=llmtr-your_key
BOT_MODEL=openai/gpt-4o

# Switching on the Responses API requires a matching binding
# BOT_RESPONSES_API=true
# BOT_MODEL=google/gemini-3.7-flash

A model without tool calling cannot drive its computer

The second thing the document raises is harder: not every catalogue entry accepts tools, and a Bot without tool calling cannot drive its computer. The very structure that gives each agent a computer of its own is therefore tied to model choice; pick wrongly and the agent talks without doing anything.

The model list answers this. In each entry's supported parameter list, the tool fields appear for models that can call functions and are absent for those that cannot. For non-chat entries that list is empty altogether. The command below prints only the identifiers that accept tools.

Cost follows model choice as well: billing is token based and draws down a credit balance. The LLMTR platform margin applies only when credits are topped up and is 8 percent; no margin is added to model prices. In an install where every agent drives its own computer the turn count rises, so tool capability and consumption together decide the model.

Listing the model identifiers that accept tool calls, without a key

curl -s https://llmtr.com/v1/models \
  | jq -r '.data[] | select(.supported_parameters | index("tools")) | .id'

Frequently asked questions

Does changing the base URL affect only the Bots?

No. The API server reads the same value for the tenant package's built-in agents. That is the design decision in the configuration document: one line moves the built-in agents and both Bots together, so a deployment cannot end up with half of itself pointed somewhere else.

Is this how I call an Anthropic model?

No, that is what ANTHROPIC_BASE_URL is for, because it is a different API rather than a different URL. LLMTR publishes an Anthropic-compatible endpoint on the llmtr.com host under the messages path. The examples on this branch cover only the OpenAI-compatible path; the Anthropic path is documented but not demonstrated.

Can I shorten the model name?

No. Names travel verbatim, and an endpoint that namespaces its catalogue expects both halves. Write LLMTR identifiers in the provider/model form, in BOT_MODEL and in the tenant package's default model field alike.

The Bot starts but never acts. What should I check?

First check whether the model you selected supports tool calling, because a Bot without it cannot drive its computer. If the supported parameter field in the model list carries no tool entries, that model is unsuitable for the job. After confirming that, check the state of the Responses flag and whether the selected provider's key is set.

Related posts