feat: Add comprehensive OpenAI base URL configuration support
This commit implements comprehensive support for custom OpenAI base URL configuration throughout the entire Archon system, enabling users to route OpenAI API calls through proxies like LiteLLM, Azure OpenAI, or other OpenAI-compatible endpoints.
Key Changes:
Backend Services
- Enhanced credential_service.py to support OPENAI_BASE_URL setting
- Updated llm_provider_service.py to use custom base_url for AsyncOpenAI clients
- Modified code_storage_service.py to support base_url for sync OpenAI clients
PydanticAI Agent Integration
- Created new agent_provider_config.py for centralized provider configuration
- Updated base_agent.py to support async initialization with custom providers
- Modified rag_agent.py and document_agent.py to use configured providers
- Updated agent server.py to handle async provider initialization
Frontend UI
- Enhanced RAGSettings.tsx with conditional OpenAI base URL input field
- Added OPENAI_BASE_URL to TypeScript interface
- Field appears only when OpenAI is selected as provider
Features:
- Optional configuration (backwards compatible)
- Consistent behavior across all OpenAI usage points
- Secure encrypted storage in database
- Comprehensive error handling and fallbacks
- Support for LiteLLM, Azure OpenAI, and other compatible endpoints
Testing:
- All Python files compile without syntax errors
- Linting issues addressed
- No breaking changes to existing functionality
Resolves: https://github.com/coleam00/Archon/issues/584
Pull Request
Summary
This PR adds comprehensive support for custom OpenAI base URL configuration throughout the entire Archon system. This enables users to route OpenAI API calls through proxies like LiteLLM, Azure OpenAI, or other OpenAI-compatible endpoints, providing much-needed flexibility for enterprise deployments and cost optimization.
Key motivation: Enable access to OpenAI API through proxy services like LiteLLM for better cost management, rate limiting, and provider switching capabilities.
Changes Made
Backend Services
- Enhanced
credential_service.py: AddedOPENAI_BASE_URLsupport in_get_provider_base_url()method - Updated
llm_provider_service.py: Modified OpenAI client creation to accept optionalbase_urlparameter for AsyncOpenAI clients - Modified
code_storage_service.py: Updated synchronous OpenAI client to support custombase_urlfor consistency
PydanticAI Agent Integration
- Created
agent_provider_config.py: New centralized module for configuring PydanticAI OpenAI providers with custom endpoints - Enhanced
base_agent.py: Added async initialization support and_get_configured_model()method for custom provider configuration - Updated
rag_agent.pyanddocument_agent.py: Modified to use custom OpenAI providers when base URL is configured - Updated
server.py: Modified streaming endpoint to handle async agent initialization
Frontend UI
- Enhanced
RAGSettings.tsx: Added conditional OpenAI Base URL input field that appears only when OpenAI is selected as provider - Updated TypeScript interface: Added
OPENAI_BASE_URL?: stringproperty to RAGSettingsProps
Type of Change
- [x] New feature (non-breaking change which adds functionality)
Affected Services
- [x] Frontend (React UI)
- [x] Server (FastAPI backend)
- [x] Agents (PydanticAI service)
Testing
- [x] All existing tests pass
- [x] Manually tested affected user flows
- [x] Docker builds succeed for all services
- [x] Python files compile without syntax errors
- [x] Linting issues addressed
Test Evidence
# Python syntax and compilation check
python3 -m py_compile src/agents/agent_provider_config.py src/agents/base_agent.py src/agents/rag_agent.py src/agents/document_agent.py src/agents/server.py
# ✅ No output = successful compilation
# Linting check on modified files
uv run ruff check src/server/services/credential_service.py src/server/services/llm_provider_service.py src/server/services/storage/code_storage_service.py
# ✅ Only pre-existing issues, no new problems introduced
# TypeScript compilation check (no errors related to our changes)
npx tsc --noEmit 2>&1 | grep -i "openai\|base.*url"
# ✅ No TypeScript errors related to OPENAI_BASE_URL changes
Checklist
- [x] My code follows the service architecture patterns
- [x] If using an AI coding assistant, I used the CLAUDE.md rules
- [x] All new and existing tests pass locally
- [x] My changes generate no new warnings
- [x] I have verified no regressions in existing features
Breaking Changes
None - This is a fully backwards-compatible change. Existing deployments will continue to work exactly as before if no OPENAI_BASE_URL is configured.
Additional Notes
Configuration Examples
LiteLLM Proxy:
# In Settings UI or environment
OPENAI_BASE_URL=http://localhost:4000/v1
Azure OpenAI:
OPENAI_BASE_URL=https://your-resource.openai.azure.com/v1
Corporate Proxy:
OPENAI_BASE_URL=https://api-gateway.company.com/openai/v1
Implementation Highlights
-
Consistent Coverage: All OpenAI usage points now support custom base URLs:
- Direct AsyncOpenAI clients (embeddings, RAG, document processing)
- Synchronous OpenAI clients (code example generation)
- PydanticAI agents (RAG and Document agents)
-
Smart Fallbacks: When custom base URL is configured but fails, the system gracefully falls back to default OpenAI endpoints with appropriate logging
-
UI Integration: The base URL field only appears when OpenAI is selected as the provider, maintaining a clean user interface
-
Security: Custom base URLs are stored encrypted in the database alongside other credentials
Files Changed (9 total)
python/src/server/services/credential_service.pypython/src/server/services/llm_provider_service.pypython/src/server/services/storage/code_storage_service.pypython/src/agents/agent_provider_config.py(new file)python/src/agents/base_agent.pypython/src/agents/rag_agent.pypython/src/agents/document_agent.pypython/src/agents/server.pyarchon-ui-main/src/components/settings/RAGSettings.tsx
Resolves: https://github.com/coleam00/Archon/issues/584
Summary by CodeRabbit
-
New Features
- Added an OpenAI Base URL field in RAG settings (visible when OpenAI is selected) to route requests to custom OpenAI‑compatible endpoints.
- System-wide configuration now centralizes OpenAI base URL and API key so UI, agents, streaming, and storage consistently use custom endpoints.
-
Documentation
- Added comprehensive docs, examples, and security guidance for OPENAI_BASE_URL, proxy setups, and recommended key handling.
[!WARNING]
Rate limit exceeded
@orestesgarcia has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 37 seconds before requesting another review.
⌛ How to resolve this issue?
After the wait time has elapsed, a review can be triggered using the
@coderabbitai reviewcommand as a PR comment. Alternatively, push new commits to this PR.We recommend that you space out your commits to avoid hitting the rate limit.
🚦 How do rate limits work?
CodeRabbit enforces hourly rate limits for each developer per organization.
Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
Please see our FAQ for further information.
📥 Commits
Reviewing files that changed from the base of the PR and between efb5f20be19520882e327872edbd4be22d4ff41c and 86042528ec1aefcd837300dd8edd7622385f4463.
📒 Files selected for processing (4)
docs/docs/rag.mdx(2 hunks)python/src/agents/agent_provider_config.py(1 hunks)python/src/agents/base_agent.py(8 hunks)python/src/server/services/llm_provider_service.py(4 hunks)
Walkthrough
Adds optional OPENAI_BASE_URL across UI and backend, introduces centralized agent provider configuration, updates agents for async lazy initialization and runtime model resolution, and makes OpenAI clients (async/sync) honor a configured base URL and API key.
Changes
| Cohort / File(s) | Summary |
|---|---|
Frontend RAG settingsarchon-ui-main/src/components/settings/RAGSettings.tsx |
Adds optional OPENAI_BASE_URL?: string to ragSettings, renders conditional OpenAI Base URL input when LLM_PROVIDER === 'openai', and persists via credentialsService.updateRagSettings. |
Credential servicepython/src/server/services/credential_service.py |
_get_provider_base_url now returns rag_settings.get("OPENAI_BASE_URL") for openai (allows custom OpenAI-compatible endpoints). |
Async LLM provider servicepython/src/server/services/llm_provider_service.py |
get_llm_client integrates get_openai_client_config(), merges api_key/base_url, and constructs openai.AsyncOpenAI(**client_kwargs) using base_url when present. |
Sync OpenAI client (storage)python/src/server/services/storage/code_storage_service.py |
Sync client now reads OPENAI_API_KEY/OPENAI_BASE_URL from env or credential cache, normalizes base_url, builds client_kwargs, and constructs OpenAI(**client_kwargs). Adds guarded credential access and debug logging. |
Agent provider configuration (new)python/src/agents/agent_provider_config.py |
New module to validate/normalize base URLs, fetch API key/base_url from credential service or env, and return either a provider-backed OpenAIChatModel or "openai:<model>"; exposes get_configured_openai_model, get_openai_client_config, and a sync helper. |
Base agent async init & model resolutionpython/src/agents/base_agent.py |
Lazy async agent initialization (_ensure_agent_initialized, _init_lock); _create_agent made async; run_stream async; adds use_custom_provider flag and _get_configured_model to resolve openai: models via agent_provider_config. |
Document / RAG agentspython/src/agents/document_agent.py, python/src/agents/rag_agent.py |
_create_agent converted to async and awaits _get_configured_model() to set the model at runtime. |
Agent server streamingpython/src/agents/server.py |
Adjusts streaming to stream_cm = await agent.run_stream(...) then async with stream_cm as stream to match new run_stream behavior. |
Docsdocs/docs/*.mdx |
Adds OPENAI_BASE_URL docs, examples, security guidance, and UI/env instructions across API reference, configuration, and RAG docs. |
Sequence Diagram(s)
sequenceDiagram
autonumber
participant UI as RAG Settings UI
participant Svc as Credential Service
participant Prov as Agent Provider Config
participant Agent as Base/Doc/RAG Agent
participant LLM as LLM Provider Service
participant Store as Code Storage Service
UI->>Svc: save rag_settings (OPENAI_BASE_URL)
Note over Agent,Prov: Agent requests model resolution at runtime
Agent->>Prov: get_configured_openai_model("gpt-x")
Prov->>Svc: read OPENAI_BASE_URL / OPENAI_API_KEY (rag_strategy or env)
alt base_url + api_key present
Prov-->>Agent: OpenAIChatModel(model, provider=OpenAIProvider(base_url, api_key))
else no base_url
Prov-->>Agent: "openai:<model>"
end
Agent->>LLM: get_llm_client(provider=openai)
LLM->>Svc: _get_provider_base_url(openai)
alt base_url set
LLM-->>Agent: AsyncOpenAI(api_key, base_url)
else
LLM-->>Agent: AsyncOpenAI(api_key)
end
Agent->>Store: build sync OpenAI client for embeddings/code ops
Store->>Svc: read OPENAI_API_KEY / OPENAI_BASE_URL (sync)
Store-->>Agent: OpenAI(api_key[, base_url])
sequenceDiagram
participant Server as Agent Server
participant Agent as Agent
participant Stream as Stream CM
Server->>Agent: run_stream(prompt, deps)
Agent-->>Server: awaitable -> async context manager
Server->>Stream: async with (awaitable result) as stream
loop streaming
Stream-->>Server: chunk/token
Server-->>Client: SSE
end
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Assessment against linked issues
| Objective | Addressed | Explanation |
|---|---|---|
| Credential service: Add support for OPENAI_BASE_URL in RAG settings [#584] | ✅ | |
| LLM provider & clients: OpenAI clients (async/sync) use custom base_url when configured [#584] | ✅ | |
| Agents: Centralized provider config + agents use custom provider / async init [#584] | ✅ | |
| Frontend: RAG Settings UI shows conditional OpenAI Base URL field [#584] | ✅ |
Suggested labels
enhancement
Suggested reviewers
- coleam00
- leex279
- TimothiousAI
Poem
I twitch my nose at a new small door,
A base URL to wander and explore.
Agents wake slowly, then stream with delight,
Through proxy tunnels, day and night.
Carrots safe, keys snug and tight—hoppy flight!
✨ Finishing Touches
- [ ] 📝 Generate Docstrings
🧪 Generate unit tests
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
I pushed a fix in commit <commit_id>, please review it.Open a follow-up GitHub issue for this discussion.
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. - PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
CodeRabbit Commands (Invoked using PR/Issue comments)
Type @coderabbitai help to get the list of available commands.
Other keywords and placeholders
- Add
@coderabbitai ignoreor@coderabbit ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
CodeRabbit Configuration File (.coderabbit.yaml)
- You can programmatically configure CodeRabbit by adding a
.coderabbit.yamlfile to the root of your repository. - Please see the configuration documentation for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation:
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
Status, Documentation and Community
- Visit our Status Page to check the current availability of CodeRabbit.
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.
Thanks for this @orestesgarcia! This is one of the high priority items for us. We have an Ollama integration coming in from @tazmon95 soon and will touch some of the same things, so I think the plan is to bring that in and then start bringing in some other crawling/settings/provider PRs like this awesome one!
@orestesgarcia ollama integration and some other big architecture changes are now in place, so this PR needs some resolving/rebasing. Let us know if you want to do that, otherwise we can close and one of can implement it based on the new codebase-structure