# How 5ire Abstracts Multiple AI Providers Through a Unified Interface

> Discover how 5ire abstracts multiple AI providers via a unified interface. Seamlessly switch between OpenAI, Azure, Anthropic, and custom endpoints without core code changes.

- Repository: [Ironben/5ire](https://github.com/nanbingxyz/5ire)
- Tags: architecture
- Published: 2026-03-07

---

**5ire abstracts multiple AI providers through a unified interface by treating every AI service as a provider object implementing the `IServiceProvider` contract, enabling seamless switching between OpenAI, Azure, Anthropic, and custom endpoints without modifying core chat logic.**

Managing heterogeneous AI backends in a single application often fragments code into provider-specific implementations. The open-source project **nanbingxyz/5ire** solves this by abstracting multiple AI providers through a unified interface, allowing developers to interact with OpenAI, Azure, Anthropic, Ollama, and custom self-hosted APIs using identical patterns. This architecture centers on a strict provider contract, a centralized registry, and generic chat services that operate on normalized configuration objects.

## The Provider Contract: Defining the Unified Interface

### IServiceProvider Interface Structure

The foundation of 5ire's abstraction layer resides in [`src/providers/types.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/types.ts), which defines the `IServiceProvider` interface. This contract standardizes how every AI service is represented, regardless of its underlying API differences. The interface includes properties for the provider name, API base URL, optional authentication key, pricing details, and a complete chat model configuration object. By enforcing this structure, 5ire ensures that any component consuming a provider can expect consistent fields for building requests and handling responses.

## Concrete Provider Implementations

### Static Metadata Pattern

Each supported AI service implements the `IServiceProvider` contract as a static metadata object exported from its own file. For example, [`src/providers/OpenAI.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/OpenAI.ts) exports a plain JavaScript object that satisfies the interface, containing the default API base URL (`https://api.openai.com/v1`), available model lists, capability flags, and default parameters. Similarly, [`src/providers/Azure.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/Azure.ts), [`src/providers/Anthropic.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/Anthropic.ts), and [`src/providers/Ollama.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/Ollama.ts) follow this identical pattern, each containing only static configuration data without business logic.

### The Provider Registry

The [`src/providers/index.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/index.ts) file functions as the central registry, re-exporting every built-in provider in a mapped object called `providers`. This module exposes two critical helper functions: `getBuiltInProvider`, which retrieves a provider configuration by its `ProviderType` identifier, and `getChatAPISchema`, which returns the appropriate API schema for chat completions. By funneling all provider access through this registry, the application can look up any AI service by name without hardcoding file paths or import statements throughout the codebase.

## Runtime Provider Management

### Merging Built-in and Custom Providers

The [`src/stores/useProviderStore.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/stores/useProviderStore.ts) module handles runtime provider state by merging the built-in registry with user-defined configurations added at runtime. This store normalizes provider fields, ensuring that custom providers added at runtime conform to the same `IServiceProvider` structure as built-in ones. It exposes selectors such as `getAvailableProvider`, `getAvailableModel`, and `getGroupedModelOptions`, which the UI and chat services use to populate dropdown menus and validate selections. The store also manages persistence, saving custom provider configurations between sessions.

### Provider Readiness and Validation

Before initiating chat requests, the store validates provider readiness by checking for required fields. For each provider instance, it verifies that the API base URL is valid and that an API key is present if the provider requires authentication. This validation layer prevents runtime errors by ensuring that only properly configured providers are exposed to the chat services, regardless of whether they are built-in services like OpenAI or custom self-hosted endpoints.

## Unified Chat Service Architecture

### The Base Service Contract

All chat implementations adhere to the `IChatService` interface defined in [`src/intellichat/services/IChatService.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/intellichat/services/IChatService.ts). This contract specifies generic methods for sending messages, handling streaming responses, and managing conversation context. By programming against this interface rather than concrete implementations, the core application logic remains agnostic to whether the underlying provider uses OpenAI's `/chat/completions` endpoint, Anthropic's Messages API, or Azure's deployment-specific URLs.

### Provider-Specific Service Implementations

Concrete services such as [`OpenAIChatService.ts`](https://github.com/nanbingxyz/5ire/blob/main/OpenAIChatService.ts), [`AzureChatService.ts`](https://github.com/nanbingxyz/5ire/blob/main/AzureChatService.ts), and [`AnthropicChatService.ts`](https://github.com/nanbingxyz/5ire/blob/main/AnthropicChatService.ts) extend a base `NextChatService` class, receiving the provider configuration object via their constructors. These implementations handle provider-specific quirks—such as Azure's deployment naming conventions or Anthropic's message formatting—while delegating common tasks like URL construction, header generation (`Authorization: Bearer …`), and payload serialization to shared utilities. This architecture ensures that adding support for a new provider requires only implementing the specific request/response mapping, without duplicating connection management or retry logic.

## Code Examples

### Retrieving a Provider Configuration

To access a provider's settings from the unified store, use the `getAvailableProvider` selector:

```typescript
import useProviderStore from '@/stores/useProviderStore';

// Get the default (or a specific) provider configuration
const provider = useProviderStore.getState().getAvailableProvider('OpenAI');

// provider now contains:
// { name: 'OpenAI', apiBase: 'https://api.openai.com/v1', apiKey: '', … }

```

### Instantiating a Chat Service

Create a chat service instance by combining the provider configuration with a chat context:

```typescript
import OpenAIChatService from '@/intellichat/services/OpenAIChatService';
import { createChatContext } from '@/intellichat/types';

// Build a chat context (model, temperature, etc.)
const context = createChatContext({
  provider,
  model: provider.chat.models[0],   // e.g. gpt‑4o
});

// Instantiate the service – the constructor receives the provider object
const chatService = new OpenAIChatService('myChat', context);

// Send a message
chatService.chat({
  message: 'Explain quantum entanglement in plain English.',
  onMessage: (partial) => console.log('Δ', partial),
  onComplete: (result) => console.log('✅', result),
  onError: (err) => console.error('❌', err),
});

```

### Adding a Custom Provider at Runtime

Extend the system with custom endpoints without modifying source code:

```typescript
import useProviderStore from '@/stores/useProviderStore';

// Define a new provider (e.g., a self‑hosted OpenAI‑compatible API)
const custom = {
  name: 'MyOpenAI',
  apiBase: 'http://localhost:8000/v1',
  apiKey: 'my-secret-key',
  currency: 'USD',
  isDefault: false,
  models: [],            // optional: pre‑populate local models
};

// Persist the custom provider and merge it with built‑ins
useProviderStore.getState().createProvider();           // creates a blank entry
useProviderStore.getState().updateProvider('MyOpenAI', custom);

```

## Summary

- **`IServiceProvider` interface** – The [`src/providers/types.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/types.ts) file defines a strict contract that every AI service must implement, ensuring consistent fields for API endpoints, authentication, and model configurations.
- **Static provider metadata** – Each supported service (OpenAI, Azure, Anthropic, Ollama) exports a plain configuration object from its own file in `src/providers/`, containing only static data without business logic.
- **Centralized registry** – [`src/providers/index.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/index.ts) aggregates all built‑in providers into a map and exposes lookup helpers like `getBuiltInProvider`, decoupling the application from specific import paths.
- **Runtime store management** – [`src/stores/useProviderStore.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/stores/useProviderStore.ts) merges built‑in and custom providers, validates readiness (URL and API key), and exposes selectors such as `getAvailableProvider` and `getAvailableModel`.
- **Generic chat services** – All chat implementations adhere to the `IChatService` interface and receive provider configuration via the `NextChatService` base class, allowing provider‑specific quirks to be handled while sharing common request‑building logic.

## Frequently Asked Questions

### What is the `IServiceProvider` interface in 5ire?

The `IServiceProvider` interface is the core contract defined in [`src/providers/types.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/types.ts) that standardizes how every AI service is represented within the application. It specifies required properties including the provider name, API base URL, optional authentication key, pricing currency, and a complete chat model configuration object, ensuring that any component interacting with a provider can rely on a consistent data structure regardless of whether it is OpenAI, Azure, or a custom endpoint.

### How does 5ire handle custom AI providers that are not built‑in?

5ire handles custom providers through the `useProviderStore` module located in [`src/stores/useProviderStore.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/stores/useProviderStore.ts), which merges built‑in providers with user‑defined configurations added at runtime. Users can define new providers by specifying a name, API base URL, and authentication credentials, then persist them using the `createProvider` and `updateProvider` store methods. The store validates these custom entries against the same `IServiceProvider` interface used for built‑in services, ensuring they integrate seamlessly with the chat services and UI components.

### Can I switch between different AI providers without changing the chat logic?

Yes, the architecture explicitly supports switching between providers without modifying core chat logic. The `IChatService` interface in [`src/intellichat/services/IChatService.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/intellichat/services/IChatService.ts) defines a generic contract that all chat implementations follow, while concrete services like `OpenAIChatService` or `AnthropicChatService` extend the base `NextChatService` class and receive provider configuration through their constructors. Because the services operate on the normalized `IServiceProvider` object and share common request‑building logic, changing from OpenAI to Azure or to a custom provider only requires selecting a different provider from the store, leaving the chat invocation code unchanged.

### Where are the built‑in AI providers registered in the 5ire codebase?

Built‑in providers are registered in the central registry located at [`src/providers/index.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/providers/index.ts). This file imports the static configuration objects from individual provider files (such as [`OpenAI.ts`](https://github.com/nanbingxyz/5ire/blob/main/OpenAI.ts), [`Azure.ts`](https://github.com/nanbingxyz/5ire/blob/main/Azure.ts), and [`Anthropic.ts`](https://github.com/nanbingxyz/5ire/blob/main/Anthropic.ts)) and aggregates them into a `providers` map object. It also exports helper functions including `getBuiltInProvider` for retrieving a specific provider by its `ProviderType` identifier and `getChatAPISchema` for resolving API schemas, effectively decoupling the rest of the application from the specific file locations of each provider implementation.