OpenFang Configuration Reference
Complete reference for config.toml, covering every configurable field in the OpenFang Agent OS.
Overview
OpenFang reads its configuration from a single TOML file:
~/.openfang/config.toml
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.) areOption<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_envandbot_token_envhold 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.
Minimal Configuration
The simplest working configuration only needs an LLM provider API key set as an environment variable. With no config file at all, OpenFang boots with Anthropic as the default provider:
# ~/.openfang/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"
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 = ""
Full Example
# ============================================================
# OpenFang Agent OS -- Complete Configuration Reference
# ============================================================
# --- Top-level fields ---
home_dir = "~/.openfang" # OpenFang home directory
data_dir = "~/.openfang/data" # SQLite databases and data files
log_level = "info" # trace | debug | info | warn | error
api_listen = "127.0.0.1:50051" # HTTP/WS API bind address
network_enabled = false # Enable OFP peer-to-peer network
api_key = "" # API Bearer token (empty = unauthenticated)
mode = "default" # stable | default | dev
language = "en" # Locale for CLI/messages
usage_footer = "full" # off | tokens | cost | full
# --- Default LLM Provider ---
[default_model]
provider = "anthropic"
model = "claude-sonnet-4-20250514"
api_key_env = "ANTHROPIC_API_KEY"
# --- Fallback Providers ---
[[fallback_providers]]
provider = "ollama"
model = "llama3.2:latest"
api_key_env = ""
[[fallback_providers]]
provider = "groq"
model = "llama-3.3-70b-versatile"
api_key_env = "GROQ_API_KEY"
# --- Memory ---
[memory]
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
[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
# --- MCP Servers ---
[[mcp_servers]]
name = "filesystem"
timeout_secs = 30
env = []
[mcp_servers.transport]
type = "stdio"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/docs"]
[[mcp_servers]]
name = "remote-api"
timeout_secs = 60
env = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
[mcp_servers.transport]
type = "sse"
url = "https://mcp.example.com/sse"
# --- A2A Protocol ---
[a2a]
enabled = false
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"
# --- 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 ---
[channels.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = []
poll_interval_secs = 1
[channels.discord]
bot_token_env = "DISCORD_BOT_TOKEN"
allowed_guilds = []
intents = 33280
[channels.slack]
app_token_env = "SLACK_APP_TOKEN"
bot_token_env = "SLACK_BOT_TOKEN"
allowed_channels = []
Section Reference
Top-Level Fields
These fields sit at the root of config.toml (not inside any [section]).
| Field | Type | Default | Description |
|---|---|---|---|
home_dir |
path | ~/.openfang |
OpenFang home directory. Stores config, agents, skills. |
data_dir |
path | ~/.openfang/data |
Directory for SQLite databases and persistent data. |
log_level |
string | "info" | Log verbosity. One of: trace, debug, info, warn, error. |
api_listen |
string | "127.0.0.1:50051" |
Bind address for the HTTP/WebSocket/SSE API server. |
network_enabled |
bool | false |
Enable the OFP peer-to-peer network layer. |
api_key |
string | "" (empty) | API authentication key. When set, all endpoints except /api/health require Authorization: Bearer <key>. Empty means unauthenticated (local development only). |
mode |
string | "default" | Kernel operating mode. |
language |
string | "en" | Language/locale code for CLI output and system messages. |
usage_footer |
string | "full" | Controls usage info appended to responses. |
[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"
| Field | Type | Default | Description |
|---|---|---|---|
provider |
string | "anthropic" | Provider name. |
model |
string | "claude-sonnet-4-20250514" | Model identifier. |
api_key_env |
string | "ANTHROPIC_API_KEY" | Name of the environment variable holding the API key. |
base_url |
string or null | null | Override the API base URL. |
[memory]
Configures the SQLite-backed memory substrate, including vector embeddings and memory decay.
[memory]
embedding_model = "all-MiniLM-L6-v2"
consolidation_threshold = 10000
decay_rate = 0.1
| Field | Type | Default | Description |
|---|---|---|---|
sqlite_path |
path or null | null | Explicit path to the SQLite database file. |
embedding_model |
string | "all-MiniLM-L6-v2" | Model name used for generating vector embeddings for semantic memory search. |
consolidation_threshold |
u64 | 10000 | Number of stored memories before automatic consolidation is triggered. |
decay_rate |
f32 | 0.1 | Memory confidence decay rate. |
[network]
Configures the OFP (OpenFang Protocol) peer-to-peer networking layer with HMAC-SHA256 mutual authentication.
[network]
listen_addresses = ["/ip4/0.0.0.0/tcp/0"]
max_peers = 50
shared_secret = ""
| Field | Type | Default | Description |
|---|---|---|---|
listen_addresses |
list of strings | ["/ip4/0.0.0.0/tcp/0"] | libp2p multiaddresses to listen on. |
bootstrap_peers |
list of strings | [] | Multiaddresses of bootstrap peers for DHT discovery. |
mdns_enabled |
bool | true | Enable mDNS for automatic local network peer discovery. |
max_peers |
u32 | 50 | Maximum number of simultaneously connected peers. |
shared_secret |
string | "" (empty) | Pre-shared secret for OFP HMAC-SHA256 mutual authentication. |
[web]
Configures web search and web fetch capabilities used by agent tools.
[web]
search_provider = "auto"
cache_ttl_minutes = 15
| Field | Type | Default | Description |
|---|---|---|---|
search_provider |
string | "auto" | Which search engine to use. |
cache_ttl_minutes |
u64 | 15 | Cache duration for search/fetch results in minutes. |
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"
dm_policy = "respond"
group_policy = "mention_only"
rate_limit_per_user = 10
| Field | Type | Default | Description |
|---|---|---|---|
model |
string or null | null | Model override for this channel. |
system_prompt |
string or null | null | System prompt override for this channel. |
dm_policy |
string | "respond" | How the bot handles direct messages. |
group_policy |
string | "mention_only" | How the bot handles group messages. |
rate_limit_per_user |
u32 | 0 | Maximum messages per user per minute. |
threading |
bool | false | Enable thread replies (where supported by the platform). |
Environment Variables
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.