How to Add Custom Providers to OmniRoute: OpenAI and Anthropic Compatible Integration
You can add custom providers to OmniRoute by registering an OpenAI-compatible or Anthropic-compatible service via the /api/v1/providers endpoint or the UI, which dynamically creates a provider node in src/lib/db/providers.ts without requiring changes to the core routing engine.
OmniRoute treats custom providers identically to built-in providers (Free, OAuth, API-Key) through a dynamic registration system. By leveraging the provider registry pattern in [open-sse/config/providerRegistry.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/open-sse/config/providerRegistry.ts), you can integrate private or third-party LLM endpoints that speak standard OpenAI or Anthropic HTTP APIs. This guide explains the complete process for adding custom providers to OmniRoute using the REST API, web interface, and JavaScript SDK.
Understanding Custom Provider Architecture
Provider ID Conventions
Custom providers follow a strict naming convention that triggers the dynamic provider branch. Valid provider IDs must match the pattern openai-compatible-<name> or anthropic-compatible-<name>, such as openai-compatible-myservice. This pattern is validated by the Zod schema in [src/shared/validation/schemas/routing.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/shared/validation/schemas/routing.ts), which allows any string ending with -compatible-* to bypass the static registry check.
Registry and Database Flow
When you register a custom provider, OmniRoute executes a four-step persistence flow:
- Validation: The
registerFallbackSchemavalidates the provider ID and connection payload. - Node Creation: The
registerProviderroutine writes to theproviderstable via [src/lib/db/providers.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/lib/db/providers.ts), creating a provider node that stores the display name, type (apikeyoroauth), and metadata. - Connection Storage: Each connection (base URL, API key, headers, default model) is stored in the
provider_connectionstable through theregisterConnectionhelper found in [src/sse/handlers/chat.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/sse/handlers/chat.ts). - Model Discovery: When routing requests, the combo router calls
fetchModelsFromProviderin [open-sse/services/combo.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/open-sse/services/combo.ts). If the provider is not in the static registry, it falls back to the connection'sdefaultModel—a behavior implemented in the Auto-Custom Provider fix.
How to Add a Custom Provider via the REST API
The fastest method to add custom providers to OmniRoute is through the /api/v1/providers endpoint. This approach is ideal for automation and infrastructure-as-code workflows.
POST /api/v1/providers
Content-Type: application/json
Authorization: Bearer $OMNIROUTE_API_KEY
{
"providerId": "openai-compatible-myservice",
"displayName": "My OpenAI-compatible Service",
"type": "apikey",
"connections": [
{
"baseUrl": "https://api.myservice.com/v1",
"apiKey": "sk-XXXXXXXXXXXXXXXXXXXX",
"defaultModel": "gpt-4o-mini",
"headers": {
"Custom-Header": "value"
}
}
]
}
The request body is validated against the Zod schema in the routing validation module. Upon success, the provider immediately appears in the routing engine and is protected by the circuit breaker logic defined in [src/shared/utils/circuitBreaker.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/shared/utils/circuitBreaker.ts).
How to Add a Custom Provider via the UI
For manual configuration, the OmniRoute dashboard provides a guided interface:
- Navigate to Settings → Provider Management.
- Click Add Provider, then select Custom OpenAI-compatible or Custom Anthropic-compatible.
- Enter the Provider ID using the required pattern (e.g.,
openai-compatible-myservice). - Input the Display Name, Base URL (e.g.,
https://api.myservice.com/v1), and API Key. - Specify a Default Model to enable the Auto-Combo fallback mechanism.
- Save the configuration. The UI invokes the same REST endpoint internally, writing the data to the provider database module.
The provider picker component (ModelSelectModal) utilizes [src/shared/components/modelSelectModalHelpers.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/shared/components/modelSelectModalHelpers.ts) to build the model list via buildNodeAliasModels, which safely handles null aliases introduced by custom providers.
Using Custom Providers in Your Application
Once registered, route traffic to your custom provider using the standard OmniRoute SDK or CLI. The model string uses the format <provider-id>/<model-name>.
import { OmniRouteClient } from "@omniroute/sdk";
const client = new OmniRouteClient({
apiKey: process.env.OMNIROUTE_API_KEY,
});
const response = await client.chat.completions.create({
model: "openai-compatible-myservice/gpt-4o-mini",
messages: [{ role: "user", content: "Explain quantum tunneling." }],
stream: true
});
console.log(response.choices[0].message.content);
The SDK automatically maps the model string to the custom provider node, selects the appropriate connection from the database, and applies the circuit breaker pattern to handle upstream failures.
Key Source Files and Implementation Details
Summary
- Custom providers in OmniRoute use the ID pattern
openai-compatible-<name>oranthropic-compatible-<name>validated by the Zod schema insrc/shared/validation/schemas/routing.ts. - Registration creates a provider node in
src/lib/db/providers.tsand stores connections viaregisterConnectioninsrc/sse/handlers/chat.ts. - No code changes are required; providers are added via the
/api/v1/providersREST endpoint or the Settings UI. - Model discovery falls back to the connection's
defaultModelwhen the provider is not in the static registry, as implemented inopen-sse/services/combo.ts. - Circuit breaker protection applies automatically to custom providers through
src/shared/utils/circuitBreaker.ts.
Frequently Asked Questions
What API formats does OmniRoute support for custom providers?
OmniRoute supports OpenAI-compatible and Anthropic-compatible HTTP APIs. Your upstream service must expose endpoints matching the OpenAI /v1/chat/completions or Anthropic message formats. The system detects the format based on the provider ID prefix (openai-compatible-* vs anthropic-compatible-*).
Where are custom provider credentials stored?
API keys and connection details are stored in the provider_connections table, accessed through the database module at [src/lib/db/providers.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/lib/db/providers.ts). Credentials are encrypted at rest and injected into request headers at runtime by the connection handler in [src/sse/handlers/chat.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/src/sse/handlers/chat.ts).
How does OmniRoute handle model discovery for custom providers?
When a custom provider is selected, the combo router attempts to fetch available models from the provider's /v1/models endpoint. If the endpoint is unavailable or returns an error, the system falls back to the defaultModel specified during registration. This logic resides in [open-sse/services/combo.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/open-sse/services/combo.ts) and is verified by the test suite in [tests/unit/auto-custom-provider-5873.test.ts](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.50/tests/unit/auto-custom-provider-5873.test.ts).
Can I use custom providers in combo routes?
Yes. Custom providers function identically to built-in providers within combo routes. You can reference them in combo configurations using their full provider ID (e.g., openai-compatible-myservice/gpt-4o-mini). The routing engine treats them as valid targets for load balancing, failover, and circuit breaker policies defined in the combo service.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →