# How Provider Executors Work in OmniRoute: Implementation Guide and Custom Use Cases

> Learn how to implement provider executors in OmniRoute and when to build custom ones. This guide explores implementation details and use cases for diverging providers.

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

---

**OmniRoute routes every request through an executor class that inherits from `BaseExecutor`, and you only need to build a custom executor when a provider diverges from the OpenAI-compatible format in its URL structure, authentication scheme, or request body requirements.**

OmniRoute uses a Strategy pattern to abstract provider-specific logic into reusable executor classes. Every request flowing through the system is handled by an executor that knows how to communicate with a specific upstream LLM provider. Understanding how these **provider executors** are implemented—and when to extend them—is essential for integrating non-standard models or optimizing routing behavior.

## The BaseExecutor Architecture

All executors in OmniRoute inherit from the core **`BaseExecutor`** class defined in [`open-sse/executors/base.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/base.ts). This base class implements the Strategy pattern and provides the common workflow that every provider follows:

- **`buildUrl`** – Constructs the request endpoint, defaulting to the provider’s static `baseUrl` or falling back to an OpenAI-compatible endpoint
- **`buildHeaders`** – Assembles request headers, adding `Content-Type`, provider-specific defaults, and handling extra API-key rotation
- **`transformRequest`** – Normalizes the request body by stripping empty fields, removing unsupported parameters, and applying provider-specific transformations like Claude-Code tool-name cloaking
- **`refreshCredentials`** – Handles token refresh for OAuth or short-lived tokens (default is a no-op)
- **`execute`** – Performs the HTTP call with intra-URL retries, timeout handling, optional fingerprinting, and request signing for Claude-compatible providers

The base class spans lines 36-90 in [`open-sse/executors/base.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/base.ts) and encapsulates the generic request lifecycle, allowing specific providers to override only the methods that differ from the standard OpenAI contract.

## When to Implement Custom Provider Executors

Custom executors are required only when a provider diverges from the OpenAI-compatible JSON schema. The following scenarios necessitate a custom implementation:

### Non-Standard Endpoint URLs

Providers like **Google Vertex AI** require complex URL paths such as `v1/projects/<project>/locations/<region>/publishers/google/models/<model>:generateContent`. In [`open-sse/executors/vertex.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/vertex.ts), the executor overrides `buildUrl` to assemble the Google-specific path and uses `resolveBaseUrl` to handle per-connection `providerSpecificData.baseUrl`.

### Azure-Specific Deployment Routing

**Azure OpenAI** requires URLs containing the deployment name and API version: `/openai/deployments/<deployment>/chat/completions?api-version=2023-05-15`. The [`azure-openai.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/azure-openai.ts) executor overrides `buildUrl` to inject the deployment and modifies `buildHeaders` to use the `api-key` header instead of Bearer tokens.

### Authentication and Token Refresh

