LibreFang Configuration Reference
Complete reference for config.toml, covering every configurable field in the LibreFang Agent OS.
LibreFang reads its configuration from a single TOML file:
~ /.librefang/config.toml
CopyCopied!
On Windows, ~ resolves to C:\Users\<username>. If the home directory cannot be determined, the system temp directory is used as a fallback.
Key behaviors:
Every struct in the configuration uses #[serde(default)], which means all fields are optional . Omitted fields receive their documented default values.
Channel sections ([channels.telegram], [channels.discord], etc.) are Option<T> -- when absent, the channel adapter is disabled . Including the section header (even empty) enables the adapter with defaults.
Secrets are never stored in config.toml directly. Instead, fields like api_key_env and bot_token_env hold the name of an environment variable that contains the actual secret. This prevents accidental exposure in version control.
Sensitive fields (api_key, shared_secret) are automatically redacted in debug output and logs.
LibreFang supports splitting configuration across multiple files using the include field. This enables modular configs (e.g., separate files for channels, MCP servers, or environment-specific overrides).
# ~/.librefang/config.toml
include = [ "channels.toml" , "mcp.toml" , "overrides/prod.toml" ]
CopyCopied!
Rules:
Paths are relative to the directory containing the root config file.
Absolute paths are rejected with an error at startup.
.. path traversal components are rejected for security.
Maximum include nesting depth: 10 levels .
Include files are deep-merged before the root config. Root config values always override values from included files.
Include files can themselves contain include arrays (subject to the depth limit).
This mechanism is useful for keeping secrets in a separate file with stricter filesystem permissions, or for sharing a base config across multiple environments.
The simplest working configuration only needs an LLM provider API key set as an environment variable. With no config file at all, LibreFang boots with Anthropic as the default provider:
# ~/.librefang/config.toml
# Minimal: just override the model if you want something other than defaults.
# Set ANTHROPIC_API_KEY in your environment.
[ default_model ]
provider = "anthropic"
model = "claude-sonnet-4-20250514"
api_key_env = "ANTHROPIC_API_KEY"
CopyCopied!
Or to use a local Ollama instance with no API key:
[ default_model ]
provider = "ollama"
model = "llama3.2:latest"
base_url = "http://localhost:11434"
api_key_env = ""
CopyCopied!
# ============================================================
# LibreFang Agent OS -- Complete Configuration Reference
# ============================================================
# --- Top-level fields ---
home_dir = "~/.librefang" # LibreFang home directory
data_dir = "~/.librefang/data" # SQLite databases and data files
log_level = "info" # trace | debug | info | warn | error
api_listen = "127.0.0.1:4545" # HTTP/WS API bind address
network_enabled = false # Enable OFP peer-to-peer network
api_key = "" # API Bearer token (empty = unauthenticated)
dashboard_user = "" # Dashboard login username (empty = no login required)
dashboard_pass = "" # Dashboard login password (supports vault:KEY syntax)
mode = "default" # stable | default | dev
language = "en" # Locale for CLI/messages
usage_footer = "full" # off | tokens | cost | full
prompt_caching = true # Enable LLM prompt caching
stable_prefix_mode = false # Reduce prompt cache invalidation
max_cron_jobs = 500 # Global max cron jobs
cors_origin = [] # CORS allowed origins
include = [] # Config file includes
[ provider_urls ]
# ollama = "http://192.168.1.100:11434/v1"
[ provider_api_keys ]
# nvidia = "NVIDIA_API_KEY"
[ provider_regions ]
# qwen = "intl" # Use Qwen international endpoint (dashscope-intl)
# minimax = "china" # Use MiniMax China endpoint (MINIMAX_CN_API_KEY)
# --- Default LLM Provider ---
[ default_model ]
provider = "anthropic"
model = "claude-sonnet-4-20250514"
api_key_env = "ANTHROPIC_API_KEY"
# base_url = "https://api.anthropic.com" # Optional override
# --- Fallback Providers ---
[[ fallback_providers ]]
provider = "ollama"
model = "llama3.2:latest"
api_key_env = ""
# base_url = "http://localhost:11434" # Uses catalog default if omitted
[[ fallback_providers ]]
provider = "groq"
model = "llama-3.3-70b-versatile"
api_key_env = "GROQ_API_KEY"
# --- Memory ---
[ memory ]
# sqlite_path = "~/.librefang/data/librefang.db" # Auto-resolved if omitted
embedding_model = "all-MiniLM-L6-v2"
consolidation_threshold = 10000
decay_rate = 0.1
# --- Network (OFP Wire Protocol) ---
[ network ]
listen_addresses = [ "/ip4/0.0.0.0/tcp/0" ]
bootstrap_peers = []
mdns_enabled = true
max_peers = 50
shared_secret = "" # Required when network_enabled = true
# --- Web Tools ---
[ web ]
search_provider = "auto" # auto | brave | tavily | perplexity | duckduckgo
cache_ttl_minutes = 15
[ web . brave ]
api_key_env = "BRAVE_API_KEY"
max_results = 5
country = ""
search_lang = ""
freshness = ""
[ web . tavily ]
api_key_env = "TAVILY_API_KEY"
search_depth = "basic" # basic | advanced
max_results = 5
include_answer = true
[ web . perplexity ]
api_key_env = "PERPLEXITY_API_KEY"
model = "sonar"
[ web . fetch ]
max_chars = 50000
max_response_bytes = 10485760 # 10 MB
timeout_secs = 30
readability = true
# --- Media Understanding ---
[ media ]
image_description = true
audio_transcription = true
video_description = false
max_concurrency = 2
# image_provider = "openai"
# audio_provider = "openai"
# --- Link Understanding ---
[ links ]
enabled = false
max_links = 3
max_content_bytes = 102400
timeout_secs = 10
# --- MCP Servers ---
[[ mcp_servers ]]
name = "filesystem"
timeout_secs = 30
env = []
[ mcp_servers . transport ]
type = "stdio"
command = "npx"
args = [ "-y" , "@modelcontextprotocol/server-filesystem" , "/tmp" ]
[[ mcp_servers ]]
name = "remote-tools"
timeout_secs = 60
env = [ "REMOTE_API_KEY" ]
[ mcp_servers . transport ]
type = "sse"
url = "https://mcp.example.com/events"
[[ mcp_servers ]]
name = "my-http-backend"
timeout_secs = 30
[ mcp_servers . transport ]
type = "http_compat"
base_url = "https://tools.example.com"
headers = [{name = "Authorization" , value_env = "MY_API_KEY" }]
[[ mcp_servers . transport . tools ]]
name = "search"
description = "Search documents"
path = "/search"
method = "post"
# --- A2A Protocol ---
[ a2a ]
enabled = false
name = "LibreFang Agent OS"
description = ""
listen_path = "/a2a"
[[ a2a . external_agents ]]
name = "research-agent"
url = "https://agent.example.com/.well-known/agent.json"
# --- RBAC Users ---
[[ users ]]
name = "Alice"
role = "owner" # owner | admin | user | viewer
api_key_hash = ""
[ users . channel_bindings ]
telegram = "123456"
discord = "987654321"
[[ users ]]
name = "Bob"
role = "user"
[ users . channel_bindings ]
slack = "U0123ABCDEF"
# --- Channel Adapters ---
# (See "Channels" section below for all 44 adapters)
[ channels . telegram ]
bot_token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = []
# default_agent = "assistant"
poll_interval_secs = 1
[ channels . discord ]
bot_token_env = "DISCORD_BOT_TOKEN"
allowed_guilds = []
intents = 37376
[ channels . slack ]
app_token_env = "SLACK_APP_TOKEN"
bot_token_env = "SLACK_BOT_TOKEN"
allowed_channels = []
# [channels.qq]
# app_id = "your-app-id"
# app_secret_env = "QQ_BOT_APP_SECRET"
# [channels.wecom]
# corp_id = "your-corp-id"
# agent_id = "your-agent-id"
# secret_env = "WECOM_SECRET"
# webhook_port = 8454
# [channels.wechat]
# bot_token_env = "WECHAT_BOT_TOKEN" # optional: skip QR login on restart
# default_agent = "assistant"
# allowed_users = []
# --- Browser Automation ---
[ browser ]
headless = true
viewport_width = 1280
viewport_height = 720
timeout_secs = 30
idle_timeout_secs = 300
max_sessions = 5
# --- Config Hot-Reload ---
[ reload ]
mode = "hybrid" # off | restart | hot | hybrid
debounce_ms = 500
# --- Shell Exec Policy ---
[ exec_policy ]
mode = "allowlist" # deny | allowlist | full
timeout_secs = 30
max_output_bytes = 102400
no_output_timeout_secs = 30
# --- Budget ---
[ budget ]
max_hourly_usd = 0.0
max_daily_usd = 0.0
max_monthly_usd = 0.0
alert_threshold = 0.8
default_max_llm_tokens_per_hour = 0
# --- Extended Thinking ---
[ thinking ]
budget_tokens = 10000
stream_thinking = false
# --- TTS ---
[ tts ]
enabled = false
max_text_length = 4096
timeout_secs = 30
[ tts . openai ]
voice = "alloy"
model = "tts-1"
format = "mp3"
speed = 1.0
# --- Docker Sandbox ---
[ docker ]
enabled = false
image = "python:3.12-slim"
network = "none"
memory_limit = "512m"
cpu_limit = 1.0
timeout_secs = 60
read_only_root = true
mode = "off" # off | non_main | all
scope = "session" # session | agent | shared
cap_add = [] # e.g., ["NET_ADMIN"]
tmpfs = [ "/tmp:size=64m" ]
pids_limit = 100
# --- Vault ---
[ vault ]
enabled = true
# path = "~/.librefang/vault.enc"
# --- Webhook Triggers ---
[ webhook_triggers ]
enabled = false
token_env = "LIBREFANG_WEBHOOK_TOKEN"
max_payload_bytes = 65536
rate_limit_per_minute = 30
# --- HTTP Proxy ---
[ proxy ]
# http_proxy = "http://proxy.corp.example:8080"
# https_proxy = "http://proxy.corp.example:8080"
# no_proxy = "localhost,127.0.0.1,.internal.corp"
# --- Session ---
[ session ]
retention_days = 0
max_sessions_per_agent = 0
cleanup_interval_hours = 24
# --- Queue ---
[ queue ]
max_depth_per_agent = 0
max_depth_global = 0
task_ttl_secs = 3600
[ queue . concurrency ]
main_lane = 3
cron_lane = 2
subagent_lane = 3
# --- Audit ---
[ audit ]
retention_days = 90
# --- External Auth (OAuth2/OIDC) ---
[ external_auth ]
enabled = false
# issuer_url = "https://accounts.google.com"
# client_id = "your-client-id"
# client_secret_env = "LIBREFANG_OAUTH_CLIENT_SECRET"
# --- Vertex AI ---
[ vertex_ai ]
# project_id = "my-gcp-project"
# region = "us-central1"
# credentials_path = "/path/to/service-account.json"
# --- Context Engine ---
[ context_engine ]
engine = "default"
# plugin = "qdrant-recall"
# --- Plugins ---
[ plugins ]
plugin_registries = []
CopyCopied!
Top-Level Fields
These fields sit at the root of config.toml (not inside any [section]).
Field Type Default Description home_dirpath ~/.librefangLibreFang home directory. Stores config, agents, skills. data_dirpath ~/.librefang/dataDirectory for SQLite databases and persistent data. log_levelstring "info"Log verbosity. One of: trace, debug, info, warn, error. api_listenstring "127.0.0.1:4545"Bind address for the HTTP/WebSocket/SSE API server. Alias: listen_addr. network_enabledbool falseEnable the OFP peer-to-peer network layer. api_keystring "" (empty)API authentication key. When set, all endpoints except /api/health require Authorization: Bearer <key>. Empty means unauthenticated (local development only). cors_originlist of strings []CORS allowed origins added to the allow list (in addition to localhost). E.g., ["https://dash.example.com"]. modestring "default"Kernel operating mode. See below. languagestring "en"Language/locale code for CLI output and system messages. usage_footerstring "full"Controls usage info appended to responses. See below. prompt_cachingbool trueEnable LLM provider prompt caching. Adds cache hints to system prompts (Anthropic: cache_control, OpenAI: automatic prefix caching). stable_prefix_modebool falseWhen enabled, avoids volatile system-prompt additions (recalled memory, canonical context) that change every turn, improving provider-side prompt cache hit rates. max_cron_jobsusize 500Global maximum number of cron jobs across all agents. workspaces_dirpath or null nullRoot directory for agent workspaces. Defaults to ~/.librefang/workspaces. includelist of strings []Config file includes (relative paths). See Config Include Mechanism . provider_urlsmap of string→string {}Provider base URL overrides. Maps provider ID to custom base URL (e.g., ollama = "http://192.168.1.100:11434/v1"). Useful for self-hosted or proxied endpoints. provider_api_keysmap of string→string {}Provider API key env var overrides. Maps provider ID to the name of an environment variable holding the key (e.g., nvidia = "NVIDIA_API_KEY"). When not set for a provider, the convention {PROVIDER_UPPER}_API_KEY is used. provider_regionsmap of string→string {}Provider region selection. Maps provider ID to a region name defined in the provider's registry TOML (e.g., qwen = "intl"). Overrides the provider's base URL and optionally its API key env var. Applied before provider_urls (lower priority).
mode values:
Value Behavior stableConservative: no auto-updates, pinned models, frozen skill registry. Uses FallbackDriver. defaultBalanced: standard operation. devDeveloper: experimental features enabled.
usage_footer values:
Value Behavior offNo usage information shown. tokensShow token counts only. costShow estimated cost only. fullShow both token counts and estimated cost (default).
[default_model]
Configures the primary LLM provider used when agents do not specify their own model.
[ default_model ]
provider = "anthropic"
model = "claude-sonnet-4-20250514"
api_key_env = "ANTHROPIC_API_KEY"
# base_url = "https://api.anthropic.com"
CopyCopied!
Field Type Default Description providerstring "anthropic"Provider name. Supported: anthropic, gemini, openai, groq, openrouter, deepseek, together, mistral, fireworks, ollama, vllm, lmstudio, perplexity, cohere, ai21, cerebras, sambanova, huggingface, xai, replicate. modelstring "claude-sonnet-4-20250514"Model identifier. Aliases like sonnet, haiku, gpt-4o, gemini-flash are resolved by the model catalog. api_key_envstring "ANTHROPIC_API_KEY"Name of the environment variable holding the API key. The actual key is read from this env var at runtime, never stored in config. base_urlstring or null nullOverride the API base URL. Useful for proxies or self-hosted endpoints. When null, the provider's default URL from the model catalog is used.
[memory]
Configures the SQLite-backed memory substrate, including vector embeddings and memory decay.
[ memory ]
# sqlite_path = "/custom/path/librefang.db"
embedding_model = "all-MiniLM-L6-v2"
consolidation_threshold = 10000
decay_rate = 0.1
CopyCopied!
Field Type Default Description sqlite_pathpath or null nullExplicit path to the SQLite database file. When null, defaults to {data_dir}/librefang.db. embedding_modelstring "all-MiniLM-L6-v2"Model name used for generating vector embeddings for semantic memory search. embedding_providerstring or null nullEmbedding provider (e.g., "openai", "ollama"). Auto-detected if null. embedding_api_key_envstring or null nullEnvironment variable name holding the API key for the embedding provider. consolidation_thresholdu64 10000Number of stored memories before automatic consolidation is triggered to merge and prune old entries. consolidation_interval_hoursu64 24How often memory consolidation runs (hours). 0 = disabled. decay_ratef32 0.1Memory confidence decay rate. 0.0 = no decay (memories never fade), 1.0 = aggressive decay. Values between 0.0 and 1.0.
[network]
Configures the OFP (LibreFang Protocol) peer-to-peer networking layer with HMAC-SHA256 mutual authentication.
[ network ]
listen_addresses = [ "/ip4/0.0.0.0/tcp/0" ]
bootstrap_peers = []
mdns_enabled = true
max_peers = 50
shared_secret = "my-cluster-secret"
CopyCopied!
Field Type Default Description listen_addresseslist of strings ["/ip4/0.0.0.0/tcp/0"]libp2p multiaddresses to listen on. Port 0 means auto-assign. bootstrap_peerslist of strings []Multiaddresses of bootstrap peers for DHT discovery. mdns_enabledbool trueEnable mDNS for automatic local network peer discovery. max_peersu32 50Maximum number of simultaneously connected peers. shared_secretstring "" (empty)Pre-shared secret for OFP HMAC-SHA256 mutual authentication. Required when network_enabled = true. Both sides must use the same secret. Redacted in logs.
[web]
Configures web search and web fetch capabilities used by agent tools.
[ web ]
search_provider = "auto"
cache_ttl_minutes = 15
CopyCopied!
Field Type Default Description search_providerstring "auto"Which search engine to use. See values below. cache_ttl_minutesu64 15Cache duration for search/fetch results in minutes. 0 = caching disabled.
search_provider values:
Value Description autoCascading fallback: tries Tavily, then Brave, then Perplexity, then DuckDuckGo, based on which API keys are available. braveBrave Search API. Requires BRAVE_API_KEY. tavilyTavily AI-native search. Requires TAVILY_API_KEY. perplexityPerplexity AI search. Requires PERPLEXITY_API_KEY. duckduckgoDuckDuckGo HTML scraping. No API key needed.
[web.brave]
[ web . brave ]
api_key_env = "BRAVE_API_KEY"
max_results = 5
country = ""
search_lang = ""
freshness = ""
CopyCopied!
Field Type Default Description api_key_envstring "BRAVE_API_KEY"Environment variable name holding the Brave Search API key. max_resultsusize 5Maximum number of search results to return. countrystring ""Country code for localized results (e.g., "US", "GB"). Empty = no filter. search_langstring ""Language code (e.g., "en", "fr"). Empty = no filter. freshnessstring ""Freshness filter. "pd" = past day, "pw" = past week, "pm" = past month. Empty = no filter.
[web.tavily]
[ web . tavily ]
api_key_env = "TAVILY_API_KEY"
search_depth = "basic"
max_results = 5
include_answer = true
CopyCopied!
Field Type Default Description api_key_envstring "TAVILY_API_KEY"Environment variable name holding the Tavily API key. search_depthstring "basic"Search depth: "basic" for fast results, "advanced" for deeper analysis. max_resultsusize 5Maximum number of search results to return. include_answerbool trueWhether to include Tavily's AI-generated answer summary in results.
[web.perplexity]
[ web . perplexity ]
api_key_env = "PERPLEXITY_API_KEY"
model = "sonar"
CopyCopied!
Field Type Default Description api_key_envstring "PERPLEXITY_API_KEY"Environment variable name holding the Perplexity API key. modelstring "sonar"Perplexity model to use for search queries.
[web.fetch]
[ web . fetch ]
max_chars = 50000
max_response_bytes = 10485760
timeout_secs = 30
readability = true
CopyCopied!
Field Type Default Description max_charsusize 50000Maximum characters returned in fetched content. Content exceeding this is truncated. max_response_bytesusize 10485760 (10 MB)Maximum HTTP response body size in bytes. timeout_secsu64 30HTTP request timeout in seconds. readabilitybool trueEnable HTML-to-Markdown readability extraction. When true, fetched HTML is converted to clean Markdown.
Configures media understanding (image description, audio transcription, video description) for messages that include attachments.
[ media ]
image_description = true
audio_transcription = true
video_description = false
max_concurrency = 2
# image_provider = "openai" # auto-detect if omitted
# audio_provider = "openai" # auto-detect if omitted
CopyCopied!
Field Type Default Description image_descriptionbool trueEnable automatic image description for incoming image attachments. audio_transcriptionbool trueEnable automatic audio transcription for incoming audio attachments. video_descriptionbool falseEnable video description. Disabled by default (expensive and slow). max_concurrencyusize 2Maximum number of concurrent media processing tasks. image_providerstring or null nullPreferred provider for image description. Auto-detected from available providers if null. audio_providerstring or null nullPreferred provider for audio transcription. Auto-detected from available providers if null.
[links]
Configures automatic link understanding — fetching and summarizing URLs found in incoming messages.
[ links ]
enabled = false
max_links = 3
max_content_bytes = 102400
timeout_secs = 10
CopyCopied!
Field Type Default Description enabledbool falseEnable automatic link understanding. When true, URLs in messages are fetched and their content is summarized before the agent processes the message. max_linksusize 3Maximum number of links to process per message. Additional links are ignored. max_content_bytesusize 102400 (100 KB)Maximum content size to fetch per link in bytes. Content exceeding this is truncated. timeout_secsu64 10Per-link fetch timeout in seconds.
[channels]
All 45 channel adapters are configured under [channels.<name>]. Each channel is Option<T> -- omitting the section disables the adapter entirely. Including the section header (even empty) enables it with default values.
Universal channel fields: Every channel adapter supports the following common fields in addition to its own specific fields:
Field Type Default Description default_agentstring or null nullAgent name to route messages to by default. account_idstring or null nullUnique identifier for this bot instance. Used for multi-bot routing via [[bindings]] match rules. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.telegram]
[ channels . telegram ]
bot_token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = []
# default_agent = "assistant"
poll_interval_secs = 1
# api_url = "https://api.telegram.org" # override for local Bot API server
# account_id = "my-telegram-bot"
CopyCopied!
Field Type Default Description bot_token_envstring "TELEGRAM_BOT_TOKEN"Env var holding the Telegram Bot API token. allowed_userslist of i64 []Telegram user IDs allowed to interact. Empty = allow all. default_agentstring or null nullAgent name to route messages to. poll_interval_secsu64 1Long-polling interval in seconds. account_idstring or null nullUnique bot instance identifier for multi-bot routing. api_urlstring or null nullOverride the Telegram Bot API base URL. Useful for local Bot API server instances. Defaults to https://api.telegram.org. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.discord]
[ channels . discord ]
bot_token_env = "DISCORD_BOT_TOKEN"
allowed_guilds = []
# default_agent = "assistant"
intents = 37376
ignore_bots = true
# account_id = "my-discord-bot"
CopyCopied!
Field Type Default Description bot_token_envstring "DISCORD_BOT_TOKEN"Env var holding the Discord bot token. allowed_guildslist of u64 []Guild (server) IDs allowed. Empty = allow all. default_agentstring or null nullAgent name to route messages to. allowed_userslist of strings []Discord user IDs allowed to interact. Empty = allow all. intentsu64 37376Gateway intents bitmask. Default = GUILD_MESSAGES | DIRECT_MESSAGES | MESSAGE_CONTENT (37376). ignore_botsbool trueWhen true, messages from other bots are ignored. account_idstring or null nullUnique bot instance identifier for multi-bot routing. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.slack]
[ channels . slack ]
app_token_env = "SLACK_APP_TOKEN"
bot_token_env = "SLACK_BOT_TOKEN"
allowed_channels = []
# account_id = "my-slack-bot"
CopyCopied!
Field Type Default Description app_token_envstring "SLACK_APP_TOKEN"Env var holding the Slack app-level token (xapp-) for Socket Mode. bot_token_envstring "SLACK_BOT_TOKEN"Env var holding the Slack bot token (xoxb-) for REST API. allowed_channelslist of strings []Channel IDs allowed. Empty = allow all. default_agentstring or null nullAgent name to route messages to. account_idstring or null nullUnique bot instance identifier for multi-bot routing. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.whatsapp]
[ channels . whatsapp ]
access_token_env = "WHATSAPP_ACCESS_TOKEN"
verify_token_env = "WHATSAPP_VERIFY_TOKEN"
phone_number_id = ""
webhook_port = 8443
allowed_users = []
# gateway_url_env = "WHATSAPP_WEB_GATEWAY_URL" # for QR/Web mode
# account_id = "my-whatsapp-bot"
# owner_numbers = [] # optional admin phone numbers
CopyCopied!
Field Type Default Description access_token_envstring "WHATSAPP_ACCESS_TOKEN"Env var holding the WhatsApp Cloud API access token. verify_token_envstring "WHATSAPP_VERIFY_TOKEN"Env var holding the webhook verification token. phone_number_idstring ""WhatsApp Business phone number ID. webhook_portu16 8443Port to listen for incoming webhook callbacks. gateway_url_envstring "WHATSAPP_WEB_GATEWAY_URL"Env var holding the WhatsApp Web gateway URL. When set, outgoing messages are routed through the QR/Web gateway instead of the Cloud API. allowed_userslist of strings []Phone numbers allowed. Empty = allow all. default_agentstring or null nullAgent name to route messages to. account_idstring or null nullUnique bot instance identifier for multi-bot routing. owner_numberslist of strings []Phone numbers with administrative privileges for this bot instance. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.signal]
[ channels . signal ]
api_url = "http://localhost:8080"
phone_number = ""
allowed_users = []
CopyCopied!
Field Type Default Description api_urlstring "http://localhost:8080"URL of the signal-cli REST API. phone_numberstring ""Registered phone number for the bot. allowed_userslist of strings []Allowed phone numbers. Empty = allow all. default_agentstring or null nullAgent name to route messages to.
[channels.matrix]
[ channels . matrix ]
homeserver_url = "https://matrix.org"
user_id = "@librefang:matrix.org"
access_token_env = "MATRIX_ACCESS_TOKEN"
allowed_rooms = []
CopyCopied!
Field Type Default Description homeserver_urlstring "https://matrix.org"Matrix homeserver URL. user_idstring ""Bot user ID (e.g., "@librefang:matrix.org"). access_token_envstring "MATRIX_ACCESS_TOKEN"Env var holding the Matrix access token. allowed_roomslist of strings []Room IDs to listen in. Empty = all joined rooms. default_agentstring or null nullAgent name to route messages to.
[channels.email]
[ channels . email ]
imap_host = "imap.gmail.com"
imap_port = 993
smtp_host = "smtp.gmail.com"
smtp_port = 587
username = "bot@example.com"
password_env = "EMAIL_PASSWORD"
poll_interval_secs = 30
folders = [ "INBOX" ]
allowed_senders = []
CopyCopied!
Field Type Default Description imap_hoststring ""IMAP server hostname. imap_portu16 993IMAP server port (993 for TLS). smtp_hoststring ""SMTP server hostname. smtp_portu16 587SMTP server port (587 for STARTTLS). usernamestring ""Email address for both IMAP and SMTP. password_envstring "EMAIL_PASSWORD"Env var holding the email password or app password. poll_interval_secsu64 30IMAP polling interval in seconds. folderslist of strings ["INBOX"]IMAP folders to monitor. allowed_senderslist of strings []Only process emails from these senders. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.teams]
[ channels . teams ]
app_id = ""
app_password_env = "TEAMS_APP_PASSWORD"
webhook_port = 3978
allowed_tenants = []
CopyCopied!
Field Type Default Description app_idstring ""Azure Bot App ID. app_password_envstring "TEAMS_APP_PASSWORD"Env var holding the Azure Bot Framework app password. webhook_portu16 3978Port for the Bot Framework incoming webhook. allowed_tenantslist of strings []Azure AD tenant IDs allowed. Empty = allow all. default_agentstring or null nullAgent name to route messages to.
[channels.mattermost]
[ channels . mattermost ]
server_url = "https://mattermost.example.com"
token_env = "MATTERMOST_TOKEN"
allowed_channels = []
CopyCopied!
Field Type Default Description server_urlstring ""Mattermost server URL. token_envstring "MATTERMOST_TOKEN"Env var holding the Mattermost bot token. allowed_channelslist of strings []Channel IDs to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.irc]
[ channels . irc ]
server = "irc.libera.chat"
port = 6667
nick = "librefang"
# password_env = "IRC_PASSWORD"
channels = [ "#librefang" ]
use_tls = false
CopyCopied!
Field Type Default Description serverstring "irc.libera.chat"IRC server hostname. portu16 6667IRC server port. nickstring "librefang"Bot nickname. password_envstring or null nullEnv var holding the server password (optional). channelslist of strings []IRC channels to join (e.g., ["#librefang", "#general"]). use_tlsbool falseUse TLS for the connection. default_agentstring or null nullAgent name to route messages to.
[channels.google_chat]
[ channels . google_chat ]
service_account_env = "GOOGLE_CHAT_SERVICE_ACCOUNT"
space_ids = []
webhook_port = 8444
CopyCopied!
Field Type Default Description service_account_envstring "GOOGLE_CHAT_SERVICE_ACCOUNT"Env var holding the service account JSON key. space_idslist of strings []Google Chat space IDs to listen in. webhook_portu16 8444Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.twitch]
[ channels . twitch ]
oauth_token_env = "TWITCH_OAUTH_TOKEN"
channels = [ "mychannel" ]
nick = "librefang"
CopyCopied!
Field Type Default Description oauth_token_envstring "TWITCH_OAUTH_TOKEN"Env var holding the Twitch OAuth token. channelslist of strings []Twitch channels to join (without # prefix). nickstring "librefang"Bot nickname in Twitch chat. default_agentstring or null nullAgent name to route messages to.
[channels.rocketchat]
[ channels . rocketchat ]
server_url = "https://rocketchat.example.com"
token_env = "ROCKETCHAT_TOKEN"
user_id = ""
allowed_channels = []
CopyCopied!
Field Type Default Description server_urlstring ""Rocket.Chat server URL. token_envstring "ROCKETCHAT_TOKEN"Env var holding the Rocket.Chat auth token. user_idstring ""Bot user ID. allowed_channelslist of strings []Channel IDs to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.zulip]
[ channels . zulip ]
server_url = "https://zulip.example.com"
bot_email = "bot@zulip.example.com"
api_key_env = "ZULIP_API_KEY"
streams = []
CopyCopied!
Field Type Default Description server_urlstring ""Zulip server URL. bot_emailstring ""Bot email address registered in Zulip. api_key_envstring "ZULIP_API_KEY"Env var holding the Zulip API key. streamslist of strings []Stream names to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.xmpp]
[ channels . xmpp ]
jid = "bot@jabber.org"
password_env = "XMPP_PASSWORD"
server = ""
port = 5222
rooms = []
CopyCopied!
Field Type Default Description jidstring ""XMPP JID (e.g., "bot@jabber.org"). password_envstring "XMPP_PASSWORD"Env var holding the XMPP password. serverstring ""XMPP server hostname. Defaults to the JID domain if empty. portu16 5222XMPP server port. roomslist of strings []MUC (multi-user chat) rooms to join. default_agentstring or null nullAgent name to route messages to.
[channels.line]
[ channels . line ]
channel_secret_env = "LINE_CHANNEL_SECRET"
access_token_env = "LINE_CHANNEL_ACCESS_TOKEN"
webhook_port = 8450
CopyCopied!
Field Type Default Description channel_secret_envstring "LINE_CHANNEL_SECRET"Env var holding the LINE channel secret. access_token_envstring "LINE_CHANNEL_ACCESS_TOKEN"Env var holding the LINE channel access token. webhook_portu16 8450Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.viber]
[ channels . viber ]
auth_token_env = "VIBER_AUTH_TOKEN"
webhook_url = ""
webhook_port = 8451
CopyCopied!
Field Type Default Description auth_token_envstring "VIBER_AUTH_TOKEN"Env var holding the Viber Bot auth token. webhook_urlstring ""Public URL for the Viber webhook endpoint. webhook_portu16 8451Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.messenger]
[ channels . messenger ]
page_token_env = "MESSENGER_PAGE_TOKEN"
verify_token_env = "MESSENGER_VERIFY_TOKEN"
webhook_port = 8452
CopyCopied!
Field Type Default Description page_token_envstring "MESSENGER_PAGE_TOKEN"Env var holding the Facebook page access token. verify_token_envstring "MESSENGER_VERIFY_TOKEN"Env var holding the webhook verify token. webhook_portu16 8452Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.reddit]
[ channels . reddit ]
client_id = ""
client_secret_env = "REDDIT_CLIENT_SECRET"
username = ""
password_env = "REDDIT_PASSWORD"
subreddits = []
CopyCopied!
Field Type Default Description client_idstring ""Reddit app client ID. client_secret_envstring "REDDIT_CLIENT_SECRET"Env var holding the Reddit client secret. usernamestring ""Reddit bot username. password_envstring "REDDIT_PASSWORD"Env var holding the Reddit bot password. subredditslist of strings []Subreddit names to monitor. default_agentstring or null nullAgent name to route messages to.
[channels.mastodon]
[ channels . mastodon ]
instance_url = "https://mastodon.social"
access_token_env = "MASTODON_ACCESS_TOKEN"
CopyCopied!
Field Type Default Description instance_urlstring ""Mastodon instance URL (e.g., "https://mastodon.social"). access_token_envstring "MASTODON_ACCESS_TOKEN"Env var holding the Mastodon access token. default_agentstring or null nullAgent name to route messages to.
[channels.bluesky]
[ channels . bluesky ]
identifier = "mybot.bsky.social"
app_password_env = "BLUESKY_APP_PASSWORD"
service_url = "https://bsky.social"
CopyCopied!
Field Type Default Description identifierstring ""Bluesky handle or DID. app_password_envstring "BLUESKY_APP_PASSWORD"Env var holding the Bluesky app password. service_urlstring "https://bsky.social"PDS (Personal Data Server) URL. default_agentstring or null nullAgent name to route messages to.
[channels.feishu]
[ channels . feishu ]
app_id = ""
app_secret_env = "FEISHU_APP_SECRET"
webhook_port = 8453
CopyCopied!
Field Type Default Description app_idstring ""Feishu/Lark app ID. app_secret_envstring "FEISHU_APP_SECRET"Env var holding the Feishu app secret. webhook_portu16 8453Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.revolt]
[ channels . revolt ]
bot_token_env = "REVOLT_BOT_TOKEN"
api_url = "https://api.revolt.chat"
CopyCopied!
Field Type Default Description bot_token_envstring "REVOLT_BOT_TOKEN"Env var holding the Revolt bot token. api_urlstring "https://api.revolt.chat"Revolt API base URL. default_agentstring or null nullAgent name to route messages to.
[channels.nextcloud]
[ channels . nextcloud ]
server_url = "https://nextcloud.example.com"
token_env = "NEXTCLOUD_TOKEN"
allowed_rooms = []
CopyCopied!
Field Type Default Description server_urlstring ""Nextcloud server URL. token_envstring "NEXTCLOUD_TOKEN"Env var holding the Nextcloud Talk auth token. allowed_roomslist of strings []Room tokens to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.guilded]
[ channels . guilded ]
bot_token_env = "GUILDED_BOT_TOKEN"
server_ids = []
CopyCopied!
Field Type Default Description bot_token_envstring "GUILDED_BOT_TOKEN"Env var holding the Guilded bot token. server_idslist of strings []Server IDs to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.keybase]
[ channels . keybase ]
username = ""
paperkey_env = "KEYBASE_PAPERKEY"
allowed_teams = []
CopyCopied!
Field Type Default Description usernamestring ""Keybase username. paperkey_envstring "KEYBASE_PAPERKEY"Env var holding the Keybase paper key. allowed_teamslist of strings []Team names to listen in. Empty = all DMs. default_agentstring or null nullAgent name to route messages to.
[channels.threema]
[ channels . threema ]
threema_id = ""
secret_env = "THREEMA_SECRET"
webhook_port = 8454
CopyCopied!
Field Type Default Description threema_idstring ""Threema Gateway ID. secret_envstring "THREEMA_SECRET"Env var holding the Threema API secret. webhook_portu16 8454Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.nostr]
[ channels . nostr ]
private_key_env = "NOSTR_PRIVATE_KEY"
relays = [ "wss://relay.damus.io" ]
CopyCopied!
Field Type Default Description private_key_envstring "NOSTR_PRIVATE_KEY"Env var holding the Nostr private key (nsec or hex format). relayslist of strings ["wss://relay.damus.io"]Nostr relay WebSocket URLs to connect to. default_agentstring or null nullAgent name to route messages to.
[channels.webex]
[ channels . webex ]
bot_token_env = "WEBEX_BOT_TOKEN"
allowed_rooms = []
CopyCopied!
Field Type Default Description bot_token_envstring "WEBEX_BOT_TOKEN"Env var holding the Webex bot token. allowed_roomslist of strings []Room IDs to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.pumble]
[ channels . pumble ]
bot_token_env = "PUMBLE_BOT_TOKEN"
webhook_port = 8455
CopyCopied!
Field Type Default Description bot_token_envstring "PUMBLE_BOT_TOKEN"Env var holding the Pumble bot token. webhook_portu16 8455Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.flock]
[ channels . flock ]
bot_token_env = "FLOCK_BOT_TOKEN"
webhook_port = 8456
CopyCopied!
Field Type Default Description bot_token_envstring "FLOCK_BOT_TOKEN"Env var holding the Flock bot token. webhook_portu16 8456Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.twist]
[ channels . twist ]
token_env = "TWIST_TOKEN"
workspace_id = ""
allowed_channels = []
CopyCopied!
Field Type Default Description token_envstring "TWIST_TOKEN"Env var holding the Twist API token. workspace_idstring ""Twist workspace ID. allowed_channelslist of strings []Channel IDs to listen in. Empty = all. default_agentstring or null nullAgent name to route messages to.
[channels.mumble]
[ channels . mumble ]
host = "mumble.example.com"
port = 64738
username = "librefang"
password_env = "MUMBLE_PASSWORD"
channel = ""
CopyCopied!
Field Type Default Description hoststring ""Mumble server hostname. portu16 64738Mumble server port. usernamestring "librefang"Bot username in Mumble. password_envstring "MUMBLE_PASSWORD"Env var holding the Mumble server password. channelstring ""Mumble channel to join. default_agentstring or null nullAgent name to route messages to.
[channels.dingtalk]
[ channels . dingtalk ]
access_token_env = "DINGTALK_ACCESS_TOKEN"
secret_env = "DINGTALK_SECRET"
webhook_port = 8457
CopyCopied!
Field Type Default Description access_token_envstring "DINGTALK_ACCESS_TOKEN"Env var holding the DingTalk webhook access token. secret_envstring "DINGTALK_SECRET"Env var holding the DingTalk signing secret. webhook_portu16 8457Port for the incoming webhook. default_agentstring or null nullAgent name to route messages to.
[channels.discourse]
[ channels . discourse ]
base_url = "https://forum.example.com"
api_key_env = "DISCOURSE_API_KEY"
api_username = "system"
categories = []
CopyCopied!
Field Type Default Description base_urlstring ""Discourse forum base URL. api_key_envstring "DISCOURSE_API_KEY"Env var holding the Discourse API key. api_usernamestring "system"Discourse API username. categorieslist of strings []Category slugs to monitor. default_agentstring or null nullAgent name to route messages to.
[channels.gitter]
[ channels . gitter ]
token_env = "GITTER_TOKEN"
room_id = ""
CopyCopied!
Field Type Default Description token_envstring "GITTER_TOKEN"Env var holding the Gitter auth token. room_idstring ""Gitter room ID to listen in. default_agentstring or null nullAgent name to route messages to.
[channels.ntfy]
[ channels . ntfy ]
server_url = "https://ntfy.sh"
topic = "my-agent-topic"
token_env = "NTFY_TOKEN"
CopyCopied!
Field Type Default Description server_urlstring "https://ntfy.sh"ntfy server URL. Can be self-hosted. topicstring ""Topic to subscribe/publish to. token_envstring "NTFY_TOKEN"Env var holding the auth token. Optional for public topics. default_agentstring or null nullAgent name to route messages to.
[channels.gotify]
[ channels . gotify ]
server_url = "https://gotify.example.com"
app_token_env = "GOTIFY_APP_TOKEN"
client_token_env = "GOTIFY_CLIENT_TOKEN"
CopyCopied!
Field Type Default Description server_urlstring ""Gotify server URL. app_token_envstring "GOTIFY_APP_TOKEN"Env var holding the Gotify app token (for sending messages). client_token_envstring "GOTIFY_CLIENT_TOKEN"Env var holding the Gotify client token (for receiving messages via WebSocket). default_agentstring or null nullAgent name to route messages to.
[channels.webhook]
[ channels . webhook ]
secret_env = "WEBHOOK_SECRET"
listen_port = 8460
# callback_url = "https://example.com/webhook"
CopyCopied!
Field Type Default Description secret_envstring "WEBHOOK_SECRET"Env var holding the HMAC signing secret for verifying incoming webhooks. listen_portu16 8460Port to listen for incoming webhook requests. callback_urlstring or null nullURL to POST outgoing messages to. default_agentstring or null nullAgent name to route messages to.
[channels.linkedin]
[ channels . linkedin ]
access_token_env = "LINKEDIN_ACCESS_TOKEN"
organization_id = ""
CopyCopied!
Field Type Default Description access_token_envstring "LINKEDIN_ACCESS_TOKEN"Env var holding the LinkedIn OAuth2 access token. organization_idstring ""LinkedIn organization ID for messaging. default_agentstring or null nullAgent name to route messages to.
[channels.qq]
QQ Bot channel adapter using the official QQ Bot Open Platform API.
[ channels . qq ]
app_id = "your-app-id"
app_secret_env = "QQ_BOT_APP_SECRET"
allowed_users = []
# default_agent = "assistant"
# account_id = "my-qq-bot"
CopyCopied!
Field Type Default Description app_idstring ""QQ Bot application ID registered on the QQ Open Platform. app_secret_envstring "QQ_BOT_APP_SECRET"Env var holding the QQ Bot application secret. The actual secret is never stored in config. allowed_userslist of strings []QQ user IDs allowed to interact. Empty = allow all. default_agentstring or null nullAgent name to route messages to. account_idstring or null nullUnique bot instance identifier for multi-bot routing. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.wecom]
WeCom (formerly WeChat Work / Enterprise WeChat) channel adapter.
[ channels . wecom ]
corp_id = "your-corp-id"
agent_id = "your-agent-id"
secret_env = "WECOM_SECRET"
webhook_port = 8454
# token_env = "WECOM_TOKEN"
# encoding_aes_key_env = "WECOM_AES_KEY"
# default_agent = "assistant"
# account_id = "my-wecom-bot"
CopyCopied!
Field Type Default Description corp_idstring ""WeCom corporation ID. agent_idstring ""WeCom application agent ID. secret_envstring "WECOM_SECRET"Env var holding the WeCom application secret. webhook_portu16 8454Port for the incoming webhook. token_envstring or null nullEnv var holding the callback verification token. Required for verifying incoming messages. encoding_aes_key_envstring or null nullEnv var holding the encoding AES key for message encryption/decryption. default_agentstring or null nullAgent name to route messages to. account_idstring or null nullUnique bot instance identifier for multi-bot routing. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[channels.wechat]
WeChat personal account channel adapter using Tencent's iLink Bot API. Connects via QR code scan — no API keys or developer accounts required.
[ channels . wechat ]
# bot_token_env = "WECHAT_BOT_TOKEN" # optional: persisted token from previous session
allowed_users = []
# default_agent = "assistant"
# account_id = "my-wechat-bot"
CopyCopied!
Field Type Default Description bot_token_envstring "WECHAT_BOT_TOKEN"Env var holding a persisted bot token from a previous QR login session. When set, skips QR login on restart. allowed_userslist of strings []WeChat user IDs allowed to interact (format: hash@im.wechat). Empty = allow all. default_agentstring or null nullAgent name to route messages to. account_idstring or null nullUnique bot instance identifier for multi-bot routing. overridesobject (defaults) Per-channel behavior overrides. See Channel Overrides .
[[mcp_servers]]
MCP (Model Context Protocol) server connections provide external tool integration. Each entry is a separate [[mcp_servers]] array element.
[[ mcp_servers ]]
name = "filesystem"
timeout_secs = 30
env = []
[ mcp_servers . transport ]
type = "stdio"
command = "npx"
args = [ "-y" , "@modelcontextprotocol/server-filesystem" , "/home/user/docs" ]
CopyCopied!
[[ mcp_servers ]]
name = "remote-api"
timeout_secs = 60
env = [ "GITHUB_PERSONAL_ACCESS_TOKEN" ]
[ mcp_servers . transport ]
type = "sse"
url = "https://mcp.example.com/sse"
CopyCopied!
[[ mcp_servers ]]
name = "my-http-backend"
timeout_secs = 30
[ mcp_servers . transport ]
type = "http_compat"
base_url = "https://tools.example.com"
headers = [{name = "Authorization" , value_env = "MY_API_KEY" }]
[[ mcp_servers . transport . tools ]]
name = "search"
description = "Search documents"
path = "/search"
method = "post"
CopyCopied!
Field Type Default Description namestring required Display name for this MCP server. Tools are namespaced as mcp_{name}_{tool}. timeout_secsu64 30Request timeout in seconds. envlist of strings []Environment variable names to pass through to the subprocess (stdio transport only).
Transport variants (tagged union on type):
typeFields Description stdiocommand (string), args (list of strings, default [])Spawn a subprocess, communicate via JSON-RPC over stdin/stdout. sseurl (string)Connect to an HTTP Server-Sent Events endpoint. http_compatbase_url (string), headers (list of header configs), tools (list of tool configs)Built-in compatibility adapter for plain HTTP/JSON tool backends without a native MCP server. Each tool maps to an HTTP endpoint.
http_compat header config:
Field Type Description namestring HTTP header name (e.g., "Authorization"). valuestring or null Static header value. value_envstring or null Env var name whose value is used as the header value (preferred for secrets).
http_compat tool config:
Field Type Default Description namestring required Tool name exposed to the LLM. descriptionstring ""Tool description shown to the LLM. pathstring required HTTP path (e.g., "/search"). methodstring "post"HTTP method: get, post, put, patch, delete. request_modestring "json_body"How arguments are sent: json_body, query, none. response_modestring "json"Response parsing: json, text. input_schemaobject {"type":"object"}JSON Schema for the tool's input parameters.
[a2a]
Agent-to-Agent protocol configuration, enabling inter-agent communication across LibreFang instances.
[ a2a ]
enabled = true
name = "LibreFang Agent OS"
description = "My production agent OS"
listen_path = "/a2a"
[[ a2a . external_agents ]]
name = "research-agent"
url = "https://agent.example.com/.well-known/agent.json"
[[ a2a . external_agents ]]
name = "code-reviewer"
url = "https://reviewer.example.com/.well-known/agent.json"
CopyCopied!
Field Type Default Description enabledbool falseWhether A2A protocol is enabled. namestring "LibreFang Agent OS"Service-level display name shown in the well-known agent card. descriptionstring ""Service-level description shown in the well-known agent card. listen_pathstring "/a2a"URL path prefix for A2A endpoints. external_agentslist of objects []External A2A agents to discover and interact with.
external_agents entries:
Field Type Description namestring Display name for the external agent. urlstring Agent card endpoint URL (typically /.well-known/agent.json).
[[fallback_providers]]
Fallback provider chain. When the primary LLM provider ([default_model]) fails, these are tried in order.
[[ fallback_providers ]]
provider = "ollama"
model = "llama3.2:latest"
api_key_env = ""
# base_url = "http://localhost:11434"
[[ fallback_providers ]]
provider = "groq"
model = "llama-3.3-70b-versatile"
api_key_env = "GROQ_API_KEY"
CopyCopied!
Field Type Default Description providerstring ""Provider name (e.g., "ollama", "groq", "openai"). modelstring ""Model identifier for this provider. api_key_envstring ""Env var name for the API key. Empty for local providers (ollama, vllm, lmstudio). base_urlstring or null nullBase URL override. Uses catalog default if null.
[[users]]
RBAC multi-user configuration. Users can be assigned roles and bound to channel platform identities.
[[ users ]]
name = "Alice"
role = "owner"
api_key_hash = "sha256_hash_of_api_key"
[ users . channel_bindings ]
telegram = "123456"
discord = "987654321"
slack = "U0ABCDEFG"
CopyCopied!
Field Type Default Description namestring required User display name. rolestring "user"User role in the RBAC hierarchy. channel_bindingsmap of string to string {}Maps channel platform names to platform-specific user IDs, binding this user identity across channels. api_key_hashstring or null nullSHA256 hash of the user's personal API key for authenticated API access.
Role hierarchy (highest to lowest privilege):
Role Description ownerFull administrative access. Can manage all agents, users, and configuration. adminCan manage agents and most settings. Cannot modify owner accounts. userCan interact with agents. Limited management capabilities. viewerRead-only access. Can view agent responses but cannot send messages.
Channel Overrides
Every channel adapter supports an [channels.<name>.overrides] sub-table that customizes agent behavior per-channel.
[ channels . telegram . overrides ]
model = "claude-haiku-4-5-20251001"
system_prompt = "You are a concise Telegram assistant."
dm_policy = "respond"
group_policy = "mention_only"
rate_limit_per_minute = 0
rate_limit_per_user = 10
threading = true
output_format = "telegram_html"
usage_footer = "tokens"
typing_mode = "instant"
CopyCopied!
Field Type Default Description modelstring or null nullModel override for this channel. Uses the agent's default model when null. system_promptstring or null nullSystem prompt override for this channel. dm_policystring "respond"How the bot handles direct messages. See below. group_policystring "mention_only"How the bot handles group messages. See below. rate_limit_per_minuteu32 0Global rate limit for this channel (messages per minute). 0 = unlimited. rate_limit_per_useru32 0Maximum messages per user per minute. 0 = unlimited. threadingbool falseEnable thread replies (where supported by the platform). output_formatstring or null nullOverride output formatting. See below. usage_footerstring or null nullOverride usage footer mode for this channel. Values: off, tokens, cost, full. typing_modestring or null nullTyping indicator behavior. See below. Defaults to instant.
dm_policy values:
Value Description respondRespond to all direct messages (default). allowed_onlyOnly respond to DMs from users in the allowed list. ignoreIgnore all direct messages.
group_policy values:
Value Description allRespond to all messages in group chats. mention_onlyOnly respond when the bot is @mentioned (default). commands_onlyOnly respond to slash commands. ignoreIgnore all group messages.
output_format values:
Value Description markdownStandard Markdown (default). telegram_htmlTelegram HTML subset (<b>, <i>, <code>, etc.). slack_mrkdwnSlack mrkdwn format (*bold*, _italic_, `code`). plain_textNo formatting markup.
typing_mode values:
Value Description instantSend typing indicator immediately on message receipt (default). messageSend typing indicator only when the first text delta arrives from the LLM. thinkingSend typing indicator only during LLM reasoning/thinking phase. neverNever send typing indicators.
[browser]
Configures the headless browser automation engine used by the browser_* agent tools.
[ browser ]
headless = true
viewport_width = 1280
viewport_height = 720
timeout_secs = 30
idle_timeout_secs = 300
max_sessions = 5
# chromium_path = "/usr/bin/chromium"
CopyCopied!
Field Type Default Description headlessbool trueRun browser in headless mode (no visible window). viewport_widthu32 1280Browser viewport width in pixels. viewport_heightu32 720Browser viewport height in pixels. timeout_secsu64 30Per-action timeout in seconds. idle_timeout_secsu64 300Auto-close browser session after this many seconds of inactivity. max_sessionsusize 5Maximum concurrent browser sessions. chromium_pathstring or null nullPath to the Chromium/Chrome binary. Auto-detected if null.
[reload]
Controls automatic config file watching and hot-reloading.
[ reload ]
mode = "hybrid"
debounce_ms = 500
CopyCopied!
Field Type Default Description modestring "hybrid"Reload mode. See below. debounce_msu64 500Debounce window in milliseconds before reloading after a file change is detected.
mode values:
Value Description offNo automatic reloading. Changes require a manual restart. restartFull daemon restart on any config change. hotHot-reload safe sections only (channels, skills, heartbeat). hybridHot-reload where possible; flag restart-required for sections that need it (default).
[exec_policy]
Controls which shell commands agents are allowed to execute via the exec and shell tools.
[ exec_policy ]
mode = "allowlist"
allowed_commands = [ "git" , "python3" , "node" ]
timeout_secs = 30
max_output_bytes = 102400
no_output_timeout_secs = 30
CopyCopied!
Field Type Default Description modestring "allowlist"Security mode. See below. safe_binslist of strings ["sleep","true","false","cat","sort","uniq","cut","tr","head","tail","wc","date","echo","printf","basename","dirname","pwd","env"]Commands that always bypass the allowlist check (stdin-only POSIX utilities). allowed_commandslist of strings []Additional commands permitted when mode = "allowlist". timeout_secsu64 30Maximum wall-clock execution time per command in seconds. max_output_bytesusize 102400Maximum combined stdout+stderr output size in bytes (100 KB default). no_output_timeout_secsu64 30Kill processes that produce no output for this many seconds. 0 = disabled.
mode values:
Value Aliases Description denynone, disabledBlock all shell execution. allowlistrestrictedOnly allow commands in safe_bins or allowed_commands (default). fullallow, all, unrestrictedAllow all commands. Unsafe -- development use only.
[approval]
Configures which tools require explicit human approval before execution. References the ApprovalPolicy type.
[ approval ]
require_approval = [ "shell_exec" ]
timeout_secs = 60
auto_approve_autonomous = false
auto_approve = false
CopyCopied!
Field Type Default Description require_approvallist of strings ["shell_exec"]List of tool names that pause execution and wait for human approval before proceeding. timeout_secsu64 60Timeout for approval requests in seconds. auto_approve_autonomousbool falseAuto-approve tools when agent is in autonomous mode. auto_approvebool falseAuto-approve all tool executions (unsafe, dev only).
[budget]
Sets global spending limits for LLM API costs. All limits default to 0.0 (unlimited).
[ budget ]
max_hourly_usd = 1.00
max_daily_usd = 10.00
max_monthly_usd = 50.00
alert_threshold = 0.8
default_max_llm_tokens_per_hour = 0
CopyCopied!
Field Type Default Description max_hourly_usdf64 0.0Maximum total LLM cost in USD per hour across all agents. 0.0 = unlimited. max_daily_usdf64 0.0Maximum total LLM cost in USD per day across all agents. 0.0 = unlimited. max_monthly_usdf64 0.0Maximum total LLM cost in USD per month across all agents. 0.0 = unlimited. alert_thresholdf64 0.8Warning threshold as a fraction of each limit (0.0–1.0). At 0.8, warnings are logged when 80% of a limit is reached. default_max_llm_tokens_per_houru64 0Global override for per-agent hourly token budget. When > 0, overrides all agents' own token limits. 0 = keep each agent's own limit.
[thinking]
Configures extended thinking (chain-of-thought reasoning) for models that support it (e.g., Claude 3.7 Sonnet with thinking mode).
[ thinking ]
budget_tokens = 10000
stream_thinking = false
CopyCopied!
Field Type Default Description budget_tokensu32 10000Maximum tokens allocated for the thinking/reasoning phase. stream_thinkingbool falseWhether to stream thinking tokens to the client (visible in the API response stream).
[tts]
Configures text-to-speech synthesis for voice output.
[ tts ]
enabled = false
provider = "openai" # openai | elevenlabs
max_text_length = 4096
timeout_secs = 30
[ tts . openai ]
voice = "alloy"
model = "tts-1"
format = "mp3"
speed = 1.0
[ tts . elevenlabs ]
voice_id = "21m00Tcm4TlvDq8ikWAM"
model_id = "eleven_monolingual_v1"
stability = 0.5
similarity_boost = 0.75
CopyCopied!
[tts] fields:
Field Type Default Description enabledbool falseEnable TTS synthesis. providerstring or null nullDefault TTS provider: "openai" or "elevenlabs". max_text_lengthusize 4096Maximum text length in characters for a single TTS request. timeout_secsu64 30Request timeout per TTS call in seconds.
[tts.openai] fields:
Field Type Default Description voicestring "alloy"Voice name. Options: alloy, echo, fable, onyx, nova, shimmer. modelstring "tts-1"TTS model: "tts-1" (fast) or "tts-1-hd" (high quality). formatstring "mp3"Output format: mp3, opus, aac, flac. speedf32 1.0Speech speed multiplier (0.25 to 4.0).
[tts.elevenlabs] fields:
Field Type Default Description voice_idstring "21m00Tcm4TlvDq8ikWAM"ElevenLabs voice ID (default: Rachel). model_idstring "eleven_monolingual_v1"ElevenLabs model ID. stabilityf32 0.5Voice stability (0.0–1.0). Higher = more consistent, less expressive. similarity_boostf32 0.75Voice similarity boost (0.0–1.0).
[docker]
Configures the Docker container sandbox for isolated code execution.
[ docker ]
enabled = false
image = "python:3.12-slim"
container_prefix = "librefang-sandbox"
workdir = "/workspace"
network = "none"
memory_limit = "512m"
cpu_limit = 1.0
timeout_secs = 60
read_only_root = true
mode = "off"
scope = "session"
reuse_cool_secs = 300
idle_timeout_secs = 86400
max_age_secs = 604800
blocked_mounts = []
CopyCopied!
Field Type Default Description enabledbool falseEnable Docker sandbox for code execution. imagestring "python:3.12-slim"Docker image to use for the sandbox container. container_prefixstring "librefang-sandbox"Prefix for container names. workdirstring "/workspace"Working directory inside the container. networkstring "none"Network mode: "none" (isolated), "bridge", or a custom network name. memory_limitstring "512m"Memory limit (e.g., "256m", "1g"). cpu_limitf64 1.0CPU limit (e.g., 0.5, 1.0, 2.0). timeout_secsu64 60Maximum execution time per command in seconds. read_only_rootbool trueMount the root filesystem as read-only. modestring "off"Activation mode. See below. scopestring "session"Container lifecycle scope. See below. reuse_cool_secsu64 300Cooldown in seconds before a released container can be reused. idle_timeout_secsu64 86400Destroy containers after this many seconds of inactivity (24 hours default). max_age_secsu64 604800Maximum container age before forced destruction (7 days default). blocked_mountslist of strings []Host paths blocked from bind mounting into containers. cap_addlist of strings []Linux capabilities to add to the container (e.g., ["NET_ADMIN"]). Use with caution. tmpfslist of strings ["/tmp:size=64m"]tmpfs mounts inside the container. Each entry is "path:options" (e.g., "/tmp:size=128m"). pids_limitu32 100Maximum number of processes inside the container. Prevents fork bombs.
mode values:
Value Description offDocker sandbox disabled (default). non_mainUse Docker only for non-main (sub) agents. allUse Docker for all agents.
scope values:
Value Description sessionOne container per session, destroyed when the session ends (default). agentOne container per agent, reused across sessions. sharedShared container pool across all agents.
[canvas]
Configures the Canvas (Agent-to-UI) tool that allows agents to render HTML in the dashboard.
[ canvas ]
enabled = false
max_html_bytes = 524288
allowed_tags = []
CopyCopied!
Field Type Default Description enabledbool falseEnable the canvas tool. max_html_bytesusize 524288Maximum HTML payload size in bytes (512 KB default). allowed_tagslist of strings []Allowed HTML tag names for sanitization. Empty = all safe tags permitted.
[auto_reply]
Configures the background auto-reply engine that can automatically respond to incoming messages without waiting for human interaction.
[ auto_reply ]
enabled = false
max_concurrent = 3
timeout_secs = 120
suppress_patterns = [ "/stop" , "/pause" ]
CopyCopied!
Field Type Default Description enabledbool falseEnable the auto-reply engine. max_concurrentusize 3Maximum number of concurrent auto-reply tasks. timeout_secsu64 120Default timeout per auto-reply task in seconds. suppress_patternslist of strings ["/stop", "/pause"]Incoming message patterns that suppress auto-reply.
[broadcast]
Configures message broadcasting to route a single incoming message to multiple agents simultaneously.
[ broadcast ]
strategy = "parallel"
routes = { "announcement-channel" = [ "agent-a" , "agent-b" , "agent-c" ] }
CopyCopied!
Field Type Default Description strategystring "parallel"Delivery strategy. "parallel" = send to all agents simultaneously; "sequential" = send one at a time in order. routesmap of string to list of strings {}Maps peer/channel identifiers to lists of agent names that receive the message.
[inbox]
File-based input inbox for async external commands. Drop text files into a watched directory and they are dispatched as messages to agents. Processed files are moved to a processed/ subdirectory to avoid redelivery.
[ inbox ]
enabled = true
directory = "~/.librefang/inbox/"
poll_interval_secs = 5
default_agent = "assistant"
CopyCopied!
Field Type Default Description enabledbool falseEnable the inbox directory watcher. directorystring or null nullDirectory to watch. Defaults to $HOME_DIR/inbox/. Supports ~ expansion. poll_interval_secsu64 5How often (in seconds) to scan the directory for new files. Minimum 1. default_agentstring or null nullAgent name to route files to when no agent: directive is found in the file.
File format: Plain text files (.txt, .md, .json, .py, etc.). The first line may contain an agent:<name> directive to target a specific agent; the rest is sent as the message body. Files without the directive use default_agent.
Safety limits: Files larger than 1 MB are skipped. Binary files (non-text extensions) are skipped. Empty files are moved to processed/ without sending.
Usage examples:
Target a specific agent:
cat > ~/.librefang/inbox/task.txt << 'EOF'
agent:code-reviewer
Please review this code for security issues:
def login(user, password):
query = f"SELECT * FROM users WHERE name='{user}' AND pass='{password}'"
return db.execute(query)
EOF
CopyCopied!
Send to the default agent:
echo "Summarize today's system logs" > ~/.librefang/inbox/summarize.txt
CopyCopied!
Cron job:
# crontab -e
0 9 * * * grep ERROR /var/log/app.log > ~/.librefang/inbox/daily_errors.txt
CopyCopied!
CI/CD post-build:
echo "agent:devops
Build failed, please analyze:
$( tail -100 build.log)" > ~/.librefang/inbox/build_ $( date +%s ) .txt
CopyCopied!
Batch processing:
for doc in ~/reports/*.md ; do
cp " $doc " ~/.librefang/inbox/
done
CopyCopied!
Check inbox status:
curl -s http://127.0.0.1:4545/api/inbox/status
# {"enabled":true,"pending_count":3,"processed_count":12,...}
CopyCopied!
[[bindings]]
Agent bindings route specific channel/account/peer combinations to specific agents. More specific bindings (more non-null fields) take priority over less specific ones.
[[ bindings ]]
agent = "support-agent"
[ bindings . match_rule ]
channel = "telegram"
guild_id = "123456"
[[ bindings ]]
agent = "vip-agent"
[ bindings . match_rule ]
channel = "discord"
peer_id = "987654321"
roles = [ "premium" ]
CopyCopied!
Top-level fields:
Field Type Description agentstring Target agent name or ID to route matched messages to. match_ruleobject Match criteria. All specified (non-null) fields must match.
match_rule fields:
Field Type Default Description channelstring or null nullChannel type to match (e.g., "discord", "telegram", "slack"). account_idstring or null nullSpecific bot account ID within the channel (for multi-bot setups). peer_idstring or null nullUser/peer ID for DM routing. guild_idstring or null nullGuild or server ID (Discord/Slack). roleslist of strings []Role-based routing; user must have at least one of these roles.
Specificity scoring (higher = matched first): peer_id (+8) > guild_id (+4) > roles (+2) = account_id (+2) > channel (+1).
[pairing]
Configures device pairing for the LibreFang mobile companion app and push notifications.
[ pairing ]
enabled = false
max_devices = 10
token_expiry_secs = 300
push_provider = "ntfy"
ntfy_url = "https://ntfy.sh"
ntfy_topic = "my-librefang-notifications"
CopyCopied!
Field Type Default Description enabledbool falseEnable device pairing. max_devicesusize 10Maximum number of paired devices. token_expiry_secsu64 300Pairing token validity in seconds (5 minutes default). push_providerstring "none"Push notification provider: "none", "ntfy", or "gotify". ntfy_urlstring or null nullntfy server URL (when push_provider = "ntfy"). ntfy_topicstring or null nullntfy topic for push notifications.
[extensions]
Configures MCP server reconnection behavior and health monitoring.
[ extensions ]
auto_reconnect = true
reconnect_max_attempts = 10
reconnect_max_backoff_secs = 300
health_check_interval_secs = 60
CopyCopied!
Field Type Default Description auto_reconnectbool trueAutomatically reconnect to MCP servers when they disconnect. reconnect_max_attemptsu32 10Maximum reconnect attempts before giving up permanently. reconnect_max_backoff_secsu64 300Maximum backoff duration in seconds between reconnect attempts. health_check_interval_secsu64 60Interval in seconds between health checks for connected extensions.
[vault]
Configures the encrypted credential vault for storing sensitive secrets.
[ vault ]
enabled = true
# path = "~/.librefang/vault.enc"
CopyCopied!
Field Type Default Description enabledbool trueEnable the credential vault. Auto-detected if vault.enc already exists. pathpath or null nullCustom vault file path. Defaults to ~/.librefang/vault.enc.
[webhook_triggers]
Enables external systems to trigger agent actions via authenticated HTTP webhooks at /hooks/wake and /hooks/agent.
[ webhook_triggers ]
enabled = true
token_env = "LIBREFANG_WEBHOOK_TOKEN"
max_payload_bytes = 65536
rate_limit_per_minute = 30
CopyCopied!
Field Type Default Description enabledbool falseEnable webhook trigger endpoints. token_envstring "LIBREFANG_WEBHOOK_TOKEN"Env var name holding the bearer token (NOT the token itself). Token must be ≥ 32 characters. Required when enabled = true. max_payload_bytesusize 65536Maximum incoming payload size in bytes (64 KB default). rate_limit_per_minuteu32 30Maximum webhook requests per minute per source IP.
[proxy]
Configures HTTP proxy for all outbound connections (LLM APIs, web search, MCP servers, etc.). Environment variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY are also respected as fallbacks.
[ proxy ]
http_proxy = "http://proxy.corp.example:8080"
https_proxy = "http://proxy.corp.example:8080"
no_proxy = "localhost,127.0.0.1,.internal.corp"
CopyCopied!
Field Type Default Description http_proxystring or null nullHTTP proxy URL. Falls back to HTTP_PROXY / http_proxy env var. Credentials in URLs are redacted in logs. https_proxystring or null nullHTTPS proxy URL. Falls back to HTTPS_PROXY / https_proxy env var. no_proxystring or null nullComma-separated list of hosts/domains that bypass the proxy. Falls back to NO_PROXY / no_proxy env var.
[[sidecar_channels]]
Sidecar channel adapters allow external processes (written in any language) to act as channel adapters. Communication uses newline-delimited JSON over stdin/stdout.
[[ sidecar_channels ]]
name = "my-custom-channel"
command = "python3"
args = [ "adapters/my_adapter.py" ]
channel_type = "custom_platform"
[ sidecar_channels . env ]
MY_API_TOKEN = "secret"
CopyCopied!
Field Type Default Description namestring required Display name for this adapter. commandstring required Executable to run (e.g., "python3", "/usr/local/bin/my-adapter"). argslist of strings []Arguments to pass to the command. envmap of string to string {}Extra environment variables to pass to the subprocess. channel_typestring or null nullChannel type identifier. Defaults to Custom(<name>) if null.
[session]
Configures automatic cleanup of idle or excess sessions.
[ session ]
retention_days = 30
max_sessions_per_agent = 100
cleanup_interval_hours = 24
CopyCopied!
Field Type Default Description retention_daysu32 0Maximum age in days for idle sessions before automatic cleanup. 0 = unlimited. max_sessions_per_agentu32 0Maximum number of sessions per agent (oldest pruned first). 0 = unlimited. cleanup_interval_hoursu32 24How often the background cleanup job runs in hours.
[queue]
Configures the agent command queue, including depth limits, TTL, and per-lane concurrency.
[ queue ]
max_depth_per_agent = 100
max_depth_global = 1000
task_ttl_secs = 3600
[ queue . concurrency ]
main_lane = 3
cron_lane = 2
subagent_lane = 3
CopyCopied!
[queue] fields:
Field Type Default Description max_depth_per_agentu32 0Maximum queued tasks per agent. New tasks are rejected when full. 0 = unlimited. max_depth_globalu32 0Maximum total queued tasks across all agents. 0 = unlimited. task_ttl_secsu64 3600Unprocessed tasks expire after this many seconds. 0 = unlimited.
[queue.concurrency] fields:
Field Type Default Description main_laneusize 3Concurrent user message tasks. cron_laneusize 2Concurrent scheduled cron job tasks. subagent_laneusize 3Concurrent subagent invocation tasks.
[external_auth]
Configures OAuth2/OIDC external authentication, allowing users to log in via identity providers like Google, GitHub, Okta, Auth0, or Keycloak.
[ external_auth ]
enabled = true
issuer_url = "https://accounts.google.com"
client_id = "your-client-id.apps.googleusercontent.com"
client_secret_env = "LIBREFANG_OAUTH_CLIENT_SECRET"
redirect_url = "http://127.0.0.1:4545/api/auth/callback"
scopes = [ "openid" , "profile" , "email" ]
allowed_domains = [ "example.com" ]
session_ttl_secs = 86400
CopyCopied!
Field Type Default Description enabledbool falseEnable external authentication. issuer_urlstring ""OIDC issuer URL for provider discovery at {issuer_url}/.well-known/openid-configuration. client_idstring ""OAuth2 client ID registered with the identity provider. client_secret_envstring "LIBREFANG_OAUTH_CLIENT_SECRET"Env var name holding the OAuth2 client secret. redirect_urlstring "http://127.0.0.1:4545/api/auth/callback"OAuth2 authorization code flow callback URL. scopeslist of strings ["openid","profile","email"]OAuth2 scopes to request. allowed_domainslist of strings []Restrict login to these email domains. Empty = allow all. audiencestring ""JWT audience claim to validate. Defaults to client_id if empty. session_ttl_secsu64 86400Session token lifetime in seconds (24 hours default). providerslist of objects []Multiple OIDC/OAuth2 providers. When configured, takes precedence over the single-provider fields above.
For multi-provider setups, use [[external_auth.providers]] with fields: id, display_name, issuer_url, auth_url, token_url, userinfo_url, jwks_uri, client_id, client_secret_env, redirect_url, scopes, allowed_domains, audience.
[vertex_ai]
Configures Google Cloud Vertex AI as an LLM provider.
[ vertex_ai ]
project_id = "my-gcp-project"
region = "us-central1"
credentials_path = "/path/to/service-account.json"
CopyCopied!
Credentials are resolved in this order:
credentials_path in config (JSON string or file path)
VERTEX_AI_SERVICE_ACCOUNT_JSON env var
GOOGLE_APPLICATION_CREDENTIALS env var (file path)
gcloud auth print-access-token CLI fallback
Field Type Default Description project_idstring or null nullGCP project ID. Falls back to VERTEX_AI_PROJECT_ID, GOOGLE_CLOUD_PROJECT, or the project_id field in the service account JSON. regionstring or null nullGCP region for the Vertex AI endpoint. Falls back to VERTEX_AI_REGION or GOOGLE_CLOUD_REGION env var. Default: "us-central1". credentials_pathstring or null nullPath to a GCP service account JSON key file, or the raw JSON string.
[oauth]
Configures OAuth client IDs for PKCE (Proof Key for Code Exchange) flows used by the dashboard.
[ oauth ]
google_client_id = "your-google-client-id.apps.googleusercontent.com"
github_client_id = "your-github-app-client-id"
microsoft_client_id = "your-azure-app-client-id"
slack_client_id = "your-slack-app-client-id"
CopyCopied!
Field Type Default Description google_client_idstring or null nullGoogle OAuth2 client ID for PKCE flow. github_client_idstring or null nullGitHub OAuth app client ID for PKCE flow. microsoft_client_idstring or null nullMicrosoft (Entra ID / Azure AD) OAuth application client ID. slack_client_idstring or null nullSlack OAuth app client ID.
[auth_profiles]
Configures multiple API key profiles per provider to enable key rotation when one key is rate-limited or exhausted.
[ auth_profiles ]
anthropic = [
{name = "primary" , api_key_env = "ANTHROPIC_API_KEY_1" , priority = 0 },
{name = "secondary" , api_key_env = "ANTHROPIC_API_KEY_2" , priority = 1 },
]
openai = [
{name = "main" , api_key_env = "OPENAI_API_KEY" , priority = 0 },
]
CopyCopied!
The value is a map from provider name to a list of AuthProfile objects:
Field Type Default Description namestring required Profile name (e.g., "primary", "secondary"). api_key_envstring required Env var name holding the API key for this profile. priorityu32 0Priority for key selection. Lower value = preferred.
Configures global tool access rules, groups, and recursion depth limits. References the ToolPolicy type.
[ tool_policy ]
subagent_max_depth = 10
subagent_max_concurrent = 5
[[ tool_policy . global_rules ]]
pattern = "shell_*"
effect = "deny"
[[ tool_policy . groups ]]
name = "web_tools"
tools = [ "web_search" , "web_fetch" ]
CopyCopied!
Field Type Default Description agent_ruleslist of ToolPolicyRule []Per-agent tool rules (highest priority, checked first). global_ruleslist of ToolPolicyRule []Global tool rules applied to all agents (checked after agent rules). groupslist of ToolGroup []Named tool groups for reuse in rules. subagent_max_depthu32 10Maximum subagent spawning depth. subagent_max_concurrentu32 5Maximum concurrent subagents.
ToolPolicyRule fields:
Field Type Description patternstring Glob pattern to match tool names (e.g., "shell_*", "web_*", "mcp_github_*"). effectstring "allow" or "deny". Deny-wins: if any deny rule matches, the tool is blocked regardless of allow rules.
ToolGroup fields:
Field Type Description namestring Group name (e.g., "web_tools", "code_tools"). toolslist of strings Tool name patterns included in this group.
[proactive_memory]
Configures proactive memory extraction (mem0-style automatic memory management). References the ProactiveMemoryConfig type.
[ proactive_memory ]
enabled = true
auto_memorize = true
auto_retrieve = true
max_retrieve = 10
extraction_threshold = 0.7
# extraction_model = "gpt-4o-mini" # optional, enables LLM-powered extraction
extract_categories = [ "user_preference" , "important_fact" , "task_context" , "relationship" ]
session_ttl_hours = 24
duplicate_threshold = 0.5
confidence_decay_rate = 0.01
max_memories_per_agent = 1000
CopyCopied!
Field Type Default Description enabledbool trueMaster toggle — when false, the entire proactive memory subsystem is disabled. auto_memorizebool trueAutomatically extract and store memories after each agent execution. auto_retrievebool trueAutomatically retrieve relevant memories before each agent execution. max_retrieveusize 10Maximum number of memories to retrieve per query. extraction_thresholdf32 0.7Confidence threshold for near-duplicate detection (0.0–1.0). extraction_modelstring or null nullLLM model to use for extraction. If null, uses rule-based extraction. extract_categorieslist of strings ["user_preference", "important_fact", "task_context", "relationship"]Categories to extract from conversations. session_ttl_hoursu32 24Session memory TTL in hours. Memories older than this are cleaned up before each agent execution. duplicate_thresholdf32 0.5Similarity threshold for duplicate detection (0.0–1.0). Uses vector cosine similarity when embeddings are available, otherwise falls back to Jaccard word overlap. confidence_decay_ratef64 0.01Confidence decay rate per day. Follows exponential decay: conf × e^(−rate × days). Default of 0.01 takes ~70 days to halve. max_memories_per_agentusize 1000Maximum memories per agent. When exceeded, oldest/lowest-confidence entries are evicted. 0 = no cap.
[context_engine]
Configures the pluggable context assembly engine that controls how agent memory is recalled and assembled into prompts.
[ context_engine ]
engine = "default"
# plugin = "qdrant-recall" # resolves to ~/.librefang/plugins/qdrant-recall/
[ context_engine . hooks ]
# ingest = "~/.librefang/scripts/my_recall.py"
# after_turn = "~/.librefang/scripts/my_indexer.py"
[[ context_engine . plugin_registries ]]
name = "Official"
github_repo = "librefang/librefang-registry"
CopyCopied!
Field Type Default Description enginestring "default"Built-in engine name. Currently only "default" is supported. pluginstring or null nullPlugin name. Resolves to ~/.librefang/plugins/<name>/plugin.toml. Takes precedence over manual hooks if set. hooks.ingeststring or null nullPython script path for the ingest hook (called on new user message). hooks.after_turnstring or null nullPython script path for the after_turn hook (called after each completed turn). plugin_registrieslist of objects Official registry Plugin registries (GitHub owner/repo) to browse for installable plugins.
[audit]
Configures audit log retention.
[ audit ]
retention_days = 90
CopyCopied!
Field Type Default Description retention_daysu32 90Number of days to retain audit log entries. 0 = unlimited retention.
[health_check]
Configures periodic health checks for LLM providers.
[ health_check ]
health_check_interval_secs = 60
CopyCopied!
Field Type Default Description health_check_interval_secsu64 60Interval in seconds between provider health checks.
[plugins]
Configures additional plugin registries to search for installable context engine plugins.
[ plugins ]
plugin_registries = [ "acme-corp/librefang-plugins" ]
CopyCopied!
Field Type Default Description plugin_registrieslist of strings []Additional GitHub owner/repo plugin registries. Merged with context_engine.plugin_registries.
Complete table of all environment variables referenced by the configuration. None of these are read by the config file itself -- they are read at runtime by the kernel and channel adapters.
LLM Provider Keys
Variable Used By Description ANTHROPIC_API_KEY[default_model]Anthropic API key (Claude models). GEMINI_API_KEYGemini driver Google Gemini API key. Alias: GOOGLE_API_KEY. OPENAI_API_KEYOpenAI-compat driver OpenAI API key. GROQ_API_KEYGroq provider Groq API key (fast Llama inference). DEEPSEEK_API_KEYDeepSeek provider DeepSeek API key. PERPLEXITY_API_KEYPerplexity provider / web search Perplexity API key. OPENROUTER_API_KEYOpenRouter provider OpenRouter API key. TOGETHER_API_KEYTogether AI provider Together AI API key. MISTRAL_API_KEYMistral provider Mistral AI API key. FIREWORKS_API_KEYFireworks provider Fireworks AI API key. COHERE_API_KEYCohere provider Cohere API key. AI21_API_KEYAI21 provider AI21 Labs API key. CEREBRAS_API_KEYCerebras provider Cerebras API key. SAMBANOVA_API_KEYSambaNova provider SambaNova API key. HUGGINGFACE_API_KEYHugging Face provider Hugging Face Inference API key. XAI_API_KEYxAI provider xAI (Grok) API key. REPLICATE_API_KEYReplicate provider Replicate API key.
Web Search Keys
Variable Used By Description BRAVE_API_KEY[web.brave]Brave Search API key. TAVILY_API_KEY[web.tavily]Tavily Search API key. PERPLEXITY_API_KEY[web.perplexity]Perplexity Search API key (shared with LLM provider).
Channel Tokens
Variable Channel Description TELEGRAM_BOT_TOKENTelegram Bot API token from @BotFather. DISCORD_BOT_TOKENDiscord Discord bot token. SLACK_APP_TOKENSlack Slack app-level token (xapp-) for Socket Mode. SLACK_BOT_TOKENSlack Slack bot token (xoxb-) for REST API. WHATSAPP_ACCESS_TOKENWhatsApp WhatsApp Cloud API access token. WHATSAPP_VERIFY_TOKENWhatsApp Webhook verification token. MATRIX_ACCESS_TOKENMatrix Matrix homeserver access token. EMAIL_PASSWORDEmail Email account password or app password. TEAMS_APP_PASSWORDTeams Azure Bot Framework app password. MATTERMOST_TOKENMattermost Mattermost bot token. TWITCH_OAUTH_TOKENTwitch Twitch OAuth token. ROCKETCHAT_TOKENRocket.Chat Rocket.Chat auth token. ZULIP_API_KEYZulip Zulip bot API key. XMPP_PASSWORDXMPP XMPP account password. GOOGLE_CHAT_SERVICE_ACCOUNTGoogle Chat Service account JSON key. LINE_CHANNEL_SECRETLINE LINE channel secret. LINE_CHANNEL_ACCESS_TOKENLINE LINE channel access token. VIBER_AUTH_TOKENViber Viber Bot auth token. MESSENGER_PAGE_TOKENMessenger Facebook page access token. MESSENGER_VERIFY_TOKENMessenger Webhook verification token. REDDIT_CLIENT_SECRETReddit Reddit app client secret. REDDIT_PASSWORDReddit Reddit bot account password. MASTODON_ACCESS_TOKENMastodon Mastodon access token. BLUESKY_APP_PASSWORDBluesky Bluesky app password. FEISHU_APP_SECRETFeishu Feishu/Lark app secret. REVOLT_BOT_TOKENRevolt Revolt bot token. NEXTCLOUD_TOKENNextcloud Nextcloud Talk auth token. GUILDED_BOT_TOKENGuilded Guilded bot token. KEYBASE_PAPERKEYKeybase Keybase paper key. THREEMA_SECRETThreema Threema Gateway API secret. NOSTR_PRIVATE_KEYNostr Nostr private key (nsec or hex). WEBEX_BOT_TOKENWebex Webex bot token. PUMBLE_BOT_TOKENPumble Pumble bot token. FLOCK_BOT_TOKENFlock Flock bot token. TWIST_TOKENTwist Twist API token. MUMBLE_PASSWORDMumble Mumble server password. DINGTALK_ACCESS_TOKENDingTalk DingTalk webhook access token. DINGTALK_SECRETDingTalk DingTalk signing secret. DISCOURSE_API_KEYDiscourse Discourse API key. GITTER_TOKENGitter Gitter auth token. NTFY_TOKENntfy ntfy auth token (optional for public topics). GOTIFY_APP_TOKENGotify Gotify app token (sending). GOTIFY_CLIENT_TOKENGotify Gotify client token (receiving). WEBHOOK_SECRETWebhook HMAC signing secret for webhook verification. LINKEDIN_ACCESS_TOKENLinkedIn LinkedIn OAuth2 access token.
KernelConfig::validate() runs at boot time and returns a list of warnings (non-fatal). The kernel still starts, but logs each warning.
What is validated
For every enabled channel (i.e., its config section is present in the TOML), the validator checks that the corresponding environment variable(s) are set and non-empty:
Channel Env vars checked Telegram bot_token_envDiscord bot_token_envSlack app_token_env, bot_token_env (both checked)WhatsApp access_token_envMatrix access_token_envEmail password_envTeams app_password_envMattermost token_envZulip api_key_envTwitch oauth_token_envRocket.Chat token_envGoogle Chat service_account_envXMPP password_envLINE access_token_envViber auth_token_envMessenger page_token_envReddit client_secret_envMastodon access_token_envBluesky app_password_envFeishu app_secret_envRevolt bot_token_envNextcloud token_envGuilded bot_token_envKeybase paperkey_envThreema secret_envNostr private_key_envWebex bot_token_envPumble bot_token_envFlock bot_token_envTwist token_envMumble password_envDingTalk access_token_envDiscourse api_key_envGitter token_envntfy token_env (only if token_env is non-empty; public topics are OK without auth)Gotify app_token_envWebhook secret_envLinkedIn access_token_env
For web search providers , the validator checks:
Provider Env var checked braveweb.brave.api_key_envtavilyweb.tavily.api_key_envperplexityweb.perplexity.api_key_envduckduckgo(no check -- no API key needed) auto(no check -- cascading fallback handles missing keys)
What is NOT validated
The api_key_env in [default_model] is not checked by validate(). Missing LLM keys cause errors at runtime when the driver is first used.
The shared_secret in [network] is not validated against network_enabled. If networking is enabled with an empty secret, authentication will fail at connection time.
MCP server configurations are not validated at config load time. Connection errors surface during the background MCP connect phase.
Agent manifests have their own separate validation.
Some subsystems have their own configuration that is not part of config.toml but is worth noting:
Session Compaction (runtime)
Configured internally via CompactionConfig (not currently exposed in config.toml):
Field Default Description threshold80Compact when session message count exceeds this. keep_recent20Number of recent messages preserved verbatim after compaction. max_summary_tokens1024Maximum tokens for the LLM summary of compacted messages.
WASM Sandbox (runtime)
Configured internally via SandboxConfig (not currently exposed in config.toml):
Field Default Description fuel_limit1000000Maximum CPU instruction budget. 0 = unlimited. max_memory_bytes16777216 (16 MB)Maximum WASM linear memory. timeout_secsnull (30s fallback)Wall-clock timeout for epoch-based interruption.
Model Routing (per-agent manifest)
Configured in agent manifests via ModelRoutingConfig:
Field Default Description simple_model"claude-haiku-4-5-20251001"Model for simple queries. medium_model"claude-sonnet-4-20250514"Model for medium-complexity queries. complex_model"claude-sonnet-4-20250514"Model for complex queries. simple_threshold100Token count below which a query is classified as simple. complex_threshold500Token count above which a query is classified as complex.
Autonomous Guardrails (per-agent manifest)
Configured in agent manifests via AutonomousConfig:
Field Default Description quiet_hoursnullCron expression for quiet hours (agent pauses during this window). max_iterations50Maximum tool-use iterations per invocation. max_restarts10Maximum automatic restarts before permanent stop. heartbeat_interval_secs30Seconds between heartbeat health checks. heartbeat_channelnullChannel to send heartbeat status to (e.g., "telegram").