# How Bella OpenAPI Implements the Protocol Adapter Pattern for AI Provider Routing

> Discover how Bella OpenAPI uses the protocol adapter pattern and Spring auto-configuration to seamlessly route requests to various AI providers without altering core controller logic.

- Repository: [Ke Technologies/bella-openapi](https://github.com/lianjiatech/bella-openapi)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Bella OpenAPI isolates every AI provider behind a unified `IProtocolAdaptor` contract, using a central `AdaptorManager` registry and Spring auto-configuration to route requests without modifying core controller logic.**

The [lianjiatech/bella-openapi](https://github.com/lianjiatech/bella-openapi) repository demonstrates a clean **protocol adapter pattern** implementation that decouples the HTTP request pipeline from vendor-specific AI provider APIs. By enforcing a standard adapter interface and automating registration through Spring Boot, the system enables zero-code changes when adding new LLM providers like OpenAI, Azure, or custom endpoints.

## Core Components of the Protocol Adapter Pattern

### The IProtocolAdaptor Contract

At the heart of the system lies the `IProtocolAdaptor` interface located in [[`api/server/src/main/java/com/ke/bella/openapi/protocol/IProtocolAdaptor.java`](https://github.com/lianjiatech/bella-openapi/blob/main/api/server/src/main/java/com/ke/bella/openapi/protocol/IProtocolAdaptor.java)](https://github.com/lianjiatech/bella-openapi/blob/develop/api/server/src/main/java/com/ke/bella/openapi/protocol/IProtocolAdaptor.java). This contract mandates four critical capabilities that every provider must expose:

- **`endpoint()`** – Returns the API path segment (e.g., `"chat/completions"`) this adapter handles.
- **`getDescription()`** – Provides a human-readable label for UI and documentation generation.
- **`getPropertyClass()`** – Declares the specific DTO class used to deserialize request bodies (e.g., `CompletionProperty`).
- **Helper methods** – Standardized utilities for authentication header construction and large-object cleanup.

### Concrete Adaptor Interfaces

Specific AI capabilities extend the base contract through typed sub-interfaces. For example, [[`CompletionAdaptor.java`](https://github.com/lianjiatech/bella-openapi/blob/main/CompletionAdaptor.java)](https://github.com/lianjiatech/bella-openapi/blob/develop/api/server/src/main/java/com/ke/bella/openapi/protocol/completion/CompletionAdaptor.java) narrows the generic contract to completion-specific request properties:

```java
package com.ke.bella.openapi.protocol.completion;

import com.ke.bella.openapi.protocol.IProtocolAdaptor;
import com.ke.bella.openapi.protocol.CompletionProperty;

public interface CompletionAdaptor<T extends CompletionProperty> extends IProtocolAdaptor {
    // Implementation provides request-building logic for completion endpoints
}

```

This inheritance strategy allows the system to maintain type safety while supporting diverse operation types (embeddings, chat, image generation) under the same routing umbrella.

### The AdaptorManager Registry

The [[`AdaptorManager.java`](https://github.com/lianjiatech/bella-openapi/blob/main/AdaptorManager.java)](https://github.com/lianjiatech/bella-openapi/blob/develop/api/server/src/main/java/com/ke/bella/openapi/protocol/AdaptorManager.java) class functions as a global singleton registry maintaining a nested map structure: **endpoint → protocol → adaptor instance**. It exposes three primary operations:

- **`getProtocolAdaptor(String endpoint, String protocol)`** – Retrieves the concrete adapter for a specific provider protocol.
- **`support(String endpoint, String protocol)`** – Boolean check verifying whether a protocol adapter exists for the given endpoint.
- **`getProtocolAdaptors(String endpoint)`** – Returns all registered adapters for an endpoint, used for capability discovery.

### Spring Auto-Configuration with BellaAutoConf

Registration occurs automatically at startup via [[`BellaAutoConf.java`](https://github.com/lianjiatech/bella-openapi/blob/main/BellaAutoConf.java)](https://github.com/lianjiatech/bella-openapi/blob/develop/api/server/src/main/java/com/ke/bella/openapi/configuration/BellaAutoConf.java). This configuration class autowires every `IProtocolAdaptor` bean discovered in the classpath and injects them into the `AdaptorManager`:

```java
@Configuration
public class BellaAutoConf {

    @Bean
    public AdaptorManager adaptorManager(@Autowired List<IProtocolAdaptor> adaptors) {
        AdaptorManager manager = AdaptorManager.getInstance();
        adaptors.forEach(adaptor -> manager.register(adaptor.endpoint(), adaptor));
        return manager;
    }
}

```

This design eliminates manual registration; adding a new provider requires only implementing the interface and annotating the class with Spring's `@Component`.

## Runtime Request Routing Flow

When a client sends a request to `/v1/chat/completions`, the following sequence executes:

1. **Controller Receipt** – The Spring controller receives the HTTP request after security interceptors validate API keys and quotas.
2. **Channel Selection** – [[`ChannelRouter.java`](https://github.com/lianjiatech/bella-openapi/blob/main/ChannelRouter.java)](https://github.com/lianjiatech/bella-openapi/blob/develop/api/server/src/main/java/com/ke/bella/openapi/protocol/ChannelRouter.java) queries available channels (provider instances) and filters them using `AdaptorManager.getInstance().support(endpoint, channel.getProtocol())`. Only channels with registered protocol adapters proceed.
3. **Adaptor Resolution** – The router returns a `ChannelDB` object, and the controller fetches the concrete implementation:

   ```java
   IProtocolAdaptor adaptor = adaptorManager.getProtocolAdaptor(
           channel.getEndpoint(), 
           channel.getProtocol()
   );
   ```

4. **Request Construction** – The controller uses `adaptor.getPropertyClass()` to deserialize the JSON body into the correct DTO (e.g., `OpenAICompletionProperty`), then invokes the adapter's builder methods to create an `okhttp3.Request` with proper authentication headers.
5. **Execution** – The adapter executes the provider-specific HTTP call, and the system handles response streaming, cost accounting, and metrics downstream.

## Adding a New AI Provider

Extending the system to support a new AI service requires three steps with zero changes to existing routing logic:

1. **Create the Implementation Class**

   ```java
   @Component
   public class AnthropicCompletionAdaptor implements CompletionAdaptor<AnthropicProperty> {
       
       @Override
       public String endpoint() {
           return "chat/completions";
       }
       
       @Override
       public String getDescription() {
           return "Anthropic Claude Chat Completion";
       }
       
       @Override
       public Class<?> getPropertyClass() {
           return AnthropicProperty.class;
       }
       
       // Provider-specific request building logic here
   }
   ```

2. **Define the Property DTO** – Create `AnthropicProperty` extending `CompletionProperty` to handle Anthropic's unique request fields.

3. **Deploy** – Spring's component scanning automatically picks up the `@Component` annotation, `BellaAutoConf` registers it with `AdaptorManager`, and the `ChannelRouter` immediately begins routing compatible requests to the new provider.

## Summary

- **IProtocolAdaptor** defines the mandatory contract for all provider integrations, standardizing endpoint names, descriptions, and property classes.
- **AdaptorManager** maintains a thread-safe registry mapping endpoints and protocols to concrete adapter instances.
- **BellaAutoConf** automates adapter discovery and registration using Spring's dependency injection container.
- **ChannelRouter** enforces protocol compatibility at runtime, filtering channels based on `AdaptorManager.support()` checks.
- **Zero-code integration** is achieved for new providers by implementing the interface and declaring a Spring bean.

## Frequently Asked Questions

### What is the protocol adapter pattern in Bella OpenAPI?

The protocol adapter pattern in Bella OpenAPI is an architectural design that isolates vendor-specific AI provider implementations behind a common interface (`IProtocolAdaptor`). This allows the core routing and controller layers to remain agnostic of whether the underlying provider is OpenAI, Azure, or a custom LLM endpoint, enabling seamless provider switching and addition without modifying business logic.

### How does the system decide which AI provider handles a request?

The `ChannelRouter` class decides by first retrieving a list of candidate channels (provider instances) that meet safety, quota, and load-balancing criteria. It then validates each channel against `AdaptorManager.support(endpoint, channel.getProtocol())` to ensure a registered adapter exists for that provider's protocol. The first valid channel is selected, and its associated adapter is retrieved via `adaptorManager.getProtocolAdaptor()` to handle the request.

### Can I add a custom AI provider without modifying existing code?

Yes. You only need to create a new class implementing `IProtocolAdaptor` (or a specialized sub-interface like `CompletionAdaptor`), annotate it with `@Component`, and ensure it is on the classpath. Spring Boot's auto-configuration in `BellaAutoConf` automatically registers the adapter with the `AdaptorManager` at startup, making it available for routing immediately.

### Where is the adapter registry stored and queried?

The adapter registry is stored as a concurrent map inside the `AdaptorManager` singleton class, mapping endpoint strings to protocol strings to adapter instances. Controllers and routers query this registry at runtime using `getProtocolAdaptor()` to retrieve the correct implementation for request building, or `getProtocolAdaptors()` to list available protocols for documentation and frontend discovery via `EndpointService`.