Skip to content

04.1 Configuration File Reference

Nikolay Vyahhi edited this page Feb 19, 2026 · 3 revisions

Configuration File Reference

Relevant source files

The following files were used as context for generating this wiki page:

This page provides a complete reference for all configuration options available in config.toml. For initial setup instructions, see Onboarding Wizard. For environment variable overrides, see Environment Variables. For secret encryption, see Secret Management.

Configuration File Location

ZeroClaw uses a TOML configuration file located at ~/.zeroclaw/config.toml by default. The workspace directory is ~/.zeroclaw/workspace.

Configuration Priority (highest to lowest):

  1. Environment Variables - Override config.toml settings
  2. config.toml - User-defined configuration
  3. Built-in Defaults - Fallback values defined in code

Multi-Workspace Support:

Use ZEROCLAW_WORKSPACE environment variable or active_workspace.toml marker file to specify alternate workspace directories. See Workspace Management for details.

Sources: src/config/schema.rs:46-144


Configuration Structure Overview

The following diagram maps configuration sections to their Rust struct definitions:

graph TB
    ConfigFile["config.toml"]
    
    ConfigFile --> TopLevel["Top-Level Fields"]
    ConfigFile --> Provider["Provider Settings"]
    ConfigFile --> Channels["channels_config"]
    ConfigFile --> Agent["agent"]
    ConfigFile --> Memory["memory"]
    ConfigFile --> Tools["Tool Configs"]
    ConfigFile --> Security["Security Configs"]
    ConfigFile --> Automation["Automation Configs"]
    ConfigFile --> Advanced["Advanced Configs"]
    
    TopLevel --> api_key["api_key: Option<String>"]
    TopLevel --> api_url["api_url: Option<String>"]
    TopLevel --> default_provider["default_provider: Option<String>"]
    TopLevel --> default_model["default_model: Option<String>"]
    TopLevel --> default_temperature["default_temperature: f64"]
    
    Provider --> reliability["reliability: ReliabilityConfig"]
    Provider --> model_routes["model_routes: Vec<ModelRouteConfig>"]
    Provider --> query_classification["query_classification: QueryClassificationConfig"]
    
    Channels --> telegram["telegram: Option<TelegramConfig>"]
    Channels --> discord["discord: Option<DiscordConfig>"]
    Channels --> slack["slack: Option<SlackConfig>"]
    Channels --> matrix["matrix: Option<MatrixConfig>"]
    Channels --> email["email: Option<EmailConfig>"]
    Channels --> whatsapp["whatsapp: Option<WhatsAppConfig>"]
    Channels --> lark["lark: Option<LarkConfig>"]
    Channels --> ChannelsEtc["+ 6 more channels"]
    
    Agent --> compact_context["compact_context: bool"]
    Agent --> max_tool_iterations["max_tool_iterations: usize"]
    Agent --> max_history_messages["max_history_messages: usize"]
    Agent --> parallel_tools["parallel_tools: bool"]
    
    Memory --> backend["backend: String"]
    Memory --> auto_save["auto_save: bool"]
    Memory --> hygiene_enabled["hygiene_enabled: bool"]
    Memory --> embedding_provider["embedding_provider: String"]
    
    Tools --> browser["browser: BrowserConfig"]
    Tools --> http_request["http_request: HttpRequestConfig"]
    Tools --> web_search["web_search: WebSearchConfig"]
    Tools --> composio["composio: ComposioConfig"]
    
    Security --> autonomy["autonomy: AutonomyConfig"]
    Security --> secrets["secrets: SecretsConfig"]
    Security --> gateway["gateway: GatewayConfig"]
    Security --> tunnel["tunnel: TunnelConfig"]
    
    Automation --> cron["cron: CronConfig"]
    Automation --> scheduler["scheduler: SchedulerConfig"]
    Automation --> heartbeat["heartbeat: HeartbeatConfig"]
    
    Advanced --> proxy["proxy: ProxyConfig"]
    Advanced --> identity["identity: IdentityConfig"]
    Advanced --> cost["cost: CostConfig"]
    Advanced --> hardware["hardware: HardwareConfig"]
    Advanced --> peripherals["peripherals: PeripheralsConfig"]
    Advanced --> agents["agents: HashMap<String, DelegateAgentConfig>"]
Loading

Sources: src/config/schema.rs:48-144


Top-Level Configuration

API Credentials

# Provider API key (can be overridden by provider-specific env vars)
api_key = "sk-..."

# Optional: Base URL override for provider API (e.g., remote Ollama)
api_url = "http://10.0.0.1:11434"

# Default provider name (openrouter, anthropic, openai, ollama, etc.)
default_provider = "openrouter"

# Default model identifier
default_model = "anthropic/claude-sonnet-4.6"

# Default temperature (0.0-1.0)
default_temperature = 0.7
Field Type Default Description
api_key Option<String> None Provider API key (encrypted when secrets.encrypt = true)
api_url Option<String> None Base URL override for provider API endpoint
default_provider Option<String> Required Provider name (see Built-in Providers)
default_model Option<String> Required Model identifier for the provider
default_temperature f64 0.7 Sampling temperature (0.0 = deterministic, 1.0 = creative)

Environment Variable Overrides:

  • OPENROUTER_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, etc. override api_key for specific providers
  • OLLAMA_BASE_URL overrides api_url for Ollama provider

Sources: src/config/schema.rs:56-61


Provider Configuration

Reliability Settings

[reliability]
max_retries = 3
initial_retry_delay_ms = 1000
max_retry_delay_ms = 60000
retry_multiplier = 2.0
retry_on_rate_limit = true
fallback_models = []
api_keys_rotation = []
Field Type Default Description
max_retries u32 3 Maximum retry attempts for failed requests
initial_retry_delay_ms u64 1000 Initial backoff delay in milliseconds
max_retry_delay_ms u64 60000 Maximum backoff delay (exponential backoff cap)
retry_multiplier f64 2.0 Backoff multiplier for each retry
retry_on_rate_limit bool true Retry on HTTP 429 rate limit errors
fallback_models Vec<String> [] Models to try if primary model fails
api_keys_rotation Vec<String> [] API keys to rotate through on failure

Sources: src/config/schema.rs:73

Model Routing

[[model_routes]]
hint = "code-heavy"
provider = "openai"
model = "gpt-4o"
weight = 1.0
Field Type Description
hint String Routing hint identifier (e.g., "code-heavy", "fast", "reasoning")
provider String Provider to route to
model String Model to use for this hint
weight f64 Weight for load balancing (not currently used)

Sources: src/config/schema.rs:82-83

Query Classification

[query_classification]
enabled = false
rules = [
  { patterns = ["debug", "fix bug"], hint = "code-heavy" }
]
Field Type Default Description
enabled bool false Enable automatic query classification
rules Vec<ClassificationRule> [] Pattern-to-hint mapping rules

ClassificationRule Structure:

Field Type Description
patterns Vec<String> Keywords/phrases to match in user message
hint String Model route hint to apply on match

Sources: src/config/schema.rs:87


Channel Configuration

All channel configurations are nested under [channels_config]. Each channel is optional and can be enabled by providing its configuration.

graph LR
    ChannelsConfig["ChannelsConfig"]
    
    ChannelsConfig --> Telegram["telegram: TelegramConfig"]
    ChannelsConfig --> Discord["discord: DiscordConfig"]
    ChannelsConfig --> Slack["slack: SlackConfig"]
    ChannelsConfig --> Matrix["matrix: MatrixConfig"]
    ChannelsConfig --> Email["email: EmailConfig"]
    ChannelsConfig --> WhatsApp["whatsapp: WhatsAppConfig"]
    ChannelsConfig --> Lark["lark: LarkConfig"]
    ChannelsConfig --> Mattermost["mattermost: MattermostConfig"]
    ChannelsConfig --> IMessage["imessage: IMessageConfig"]
    ChannelsConfig --> IRC["irc: IrcConfig"]
    ChannelsConfig --> DingTalk["dingtalk: DingTalkConfig"]
    ChannelsConfig --> QQ["qq: QQConfig"]
    ChannelsConfig --> Signal["signal: SignalConfig"]
    
    Telegram --> TGFields["bot_token: String<br/>allowed_users: Vec<String><br/>stream_mode: StreamMode<br/>mention_only: bool"]
    Discord --> DCFields["bot_token: String<br/>guild_id: Option<String><br/>allowed_users: Vec<String><br/>mention_only: bool"]
    Slack --> SLFields["bot_token: String<br/>app_token: Option<String><br/>allowed_users: Vec<String>"]
Loading

Sources: src/config/schema.rs:96, src/channels/mod.rs:1-31

Telegram

[channels_config.telegram]
bot_token = "123456789:ABC..."
allowed_users = ["alice", "bob"]
stream_mode = "draft"  # "none" | "draft" | "chunk"
draft_update_interval_ms = 1000
mention_only = false
Field Type Default Description
bot_token String Required Telegram Bot API token from @BotFather
allowed_users Vec<String> [] Allowed Telegram usernames (deny-by-default)
stream_mode StreamMode "draft" Streaming mode for responses
draft_update_interval_ms u64 1000 Milliseconds between draft message updates
mention_only bool false Only respond when bot is mentioned

StreamMode Options:

  • "none" - No streaming (wait for complete response)
  • "draft" - Update draft message as response arrives
  • "chunk" - Send multiple messages as chunks arrive

Sources: src/config/mod.rs:15

Discord

[channels_config.discord]
bot_token = "MTAxNjc..."
guild_id = "123456789"
allowed_users = ["user#1234"]
listen_to_bots = false
mention_only = true
Field Type Default Description
bot_token String Required Discord bot token
guild_id Option<String> None Optional guild/server ID to restrict to
allowed_users Vec<String> [] Allowed Discord user IDs or discriminators
listen_to_bots bool false Whether to respond to other bots
mention_only bool false Only respond when bot is @mentioned

Sources: src/config/mod.rs:15

Slack

[channels_config.slack]
bot_token = "xoxb-..."
app_token = "xapp-..."  # Required for Socket Mode
allowed_users = ["U12345"]
Field Type Description
bot_token String Slack Bot User OAuth Token
app_token Option<String> App-level token for Socket Mode
allowed_users Vec<String> Allowed Slack user IDs

Sources: src/config/mod.rs:15

Matrix

[channels_config.matrix]
homeserver_url = "https://matrix.org"
username = "@bot:matrix.org"
password = "..."
allowed_users = ["@alice:matrix.org"]
Field Type Description
homeserver_url String Matrix homeserver URL
username String Bot Matrix ID
password String Bot password
allowed_users Vec<String> Allowed Matrix user IDs

Sources: src/config/mod.rs:15

Email

[channels_config.email]
imap_server = "imap.gmail.com"
imap_port = 993
smtp_server = "smtp.gmail.com"
smtp_port = 587
username = "bot@example.com"
password = "..."
allowed_senders = ["alice@example.com"]
Field Type Default Description
imap_server String Required IMAP server hostname
imap_port u16 993 IMAP port (typically 993 for SSL)
smtp_server String Required SMTP server hostname
smtp_port u16 587 SMTP port (typically 587 for STARTTLS)
username String Required Email account username
password String Required Email account password
allowed_senders Vec<String> [] Allowed sender email addresses

Sources: src/channels/mod.rs:4-5

WhatsApp

[channels_config.whatsapp]
api_key = "EAABsb..."
phone_number_id = "1234567890"
webhook_verify_token = "random_secret"
allowed_numbers = ["+1234567890"]
Field Type Description
api_key String Meta WhatsApp API access token
phone_number_id String WhatsApp Business phone number ID
webhook_verify_token String Verification token for webhook setup
allowed_numbers Vec<String> Allowed phone numbers in E.164 format

Sources: src/config/schema.rs:1, src/channels/mod.rs:15

Lark (Feishu)

[channels_config.lark]
app_id = "cli_..."
app_secret = "..."
encrypt_key = "..."  # Optional
verification_token = "..."  # Optional
allowed_users = ["ou_123"]
use_feishu = false  # true for Feishu (China), false for Lark (International)
receive_mode = "websocket"  # "websocket" | "webhook"
port = 3001  # Only for webhook mode
Field Type Default Description
app_id String Required Lark/Feishu app ID
app_secret String Required Lark/Feishu app secret
encrypt_key Option<String> None Optional encryption key for webhook
verification_token Option<String> None Optional verification token for webhook
allowed_users Vec<String> [] Allowed user IDs
use_feishu bool false Use Feishu (China) endpoints instead of Lark
receive_mode LarkReceiveMode "websocket" Message receive mode
port Option<u16> None Port for webhook mode

Sources: src/config/mod.rs:15

Additional Channels

Mattermost, iMessage, IRC, DingTalk, QQ, Signal - Each follows similar patterns with channel-specific authentication and allowlist fields. See Channel Implementations for complete details.

Sources: src/channels/mod.rs:1-31


Agent Configuration

[agent]
compact_context = false
max_tool_iterations = 10
max_history_messages = 50
parallel_tools = false
tool_dispatcher = "auto"  # "auto" | "native" | "prompt"
Field Type Default Description
compact_context bool false Use reduced context for 13B or smaller models
max_tool_iterations usize 10 Maximum tool call loop iterations
max_history_messages usize 50 Maximum conversation history size
parallel_tools bool false Execute multiple tool calls in parallel
tool_dispatcher String "auto" Tool dispatch strategy

Tool Dispatcher Modes:

  • "auto" - Use provider's native function calling if available, else prompt-guided
  • "native" - Force native function calling (fails if unsupported)
  • "prompt" - Force prompt-guided tool calling (works with any model)

Sources: src/config/schema.rs:243-280


Memory Configuration

[memory]
backend = "sqlite"  # "sqlite" | "postgres" | "lucid" | "markdown" | "none"
auto_save = true
hygiene_enabled = true
archive_after_days = 7
purge_after_days = 30
conversation_retention_days = 30

# Embedding configuration for vector search
embedding_provider = "openai"  # "openai" | "ollama" | "none"
embedding_model = "text-embedding-3-small"
embedding_dimensions = 1536
vector_weight = 0.7
keyword_weight = 0.3
min_relevance_score = 0.4
embedding_cache_size = 10000
chunk_max_tokens = 512

# Response caching
response_cache_enabled = false
response_cache_ttl_minutes = 60
response_cache_max_entries = 5000

# Memory snapshots
snapshot_enabled = false
snapshot_on_hygiene = false
auto_hydrate = true

# SQLite tuning
sqlite_open_timeout_secs = 5
Field Type Default Description
backend String "sqlite" Memory backend implementation
auto_save bool true Automatically save conversations to memory
hygiene_enabled bool true Enable automatic cleanup of old entries
archive_after_days u32 7 Days before archiving old entries
purge_after_days u32 30 Days before permanently deleting entries
conversation_retention_days u32 30 Days to retain conversation history
embedding_provider String "none" Provider for generating embeddings
embedding_model String "text-embedding-3-small" Model for embeddings
embedding_dimensions usize 1536 Embedding vector dimensions
vector_weight f64 0.7 Weight for vector similarity in hybrid search
keyword_weight f64 0.3 Weight for keyword matching in hybrid search
min_relevance_score f64 0.4 Minimum relevance score for recall results
embedding_cache_size usize 10000 Number of embeddings to cache in memory
chunk_max_tokens usize 512 Maximum tokens per memory chunk
response_cache_enabled bool false Enable response caching
response_cache_ttl_minutes u64 60 Cache entry TTL
response_cache_max_entries usize 5000 Maximum cached entries
snapshot_enabled bool false Enable memory snapshots
snapshot_on_hygiene bool false Auto-snapshot before hygiene cleanup
auto_hydrate bool true Auto-restore from snapshots on startup
sqlite_open_timeout_secs Option<u32> None SQLite connection timeout

