Understanding the Nanobot Config File Format: A Complete Guide to Pydantic-Based Configuration

Nanobot uses a single JSON configuration file located at ~/.nanobot/config.json that is parsed into a hierarchy of Pydantic models defined in nanobot/config/schema.py, supporting environment variable overrides and validation for agents, providers, channels, and tools.

The HKUDS/nanobot project relies on a declarative configuration system to manage its multi-agent runtime, transcription services, and LLM provider integrations. Understanding the nanobot config file format is essential for customizing agent behavior, adding custom providers, and enforcing security policies. This guide examines the schema definitions, validation logic, and runtime loading mechanisms that power nanobot's flexible configuration system.

Root Configuration Structure

The entry point for all configuration is the Config class in nanobot/config/schema.py, which inherits from Pydantic's BaseSettings to enable environment variable integration.

class Config(BaseSettings):
    agents: AgentsConfig = Field(default_factory=AgentsConfig)
    channels: ChannelsConfig = Field(default_factory=ChannelsConfig)
    transcription: TranscriptionConfig = Field(default_factory=TranscriptionConfig)
    providers: ProvidersConfig = Field(default_factory=ProvidersConfig)
    api: ApiConfig = Field(default_factory=ApiConfig)
    gateway: GatewayConfig = Field(default_factory=GatewayConfig)
    tools: ToolsConfig = Field(default_factory=ToolsConfig)
    model_presets: dict[str, ModelPresetConfig] = Field(
        default_factory=dict,
        validation_alias=AliasChoices("modelPresets", "model_presets"),
        serialization_alias="modelPresets",
    )

Each attribute represents a subsystem configuration with default factories that lazily instantiate nested models. Because the class extends BaseSettings, environment variables prefixed with NANOBOT_ automatically override JSON values, enabling dynamic configuration without file modifications.

Agent and Model Configuration

Agent behavior is controlled through a nested hierarchy of configuration models that define defaults and reusable presets.

AgentsConfig and AgentDefaults

The AgentsConfig class holds the default agent configuration through its defaults: AgentDefaults field. The AgentDefaults model specifies core runtime parameters including:

  • workspace – The working directory for agent file operations
  • model_preset – Reference to a named preset configuration
  • model – Direct model specification (e.g., "gpt-4", "claude-3-opus")
  • provider – Target LLM provider identifier
  • max_tool_iterations – Safety limit for recursive tool calls
  • timezone – IANA timezone string for temporal operations
  • unified_session – Boolean for session persistence across interactions

Model Preset Resolution

Named model presets are defined in model_presets as dictionaries mapping strings to ModelPresetConfig objects. Each preset encapsulates model, provider, max_tokens, temperature, and reasoning_effort parameters.

The resolution logic resides in Config.resolve_default_preset() and Config.resolve_preset(name), which build a complete ModelPresetConfig by merging named presets with implicit defaults (source lines 38-45 in nanobot/config/schema.py). This allows users to define quick-switch profiles for different tasks while maintaining fallback values.

Provider Configuration

LLM provider settings are managed through ProvidersConfig, which enumerates supported providers while allowing arbitrary custom providers via extra fields.

ProviderConfig Schema

Every provider, whether built-in or custom, uses the ProviderConfig base model:

class ProviderConfig(Base):
    api_key: str | None = Field(default=None, repr=False)
    api_base: str | None = None
    api_type: Literal["auto", "chat_completions", "responses"] = "auto"
    extra_headers: dict[str, str] | None = None
    extra_body: dict[Any, Any] | None = None
    extra_query: dict[str, str] | None = None
    proxy: str | None = None
    thinking_style: str | None = None

Critical validation rules apply to these fields. The api_key field uses repr=False to prevent accidental exposure in logs. The api_type parameter is restricted to "auto" for all providers except OpenAI, enforced by _validate_api_type_scope() (source lines 98-106). Custom providers defined in the JSON file are automatically converted to ProviderConfig instances via convert_extra_providers() (source lines 80-93).

Provider Matching Algorithm

At runtime, nanobot selects providers using Config._match_provider(), which implements a sophisticated matching algorithm (source lines 64-131). The method evaluates model name prefixes, explicit provider declarations, keyword matches, and finally falls back to any provider with a configured api_key. This enables zero-configuration operation when only one provider has authentication credentials.

Channel, Tool, and Auxiliary Settings

Beyond agents and providers, the nanobot config file format supports granular control over communication channels and tool execution.

ChannelsConfig

ChannelsConfig manages per-chat-application behavior, controlling streaming output, tool-hint display visibility, and retry limits (source lines 22-38). These settings allow fine-tuning of the user experience across different messaging platforms.

ToolsConfig

The ToolsConfig class aggregates settings for all built-in tools including web search, code execution, filesystem access, and image generation. Notable security flags include:

  • restrict_to_workspace – Boolean enforcing that all file operations remain within the designated workspace directory
  • webui_allow_local_service_access – Permission flag allowing the WebUI to connect to localhost services

Tool classes are lazily imported via _lazy_default() to prevent circular import issues during configuration loading.

Auxiliary Subsystems

Additional configuration sections include:

  • TranscriptionConfig – Audio transcription service parameters and defaults
  • ApiConfig – OpenAI-compatible HTTP API server settings (host, port, optional API key)
  • GatewayConfig – Nanobot gateway server options including heartbeat intervals
  • HeartbeatConfig – Periodic housekeeping job scheduling (now cron-based)

