feat: support per-channel OpenAI-compatible LLM endpoints - #19
Open
jimmyzhuu wants to merge 1 commit into
Open
Conversation
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.
Summary
This adds per-channel support for OpenAI-compatible LLM endpoints through
tools.toml.Channels can now override not only the LiteLLM model name, but also the API base URL and the environment variable used for the API key. This makes it possible to route different Slack channels to different OpenAI-compatible gateways without changing application code or storing secrets in channel config files.
What changed
LLM configuration
tools.tomlnow supports these fields under[llm]:The runtime behavior is:
modeloverrides the globalLLM_MODELfor that channel.api_baseis passed tolitellm.acompletion.api_key_envis resolved from the process environment and passed asapi_key.acompletion(...)still take precedence over channel config.api_key_envis configured but the environment variable is missing, TagOpen fails fast with a clear configuration error instead of falling back to another provider key.Docs and examples
channels/example/tools.toml.Test baseline fixes
While adding the new LLM tests, two existing test blockers surfaced:
tagopen/gateway/router.pyreferencedasyncioin a dataclass annotation before importing it, which caused test collection to fail.MessageStore.get_recent_messages()sorted recent rows bycreated_at, which can be unstable for rapid inserts in SQLite. It now selects recent rows by autoincrementid, then returns them chronologically.Why this is needed
Open Claude Tag already supports LiteLLM and per-channel model overrides, but many real deployments use OpenAI-compatible APIs behind custom gateways or cloud provider endpoints.
Without
api_baseandapi_key_env, users have to rely on global provider environment variables or code changes to route a channel to a compatible endpoint. This change keeps the existing default path unchanged while making channel-level endpoint routing configurable.User impact
A channel can now be configured to use a specific compatible endpoint:
This keeps secrets out of
tools.tomland allows different channels to use different endpoints or credentials.Validation
Unit tests
Result:
Result:
The new LLM tests cover:
api_baseinjectionapi_key_envresolutionapi_key_envis configured but missingtools.tomlfallback behaviorLint
Result:
ruff check .still reports pre-existing lint issues in files outside this change. The files touched by this PR pass Ruff.Real endpoint smoke test
A real smoke test passed against the Baidu Qianfan OpenAI-compatible endpoint using:
api_base:https://qianfan.baidubce.com/v2model:openai/ernie-4.5-turbo-32kapi_key_envThe smoke test used a temporary channel config and called the new
tagopen.llm.acompletion(channel_id=...)path directly. The response returned non-empty assistant content.