Backend Options:

  • sqlite - Full-featured SQL backend with FTS5 and vector search
  • postgres - PostgreSQL backend for production deployments
  • lucid - Lightweight Lucid-based backend (deprecated)
  • markdown - File-based storage in workspace/memory/*.md
  • none - No memory (stateless mode)

Sources: src/config/schema.rs:99


Tool Configuration

Browser Automation

[browser]
enabled = false
allowed_domains = ["example.com", "github.com"]
session_name = "default"
backend = "agent_browser"  # "agent_browser" | "rust_native" | "computer_use" | "auto"
native_headless = true
native_webdriver_url = "http://127.0.0.1:9515"
native_chrome_path = "/usr/bin/google-chrome"

[browser.computer_use]
endpoint = "http://127.0.0.1:8787/v1/actions"
api_key = ""
timeout_ms = 15000
allow_remote_endpoint = false
window_allowlist = []
max_coordinate_x = 1920
max_coordinate_y = 1080
Field Type Default Description
enabled bool false Enable browser automation tools
allowed_domains Vec<String> [] Domains the browser can access
session_name Option<String> None Browser session identifier
backend String "agent_browser" Browser automation backend
native_headless bool true Run browser in headless mode
native_webdriver_url String "http://127.0.0.1:9515" WebDriver URL for rust_native
native_chrome_path Option<String> None Chrome/Chromium binary path

Computer Use Sidecar Settings:

Field Type Default Description
endpoint String "http://127.0.0.1:8787/v1/actions" Computer-use API endpoint
api_key Option<String> None Bearer token for sidecar
timeout_ms u64 15000 Per-action timeout
allow_remote_endpoint bool false Allow non-localhost endpoints
window_allowlist Vec<String> [] Allowed window titles
max_coordinate_x Option<i64> None Max X coordinate boundary
max_coordinate_y Option<i64> None Max Y coordinate boundary

Sources: src/config/schema.rs:642-740

HTTP Requests

[http_request]
enabled = false
allowed_domains = ["api.example.com"]
max_response_size = 1000000  # 1MB
timeout_secs = 30
Field Type Default Description
enabled bool false Enable HTTP request tool
allowed_domains Vec<String> [] Domains the tool can access
max_response_size usize 1000000 Maximum response size in bytes
timeout_secs u64 30 Request timeout in seconds

Sources: src/config/schema.rs:743-767

Web Search

[web_search]
enabled = true
provider = "duckduckgo"  # "duckduckgo" | "brave"
brave_api_key = ""  # Required if provider = "brave"
max_results = 5
timeout_secs = 15
Field Type Default Description
enabled bool true Enable web search tool
provider String "duckduckgo" Search provider
brave_api_key Option<String> None Brave Search API key
max_results usize 5 Maximum search results (1-10)
timeout_secs u64 15 Request timeout

Sources: src/config/schema.rs:770-811

Composio Integration

[composio]
enabled = false
api_key = ""  # Composio API key
entity_id = "default"
Field Type Default Description
enabled bool false Enable Composio integration
api_key Option<String> None Composio API key (encrypted)
entity_id String "default" Entity ID for multi-user setups

Composio provides OAuth-managed access to 1000+ third-party applications (Gmail, GitHub, Notion, Slack, etc.) without storing raw OAuth tokens locally. See Composio Integration for usage details.

Sources: src/config/schema.rs:598-625, src/tools/composio.rs:18-27


Security Configuration

Autonomy Level

[autonomy]
level = "supervised"  # "readonly" | "supervised" | "full"
workspace_only = true
forbidden_paths = ["/etc", "/sys", "/proc"]
allowed_commands = []  # Empty = all commands allowed
Field Type Default Description
level AutonomyLevel "supervised" Agent autonomy mode
workspace_only bool true Restrict file operations to workspace directory
forbidden_paths Vec<String> System dirs Paths that cannot be accessed
allowed_commands Vec<String> [] Command allowlist (empty = all allowed)

Autonomy Levels:

  • readonly - Agent can read files but cannot execute tools that modify state
  • supervised - Agent can execute tools but may require approval
  • full - Agent can execute all tools autonomously

Sources: src/config/schema.rs:67, src/security/mod.rs

Secret Encryption

[secrets]
encrypt = true
Field Type Default Description
encrypt bool true Encrypt API keys and tokens in config.toml

When enabled, secrets are encrypted using ChaCha20-Poly1305 AEAD with a key stored in ~/.zeroclaw/secret.key. See Secret Management for details.

Sources: src/config/schema.rs:628-640

Gateway Security

[gateway]
port = 3000
host = "127.0.0.1"
require_pairing = true
allow_public_bind = false
paired_tokens = []  # Managed automatically

# Rate limiting
pair_rate_limit_per_minute = 10
webhook_rate_limit_per_minute = 60
trust_forwarded_headers = false
rate_limit_max_keys = 10000

# Idempotency
idempotency_ttl_secs = 300
idempotency_max_keys = 10000
Field Type Default Description
port u16 3000 Gateway HTTP port
host String "127.0.0.1" Bind address
require_pairing bool true Require pairing before accepting requests
allow_public_bind bool false Allow binding to non-localhost addresses
paired_tokens Vec<String> [] Paired bearer tokens (auto-managed)
pair_rate_limit_per_minute u32 10 Max /pair requests per minute per IP
webhook_rate_limit_per_minute u32 60 Max /webhook requests per minute per IP
trust_forwarded_headers bool false Trust X-Forwarded-For headers
rate_limit_max_keys usize 10000 Max distinct IPs tracked by rate limiter
idempotency_ttl_secs u64 300 Webhook idempotency key TTL
idempotency_max_keys usize 10000 Max idempotency keys in memory

Security Notes:

  • Gateway binds to localhost by default for security
  • Pairing generates a 6-digit code for client authentication
  • Set allow_public_bind = true only when using a trusted tunnel

Sources: src/config/schema.rs:502-596

Tunnel Configuration

[tunnel]
provider = "none"  # "none" | "tailscale" | "cloudflare" | "ngrok" | "custom"
custom_command = ""
Field Type Default Description
provider String "none" Tunnel provider
custom_command Option<String> None Custom tunnel command (for provider = "custom")

Sources: src/config/schema.rs:105


Scheduling and Automation

Cron Jobs

[cron]
enabled = true
storage_file = "cron_jobs.json"
Field Type Default Description
enabled bool true Enable cron job scheduler
storage_file String "cron_jobs.json" Cron job storage file name

Cron jobs are managed via the cron_add, cron_list, cron_remove, cron_update, cron_run, and cron_runs tools. See Cron Job Configuration for usage.

Sources: src/config/schema.rs:94

Scheduler

[scheduler]
enabled = true
max_concurrent_jobs = 4
Field Type Default Description
enabled bool true Enable background job scheduler
max_concurrent_jobs usize 4 Maximum concurrent scheduled jobs

Sources: src/config/schema.rs:76

Heartbeat

[heartbeat]
enabled = false
interval_secs = 3600
channels = ["telegram"]
message = "System operational"
Field Type Default Description
enabled bool false Enable periodic heartbeat messages
interval_secs u64 3600 Heartbeat interval in seconds
channels Vec<String> [] Channels to send heartbeat to
message String "System operational" Heartbeat message template

Sources: src/config/schema.rs:90


Advanced Configuration

Proxy Settings

[proxy]
enabled = false
http_proxy = "http://proxy.example.com:8080"
https_proxy = "http://proxy.example.com:8080"
all_proxy = "socks5://proxy.example.com:1080"
no_proxy = ["localhost", "127.0.0.1"]
scope = "zeroclaw"  # "environment" | "zeroclaw" | "services"
services = ["provider.*", "channel.telegram"]
Field Type Default Description
enabled bool false Enable proxy support
http_proxy Option<String> None HTTP proxy URL
https_proxy Option<String> None HTTPS proxy URL
all_proxy Option<String> None Fallback proxy for all schemes
no_proxy Vec<String> [] Bypass proxy for these domains
scope ProxyScope "zeroclaw" Proxy application scope
services Vec<String> [] Service selectors (when scope = "services")

Proxy Scopes:

  • environment - Use system environment proxy variables only
  • zeroclaw - Apply proxy to all ZeroClaw connections
  • services - Apply proxy selectively to matching services

Service Selectors:

Use glob-style patterns: "provider.*", "channel.telegram", "tool.browser", etc.

Supported service keys: See src/config/schema.rs:12-37 for complete list.

Sources: src/config/schema.rs:813-1029

Identity Format

[identity]
format = "openclaw"  # "openclaw" | "aieos"
aieos_path = "identity.json"
aieos_inline = ""  # JSON string (alternative to file)
Field Type Default Description
format String "openclaw" Identity format
aieos_path Option<String> None Path to AIEOS JSON file (relative to workspace)
aieos_inline Option<String> None Inline AIEOS JSON (alternative to file)

Identity Formats:

  • openclaw - Use workspace markdown files (AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, MEMORY.md)
  • aieos - Use AIEOS JSON structure for identity and behavior

Sources: src/config/schema.rs:283-309

Cost Tracking

[cost]
enabled = false
daily_limit_usd = 10.0
monthly_limit_usd = 100.0
warn_at_percent = 80
allow_override = false

[cost.prices]
"anthropic/claude-sonnet-4-20250514" = { input = 3.0, output = 15.0 }
"openai/gpt-4o" = { input = 5.0, output = 15.0 }
Field Type Default Description
enabled bool false Enable cost tracking
daily_limit_usd f64 10.0 Daily spending limit in USD
monthly_limit_usd f64 100.0 Monthly spending limit in USD
warn_at_percent u8 80 Warn when spending reaches this percent
allow_override bool false Allow --override flag to exceed limits
prices HashMap<String, ModelPricing> Defaults Per-model pricing (USD per 1M tokens)

ModelPricing Structure:

Field Type Description
input f64 Input token price per 1M tokens
output f64 Output token price per 1M tokens

Sources: src/config/schema.rs:311-450

Hardware Configuration

[hardware]
enabled = false
transport = "serial"  # "none" | "native" | "serial" | "probe"
serial_port = "/dev/ttyACM0"
baud_rate = 115200
probe_target = "STM32F401RE"
workspace_datasheets = false
Field Type Default Description
enabled bool false Enable hardware access
transport HardwareTransport "none" Hardware communication transport
serial_port Option<String> None Serial port path
baud_rate u32 115200 Serial baud rate
probe_target Option<String> None Debug probe target chip
workspace_datasheets bool false Enable datasheet RAG for pin lookups

Transport Modes:

  • none - No hardware access
  • native - Native GPIO access (Raspberry Pi)
  • serial - Serial communication (Arduino, STM32)
  • probe - Debug probe (ARM Cortex-M)

Sources: src/config/schema.rs:173-241

Peripherals

[peripherals]
enabled = false
datasheet_dir = "datasheets"

[[peripherals.boards]]
board = "nucleo-f401re"
transport = "serial"
path = "/dev/ttyACM0"
baud = 115200
Field Type Default Description
enabled bool false Enable peripheral board support
datasheet_dir Option<String> None Datasheet directory for RAG
boards Vec<PeripheralBoardConfig> [] Board configurations

PeripheralBoardConfig Structure:

Field Type Default Description
board String Required Board type (nucleo-f401re, rpi-gpio, esp32)
transport String "serial" Transport mode
path Option<String> None Device path (e.g., /dev/ttyACM0)
baud u32 115200 Baud rate

Sources: src/config/schema.rs:453-500

Delegate Agents

[agents.researcher]
provider = "ollama"
model = "llama3"
system_prompt = "You are a research assistant."
api_key = ""
temperature = 0.3
max_depth = 3

[agents.coder]
provider = "openrouter"
model = "anthropic/claude-sonnet-4-20250514"
temperature = 0.7
max_depth = 2

Each [agents.<name>] section defines a sub-agent configuration for the delegate tool.

Field Type Default Description
provider String Required Provider for this sub-agent
model String Required Model for this sub-agent
system_prompt Option<String> None Custom system prompt
api_key Option<String> None API key override
temperature Option<f64> 0.7 Temperature override
max_depth u32 3 Max recursion depth for nested delegation

See Delegation Tools for usage.

Sources: src/config/schema.rs:146-171, src/tools/delegate.rs:1-267


Runtime Configuration

[runtime]
adapter = "native"  # "native" | "docker"
Field Type Default Description
adapter String "native" Runtime adapter for tool execution

Runtime Adapters:

  • native - Direct subprocess execution on host
  • docker - Sandboxed execution in Docker containers

See Runtime Adapters for details.

Sources: src/config/schema.rs:70


Configuration Loading Flow

The following diagram shows how configuration is loaded and merged:

flowchart TD
    Start([Config::load_or_init])
    
    Start --> CheckFile{config.toml<br/>exists?}
    
    CheckFile -->|No| InitDefaults["Create default config<br/>Config::default()"]
    CheckFile -->|Yes| ParseTOML["Parse TOML<br/>toml::from_str()"]
    
    InitDefaults --> CheckEncrypt
    ParseTOML --> CheckEncrypt{secrets.encrypt?}
    
    CheckEncrypt -->|Yes| LoadSecretKey["Load secret.key<br/>SecretStore::load()"]
    CheckEncrypt -->|No| ApplyEnv
    
    LoadSecretKey --> DecryptSecrets["Decrypt secrets<br/>ChaCha20Poly1305"]
    DecryptSecrets --> ApplyEnv["Apply environment<br/>variable overrides"]
    
    ApplyEnv --> ValidateProxy{proxy.enabled?}
    ValidateProxy -->|Yes| ProxyValidation["ProxyConfig::validate()"]
    ValidateProxy -->|No| SetRuntime
    
    ProxyValidation --> ProxyScope{proxy.scope?}
    ProxyScope -->|environment| EnvProxyOnly["Use system env proxy"]
    ProxyScope -->|zeroclaw| ApplyGlobal["Apply to all requests"]
    ProxyScope -->|services| ApplySelective["Apply to matching services"]
    
    EnvProxyOnly --> SetRuntime
    ApplyGlobal --> SetRuntime["set_runtime_proxy_config()"]
    ApplySelective --> SetRuntime
    
    SetRuntime --> ReturnConfig["Return Config"]
Loading

Sources: src/config/schema.rs:1120-1200, src/config/schema.rs:1202-1315


Configuration Validation

Configuration validation occurs at multiple stages:

graph TB
    LoadConfig["Config::load_or_init()"]
    
    LoadConfig --> ValidateTOML["TOML syntax validation<br/>toml::from_str()"]
    ValidateTOML --> ValidateSecrets["Secret decryption<br/>SecretStore"]
    ValidateSecrets --> ValidateProxy["Proxy validation<br/>ProxyConfig::validate()"]
    ValidateProxy --> ValidateChannels["Channel validation<br/>bot_token, credentials"]
    ValidateChannels --> ValidateProvider["Provider validation<br/>create_provider()"]
    ValidateProvider --> ValidateMemory["Memory validation<br/>create_memory()"]
    ValidateMemory --> InitSubsystems["Initialize subsystems"]
    
    ValidateTOML -.failure.-> ConfigError["anyhow::Error"]
    ValidateSecrets -.failure.-> ConfigError
    ValidateProxy -.failure.-> ConfigError
    ValidateChannels -.failure.-> ConfigError
    ValidateProvider -.failure.-> ConfigError
    ValidateMemory -.failure.-> ConfigError
    
    ConfigError --> UserFeedback["Display error message<br/>with field name"]
Loading

Sources: src/config/schema.rs:1120-1315


Common Configuration Patterns

Minimal Configuration

# Fastest path to operational agent
api_key = "sk-..."
default_provider = "openrouter"
default_model = "anthropic/claude-sonnet-4.6"

Production Configuration

# Production-ready setup with monitoring and rate limiting
api_key = "sk-..."
default_provider = "openrouter"
default_model = "anthropic/claude-sonnet-4.6"
default_temperature = 0.7

[secrets]
encrypt = true

[autonomy]
level = "supervised"
workspace_only = true

[gateway]
require_pairing = true
allow_public_bind = false
pair_rate_limit_per_minute = 10
webhook_rate_limit_per_minute = 60

[memory]
backend = "sqlite"
auto_save = true
hygiene_enabled = true
embedding_provider = "openai"
embedding_model = "text-embedding-3-small"

[reliability]
max_retries = 3
retry_on_rate_limit = true
fallback_models = ["anthropic/claude-3.5-sonnet"]

[cost]
enabled = true
daily_limit_usd = 50.0
monthly_limit_usd = 500.0

[heartbeat]
enabled = true
interval_secs = 3600
channels = ["telegram"]

Multi-Channel Configuration

# Multiple communication channels
api_key = "sk-..."
default_provider = "openrouter"
default_model = "anthropic/claude-sonnet-4.6"

[channels_config.telegram]
bot_token = "123:ABC..."
allowed_users = ["alice", "bob"]
stream_mode = "draft"

[channels_config.discord]
bot_token = "MTAx..."
guild_id = "123456789"
allowed_users = ["user#1234"]
mention_only = true

[channels_config.slack]
bot_token = "xoxb-..."
app_token = "xapp-..."
allowed_users = ["U12345"]

Multi-Agent Workflow

# Delegate agents for specialized tasks
api_key = "sk-..."
default_provider = "openrouter"
default_model = "anthropic/claude-sonnet-4.6"

[agents.researcher]
provider = "openrouter"
model = "perplexity/sonar-pro"
system_prompt = "You are a research assistant. Provide detailed, well-sourced information."
temperature = 0.3
max_depth = 2

[agents.coder]
provider = "openrouter"
model = "anthropic/claude-sonnet-4.6"
system_prompt = "You are a code generation expert. Write clean, efficient code."
temperature = 0.7
max_depth = 2

[agents.summarizer]
provider = "openrouter"
model = "openai/gpt-4o-mini"
system_prompt = "You are a summarization expert. Provide concise summaries."
temperature = 0.5
max_depth = 1

Sources: src/onboard/wizard.rs:300-463


Configuration File Example

Complete example configuration with commonly used settings:

# ~/.zeroclaw/config.toml

# ── Core Settings ────────────────────────────────────────────────
api_key = "sk-or-v1-..."
default_provider = "openrouter"
default_model = "anthropic/claude-sonnet-4.6"
default_temperature = 0.7

# ── Security ─────────────────────────────────────────────────────
[secrets]
encrypt = true

[autonomy]
level = "supervised"
workspace_only = true
forbidden_paths = ["/etc", "/sys", "/proc", "/boot"]
allowed_commands = []

[gateway]
port = 3000
host = "127.0.0.1"
require_pairing = true
allow_public_bind = false
pair_rate_limit_per_minute = 10
webhook_rate_limit_per_minute = 60

# ── Channels ─────────────────────────────────────────────────────
[channels_config.telegram]
bot_token = "123456789:ABC..."
allowed_users = ["alice"]
stream_mode = "draft"
draft_update_interval_ms = 1000
mention_only = false

# ── Agent Configuration ──────────────────────────────────────────
[agent]
compact_context = false
max_tool_iterations = 10
max_history_messages = 50
parallel_tools = false

# ── Memory ───────────────────────────────────────────────────────
[memory]
backend = "sqlite"
auto_save = true
hygiene_enabled = true
archive_after_days = 7
purge_after_days = 30
embedding_provider = "openai"
embedding_model = "text-embedding-3-small"
embedding_dimensions = 1536
vector_weight = 0.7
keyword_weight = 0.3
min_relevance_score = 0.4

# ── Provider Reliability ─────────────────────────────────────────
[reliability]
max_retries = 3
initial_retry_delay_ms = 1000
max_retry_delay_ms = 60000
retry_multiplier = 2.0
retry_on_rate_limit = true
fallback_models = []

# ── Tools ────────────────────────────────────────────────────────
[browser]
enabled = false
allowed_domains = []
backend = "agent_browser"

[http_request]
enabled = false
allowed_domains = []
max_response_size = 1000000
timeout_secs = 30

[web_search]
enabled = true
provider = "duckduckgo"
max_results = 5
timeout_secs = 15

[composio]
enabled = false
api_key = ""
entity_id = "default"

# ── Cost Tracking ────────────────────────────────────────────────
[cost]
enabled = false
daily_limit_usd = 10.0
monthly_limit_usd = 100.0
warn_at_percent = 80

# ── Scheduling ───────────────────────────────────────────────────
[cron]
enabled = true
storage_file = "cron_jobs.json"

[heartbeat]
enabled = false
interval_secs = 3600
channels = []
message = "System operational"

# ── Advanced ─────────────────────────────────────────────────────
[proxy]
enabled = false
scope = "zeroclaw"

[identity]
format = "openclaw"

[hardware]
enabled = false
transport = "none"

[peripherals]
enabled = false

Sources: src/config/schema.rs:48-144, src/onboard/wizard.rs:104-143


Clone this wiki locally