How to Integrate Custom AI Models into HolaOS: A Complete Developer Guide
Yes, HolaOS supports custom AI model integration through its model‑agnostic harness architecture, allowing you to register any provider and model without modifying core runtime code.
The HolaOS platform is designed around a declarative model registry system that decouples AI capabilities from specific vendors. Whether you need to connect a private OpenAI‑compatible endpoint, an Ollama instance, or a proprietary model gateway, the runtime resolves models dynamically through typed configuration fields and a centralized routing layer.
Understanding the HolaOS Model Architecture
HolaOS uses three core abstractions for AI model integration:
- Provider: A connection configuration (base URL, authentication, timeouts) identified by a
provider_id - Model: A concrete model descriptor registered under a provider, identified by a
model_id - Harness: The runtime component that consumes models through the routing layer
The ModelRegistry class in runtime/harness-host/src/pi.ts maintains these mappings in memory, while the routing layer in runtime/harnesses/src/model-routing.ts handles normalization and lookup at request time.
This separation means you can add, remove, or swap models without redeploying the core platform—only the registry configuration changes.
Registering a Custom Model Provider
Before adding individual models, you must register the provider that hosts them. This typically occurs during server initialization.
// runtime/harness-host/src/pi.ts
import { ModelRegistry } from "./model-registry";
import { buildPiProviderConfig } from "./provider-config";
const modelRegistry = ModelRegistry.create();
// Register a custom proxy or direct endpoint
modelRegistry.registerProvider(
"my_custom_proxy",
buildPiProviderConfig({
baseUrl: "https://my-model-gateway.example.com",
authToken: process.env.MY_PROXY_TOKEN,
})
);
The buildPiProviderConfig helper constructs a normalized configuration object that the runtime uses for connection pooling and retry logic. Supported provider types include openai, ollama_direct, and holaboss_model_proxy.
Adding Models to the Registry
Once the provider exists, register specific models under it:
// Continued from above
modelRegistry.registerModel("my_custom_proxy", {
id: "my-gpt-5-custom",
name: "My Custom GPT-5",
maxTokens: 8192,
// Additional metadata for runtime optimizations
});
The id field becomes your model_id throughout the system. The name field appears in UI selectors and logs. Optional fields like maxTokens guide the runtime's request batching and context window management.
Consuming Custom Models in Harness Requests
With the model registered, reference it in any harness payload:
// runtime/harnesses/src/pi.ts
import type { HarnessModelRoutingRequest } from "./model-routing";
const request: HarnessModelRoutingRequest = {
provider_id: "my_custom_proxy",
model_id: "my-gpt-5-custom",
model_client: "openai", // Routing hint for protocol adaptation
// Prompt, temperature, and other inference parameters follow
};
await startPiTool(request);
The startPiTool function delegates to resolvePiModel in the registry, which validates that the provider_id + model_id pair exists and injects the resolved endpoint into the request pipeline.
Exposing Model Selection in Plugin Templates
Plugins can surface model choices to end users through typed configuration variables. The BaseFieldType system in runtime/state-store/src/store.ts includes a dedicated model_id type for this purpose.
// runtime/api-server/src/plugin-templates.ts
const MY_PLUGIN_TEMPLATE = defineTemplate({
id: "my_plugin",
version: "1",
name: "My Plugin",
pluginVariables: [
{
key: "model_id",
type: "string",
default: "my-gpt-5-custom"
}
],
instantiateWorkflows: ({ typedConfig, plugin }) => [
{
workflowId: `${plugin.pluginId}__run`,
name: "Run with custom model",
nodes: [
{
id: "model",
type: "pi",
payload: { model_id: typedConfig.model_id },
},
// Additional workflow nodes
],
edges: [{ from: "model", to: "next" }],
},
],
});
The typedConfig.model_id value flows through the state store's type system, ensuring compile-time validation and runtime persistence of the user's selection.
Model ID Normalization and Routing
The routing layer in runtime/harnesses/src/model-routing.ts performs two critical operations:
normalizeHarnessModelId: Sanitizes incomingmodel_idvalues to handle aliases, versioning suffixes, and legacy formats- Registry lookup: Resolves the normalized ID against the in-memory ModelRegistry
This indirection enables zero-downtime model migrations—you can update the registry mapping while keeping existing workflow definitions unchanged.
Key Source Files for Custom Model Integration
| Component | File Path | Purpose |
|---|---|---|
| Model registry | runtime/harness-host/src/pi.ts |
Provider and model registration; resolvePiModel implementation |
| Routing logic | runtime/harnesses/src/model-routing.ts |
normalizeHarnessModelId and request routing |
| State field definitions | runtime/state-store/src/store.ts |
BaseFieldType enum including model_id |
| Template SDK | runtime/api-server/src/plugin-template-sdk.ts |
defineTemplate and plugin variable system |
| SDK documentation | docs/plugin-sdk.md |
Complete plugin development reference |
Summary
- HolaOS uses a declarative registry—no core code changes required for new models
- Three-step integration: register provider → register model → reference in payloads
- Typed configuration via
BaseFieldType.model_idenables plugin-level model selection - Routing layer abstraction handles normalization and endpoint injection transparently
- Source locations:
runtime/harness-host/src/pi.tsfor registry,runtime/harnesses/src/model-routing.tsfor routing
Frequently Asked Questions
What model protocols does HolaOS support?
HolaOS supports any OpenAI‑compatible API, Ollama endpoints, and custom protocols through the model_client routing hint. The buildPiProviderConfig function in runtime/harness-host/src/pi.ts adapts connection parameters accordingly.
Can I switch models without restarting the runtime?
Yes. The ModelRegistry is designed for dynamic updates, though provider registration typically occurs at startup. Hot-reloading of model configurations depends on your deployment's registry refresh strategy.
How do I validate that my custom model is reachable?
The harness system includes health check integrations through resolvePiModel. Check runtime logs for registry lookup results and endpoint resolution status when invoking startPiTool.
Where should I store provider credentials?
Use environment variables injected into buildPiProviderConfig, as shown in the registration example. Never commit tokens to the model registry definition—reference them through process.env at initialization time.
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 →