# Nanobot Dynamic Configuration Loading: Runtime Config Management Explained

> Explore Nanobot dynamic configuration loading for runtime config management. Learn how Pydantic, env vars, and file watchers enable real-time updates without agent restarts.

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

---

**Nanobot implements a hot-reloading configuration system using Pydantic models, environment variable overrides, and file-system watchers to enable real-time updates without restarting the agent.**

Nanobot's configuration system provides type-safe, runtime-reloading capabilities through a modular Python architecture. The HKUDS/nanobot repository implements this via four specialized modules that handle schema validation, path resolution, loading orchestration, and file watching. This design allows developers to modify settings dynamically while maintaining strict validation and environment-based secret management.

## Configuration Architecture Overview

The dynamic configuration system spans four core modules in `nanobot/config/`. Each component handles a specific aspect of the loading lifecycle, from schema definition to runtime monitoring.

### Configuration Schema ([`nanobot/config/schema.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/schema.py))

The `Config` class in [`nanobot/config/schema.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/schema.py) defines the Pydantic-based data model that describes every configurable option. Inheriting from **Pydantic's `BaseSettings`**, this schema enables automatic environment variable overrides for any field defined in the model.

The schema uses camelCase aliases to ensure seamless JSON compatibility while maintaining Pythonic snake_case attribute access. It provides default values and validation for complex nested structures, including provider credentials, logging levels, and tool limits.

### Path Resolution ([`nanobot/config/paths.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/paths.py))

[`nanobot/config/paths.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/paths.py) centralizes filesystem location management across platforms. It resolves platform-specific directories using XDG standards on Linux and AppData on Windows, guaranteeing that required directories exist before first use.

This module computes the location of `~/.nanobot/config.json` and other runtime directories, abstracting cross-platform differences behind a consistent API.

### Loading Orchestration ([`nanobot/config/loader.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/loader.py))

The [`nanobot/config/loader.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/loader.py) module orchestrates the configuration discovery and instantiation process. The `load()` function discovers the user's config file, merges JSON contents with schema defaults, and initiates the file watcher.

Key behaviors include:

- **Discovery**: Locates `~/.nanobot/config.json` or respects the `NANOBOT_CONFIG` environment variable for custom paths
- **Merging**: Parses JSON into a validated `Config` instance, applying defaults for missing keys
- **Dynamic Reload**: Triggers `reload()` callbacks when the watcher detects file changes, propagating new values to provider factories and logging subsystems

### File System Watching ([`nanobot/config/watcher.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/watcher.py))

[`nanobot/config/watcher.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/watcher.py) implements the hot-reloading mechanism using the `watchdog` library. It monitors the configuration file for modifications and emits debounced change events to prevent excessive reloads during rapid edits.

When the watcher detects a change, it invokes `loader.reload()`, which recreates the `Config` instance and updates the running bot's settings without requiring a restart.

## How Dynamic Reloading Works

Nanobot achieves zero-downtime configurability through a structured loading flow that activates at startup and continues monitoring throughout the application lifecycle.

1. **Application startup** calls `nanobot.config.loader.load()`, which resolves the config file location via [`paths.py`](https://github.com/HKUDS/nanobot/blob/main/paths.py)
2. **JSON parsing** converts the file contents into a `Config` object using the Pydantic schema
3. **Validation** runs automatically, filling missing fields with defaults and type-checking all values
4. **Watcher initialization** starts the file-system monitor in a background thread
5. **Runtime updates** trigger when [`config.json`](https://github.com/HKUDS/nanobot/blob/main/config.json) changes, invoking `loader.reload()` to refresh the configuration instance
6. **Propagation** distributes new values to dependent subsystems, including provider factories, loggers, and tool limit handlers

## Environment Variable Integration

Because the `Config` model inherits from **Pydantic's `BaseSettings`**, any environment variable matching a field name automatically overrides the corresponding JSON configuration. This dual-source approach enables secure secret management through environment injection while keeping general settings in readable files.

For example, setting `NANOBOT_LOG_LEVEL=DEBUG` overrides the `log_level` field in [`config.json`](https://github.com/HKUDS/nanobot/blob/main/config.json), and `NANOBOT_PROVIDERS__OPENAI__API_KEY` can inject API credentials without storing them in the configuration file.

## Practical Implementation Examples

The following patterns demonstrate common interactions with Nanobot's configuration system:

```python

# Load configuration automatically with validation

from nanobot.config.loader import load

config = load()               # Returns a validated Config instance

print(config.log_level)       # → "INFO" (default or user-provided)

```

Access nested provider settings safely through the typed schema:

```python

# Access nested provider configuration

openai_cfg = config.providers.openai
print(openai_cfg.api_key)     # Resolved from env var or config file

```

Runtime updates require no additional code. Edit `~/.nanobot/config.json` manually, and the background watcher triggers `load()` automatically:

```python

# No manual reload required - the watcher updates config automatically

# Changes to ~/.nanobot/config.json propagate within seconds

```

## Summary

- **Modular architecture**: Four specialized modules ([`schema.py`](https://github.com/HKUDS/nanobot/blob/main/schema.py), [`paths.py`](https://github.com/HKUDS/nanobot/blob/main/paths.py), [`loader.py`](https://github.com/HKUDS/nanobot/blob/main/loader.py), [`watcher.py`](https://github.com/HKUDS/nanobot/blob/main/watcher.py)) handle distinct configuration concerns
- **Type safety**: Pydantic-based validation ensures all configuration values meet schema requirements before application use
- **Hot reloading**: File-system watching via `watchdog` enables real-time configuration updates without process restarts
- **Environment overrides**: `BaseSettings` inheritance allows environment variables to override JSON configuration for secure secret management
- **Cross-platform support**: Automatic resolution of XDG and AppData directories ensures consistent behavior across Linux, macOS, and Windows

## Frequently Asked Questions

### How does Nanobot detect configuration file changes?

Nanobot uses `watchdog` in [`nanobot/config/watcher.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/watcher.py) to monitor the configuration file for modifications. The watcher emits debounced events when the file changes, triggering `loader.reload()` to recreate the `Config` instance with updated values. This process occurs in a background thread without interrupting the main application flow.

### Can I override specific configuration values using environment variables?

Yes. Because the configuration model in [`nanobot/config/schema.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/schema.py) inherits from Pydantic's `BaseSettings`, any environment variable matching a field name (e.g., `NANOBOT_LOG_LEVEL`) automatically overrides the corresponding value in [`config.json`](https://github.com/HKUDS/nanobot/blob/main/config.json). Nested fields use double underscores (e.g., `NANOBOT_PROVIDERS__OPENAI__API_KEY`) following Pydantic's environment variable naming convention.

### Where does Nanobot look for the configuration file by default?

By default, Nanobot resolves the configuration file path using [`nanobot/config/paths.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/paths.py), which locates `~/.nanobot/config.json` (or platform-specific equivalents like AppData on Windows). You can override this location by setting the `NANOBOT_CONFIG` environment variable to a custom file path before starting the application.

### Is it safe to edit the configuration while Nanobot is running?

Yes. The configuration system is designed for concurrent access during file modifications. The watcher in [`nanobot/config/watcher.py`](https://github.com/HKUDS/nanobot/blob/main/nanobot/config/watcher.py) implements debouncing to handle rapid successive edits, and Pydantic validation ensures that only valid configurations are applied. Invalid JSON or schema violations during a reload will typically fail gracefully, preserving the previous valid configuration.