# How to Add a Custom Provider to the OmniRoute Registry: Step-by-Step Guide

> Learn how to add a custom provider to the OmniRoute registry with this step-by-step guide on inserting metadata, validating schemas, and implementing custom executors.

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

---

**To add a custom provider to the OmniRoute registry, insert a metadata object into the correct authentication category file under `src/shared/constants/providers/`, ensure it passes the Zod schema validation in [`src/shared/constants/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts), and optionally implement a custom executor if the API is not OpenAI-compatible.**

OmniRoute catalogs every LLM provider in a single registry that powers routing logic, UI listings, and API validation. When you add a custom provider to the OmniRoute registry, the central `AI_PROVIDERS` proxy in [`src/shared/constants/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts) automatically discovers the entry from its category import, so no manual registration step is required. Every definition is validated against a strict Zod schema to guarantee consistency across the routing engine.

## Choose the Authentication Category

OmniRoute organizes providers by authentication type. You must add your definition to the correct file so the UI and validation layers handle credentials properly:

- **No-auth:** [`src/shared/constants/providers/noauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers/noauth.ts) — for providers that require no credentials.
- **OAuth:** [`src/shared/constants/providers/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers/oauth.ts) — for providers that use an OAuth flow.
- **API-key:** `src/shared/constants/providers/apikey/*.ts` — for bearer-style API key services.
- **Web-cookie:** [`src/shared/constants/providers/web-cookie.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers/web-cookie.ts) — for session-cookie-based access.
- **Local / Self-hosted:** [`src/shared/constants/providers/local.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers/local.ts) — for Ollama, LM Studio, and similar.
- **Specialized:** additional files under `src/shared/constants/providers/` for search, audio-only, upstream-proxy, cloud-agent, and system providers.

Third-party LLM services usually fall under **OAuth** or **API-key**, so pick the category that matches the provider’s authentication method.

## Insert the Provider Definition into the OmniRoute Registry

Open the file that matches your selected category and append a new object literal. Below is the pattern for an OAuth provider called **ExampleAI** in [`src/shared/constants/providers/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers/oauth.ts):

```ts
// src/shared/constants/providers/oauth.ts
export const OAUTH_PROVIDERS = {
  // Existing providers …
  exampleai: {
    id: "exampleai",               // Unique identifier (used everywhere)
    alias: "exa",                  // Short alias used in UI and CLI (optional)
    name: "ExampleAI",             // Human-readable name
    icon: "smart_toy",             // Icon name from the built-in icon set
    color: "#123456",              // Brand colour (hex)
    subscriptionRisk: true,        // Set true if the provider requires a paid subscription
    riskNoticeVariant: "oauth",    // Schema variant (e.g., "oauth", "webCookie", "deprecated", "embedded-service")
    authHint: "Paste the OAuth token from the ExampleAI dashboard.", // Optional UI hint
    hasFree: true,                 // Optional – indicate a free tier exists
  },
};

```

The `exampleai` key and the `id` field must be unique across all provider categories.

### Required and Optional Fields

The Zod schema in [`src/shared/validation/providerSchema.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/validation/providerSchema.ts) enforces the following shape for every entry:

- **`id`** — stable identifier; must be unique across all categories.
- **`name`** — display name shown in the UI.
- **`icon`** — icon name from the UI icon library.
- **`color`** — brand colour as a hex string.
- **`subscriptionRisk`** — boolean indicating whether the provider may charge users.
- **`riskNoticeVariant`** — documented variants include `"oauth"`, `"webCookie"`, `"deprecated"`, and `"embedded-service"`.

Optional but recommended fields include **`alias`** for CLI shortcuts, **`authHint`** for helper text in the Add Provider dialog, **`hasFree`** to signal a free tier, and **`website`** or **`textIcon`** for extra branding.

### How the Global Registry Discovers New Providers

You do not need to import the new entry manually. The file [`src/shared/constants/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts) pulls in every category constant on lines 13–22 and merges them into the exported `AI_PROVIDERS` proxy:

```ts
// src/shared/constants/providers.ts
import { NOAUTH_PROVIDERS } from "./providers/noauth";
import { OAUTH_PROVIDERS } from "./providers/oauth";
import { WEB_COOKIE_PROVIDERS } from "./providers/web-cookie";
import { APIKEY_PROVIDERS } from "./providers/apikey";
import { LOCAL_PROVIDERS } from "./providers/local";
import { SEARCH_PROVIDERS } from "./providers/search";
import { AUDIO_ONLY_PROVIDERS } from "./providers/audio";
import { UPSTREAM_PROXY_PROVIDERS } from "./providers/upstream-proxy";
// … additional category imports (lines 13–22)

```

Because the aggregator imports the entire category constant, your new provider is automatically visible to the routing engine and UI as soon as you save the file.

## Validate Your Changes Against the Zod Schema

At the bottom of [`src/shared/constants/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts), the library validates each section using `validateProviders` from the provider schema:

```ts
// src/shared/constants/providers.ts (lines 32–43)
import { validateProviders } from "../validation/providerSchema";

validateProviders(NOAUTH_PROVIDERS, "NOAUTH_PROVIDERS");
validateProviders(OAUTH_PROVIDERS, "OAUTH_PROVIDERS");
validateProviders(APIKEY_PROVIDERS, "APIKEY_PROVIDERS");
// … additional validation calls

```

After adding your definition, run the type-check command:

```bash
npm run typecheck:core

```

If any field violates the schema, the command prints a clear error pointing to the offending property. You should also run `npm run lint && npm run test` to confirm that formatting and existing functionality remain intact.

## Add Custom Request Handling for Non-Standard APIs (Optional)

Providers that follow the OpenAI request shape work out-of-the-box with the default executor in [`open-sse/executors/default.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/default.ts). If your custom provider uses a non-standard API, custom headers, or a different payload format, you must:

1. **Create a new executor** under `open-sse/executors/` that extends `BaseExecutor`.
2. **Register it** in [`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts) inside the `getExecutor()` factory so the router can resolve it by provider ID.
3. **Add a translator** (if needed) under `open-sse/translator/` to map between OmniRoute’s internal format and the provider’s format.

Refer to [`docs/frameworks/EXECUTORS.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/frameworks/EXECUTORS.md) in the repository for the full custom executor specification.

## Full Example: Adding an API-Key Provider to the OmniRoute Registry

Below is a complete snippet for an imaginary API-key provider called **FastAI** in the API-key category file:

```ts
// src/shared/constants/providers/apikey/index.ts
export const APIKEY_PROVIDERS = {
  // Existing providers …
  fastai: {
    id: "fastai",
    alias: "fa",
    name: "FastAI",
    icon: "bolt",
    color: "#00A8E8",
    subscriptionRisk: false,
    riskNoticeVariant: "apikey",
    authHint: "Paste your FastAI API key (Bearer token).",
    hasFree: true,
  },
};

```

The `APIKEY_PROVIDERS` object is defined in [`src/shared/constants/providers/apikey/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers/apikey/index.ts). After committing the change, run:

```bash
npm run lint
npm run typecheck:core
npm run test

```

Once the build succeeds, FastAI appears in the **Add Provider** dropdown, becomes selectable in the UI, and is fully routable by the combo engine.

## Summary

- **Pick the authentication category** that matches the provider in `src/shared/constants/providers/`.
- **Define the provider object** with all required Zod fields: `id`, `name`, `icon`, `color`, `subscriptionRisk`, and `riskNoticeVariant`.
- **Save the file** — [`src/shared/constants/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts) auto-imports the category and exposes the provider through the `AI_PROVIDERS` proxy.
- **Run `npm run typecheck:core`** to confirm schema compliance and catch validation errors early.
- **Implement a custom executor and translator** only if the provider deviates from the standard OpenAI request format.

## Frequently Asked Questions

### What fields are required when adding a custom provider to the OmniRoute registry?

The Zod schema enforces **`id`**, **`name`**, **`icon`**, **`color`**, **`subscriptionRisk`**, and **`riskNoticeVariant** for every provider. Fields such as `alias`, `authHint`, `hasFree`, and `website` are optional but recommended for a better UI experience.

### Do I need to manually import my new provider into a central registry?

No. The file [`src/shared/constants/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/providers.ts) already imports each category constant on lines 13–22 and merges them into the `AI_PROVIDERS` proxy. As long as you add your object to the correct category file, the rest of the system discovers it automatically without extra imports.

### How do I know if I need a custom executor?

You only need a custom executor if the provider does not follow the standard OpenAI request shape. The default executor in [`open-sse/executors/default.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/default.ts) handles most OpenAI-compatible services. For non-standard payloads or custom headers, create an executor in `open-sse/executors/` and wire it into [`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts).

### What command should I run to validate a new provider entry?

Run `npm run typecheck:core` to execute the Zod validation against your changes. You should also run `npm run lint` and `npm run test` to ensure that formatting and existing functionality remain intact.