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 operationsmodel_preset– Reference to a named preset configurationmodel– Direct model specification (e.g., "gpt-4", "claude-3-opus")provider– Target LLM provider identifiermax_tool_iterations– Safety limit for recursive tool callstimezone– IANA timezone string for temporal operationsunified_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 directorywebui_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 defaultsApiConfig– OpenAI-compatible HTTP API server settings (host, port, optional API key)GatewayConfig– Nanobot gateway server options including heartbeat intervalsHeartbeatConfig– 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:
- Locates the configuration file at
~/.nanobot/config.json(or creates defaults if missing) - Parses JSON content through the Pydantic
Configmodel - Applies environment variable overrides
- 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.jsonparsed by Pydantic models innanobot/config/schema.py. - The root
Configclass extendsBaseSettings, enabling environment variable overrides with theNANOBOT_prefix. - Agent behavior is configured through
AgentsConfigandAgentDefaults, withModelPresetConfigenabling reusable model parameter sets. - Provider configuration supports both built-in services and custom endpoints via
ProvidersConfigand the extensibleProviderConfigbase class. - The
_match_provider()method implements intelligent provider selection based on model names, prefixes, and available API keys. - Security features include
restrict_to_workspacefor filesystem isolation andrepr=Falsefor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →