# How to Register New AI Models After Discovering Them from a Provider API in Open Notebook

> Easily register new AI models discovered from a provider API in Open Notebook. Use sync_provider_models or a POST request to automatically persist new models.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-06-28

---

**Call `sync_provider_models(provider, auto_register=True)` or POST to `/models/sync/{provider}` to discover and persist new models from any configured provider API.**

Open Notebook maintains a central registry of AI models in SurrealDB to power its LangGraph workflows and UI features. When you need to register new AI models discovered from a provider API, the system provides both REST endpoints and Python async functions to handle discovery, classification, and persistence automatically. This article explains the complete registration pipeline based on the actual implementation in the `lfnovo/open-notebook` repository.

## Understanding the Model Registration Pipeline

The registration flow consists of three coordinated stages: discovery, synchronization, and API exposure.

### Step 1: Model Discovery

Provider-specific async functions query external APIs and classify model types. In [`open_notebook/ai/model_discovery.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_discovery.py), functions like `discover_openai_models` and `discover_google_models` fetch available models and use the `classify_model_type` helper to categorize them as `language`, `embedding`, `speech_to_text`, or `text_to_speech`. Each function returns a list of `DiscoveredModel` objects containing the name, provider, type, and optional description.

### Step 2: Synchronization and Registration

The `sync_provider_models` function (lines 64-88 in [`open_notebook/ai/model_discovery.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_discovery.py)) handles the actual registration. It first calls `discover_provider_models` to get fresh data, then queries the existing `model` table in SurrealDB to build a set of current `(name, type)` tuples for O(1) duplicate detection. For each new model, it creates a `Model` instance and persists it with `await new_model.save()`. The function returns a tuple of `(discovered, new, existing)` counts.

### Step 3: REST API Exposure

The FastAPI router in [`api/routers/models.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/models.py) exposes two endpoints:
- `POST /models/sync/{provider}` – triggers discovery and registration for a single provider
- `POST /models/sync` – runs parallel sync across all configured providers using `asyncio.gather`

Both endpoints first call `provision_provider_keys` to load stored credentials into environment variables before discovery begins.

## How to Register New AI Models from the REST API

### Single Provider Sync

To register models from a specific provider like OpenAI or Google, send a POST request to the sync endpoint:

```bash
curl -X POST http://localhost:5055/models/sync/openai

```

The response returns a JSON payload showing how many models were discovered, newly registered, and already existing:

```json
{
  "provider": "openai",
  "discovered": 38,
  "new": 12,
  "existing": 26
}

```

### Bulk Sync for All Providers

To refresh the model registry across all configured providers simultaneously:

```bash
curl -X POST http://localhost:5055/models/sync

```

This endpoint uses `asyncio.gather` to run discovery in parallel for every provider defined in `PROVIDER_DISCOVERY_FUNCTIONS`, aggregating results into a single response with per-provider totals.

## Programmatic Registration in Python

### Using sync_provider_models Directly

For custom scripts or automated pipelines, import the discovery module and call `sync_provider_models` with `auto_register=True`:

```python
import asyncio
from open_notebook.ai.model_discovery import sync_provider_models

async def register_openai():
    discovered, new, existing = await sync_provider_models("openai", auto_register=True)
    print(f"Discovered: {discovered}, New: {new}, Existing: {existing}")

if __name__ == "__main__":
    asyncio.run(register_openai())

```

### Inspecting Before Registering

To preview discovered models without persisting them, use the `discover_provider_models` function directly:

```python
from open_notebook.ai.model_discovery import discover_provider_models

async def preview_models():
    models = await discover_provider_models("openai")
    for model in models:
        print(f"{model.name}: {model.model_type}")

```

### Manual Model Creation

For custom models not listed by provider APIs, instantiate the `Model` class directly from [`open_notebook/ai/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/models.py):

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

async def add_custom_model():
    custom = Model(
        name="my-custom-tts-v1",
        provider="elevenlabs",
        type="text_to_speech",
        credential=None
    )
    await custom.save()
    print(f"Created model ID: {custom.id}")

```

## Behind the Scenes: Credentials and Classification

Before any discovery occurs, the system must provision API keys. 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) loads stored `Credential` records from SurrealDB and injects them into environment variables, allowing discovery functions to authenticate via `os.getenv`.

The `classify_model_type` helper uses provider-specific pattern tables (`OPENAI_MODEL_TYPES`, `GOOGLE_MODEL_TYPES`, etc.) to map model names to supported types. This classification happens during discovery, ensuring each `Model` record is created with the correct type field.

## Summary

- **Open Notebook** stores AI models in a SurrealDB table named `model` and provides automated discovery via [`open_notebook/ai/model_discovery.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_discovery.py).
- **Register new AI models** by calling `POST /models/sync/{provider}` for single providers or `POST /models/sync` for all providers.
- **The `sync_provider_models` function** handles duplicate detection efficiently using set comparisons and persists new records via `await new_model.save()`.
- **Credentials are provisioned automatically** before discovery via `provision_provider_keys`, which loads stored credentials into environment variables.
- **Custom models** can be added manually by instantiating the `Model` class directly if they are not available through provider APIs.

## Frequently Asked Questions

### How does Open Notebook handle duplicate models during registration?

The `sync_provider_models` function queries all existing models for the provider in a single SELECT statement and builds a set of `(name, type)` tuples. When processing discovered models, it checks membership in this set with O(1) complexity, skipping any duplicates and only persisting truly new entries.

### What credentials are required to register new AI models?

The system requires valid API keys for the target provider, stored either as `Credential` records in SurrealDB or as environment variables. The `provision_provider_keys` function loads these credentials into the environment before discovery functions execute, ensuring authentication headers are available when calling provider APIs.

### Can I register a model that is not returned by the provider's API?

Yes. While automatic discovery handles most cases, you can manually create `Model` records by instantiating the `Model` class from [`open_notebook/ai/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/models.py) with your custom name, provider, and type. This is useful for custom fine-tuned models or private endpoints not listed in public API responses.

### Why are some models classified as `language` while others are `embedding`?

The `classify_model_type` function in [`open_notebook/ai/model_discovery.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_discovery.py) uses provider-specific pattern mappings (such as `OPENAI_MODEL_TYPES`) to inspect model names and assign categories. For example, models containing "embedding" in their name are classified as `embedding`, while others may default to `language` or `text_to_speech` based on naming conventions specific to each provider.