AdaptorManager in Bella OpenAPI: How Protocol Requests Are Routed to AI Providers
AdaptorManager is a singleton registry that maintains a thread-safe map of protocol adapters, enabling Bella OpenAPI to route incoming requests to the correct AI provider implementation based on endpoint and protocol matching.
The AdaptorManager serves as the central routing authority in Bella OpenAPI (lianjiatech/bella-openapi), managing the discovery and dispatch of requests to provider-specific implementations like OpenAI, Gemini, and Azure. This component bridges the generic Bella API surface with native AI provider protocols, ensuring that each request reaches the appropriate adapter for translation and execution.
AdaptorManager Singleton Design and Registry Structure
The AdaptorManager follows the singleton pattern to maintain a centralized, thread-safe registry of all available protocol adapters. At its core, the manager stores a nested concurrent hash map where the outer key represents the endpoint name (e.g., chat/completions), and the inner map associates adapter class names with their instantiated implementations.
In api/server/src/main/java/com/ke/bella/openapi/protocol/AdaptorManager.java, the registry is defined as:
public class AdaptorManager {
private static final AdaptorManager INSTANCE = new AdaptorManager();
private final Map<String, Map<String, IProtocolAdaptor>> adaptors = new ConcurrentHashMap<>();
private AdaptorManager() { }
public static AdaptorManager getInstance() {
return INSTANCE;
}
…
}
Key design details:
- Outer map key: The endpoint path (e.g.,
chat/completions,audio/transcriptions) - Inner map key: The simple class name of the adapter (e.g.,
OpenAIAdaptor,GeminiAdaptor) - Value: The
IProtocolAdaptorimplementation instance
This structure allows multiple adapters to register for the same endpoint, supporting protocol diversity within a single API surface.
Registering Adapters with AdaptorManager at Startup
Registration occurs automatically during Spring Boot initialization through api/server/src/main/java/com/ke/bella/openapi/configuration/BellaAutoConf.java. The configuration class injects all beans implementing IProtocolAdaptor and registers them with the singleton manager.
@Bean
public AdaptorManager adaptorManager(@Autowired List<IProtocolAdaptor> adaptors) {
AdaptorManager manager = AdaptorManager.getInstance();
adaptors.forEach(adaptor -> manager.register(adaptor.endpoint(), adaptor));
return manager;
}
Each adapter implements the endpoint() method to declare which Bella OpenAPI endpoint it handles. During startup, the manager populates its internal map by calling register(String endpoint, IProtocolAdaptor adaptor), making the adapters available for runtime routing without manual configuration.
Querying AdaptorManager for Protocol Support
The AdaptorManager exposes several query methods to verify adapter availability and retrieve implementations:
getProtocols(String endpoint): Returns the set of registered protocol names for a specific endpoint.support(String endpoint, String protocol): Validates whether a given protocol adapter exists for the requested endpoint.getProtocolAdaptor(String endpoint, String protocol): Retrieves the rawIProtocolAdaptorinterface implementation.getProtocolAdaptor(String endpoint, String protocol, Class<T> clazz): Returns the adapter cast to a concrete subclass (e.g.,CompletionAdaptor.class).
These methods enable both the routing layer and controllers to validate capabilities before attempting request execution.
Request Routing Through AdaptorManager
ChannelRouter Protocol Filtering
When a request arrives, the ChannelRouter in api/server/src/main/java/com/ke/bella/openapi/protocol/ChannelRouter.java first queries the database for candidate channels (provider instances), then filters these channels by protocol support using the AdaptorManager:
List<ChannelDB> endpointMatched = channels.stream()
.filter(channel -> AdaptorManager.getInstance()
.support(endpoint, channel.getProtocol()))
.collect(Collectors.toList());
Only channels with a registered adapter for the requested endpoint survive this filter. The router subsequently applies safety-level, quota, and rate-limit checks to select the final channel for execution.
Controller Adapter Retrieval
After the router selects a channel, controllers obtain the concrete adapter instance to process the request. The ChatController in api/server/src/main/java/com/ke/bella/openapi/endpoints/ChatController.java demonstrates this pattern:
// ChatController – completion request
CompletionAdaptor<?> adaptor = adaptorManager.getProtocolAdaptor(
endpoint, protocol, CompletionAdaptor.class);
ChatResponse resp = adaptor.completion(request);
Every endpoint controller follows this delegation model: query the AdaptorManager for the specific implementation, then invoke the provider-specific translation logic.
Extending AdaptorManager with Custom Adapters
Registering a New Provider Adapter
To add support for a new AI provider, implement IProtocolAdaptor and declare it as a Spring component. The framework automatically discovers and registers the adapter.
// Example: a new provider called "FooAI"
@Component
public class FooCompletionAdaptor implements IProtocolAdaptor<CompletionRequest, CompletionResponse> {
@Override
public String endpoint() {
return "chat/completions"; // the Bella endpoint this adaptor handles
}
@Override
public String getDescription() {
return "FooAI completion service";
}
// implementation of the actual call to FooAI …
}
No additional registration code is required—the BellaAutoConf class handles injection into the AdaptorManager during context refresh.
Manual Adapter Lookup
For specialized use cases requiring direct adapter access, obtain the singleton instance and query by endpoint and protocol:
AdaptorManager manager = AdaptorManager.getInstance();
// Verify support first (optional)
if (!manager.support("chat/completions", "FooCompletionAdaptor")) {
throw new IllegalArgumentException("Protocol not supported");
}
// Get the concrete adaptor
FooCompletionAdaptor adaptor = manager.getProtocolAdaptor(
"chat/completions", "FooCompletionAdaptor", FooCompletionAdaptor.class);
// Use it
CompletionResponse resp = adaptor.completion(myRequest);
Summary
- AdaptorManager is a singleton registry in
api/server/src/main/java/com/ke/bella/openapi/protocol/AdaptorManager.javathat maps Bella OpenAPI endpoints to protocol-specific adapter implementations. - Registration occurs automatically at startup via
api/server/src/main/java/com/ke/bella/openapi/configuration/BellaAutoConf.java, which injects allIProtocolAdaptorbeans into the manager. - Routing relies on the
support()method to filter database channels inChannelRouter.java, ensuring only compatible providers are considered for request handling. - Execution follows a delegation pattern where controllers retrieve typed adapters via
getProtocolAdaptor()and invoke provider-specific translation methods. - Extensibility is achieved by implementing
IProtocolAdaptorand declaring the class as a Spring component, requiring no manual registry configuration.
Frequently Asked Questions
What is the primary responsibility of AdaptorManager in Bella OpenAPI?
AdaptorManager maintains a centralized registry of protocol adapters and serves as the lookup authority for routing requests. It enables the framework to dispatch requests to the correct provider-specific implementation (such as OpenAI or Gemini) based on the endpoint path and protocol identifier, abstracting provider differences from the core API layer.
How does AdaptorManager support multiple AI providers for the same endpoint?
The manager stores a nested map structure where each endpoint key maps to multiple protocol adapters. During routing, ChannelRouter filters candidate channels by checking AdaptorManager.support(), allowing the system to maintain parallel implementations for providers like Azure, OpenAI, and Gemini under a single chat/completions endpoint.
Can developers add custom protocol adapters without modifying core Bella OpenAPI code?
Yes. Developers implement the IProtocolAdaptor interface, annotate the class with @Component, and implement the endpoint() method to declare the target API path. Spring Boot's component scanning automatically injects the adapter into BellaAutoConf, which registers it with the AdaptorManager singleton at startup without requiring changes to the core registry logic.
What happens if a request specifies a protocol with no registered adapter?
If AdaptorManager.support() returns false for the requested endpoint and protocol combination, the ChannelRouter filters out all channels associated with that protocol, resulting in an empty candidate list. This typically causes the routing layer to return an error indicating that no available channel supports the requested protocol, preventing invalid requests from reaching the execution stage.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →