How the Open Notebook Key Provider Falls Back from Database Credentials to Environment Variables
The Open Notebook key provider implements a database-first lookup strategy that automatically falls back to environment variables when credentials are missing, querying the Credential table before checking the PROVIDER_CONFIG mapping.
The lfnovo/open-notebook repository manages AI provider authentication through a resilient credential system that prioritizes secure database storage. Understanding how the key provider falls back from database credentials to environment variables ensures seamless operation when database records are unavailable or when integrating with libraries that expect standard environment-based API keys.
Database-First Lookup Strategy in key_provider.py
The core logic resides in open_notebook/ai/key_provider.py, where the _get_default_credential() helper function queries the Credential table for provider-specific records. According to the source code, this function searches for the first database record belonging to the requested provider (lines 77-84).
When a credential exists in the database, the function extracts the api_key field and returns the secret value directly (lines 98-101). This database-first approach ensures that user-configured keys stored in the application database take precedence over system environment variables.
The Environment Variable Fallback Mechanism
If the database query returns no results or the credential lacks an API key, the provider executes a fallback to environment variables. The mapping between providers and their canonical environment variable names is defined in the PROVIDER_CONFIG dictionary (lines 28-63).
For example, the "openai" provider maps to OPENAI_API_KEY, while other providers follow similar canonical naming conventions. The fallback logic checks this specific environment variable when no valid database credential is available (lines 102-108).
Complete Fallback Flow
The resolution follows this strict priority order:
- Query the
Credentialtable for the provider using_get_default_credential() - Return the stored
api_keyif found and valid - Check the environment variable specified in
PROVIDER_CONFIGfor that provider - Return
Noneif neither source provides a key (lines 109-111)
Provisioning Keys at Runtime
The public get_api_key() coroutine encapsulates this fallback logic for higher-level consumption. Additionally, the module provides provisioning utilities that populate environment variables from database credentials before model instantiation.
Per-Provider Provisioning
The provision_provider_keys() function ensures specific provider credentials are loaded into the environment. This is critical when creating model instances that expect standard environment variables:
from open_notebook.ai.key_provider import provision_provider_keys
async def create_openai_model():
await provision_provider_keys("openai") # DB → env if present
# Model factory now finds the key in environment
Global Startup Provisioning
For application initialization, provision_all_keys() iterates through all configured providers (lines 46-81). While useful for startup scripts, this approach is deprecated for per-request use in favor of targeted provisioning:
from open_notebook.ai.key_provider import provision_all_keys
async def startup():
results = await provision_all_keys()
print("Provisioning results:", results)
Integration with the Credential Domain Model
The fallback mechanism relies on open_notebook/domain/credential.py, which defines the Pydantic Credential model and the get_by_provider async query. The AI model factory in open_notebook/ai/model_factory.py consumes these keys, whether sourced directly from the database or inherited from environment variables populated by the provisioning functions.
Summary
- The key provider in
open_notebook/ai/key_provider.pyprioritizes database credentials over environment variables _get_default_credential()queries theCredentialtable first (lines 77-84)- Falls back to
PROVIDER_CONFIGenvironment mappings when no database record exists (lines 102-108) - Returns
Noneonly when both database and environment sources fail (lines 109-111) - Use
provision_provider_keys()to expose database credentials as environment variables for legacy model clients
Frequently Asked Questions
What happens if both the database and environment variable are missing?
The get_api_key() function returns None when neither the Credential table contains a record for the provider nor the corresponding environment variable is set in the system's PROVIDER_CONFIG mapping. This signals to calling code that no authentication is available for the requested AI provider.
Which takes precedence: database credentials or environment variables?
Database credentials always take precedence. The code explicitly checks the database first (lines 98-101) and only falls back to environment variables (lines 102-108) when no valid database credential exists. This ensures that application-specific configurations in the database override system-level environment settings.
How does the provider know which environment variable to check?
The PROVIDER_CONFIG mapping (lines 28-63) defines the canonical environment variable name for each provider. For example, the "openai" provider maps to OPENAI_API_KEY, ensuring consistent fallback behavior across different AI services without hardcoding variable names throughout the application.
Can I use database credentials without modifying environment variables?
Yes. The get_api_key() coroutine returns the database value directly without side effects on the environment. Only the provision_provider_keys() and provision_all_keys() functions explicitly populate environment variables to maintain compatibility with libraries that expect standard environment-based authentication.
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 →