Customizing Nanobot Behavior with Config: A Complete Guide to the Configuration System

Nanobot reads runtime settings from ~/.nanobot/config.json, validates them against a Pydantic schema defined in nanobot/config/schema.py, and supports live reloading via nanobot/config/watcher.py to update behavior without restarting the process.

The HKUDS/nanobot framework provides a declarative configuration system that allows developers to adjust agent behavior, provider settings, and UI features without modifying source code. By leveraging strongly-typed Pydantic models and asynchronous file watching, nanobot enables both static configuration and dynamic updates during runtime.

Understanding the Configuration Architecture

Nanobot’s configuration system is modular, separating schema definition, file I/O, path resolution, and live monitoring into distinct components.

Schema Definition resides in nanobot/config/schema.py, where the Config class inherits from Pydantic’s BaseSettings. This class declares all configurable options—including booleans, strings, enums, and nested objects for providers, channels, and UI flags—providing type safety and automatic validation.

Dynamic Loading is handled by the ConfigLoader class in nanobot/config/loader.py. This module reads the JSON configuration file, validates it against the schema, and caches the resulting object for injection into core components.

Path Resolution utilities in nanobot/config/paths.py determine default locations for the configuration file, cache directories, and runtime data, ensuring consistent file-system access across platforms.

Configuration File Structure and Schema

The user-level configuration file follows a hierarchical JSON structure validated by the Pydantic schema. Key sections include tools, providers, and ui.

Below is a minimal config.json that enables the filesystem tool, sets the default OpenAI model, and activates debug logging:

{
  "tools": {
    "filesystem": true,
    "shell": false
  },
  "providers": {
    "openai": {
      "model": "gpt-4o-mini",
      "api_key": "YOUR_OPENAI_API_KEY"
    }
  },
  "ui": {
    "debug": true
  }
}
  • The tools section toggles built-in capabilities; setting filesystem to true enables file access while shell remains disabled.
  • The providers.openai block selects gpt-4o-mini as the default model, with the schema validating the model name against allowed values.
  • Setting ui.debug to true enables verbose logging in the Web UI endpoints.

Loading and Validating Configuration

At startup, nanobot initializes the configuration by invoking ConfigLoader.load(), which returns a fully-typed Config object. This object is then passed to the agent loop, provider factories, and web interface.

To load the configuration programmatically and inspect the active model:

from nanobot.config.loader import ConfigLoader

# Load (and watch) the user configuration

config = ConfigLoader.load()

print(f"Active OpenAI model: {config.providers.openai.model}")

ConfigLoader.load() performs three operations: it resolves the file path using helpers from nanobot/config/paths.py, parses the JSON content, and validates the structure against the Config schema. Accessing nested attributes is type-safe thanks to Pydantic’s runtime validation.

Enabling Live Reload for Dynamic Updates

Nanobot supports hot-reloading of configuration without process restarts through the ConfigWatcher class in nanobot/config/watcher.py. This component uses asyncio to monitor filesystem events and triggers ConfigLoader.reload() whenever ~/.nanobot/config.json changes.

To implement live reloading in your application:

import asyncio
from nanobot.config.watcher import ConfigWatcher

async def main():
    watcher = ConfigWatcher()
    await watcher.start()          # Starts an asyncio task that watches the file

    # Application continues running; any change to ~/.nanobot/config.json

    # triggers a reload automatically.

asyncio.run(main())

When the watcher detects a file modification, it invokes the reload mechanism, propagating new settings to running components. This enables on-the-fly toggling of features such as debug logging, tool enablement, or custom command routing.

Integrating Config with Core Components

The loaded Config object serves as the single source of truth for multiple subsystems:

  • Agent Loop (nanobot/agent/loop.py): Consumes configuration for session key management, hook registration, and context building.
  • Provider Factories (nanobot/providers/factory.py): Uses the configuration to select default models, instantiate LLM clients, and inject credentials.
  • Web UI (nanobot/webui/settings_api.py): Exposes configurable UI flags through HTTP API endpoints, allowing the frontend to reflect backend settings dynamically.

This integration ensures that changes to ~/.nanobot/config.json propagate consistently across the agent’s decision-making logic, external API calls, and user interface.

Summary

  • Nanobot stores user settings in ~/.nanobot/config.json, validated by the Pydantic schema in nanobot/config/schema.py.
  • The ConfigLoader class in nanobot/config/loader.py handles file reading, validation, and object instantiation.
  • Live reload is implemented via ConfigWatcher in nanobot/config/watcher.py, enabling configuration updates without restarting the process.
  • Configuration affects three primary areas: the AgentLoop for session management, provider factories for LLM selection, and the Web UI for interface flags.
  • Path resolution utilities in nanobot/config/paths.py ensure cross-platform compatibility for config and cache locations.

Frequently Asked Questions

Where is the nanobot configuration file located?

By default, nanobot looks for config.json in the ~/.nanobot/ directory. The exact path is resolved at runtime by helper functions in nanobot/config/paths.py, which handle platform-specific directory conventions and allow for environment-based overrides.

How does nanobot handle configuration changes without restarting?

Nanobot uses the ConfigWatcher class implemented in nanobot/config/watcher.py to monitor the configuration file for filesystem events using asyncio. When a change is detected, the watcher triggers ConfigLoader.reload(), which re-reads and re-validates the JSON file, updating the in-memory configuration object and propagating changes to the agent loop, providers, and web UI.

What configuration options are available in the schema?

The schema defined in nanobot/config/schema.py includes fields for tools (enabling/disabling filesystem, shell, and other capabilities), providers (model selection and API credentials for OpenAI and other LLM services), and ui (debug flags and interface settings). All options are strongly typed using Pydantic, supporting booleans, strings, enums, and nested configuration objects.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →