How to Configure AI Provider Credentials in the Database Instead of Environment Variables
Open Notebook stores AI provider authentication data in SurrealDB's credential table, automatically decrypting and injecting these secrets into environment variables at runtime to override static env-var configurations.
Open Notebook provides a flexible, database-first approach to managing AI provider credentials. Rather than relying solely on static environment variables, you can configure AI provider credentials in the database, enabling runtime updates without service restarts while maintaining backward compatibility with existing env-var setups.
Understanding the Database-First Credential Architecture
Open Notebook uses SurrealDB as the backing store for credential management, implementing a secure encryption layer and a runtime injection system. When a model is provisioned, the system queries the database first, decrypts the stored secrets, and populates the appropriate environment variables dynamically.
This architecture ensures that database-stored credentials take precedence over environment variables, while still allowing legacy env-var configurations to function as fallbacks.
The Credential Model and Encryption
The Credential model in open_notebook/domain/credential.py defines the schema for storing provider authentication data. Before saving, the _prepare_save_data method encrypts the api_key field to ensure secrets are never stored in plaintext. The model also includes a flexible config object (added in Migration 15) that preserves provider-specific settings such as num_ctx, base_url, or custom endpoints.
Key fields include:
provider– The AI provider name (e.g.,openai,azure_openai,ollama)api_key– Encrypted secret keymodalities– Supported model types (language, embedding, image)base_url– Custom endpoint URL for self-hosted providers
The Key Provider Module
The open_notebook/ai/key_provider.py module handles runtime credential resolution. The provision_provider_keys function retrieves the default credential for a specified provider and injects the decrypted values into os.environ using provider-specific variable names defined in PROVIDER_CONFIG.
Storing Credentials in SurrealDB
You can populate the credential table either through the REST API or directly via Python code. Both methods automatically encrypt sensitive data before persistence.
Using the Credentials API
The Credentials API router (api/routers/credentials.py) exposes CRUD endpoints for managing credentials. Create a new credential by POSTing to the credentials endpoint:
curl -X POST http://localhost:5055/credentials \
-H "Content-Type: application/json" \
-d '{
"name": "OpenAI Production",
"provider": "openai",
"modalities": ["language", "embedding"],
"api_key": "sk-REDACTED",
"config": {"num_ctx": 16384}
}'
Programmatic Credential Creation
For self-hosted providers like Ollama, you can create credentials directly in Python:
from open_notebook.domain.credential import Credential
await Credential(
name="Local Ollama",
provider="ollama",
api_key="dummy", # Ollama may not require a key
base_url="http://localhost:11434"
).save()
Runtime Loading and Environment Variable Injection
When provisioning models, Open Notebook automatically loads database credentials before initializing the AI client. This process ensures that any runtime updates to the credential table are immediately available without restarting the service.
How provision_provider_keys Works
The workflow occurs in open_notebook/ai/models.py when AIFactory.create_language() is invoked:
provision_provider_keyscalls_get_default_credentialinternally_get_default_credentialexecutesSELECT * FROM credential WHERE provider = $providerviaCredential.get_by_provider- Decryption – The
decrypt_valuemethod decrypts the stored API key - Injection – The key and configuration are written to
os.environ(e.g.,OPENAI_API_KEY,AZURE_OPENAI_ENDPOINT)
Provider-Specific Configuration Mapping
The PROVIDER_CONFIG dictionary maps provider names to their corresponding environment variable names. When provisioning, the system copies not only the api_key but also provider-specific fields like base_url, endpoint, or project into the appropriate env vars.
from open_notebook.ai.key_provider import provision_provider_keys
from esperanto import AIFactory
# Load DB-stored OpenAI credentials into env vars
await provision_provider_keys("openai")
# Create model using the dynamically loaded credentials
model = AIFactory.create_language(model_name="gpt-4", provider="openai")
Reading Credentials for Custom Logic
If you need to access credentials directly for custom implementations, use the Credential domain model:
from open_notebook.domain.credential import Credential
# Get all stored OpenAI credentials
openai_creds = await Credential.get_by_provider("openai")
for cred in openai_creds:
print(cred.name, cred.api_key.get_secret_value())
Summary
- Database-First Approach: Open Notebook queries SurrealDB's
credentialtable before checking environment variables, allowing runtime credential updates without service restarts. - Automatic Encryption: The
Credentialmodel inopen_notebook/domain/credential.pyencrypts API keys via_prepare_save_databefore storage. - Runtime Injection: The
provision_provider_keysfunction inopen_notebook/ai/key_provider.pydecrypts credentials and injects them intoos.environduring model provisioning. - Flexible Configuration: The
configfield supports provider-specific settings likebase_url,num_ctx, and custom endpoints. - Backward Compatibility: If no database credential exists, the system falls back to existing environment variables.
Frequently Asked Questions
How are API keys secured when stored in the database?
API keys are encrypted before storage using the _prepare_save_data method in the Credential model. When retrieved, the decrypt_value method decrypts the secret only at runtime, ensuring plaintext keys never persist in the database.
Can I use multiple credentials for the same provider?
Yes, the Credential.get_by_provider method returns all credentials for a given provider. However, _get_default_credential selects the first matching record, so the system typically uses the earliest created credential unless you implement custom selection logic.
What happens if no credential exists in the database?
If provision_provider_keys finds no matching credential in SurrealDB, the function exits without modifying environment variables. The application then relies on existing environment variables (e.g., OPENAI_API_KEY), maintaining backward compatibility with traditional configuration methods.
Which environment variables are set when provisioning credentials?
The specific variables depend on the provider configuration. For OpenAI, the system sets OPENAI_API_KEY. For Azure OpenAI, it sets AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, and related project fields. Self-hosted providers like Ollama receive OLLAMA_API_BASE mapped from the base_url field.
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 →