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

> Integrate a new AI provider into OmniRoute with this step-by-step guide. Learn to register identifiers, configure endpoints, and update the UI for seamless routing.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-07

---

**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](https://github.com/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts):

```typescript
// 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/config/providerRegistry.ts):

```typescript
// 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/customProvider.ts):

```typescript
// 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts):

```typescript
// 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts):

```typescript
// 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

### Featured Providers List

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:

- [`src/app/api/v1/models/catalog.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/models/catalog.ts)

---

## 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:

```typescript
// 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:

```bash
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

```bash
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/providers.ts), [`providerRegistry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/providers.ts) (`"API_KEY"` or `"OAUTH"`) determines the authentication flow. API key providers use the `authHeader` function from [`providerRegistry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/featuredProviders.ts).