# Provisioning Chain for Multi-Provider AI Models via the Esperanto Library

> Discover the provisioning chain for multi-provider AI models using the Esperanto library. Learn how Open Notebook selects models, resolves defaults, injects credentials, and instantiates unified Esperanto objects.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: architecture
- Published: 2026-06-19

---

**Open Notebook provisions multi-provider AI models through a layered chain that selects models based on content size, resolves database defaults, injects credentials into environment variables, and instantiates unified Esperanto objects that expose LangChain-compatible interfaces.**

The `lfnovo/open-notebook` repository implements a sophisticated provisioning chain that decouples model selection from provider-specific implementation details. By leveraging the Esperanto library as a unified abstraction layer, the system supports over eight AI providers—including OpenAI, Anthropic, Google, Azure, and Vertex—through a single, consistent code path. This architecture enables dynamic model selection based on content characteristics while maintaining secure credential management via SurrealDB.

## The Five-Layer Provisioning Pipeline

### Layer 1: Request Handling and Context-Aware Selection

The provisioning chain begins in [`open_notebook/ai/provision.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/provision.py) with the `provision_langchain_model` helper function. This entry point determines which model to instantiate based on three criteria:

1. **Token-based routing**: If the supplied content exceeds 105,000 tokens, the system automatically selects the large-context default model.
2. **Explicit override**: If a specific `model_id` is provided in the request, that model takes precedence.
3. **Type-based fallback**: Otherwise, the function retrieves the default model for the requested `default_type` (e.g., "chat", "embedding", "text_to_speech").

Once selected, the model identifier is passed to the Model Manager for instantiation.

### Layer 2: Database-Driven Model Resolution

The `ModelManager` class in [`open_notebook/ai/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/models.py) converts database records into concrete Esperanto objects. It operates through two primary methods:

- **`get_default_model`**: Reads the `DefaultModels` singleton from SurrealDB to retrieve the default model ID for a specific type (chat, transformation, tools, embedding, etc.).
- **`get_model`**: Loads the `Model` record containing fields for `name`, `provider`, `type`, and an optional `credential` reference.

When a credential is linked to the model record, the manager triggers credential injection before instantiation.

### Layer 3: Secure Credential Injection

Before instantiating any provider object, the system ensures environment variables are properly configured. The `provision_provider_keys` function in [`open_notebook/ai/key_provider.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/key_provider.py) maps stored credentials to provider-specific environment variables:

- **Simple providers**: Sets a single API key variable (e.g., `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`).
- **Complex providers**: Injects endpoint URLs and auxiliary variables for Azure or Vertex configurations.

If no credential exists in the database, the function falls back to pre-existing environment variables, preserving backward compatibility with shell-based configuration.

### Layer 4: Unified Factory Instantiation

With the environment prepared, `ModelManager` constructs the appropriate Esperanto object via the `AIFactory` class:

- `AIFactory.create_language()` for chat models
- `AIFactory.create_embedding()` for vector models  
- `AIFactory.create_speech_to_text()` for audio transcription
- `AIFactory.create_text_to_speech()` for voice synthesis

This factory pattern abstracts provider-specific initialization, allowing the same code path to instantiate models from any supported provider.

### Layer 5: LangChain Integration

The final step converts the Esperanto model into a LangChain-compatible interface. `provision_langchain_model` calls `model.to_langchain()` on the `LanguageModel` wrapper, returning a `BaseChatModel` instance that integrates directly with LangGraph workflows for source ingestion, chat, and text transformation.

## Practical Implementation Examples

The following examples demonstrate how to interact with the provisioning chain in application code:

**Automatically select a large-context model for long inputs:**

```python
await provision_langchain_model(
    content=very_long_text,
    model_id=None,
    default_type="chat",
)

```

**Explicitly request a specific model by ID:**

```python
await provision_langchain_model(
    content=short_prompt,
    model_id="model:openai:gpt-4o",
    default_type="chat",
)

```

**Retrieve the default embedding model for search workflows:**

```python
from open_notebook.ai.models import model_manager

embedding_model = await model_manager.get_embedding_model()

# Returns an Esperanto EmbeddingModel ready for vector generation

```

**Manually provision environment variables before direct API calls:**

```python
await provision_provider_keys("anthropic")

# Subsequent AIFactory calls automatically pick up ANTHROPIC_API_KEY

```

## Summary

- The provisioning chain starts at `provision_langchain_model` in [`open_notebook/ai/provision.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/provision.py), which routes requests based on token count (105,000 threshold) and default type.
- `ModelManager` in [`open_notebook/ai/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/models.py) resolves database records from the `DefaultModels` singleton and `Model` table in SurrealDB.
- `provision_provider_keys` in [`open_notebook/ai/key_provider.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/key_provider.py) securely injects credentials into environment variables, supporting both simple keys and complex Azure/Vertex configurations.
- `AIFactory` methods create provider-agnostic Esperanto objects that expose unified interfaces for language, embedding, and speech operations.
- The `to_langchain()` method bridges Esperanto models into LangChain `BaseChatModel` instances for downstream workflow integration.

## Frequently Asked Questions

### What happens if no credential is stored in the database for a requested model?

The credential injection step falls back to existing environment variables. If `provision_provider_keys` finds no matching `Credential` record in SurrealDB, it leaves the current environment unchanged, allowing the system to use pre-configured shell variables or mounted secrets.

### How does Open Notebook handle content that exceeds standard context windows?

The `provision_langchain_model` function counts input tokens before model selection. When content exceeds 105,000 tokens, it automatically routes the request to the large-context default model configured in the `DefaultModels` singleton, preventing truncation errors without manual intervention.

### What is the role of the DefaultModels singleton in the provisioning chain?

`DefaultModels` acts as a centralized configuration store in SurrealDB that maps model types (chat, embedding, tools, transformation) to specific model IDs. The `ModelManager.get_default_model` method queries this singleton to resolve which concrete model to instantiate when the request does not specify an explicit `model_id`.

### How many AI providers does this architecture support?

The provisioning chain supports over eight distinct providers—including OpenAI, Anthropic, Google, Azure, and Vertex—through Esperanto's unified factory methods. New providers can be added by updating the credential mapping in [`key_provider.py`](https://github.com/lfnovo/open-notebook/blob/main/key_provider.py) and creating corresponding `Model` records in the database, without modifying the core provisioning logic.