Providers using OAuth or short-lived tokens must override **`refreshCredentials`**. The Vertex executor ([`vertex.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/vertex.ts)) calls the Google token endpoint to fetch fresh OAuth access tokens before each request, then adds `Authorization: Bearer …` headers in `buildHeaders`.

### Request Signing and Body Transformation

**Anthropic Claude-Code** requires signed request bodies and mandatory billing headers. The [`claude.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/claude.ts) executor overrides `transformRequest` for tool-name cloaking and context editing, and extends `execute` to add billing headers and call `signRequestBody`.

**Groq** rejects certain fields like `prompt_cache_retention`. The [`groq.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/groq.ts) executor overrides `transformRequest` to call `stripGroqUnsupportedFields`, ensuring compatibility without modifying the base class.

## Using the DefaultExecutor for OpenAI-Compatible Providers

If a provider already conforms to the OpenAI-compatible JSON schema, use the generic **`DefaultExecutor`** located in [`open-sse/executors/default.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/default.ts). This class inherits all behavior from `BaseExecutor` without any overrides, making it suitable for standard OpenAI-compliant endpoints.

The executor selection logic in `getExecutor()` ([`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts)) automatically returns `DefaultExecutor` for any provider ID not explicitly mapped to a custom class.

## Implementing a Custom Executor

Follow these steps to add support for a new provider that requires custom handling.

### Creating the Executor Class

Extend `BaseExecutor` and override only the methods that differ from the OpenAI standard. Here is a minimal example for a fictional "my-cloud" provider:

```typescript
import { BaseExecutor, ProviderCredentials, ExecuteInput } from '@/open-sse/executors/base.ts';

export class MyCloudExecutor extends BaseExecutor {
  // Custom URL composition for Azure-style endpoints
  buildUrl(model: string, stream: boolean, urlIndex = 0, credentials: ProviderCredentials | null) {
    const base = this.getBaseUrls()[urlIndex];
    return `${base}/v1/models/${model}:predict`;
  }

  // Custom header for my-cloud authentication
  buildHeaders(credentials: ProviderCredentials, stream = true) {
    const { headers } = super.buildHeadersPreamble(credentials, stream);
    if (credentials.apiKey) {
      headers['x-my-token'] = credentials.apiKey;
    }
    return headers;
  }

  // No body transformation needed – payload forwards as-is
}

```

### Registering the Executor

Add your executor to the registry in [`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts):

```typescript
import { MyCloudExecutor } from '@/open-sse/executors/my-cloud.ts';
import { executorRegistry } from '@/open-sse/executors/index.ts';

executorRegistry.set('my-cloud', (config) => new MyCloudExecutor('my-cloud', config));

```

### Selecting Executors at Runtime

Use the `getExecutor()` factory function to retrieve the appropriate executor for a provider:

```typescript
import { getExecutor } from '@/open-sse/executors/index.ts';

const executor = getExecutor('my-cloud', {
  baseUrl: 'https://api.mycloud.com/v1',
  timeoutMs: 30_000,
});

await executor.execute({
  model: 'llama-3-70b',
  body: { messages: [{ role: 'user', content: 'Hello' }] },
  stream: true,
  credentials: {
    apiKey: process.env.MYCLOUD_API_KEY,
    providerSpecificData: {},
  },
  signal: abortCtrl.signal,
});

```

## Summary

- **All executors inherit from `BaseExecutor`** ([`open-sse/executors/base.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/base.ts)), which implements the Strategy pattern for the request lifecycle
- **Override specific methods** (`buildUrl`, `buildHeaders`, `transformRequest`, `refreshCredentials`) only when the provider diverges from OpenAI standards
- **Use `DefaultExecutor`** for any OpenAI-compatible provider without modification
- **Register custom executors** in [`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts) to make them available to the routing layer via `getExecutor()`

## Frequently Asked Questions

### What is the difference between BaseExecutor and DefaultExecutor in OmniRoute?

**`BaseExecutor`** is the abstract class in [`open-sse/executors/base.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/base.ts) that defines the request lifecycle and common functionality for all providers. **`DefaultExecutor`** is a concrete implementation in [`open-sse/executors/default.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/default.ts) that inherits from `BaseExecutor` without adding any overrides, making it suitable for standard OpenAI-compatible providers.

### How do I add support for a new LLM provider that uses OAuth2 authentication?

Extend `BaseExecutor` and override the **`refreshCredentials`** method to fetch fresh tokens from the OAuth endpoint, as demonstrated in [`open-sse/executors/vertex.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/vertex.ts). Then override **`buildHeaders`** to inject the `Authorization: Bearer …` header using the refreshed token.

### Can I use the same executor for multiple providers if they are both OpenAI-compatible?

Yes. For any provider that follows the OpenAI JSON schema, you can use **`DefaultExecutor`** without modification. The `getExecutor()` function in [`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts) automatically falls back to `DefaultExecutor` for any provider ID not explicitly registered to a custom class.

### Where should I register a new custom executor in the codebase?

Register custom executors in **[`open-sse/executors/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/index.ts)** by importing the class and adding it to the `executorRegistry` Map with the provider ID as the key. This allows `getExecutor()` to instantiate the correct class when routing requests to that provider.