Each follows the consistent Pydantic pattern of typed fields with validation constraints and sensible defaults.

Validation, Aliases, and Environment Overrides

The nanobot config file format supports flexible input handling through Pydantic's validation and alias systems.

Field Aliases

The AliasChoices mechanism allows multiple JSON key formats for the same field. For example, model_presets accepts both "modelPresets" (camelCase) and "model_presets" (snake_case) during validation, while serializing exclusively to "modelPresets" for consistency.

Environment Variable Override

Because Config extends BaseSettings, environment variables prefixed with NANOBOT_ override file values. Nested fields use double underscores as delimiters:

export NANOBOT_AGENTS__DEFAULTS__WORKSPACE="/tmp/custom-workspace"
export NANOBOT_API__PORT=9100

Field Validators

Custom validators enforce domain constraints. For instance, the timezone field validates against known IANA timezone databases (source lines 66-75), preventing runtime errors from invalid locale strings.

Loading and Runtime Behavior

Configuration persistence and hot-reloading are handled by dedicated modules in the nanobot/config/ package.

Configuration Loading Pipeline

The nanobot.config.loader module handles the initialization sequence:

  1. Locates the configuration file at ~/.nanobot/config.json (or creates defaults if missing)
  2. Parses JSON content through the Pydantic Config model
  3. Applies environment variable overrides
  4. Returns a validated configuration instance

If the configuration file is absent, nanobot uses default values and prompts the user to run nanobot onboard for initial setup.

File Watching and Hot Reload

The nanobot.config.watcher module monitors the configuration file for changes during runtime. When modifications are detected, the watcher triggers a configuration reload without requiring process restart, enabling dynamic adjustment of agent parameters and provider credentials.

Path Resolution

Utility functions in nanobot.config.paths provide cross-platform resolution of configuration directories, workspace locations, and related filesystem paths, ensuring consistent behavior across operating systems.

Practical Configuration Examples

Reading Configuration Programmatically

Access the parsed configuration in Python to inspect runtime settings:

from nanobot.config.schema import Config

# Load from default location with environment overrides

cfg = Config()

# Access workspace path

print("Workspace:", cfg.agents.defaults.workspace)

# Resolve a named model preset

preset = cfg.resolve_preset(name="primary")
print(f"Using model: {preset.model} via provider: {preset.provider}")

Adding a Custom Provider

Extend nanobot with proprietary or self-hosted LLM endpoints by adding custom provider definitions:

{
  "providers": {
    "mycorp": {
      "apiKey": "sk-custom-key",
      "apiBase": "https://api.internal.corp.com/v1",
      "thinkingStyle": "detailed"
    }
  },
  "modelPresets": {
    "corp-default": {
      "model": "mycorp/gpt-4",
      "provider": "mycorp",
      "max_tokens": 8192,
      "temperature": 0.2
    }
  }
}

Enforcing Workspace Security

Programmatically restrict tools to the workspace directory:

from nanobot.config.schema import Config
import json
from pathlib import Path

cfg = Config()
cfg.tools.restrict_to_workspace = True

# Persist changes

config_path = Path("~/.nanobot/config.json").expanduser()
config_path.write_text(
    json.dumps(cfg.model_dump(mode="json"), indent=2)
)

Environment-Based Port Configuration

Override the gateway server port without modifying the configuration file:

export NANOBOT_GATEWAY__PORT=8080
nanobot gateway

Summary

  • The nanobot config file format uses a single JSON file at ~/.nanobot/config.json parsed by Pydantic models in nanobot/config/schema.py.
  • The root Config class extends BaseSettings, enabling environment variable overrides with the NANOBOT_ prefix.
  • Agent behavior is configured through AgentsConfig and AgentDefaults, with ModelPresetConfig enabling reusable model parameter sets.
  • Provider configuration supports both built-in services and custom endpoints via ProvidersConfig and the extensible ProviderConfig base class.
  • The _match_provider() method implements intelligent provider selection based on model names, prefixes, and available API keys.
  • Security features include restrict_to_workspace for filesystem isolation and repr=False for API key protection.
  • Configuration changes are detected at runtime by nanobot.config.watcher, enabling hot-reloading without service interruption.

Frequently Asked Questions

Where is the nanobot configuration file located?

The default location is ~/.nanobot/config.json on Unix-like systems, resolved through the nanobot.config.paths module. If the file does not exist, nanobot initializes with default values and prompts you to run nanobot onboard to generate the initial configuration.

How do I override configuration values using environment variables?

Set environment variables prefixed with NANOBOT_ using double underscores to denote nested fields. For example, NANOBOT_AGENTS__DEFAULTS__MODEL overrides the default agent model, while NANOBOT_PROVIDERS__OPENAI__API_KEY sets the OpenAI API key without storing it in the JSON file.

Can I add custom LLM providers not included in the default schema?

Yes, the ProvidersConfig class accepts extra fields that are automatically converted to ProviderConfig instances via convert_extra_providers(). Simply add a new key to the providers object in your JSON file with apiKey, apiBase, and other standard fields, then reference it in your modelPresets or agent defaults.

What validation occurs when loading the configuration?

Pydantic validates all fields against their type annotations, with additional custom validators enforcing business logic such as IANA timezone validation for the timezone field and API type restrictions enforced by _validate_api_type_scope(). Invalid configurations raise validation errors with detailed messages indicating the problematic field and accepted values.

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 →