How to Add a New AI Provider to OmniRoute: A Step-by-Step Integration Guide

To add a new AI provider to OmniRoute, you must register the provider identifier, create a registry entry with endpoints and models, wire up an executor and optional translator, and update the dashboard UI—covering the full routing pipeline from API through frontend.

This guide walks through the complete provider integration process for the diegosouzapw/OmniRoute universal AI routing layer. Whether you're connecting an OpenAI-compatible API or a custom LLM service, these steps ensure your provider is fully functional across the routing engine, CLI, and web dashboard.


Step 1: Register the Provider Identifier

Every provider in OmniRoute starts with a canonical identifier in the shared constants file. This makes the provider name searchable throughout the codebase and establishes the foundation for type safety.

Add your provider to src/shared/constants/providers.ts:

// src/shared/constants/providers.ts
export const PROVIDERS = {
  ...DEFAULT_PROVIDERS,
  "mynewai": {
    id: "mynewai",
    name: "MyNewAI",
    category: "API_KEY",
    // optional: oauthConfig, defaultModel, etc.
  },
};

The category field determines authentication behavior—use "API_KEY" for key-based auth or "OAUTH" for OAuth flows.


Step 2: Create a Registry Entry

The provider registry is the single source of truth for routing and capability checks. Populate it with endpoint URLs, authentication headers, model lists, and transformer references.

Update open-sse/config/providerRegistry.ts:

// open-sse/config/providerRegistry.ts
REGISTRY["mynewai"] = {
  baseUrl: "https://api.mynewai.com/v1",
  authHeader: (key) => ({ Authorization: `Bearer ${key}` }),
  models: ["gpt-4o", "gpt-4-mini"],
  // If custom translator needed:
  requestTransformer: "mynewaiRequest",
  responseTransformer: "mynewaiResponse",
};

This registry entry tells OmniRoute where to send requests and how to authenticate them.


Step 3: Select or Create an Executor

OmniRoute uses executors to handle HTTP transport, retry logic, and error processing.

  • Default path: Most OpenAI-compatible providers work with DefaultExecutor—no code required.
  • Custom path: Create a subclass of BaseExecutor if you need special headers, request signing, or unique error handling.

Custom Executor Example

Create open-sse/executors/customProvider.ts:

// open-sse/executors/customProvider.ts
import { BaseExecutor } from "./base";

export class MyNewAIExecutor extends BaseExecutor {
  // Override only what differs from DefaultExecutor
  protected buildHeaders(cfg) {
    const base = super.buildHeaders(cfg);
    // MyNewAI requires an extra header:
    return { ...base, "X-MyNewAI-Client": cfg.clientId };
  }
}

Base executor reference: open-sse/executors/base.ts defines the interface all executors must implement.


Step 4: Wire the Executor Into the Factory

Connect your custom executor to the provider ID in open-sse/executors/index.ts:

// open-sse/executors/index.ts
import { MyNewAIExecutor } from "./customProvider";

export function getExecutor(providerId: string) {
  switch (providerId) {
    case "mynewai":
      return new MyNewAIExecutor();
    // existing cases…
  }
}

The factory is called at request time to instantiate the correct executor for each routed request.


Step 5: Add Request/Response Translators (Optional)

If your provider deviates from OpenAI's request/response format, implement translators to convert between OmniRoute's canonical shape and the provider's native API.

Register transformers in open-sse/translator/index.ts:

// open-sse/translator/index.ts
export const requestTransformers = {
  ...DEFAULT_TRANSFORMERS,
  mynewaiRequest: (body) => ({
    prompt: body.messages.map((m) => m.content).join("\n"),
    temperature: body.temperature,
    max_tokens: body.max_tokens,
  }),
};

export const responseTransformers = {
  ...DEFAULT_TRANSFORMERS,
  mynewaiResponse: (raw) => ({
    choices: [{
      message: {
        role: "assistant",
        content: raw.generated_text,
      },
    }],
  }),
};

Then reference these transformers by name in your registry entry (see Step 2).


Step 6: Expose the Provider in the Public API

OmniRoute's REST routes under src/app/api/v1/providers/[provider]/* automatically pick up registry entries. No code change is required for standard chat completions.

The dynamic route handler lives at:

  • src/app/api/v1/providers/[provider]/chat/completions/route.ts

Only create custom routes if you need special endpoints like OAuth callbacks or model management APIs.


Step 7: Add Dashboard UI Support

Add your provider to the dashboard's "Add Provider" UI in src/app/(dashboard)/dashboard/providers/featuredProviders.ts.

Provider Detail Page

Create a helper file for your provider page by copying an existing implementation:

  • Template: src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts

Adjust the provider ID and any provider-specific configuration widgets.


Step 8: Update the Model Catalog

The model catalog at /api/v1/models/catalog pulls data directly from REGISTRY. No extra code is needed if your registry entry includes a models array.

However, if you maintain static capability maps (feature flags per model), update:


Step 9: Handle Database Migrations (Rarely Needed)

Most providers store credentials in the existing provider_connections table. No migration required.

Create a new migration in db/migrations/ only if you need additional per-provider tables. Bump the schema version accordingly.


Step 10: Test Your Integration

Unit Tests

Mock the provider's HTTP endpoint and verify request shaping:

// tests/unit/providers/mynewai.test.ts
import { vi } from "vitest";

vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
  ok: true,
  json: async () => ({ choices: [{ text: "hello" }] }),
}));

// Call the route with providerId = "mynewai" and assert the response

Integration Tests

Execute the full routing pipeline:

curl -X POST http://localhost:3000/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"provider":"mynewai","model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'

CLI Verification

npm run test:all
omniroute providers list

Summary

Adding an AI provider to OmniRoute requires coordinated updates across four architectural layers:

  • Configuration layer — constants and registry (providers.ts, providerRegistry.ts)
  • Execution layer — executor factory and optional custom implementations (executors/)
  • Translation layer — request/response format adapters (translator/)
  • Presentation layer — dashboard UI and API routes ((dashboard)/, api/v1/)

The providerRegistry.ts serves as the central integration point—all other components consume it. Test with both mocked unit tests and live integration calls to ensure end-to-end reliability.


Frequently Asked Questions

What is the minimum code needed to add an OpenAI-compatible provider?

For fully OpenAI-compatible APIs, you only need Steps 1, 2, and 7: register the constant, add a registry entry with baseUrl and models, and list it in the dashboard featured providers. The DefaultExecutor handles transport and the standard translator handles JSON formatting.

When do I need a custom executor versus using the default?

Create a custom executor when your provider requires non-standard headers, request signing, special retry logic, or unique error code handling. If the provider accepts standard Authorization: Bearer headers and returns OpenAI-compatible SSE streams, the default executor suffices.

How does OmniRoute handle authentication for different provider types?

The category field in providers.ts ("API_KEY" or "OAUTH") determines the authentication flow. API key providers use the authHeader function from providerRegistry.ts. OAuth providers trigger additional redirect flows managed by dedicated OAuth handlers in the API routes.

Can I add a provider without modifying the dashboard UI?

Yes—the provider will function via direct API calls to /api/v1/chat/completions with "provider": "your-id". However, users won't see it in the web interface's "Add Provider" list until you update featuredProviders.ts.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →