Validating Nanobot Config Against Schema: A Developer's Guide
Nanobot validates its JSON configuration files against a Pydantic schema defined in nanobot/config/schema.py, automatically raising detailed validation errors through the loader in nanobot/config/loader.py before the application starts.
The HKUDS/nanobot repository uses a robust configuration system that safeguards runtime settings through strict schema validation. When validating nanobot config against schema, the system checks types, enforces constraints, and handles defaults automatically, ensuring that only well-formed configurations reach the execution layer. This validation pipeline prevents agent failures caused by missing API keys, incorrect data types, or out-of-range values.
Configuration Architecture and Key Files
The validation system spans four core modules that work together to parse, validate, and monitor configuration files. Understanding these components is essential for debugging validation failures or extending the schema.
Schema Definition in schema.py
The source of truth for configuration structure lives in nanobot/config/schema.py. This file contains the Pydantic Config model that defines every valid field, type, and constraint. The schema supports aliasing between camelCase and snake_case keys, allowing seamless integration with JSON-style configuration files while maintaining Pythonic naming conventions in the codebase.
The Loading Pipeline in loader.py
The nanobot/config/loader.py module implements the load_config() function, which orchestrates the validation process. When invoked, this function reads the raw JSON from the user's config file (default location: ~/.nanobot/config.json) and parses it through the Pydantic model using Config.parse_raw(). This step triggers Pydantic's automatic type coercion and validation, raising a pydantic.ValidationError immediately if any field violates the schema constraints.
Live Monitoring with watcher.py
Configuration changes during runtime are handled by nanobot/config/watcher.py. The ConfigWatcher class runs in a background thread or async task, monitoring the config file for modifications. Upon detecting a change, it triggers a reload cycle through the same loader, ensuring that live edits pass validation before being applied to the running agent.
How Runtime Validation Works
When Nanobot initializes, the validation flow executes in four distinct stages to ensure data integrity.
Type Checking and Value Constraints
The Pydantic schema enforces strict type checking for every attribute, requiring fields to match declared types such as int, str, bool, or list. Beyond basic types, the schema applies value constraints including numeric ranges, regex patterns, and enumerated choices. Default values populate automatically for omitted keys, ensuring backward compatibility when new configuration options are added to schema.py.
Handling Validation Errors
If validation fails during the loading process, the system raises a pydantic.ValidationError that details the offending keys, expected types, and actual received values. This immediate feedback prevents Nanobot from launching with an inconsistent configuration, allowing developers to correct issues before the agent attempts to execute tasks.
Implementing Manual Validation
You can leverage the same validation pipeline in custom scripts or testing environments by importing the loader and schema directly.
Loading and Validating Configurations
Use the load_config() function to validate a configuration file programmatically:
from pathlib import Path
from nanobot.config.loader import load_config
# Path to the user-provided config file
config_path = Path.home() / ".nanobot" / "config.json"
try:
config = load_config(config_path)
print("Config loaded and validated successfully!")
except Exception as e:
# Pydantic ValidationError provides a detailed report
print(f"Configuration error: {e}")
Enabling Live Reload in Custom Scripts
For long-running processes that need to react to configuration changes, instantiate the ConfigWatcher:
from nanobot.config.watcher import ConfigWatcher
from pathlib import Path
watcher = ConfigWatcher(Path.home() / ".nanobot" / "config.json")
watcher.start() # Starts background monitoring
# ... run your agent ...
watcher.stop() # Clean shutdown
Extending the Schema with Custom Validators
To add new configuration options with custom validation logic, modify nanobot/config/schema.py:
from pydantic import BaseModel, Field, validator
class Config(BaseModel):
api_key: str = Field(..., description="OpenAI API key")
max_tokens: int = Field(1024, ge=1, le=4096)
@validator("api_key")
def api_key_must_be_nonempty(cls, v):
if not v.strip():
raise ValueError("api_key cannot be empty")
return v
Summary
- Schema Location: The Pydantic model in
nanobot/config/schema.pydefines all valid configuration fields, types, and constraints. - Validation Entry Point: The
load_config()function innanobot/config/loader.pyparses JSON and raisespydantic.ValidationErrorfor invalid data. - Default Path: Configuration files reside at
~/.nanobot/config.jsonby default, as defined innanobot/config/paths.py. - Live Monitoring: The
ConfigWatcherclass innanobot/config/watcher.pyenables hot-reloading with continuous validation. - Error Handling: Validation failures produce detailed error messages specifying exactly which fields violate the schema requirements.
Frequently Asked Questions
What happens if my config.json file has a typo in a field name?
If you include an unrecognized field name, Pydantic will either ignore it (depending on the model's extra setting) or raise a validation error. The strict mode in Nanobot's schema typically raises a pydantic.ValidationError indicating that the extra field is not permitted, helping you catch typos immediately during startup.
Can I use environment variables instead of the JSON config file?
While the default loader reads from ~/.nanobot/config.json, you can manually construct a Config object from environment variables by parsing them into a dictionary and passing it to the Pydantic model. However, the built-in load_config() function specifically targets JSON file validation; for environment-based configs, you would instantiate the Config model directly with Config.parse_obj(env_dict).
How does the ConfigWatcher handle validation errors during a live reload?
When ConfigWatcher detects a file change, it attempts to reload the configuration through the standard loader. If the new file content fails validation, the watcher catches the pydantic.ValidationError, typically logs the error, and keeps the previous valid configuration active. This prevents the running agent from crashing due to malformed live edits.
Where can I find the default configuration paths used by Nanobot?
Default filesystem locations are centralized in nanobot/config/paths.py. This module defines constants for the default config directory (~/.nanobot/), the primary config file location, and data directories, ensuring consistent path resolution across the validation pipeline.
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 →