# Validating Nanobot Config Against Schema: A Developer's Guide

> Learn to validate nanobot config against schema using Pydantic. Catch configuration errors early with detailed validation alerts before your application begins.

- Repository: [✨Data Intelligence Lab@HKU✨/nanobot](https://github.com/HKUDS/nanobot)
- Tags: how-to-guide
- Published: 2026-07-22

---

**Nanobot validates its JSON configuration files against a Pydantic schema defined in [`nanobot/config/schema.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/schema.py), automatically raising detailed validation errors through the loader in [`nanobot/config/loader.py`](https://github.com/HKUDS/nanobot/blob/main/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`](https://github.com/HKUDS/nanobot/blob/main/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`](https://github.com/HKUDS/nanobot/blob/main/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`](https://github.com/HKUDS/nanobot/blob/main/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`](https://github.com/HKUDS/nanobot/blob/main/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:

```python
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`:

```python
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`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/schema.py):

```python
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.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/schema.py) defines all valid configuration fields, types, and constraints.
- **Validation Entry Point**: The `load_config()` function in [`nanobot/config/loader.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/loader.py) parses JSON and raises `pydantic.ValidationError` for invalid data.
- **Default Path**: Configuration files reside at `~/.nanobot/config.json` by default, as defined in [`nanobot/config/paths.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/paths.py).
- **Live Monitoring**: The `ConfigWatcher` class in [`nanobot/config/watcher.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/watcher.py) enables 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`](https://github.com/HKUDS/nanobot/blob/main/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.