Frona is configured through a YAML config file at data/config.yaml. You can change the path by setting the FRONA_CONFIG environment variable.
Environment variables can also configure Frona. They are documented separately in the Environment Variables reference.
When Frona writes the config back to disk (for example after you change a setting in the UI), fields left at their default value are omitted to keep the file compact. Those fields are reconstituted from their defaults on load, so a partial block is valid — you only need to list the values you actually want to change.
Server
General server settings.
server:
port: 3001
base_url: https://frona.example.com
backend_url: http://localhost:3001
frontend_url: http://localhost:3000
external_url: https://frona.example.com
static_dir: /app/static
issuer_url: https://frona.example.com
max_concurrent_tasks: 10
sse_pending_events_secs: 60
cors_origins: https://app.example.com
max_body_size_bytes: 104857600
shutdown_timeout_secs: 60
timezone: America/Los_Angeles| Field | Type | Default | Description |
|---|---|---|---|
port | integer | 3001 | HTTP server port |
base_url | string | -- | Public-facing base URL, used for callbacks and links |
backend_url | string | -- | Override backend API URL |
frontend_url | string | -- | Override frontend URL |
external_url | string | -- | Externally-reachable URL of the server (e.g., ngrok tunnel, public domain). Default callback target for inbound webhooks (Twilio, Telegram, etc.). Falls back to backend_url then base_url if unset. |
static_dir | string | /app/static | Directory serving the frontend static files |
issuer_url | string | -- | JWT token issuer URL |
max_concurrent_tasks | integer | 10 | Maximum concurrent background tasks across all agents |
sse_pending_events_secs | integer | 60 | How long to buffer SSE events after client disconnects |
cors_origins | string | -- | Allowed CORS origins |
max_body_size_bytes | integer | 104857600 (100 MB) | Maximum HTTP request body size |
shutdown_timeout_secs | integer | 60 | Graceful shutdown timeout |
timezone | string | auto-detect | Server-default IANA timezone used for cron scheduling, reminders, and the <temporal_context> block when a user has no profile timezone and no per-task override. Leave empty to auto-detect from the TZ env var, then /etc/localtime, falling back to UTC. |
Sandbox
Per-process resource limits and global caps for the CLI/Python/Node.js sandboxes. See Sandbox for the security model.
sandbox:
disabled: false
max_cpu_pct: 95.0
max_memory_pct: 80.0
timeout_secs: 0
max_total_cpu_pct: 98.0
max_total_memory_pct: 90.0
default_network_access: true| Field | Type | Default | Description |
|---|---|---|---|
disabled | boolean | false | Disable filesystem sandboxing. Enable only if your OS does not support Landlock. Not recommended for production. |
max_cpu_pct | float | 95.0 | Per-principal CPU usage limit as percentage of total system CPU. Sandboxed processes that exceed this are killed. |
max_memory_pct | float | 80.0 | Per-principal memory usage limit as percentage of total system memory. |
timeout_secs | integer | 0 | Default sandbox execution timeout in seconds. 0 means no timeout. |
max_total_cpu_pct | float | 98.0 | Global CPU cap across all sandboxed processes. |
max_total_memory_pct | float | 90.0 | Global memory cap across all sandboxed processes. |
default_network_access | boolean | true | Grant all sandbox principals outbound network access by default. Override with forbid policies. |
Auth
Authentication and token settings.
auth:
encryption_secret: change-this-in-production
access_token_expiry_secs: 900
refresh_token_expiry_secs: 604800
presign_expiry_secs: 86400
ephemeral_token_expiry_secs: 300
allow_registration: true| Field | Type | Default | Description |
|---|---|---|---|
encryption_secret | string | dev-secret-change-in-production | Secret used to derive the AES-256 key that encrypts JWT signing keypairs at rest. Must be changed in production |
access_token_expiry_secs | integer | 900 (15 min) | How long access tokens are valid |
refresh_token_expiry_secs | integer | 604800 (7 days) | How long refresh tokens are valid |
presign_expiry_secs | integer | 86400 (24 hours) | How long pre-signed URLs are valid |
ephemeral_token_expiry_secs | integer | 300 (5 min) | Lifetime of stateless ephemeral principal tokens injected into sandboxed processes |
allow_registration | boolean | true | Allow anyone to sign up from the Register page. Set to false on shared installs so only admins can create accounts. See Managing Users. |
:::caution[Change the encryption secret in production] encryption_secret is used to derive an AES-256 encryption key (via SHA-256) that protects the JWT signing keypairs stored in the database. It is not used directly for JWT signing; instead it encrypts the private keys that do the signing.
A built-in default is provided for local development, but you must set your own value in production. If the default is left in place and database files are ever exposed (backup leak, file traversal, shared host), an attacker could decrypt the signing keypairs and forge authentication tokens for any user.
Generate a strong random secret:
openssl rand -base64 32:::
SSO
OpenID Connect single sign-on. Disabled by default.
sso:
enabled: true
authority: https://auth.example.com
client_id: your-client-id
client_secret: your-client-secret
scopes: openid email
disable_local_auth: false
signups_match_email: true
allow_unknown_email_verification: true
client_cache_expiration: 0| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable OIDC authentication |
authority | string | -- | OpenID Connect authority URL |
client_id | string | -- | OAuth client ID |
client_secret | string | -- | OAuth client secret |
scopes | string | openid email | OpenID scopes to request |
disable_local_auth | boolean | false | Force SSO-only authentication. Disables local login |
signups_match_email | boolean | true | Match SSO signups to existing accounts by email |
allow_unknown_email_verification | boolean | true | Accept emails not verified by the identity provider |
client_cache_expiration | integer | 0 | Client metadata cache expiration in seconds |
Database
database:
path: data/db| Field | Type | Default | Description |
|---|---|---|---|
path | string | data/db | Path to the SurrealDB data directory |
Browser
Headless Chrome configuration for browser automation. Optional. If not configured, browser tools are unavailable.
browser:
ws_url: ws://browserless:3333
profiles_path: /profiles
connection_timeout_ms: 30000
api_token: your-browserless-token| Field | Type | Default | Description |
|---|---|---|---|
ws_url | string | -- | WebSocket URL of the Browserless instance |
profiles_path | string | /profiles | Directory for storing browser profiles |
connection_timeout_ms | integer | 30000 (30s) | Timeout for connecting to the browser service |
api_token | string | -- | Authentication token for the Browserless HTTP API |
Search
Web search provider configuration. Optional. If not configured, search tools are unavailable.
search:
provider: searxng
searxng_base_url: http://searxng:8080| Field | Type | Default | Description |
|---|---|---|---|
provider | string | -- | Search provider: searxng, tavily, or brave |
searxng_base_url | string | -- | Base URL of the SearXNG instance |
Vault
External vault provider configuration. Credentials set here create system-managed vault connections that sync automatically on startup. See Vault Providers for details.
vault:
onepassword_service_account_token: ops_...
onepassword_vault_id: abc123
bitwarden_client_id: user.xxx
bitwarden_client_secret: xxx
bitwarden_master_password: xxx
bitwarden_server_url: https://vault.example.com
hashicorp_address: http://localhost:8200
hashicorp_token: hvs.xxx
hashicorp_mount: secret
keepass_path: /path/to/vault.kdbx
keepass_password: xxx| Field | Type | Default | Description |
|---|---|---|---|
onepassword_service_account_token | string | -- | 1Password service account token |
onepassword_vault_id | string | -- | 1Password default vault ID |
bitwarden_client_id | string | -- | Bitwarden personal API key client ID |
bitwarden_client_secret | string | -- | Bitwarden personal API key client secret |
bitwarden_master_password | string | -- | Bitwarden master password |
bitwarden_server_url | string | -- | Bitwarden server URL (for self-hosted) |
hashicorp_address | string | -- | HashiCorp Vault server address |
hashicorp_token | string | -- | HashiCorp Vault auth token |
hashicorp_mount | string | secret | HashiCorp Vault KV2 mount path |
keepass_path | string | -- | Path to KeePass .kdbx file |
keepass_password | string | -- | KeePass master password |
Storage
File storage paths. As of v2026.5.5 all per-user state lives under a single root, {data_dir}/users/{user_handle}/{subsystem}/.... See Workspaces for the layout.
storage:
data_dir: data
shared_config_dir: resources
skills_dir: data/skills
cache_dir: data/system/cache| Field | Type | Default | Description |
|---|---|---|---|
data_dir | string | data | Root data directory. Per-user state lives at {data_dir}/users/{user_handle}/... (workspaces, uploaded files, MCP server data, channel sessions, vault, tokens). Browser profiles are kept separately on the browserless container's volume (browser.profiles_path). |
shared_config_dir | string | resources | Read-only shared prompts and agent configurations that ship with the binary |
skills_dir | string | data/skills | Directory for installed shared skills |
cache_dir | string | data/system/cache | Directory for system caches (skill registry, etc.) |
Scheduler
Background job intervals.
scheduler:
poll_secs: 60| Field | Type | Default | Description |
|---|---|---|---|
poll_secs | integer | 60 (1 min) | How often the scheduler checks for due tasks |
Memory
Select the memory backend and configure background memory work. Existing installations default to basic until PKM is explicitly enabled; fresh installations choose a backend during setup. See Personal Knowledge Management for the PKM architecture and user experience.
memory:
backend: pkm
model_group: memory
basic_compaction_token_threshold: 3000
basic_compaction_secs: 7200
basic_space_compaction_secs: 3600
pkm_search_top_k: 8
pkm_short_memory_half_life_secs: 1209600
pkm_short_memory_demote_threshold: 0.1
pkm_short_memory_top_n: 16
pkm_short_memory_token_cap: 3000
pkm_playbook_index_token_cap: 1500
pkm_consolidate_secs: 60
pkm_consolidate_idle_secs: 300
pkm_consolidation_concurrency: 4
pkm_consolidation_max_tool_turns: 8
pkm_consolidation_max_submissions: 8
pkm_playbook_max_tool_turns: 20
pkm_playbook_max_submissions: 20
pkm_extract_max_tokens: 10000
pkm_extract_max_messages: 300
pkm_extract_agent_evidence_lookback_messages: 10
pkm_extract_agent_evidence_result_token_cap: 4000
pkm_consolidation_max_attempts: 3
pkm_adjudication_max_attempts_per_batch: 40
pkm_consolidation_checkpoint_failure_cap: 2
pkm_consolidation_retry_base_secs: 120
pkm_consolidation_keep_records: 20General and basic memory
| Field | Type | Default | Description |
|---|---|---|---|
backend | string | basic for upgrades | Memory backend: basic or pkm |
model_group | string | memory | Model group used for background memory work; falls back to primary when undefined |
basic_compaction_token_threshold | integer | 3000 | Skip basic user/agent memory compaction below this token count |
basic_compaction_secs | integer | 7200 | Interval between basic user/agent memory compaction runs |
basic_space_compaction_secs | integer | 3600 | Interval between basic space-memory compaction runs |
PKM retrieval and short memory
| Field | Type | Default | Description |
|---|---|---|---|
pkm_search_top_k | integer | 8 | Maximum results returned by memory_search |
pkm_short_memory_half_life_secs | integer | 1209600 (14 days) | Recency-decay half-life for short memories |
pkm_short_memory_demote_threshold | float | 0.1 | Drop a short memory from prompt injection when its decay score falls below this value |
pkm_short_memory_top_n | integer | 16 | Maximum short-memory lines injected into a prompt |
pkm_short_memory_token_cap | integer | 3000 | Token budget for the short-memory prompt block |
pkm_playbook_index_token_cap | integer | 1500 | Token budget for the available-playbooks index |
PKM consolidation
| Field | Type | Default | Description |
|---|---|---|---|
pkm_consolidate_secs | integer | 60 | How often the sweep scans for eligible chats |
pkm_consolidate_idle_secs | integer | 300 | How long a chat must be idle before consolidation |
pkm_consolidation_concurrency | integer | 4 | Maximum parallel extraction or page-authoring model calls |
pkm_consolidation_max_tool_turns | integer | 8 | Exploration-tool turns allowed for classify and resolve |
pkm_consolidation_max_submissions | integer | 8 | Structured submissions allowed for classify, resolve, and reconcile |
pkm_playbook_max_tool_turns | integer | 20 | Exploration-tool turns allowed for playbook resolution and authoring |
pkm_playbook_max_submissions | integer | 20 | Structured submissions allowed for playbook resolution and authoring |
pkm_extract_max_tokens | integer | 10000 | Maximum estimated transcript tokens in one extraction request |
pkm_extract_max_messages | integer | 300 | Maximum messages consumed by one extraction request |
pkm_extract_agent_evidence_lookback_messages | integer | 10 | Same-chat agent messages searched backward for qualified tool evidence |
pkm_extract_agent_evidence_result_token_cap | integer | 4000 | Token cap for each scoped evidence search or read |
pkm_consolidation_max_attempts | integer | 3 | Failures allowed at the current stage before abandoning a pass |
pkm_adjudication_max_attempts_per_batch | integer | 40 | Submission attempts allowed for each ontology-adjudication batch |
pkm_consolidation_checkpoint_failure_cap | integer | 2 | Fatal post-extraction checkpoint resets allowed before terminal failure |
pkm_consolidation_retry_base_secs | integer | 120 | Base retry delay; doubles per attempt and is quantized by the sweep cadence |
pkm_consolidation_keep_records | integer | 20 | Finished consolidation records retained per user |
Inference
LLM inference settings.
inference:
max_tool_turns: 200
default_max_tokens: 8192
compaction_trigger_pct: 80
history_truncation_pct: 90| Field | Type | Default | Description |
|---|---|---|---|
max_tool_turns | integer | 200 | Maximum tool call iterations per agent response |
default_max_tokens | integer | 8192 | Default max tokens for LLM responses |
compaction_trigger_pct | integer | 80 | Context usage percentage that triggers message compaction |
history_truncation_pct | integer | 90 | Context usage percentage that triggers history truncation |
Voice
Twilio voice call configuration. Optional. If not configured, voice tools are unavailable.
voice:
provider: twilio
twilio_account_sid: your-account-sid
twilio_auth_token: your-auth-token
twilio_from_number: "+15551234567"
twilio_voice_id: Polly.Matthew
twilio_speech_model: enhanced| Field | Type | Default | Description |
|---|---|---|---|
provider | string | -- | Voice provider. Currently only twilio is supported |
twilio_account_sid | string | -- | Twilio account SID |
twilio_auth_token | string | -- | Twilio auth token |
twilio_from_number | string | -- | Twilio phone number for outbound calls (E.164 format) |
twilio_voice_id | string | -- | Twilio voice ID for text-to-speech |
twilio_speech_model | string | -- | Twilio speech recognition model |
Twilio webhook callbacks use server.external_url (falling back to backend_url/base_url). The old voice.callback_base_url field has been removed; set server.external_url instead.
Providers
LLM provider API keys and endpoints. Providers can also be auto-discovered from environment variables (e.g., ANTHROPIC_API_KEY, OPENAI_API_KEY).
providers:
anthropic:
api_key: sk-ant-...
enabled: true
openai:
api_key: sk-...
enabled: true
ollama:
base_url: http://localhost:11434/v1
enabled: true| Field | Type | Default | Description |
|---|---|---|---|
api_key | string | -- | API key for the provider |
base_url | string | -- | Custom base URL (for self-hosted models like Ollama) |
enabled | boolean | true | Whether this provider is active |
Supported providers: anthropic, openai, groq, openrouter, deepseek, gemini, cohere, mistral, perplexity, together, xai, hyperbolic, moonshot, mira, galadriel, huggingface, ollama.
Models
Model groups define which LLM an agent uses. Each group is tagged with a provider and has a primary model, optional fallbacks, and provider-specific parameters.
Model groups can be configured in YAML or in the administration UI.
Frona resolves each model's context window and maximum output against a live model catalog, so you usually don't set context_window or max_tokens yourself — they're filled in from the catalog, including for vendor-namespaced IDs used by aggregators like OpenRouter. An explicit value in your config always takes precedence; the catalog only fills what you leave unset.
Common fields
These fields are available for all providers:
| Field | Type | Default | Description |
|---|---|---|---|
provider | string | required | Provider name (see below) |
model | string | required | Model ID. For aggregator providers like OpenRouter, use the vendor-namespaced form (e.g. anthropic/claude-sonnet-4-5, qwen/qwen3-coder) |
fallbacks | list | [] | Fallback model groups tried in order if the primary fails |
max_tokens | integer | catalog | Maximum tokens to generate per response. Filled from the model catalog when unset |
temperature | float | -- | Sampling temperature (0.0-2.0) |
context_window | integer | catalog | Override the context window size. Filled from the model catalog when unset |
retry.max_retries | integer | 10 | Maximum retry attempts on failure |
retry.initial_backoff_ms | integer | 1000 (1s) | Initial backoff between retries |
retry.backoff_multiplier | float | 2.0 | Exponential backoff multiplier |
retry.max_backoff_ms | integer | 60000 (60s) | Maximum backoff duration |
Anthropic
models:
primary:
provider: anthropic
model: claude-sonnet-4-5-20250514
max_tokens: 8192
thinking:
type: enabled
budget_tokens: 10000
top_p: 0.9
top_k: 40| Property | Type | Description |
|---|---|---|
thinking.type | string | enabled or disabled |
thinking.budget_tokens | integer | Token budget used when thinking is enabled |
top_p | float | Nucleus-sampling probability |
top_k | integer | Limit sampling to the highest-probability tokens |
stop_sequences | list of strings | Sequences that stop generation |
OpenAI
models:
openai_reasoning:
provider: openai
model: gpt-5
api: responses
top_p: 0.9
reasoning_effort: high| Property | Type | Description |
|---|---|---|
api | string | responses or chat_completions; see API selection below |
top_p | float | Nucleus-sampling probability |
min_p | float | Minimum probability threshold |
frequency_penalty | float | Penalize tokens according to their frequency |
presence_penalty | float | Penalize tokens that have already appeared |
seed | integer | Sampling seed when supported by the model |
max_completion_tokens | integer | Provider-specific completion-token limit |
reasoning_effort | string | Reasoning level such as low, medium, or high |
logprobs | boolean | Return token log probabilities |
top_logprobs | integer | Number of most likely tokens included with log probabilities |
stop | list of strings | Sequences that stop generation |
For the openai provider, api selects the request protocol:
| Value | Behavior |
|---|---|
responses | Use the OpenAI Responses API, including its reasoning and tool-call representation |
chat_completions | Use the Chat Completions API |
The field is optional. Frona uses the live model catalogue's protocol metadata when it recognizes the model; an unrecognized model defaults to chat_completions. Set api explicitly when using a proxy or custom endpoint whose protocol differs from the catalogue default.
The api field applies only to OpenAI. Other OpenAI-compatible providers use their supported compatibility endpoint.
Groq
Groq supports top_p, min_p, frequency_penalty, presence_penalty, seed, max_completion_tokens, reasoning_effort, logprobs, top_logprobs, and stop. It does not support OpenAI's api selector.
models:
fast:
provider: groq
model: llama-3.3-70b-versatile
top_p: 0.9OpenRouter
OpenRouter supports top_p, min_p, frequency_penalty, presence_penalty, seed, max_completion_tokens, reasoning_effort, logprobs, top_logprobs, and stop. Use vendor-namespaced model IDs.
models:
routed:
provider: openrouter
model: anthropic/claude-sonnet-4-6
reasoning_effort: highDeepSeek
DeepSeek supports top_p, min_p, frequency_penalty, presence_penalty, seed, max_completion_tokens, reasoning_effort, logprobs, top_logprobs, and stop.
models:
deepseek:
provider: deepseek
model: deepseek-chat
top_p: 0.9xAI
xAI supports top_p, min_p, frequency_penalty, presence_penalty, seed, max_completion_tokens, reasoning_effort, logprobs, top_logprobs, and stop.
models:
grok:
provider: xai
model: grok-2-latest
temperature: 0.7Together AI
Together AI supports top_p, min_p, frequency_penalty, presence_penalty, seed, max_completion_tokens, reasoning_effort, logprobs, top_logprobs, and stop.
models:
together:
provider: together
model: meta-llama/Llama-3.3-70B-Instruct-Turbo
top_p: 0.9Hyperbolic
Hyperbolic supports top_p, min_p, frequency_penalty, presence_penalty, seed, max_completion_tokens, reasoning_effort, logprobs, top_logprobs, and stop.
models:
hyperbolic:
provider: hyperbolic
model: meta-llama/Llama-3.3-70B-Instruct
temperature: 0.7Gemini
models:
reasoning:
provider: gemini
model: gemini-2.5-pro
thinking_config:
thinking_budget: 10000
include_thoughts: true| Property | Type | Description |
|---|---|---|
thinking_config.thinking_budget | integer | Token budget reserved for thinking |
thinking_config.include_thoughts | boolean | Include thought summaries in the response |
top_p | float | Nucleus-sampling probability |
top_k | integer | Limit sampling to the highest-probability tokens |
stop_sequences | list of strings | Sequences that stop generation |
candidate_count | integer | Number of response candidates to generate |
Ollama
models:
local:
provider: ollama
model: llama3.1
num_ctx: 8192
num_predict: 4096| Property | Type | Description |
|---|---|---|
think | boolean | Enable model thinking when supported |
num_ctx | integer | Ollama context-window size |
num_predict | integer | Maximum tokens to predict |
num_batch | integer | Prompt-processing batch size |
num_keep | integer | Prompt tokens retained during context shifting |
num_thread | integer | CPU threads used by the model |
num_gpu | integer | Model layers offloaded to the GPU |
top_k, top_p, min_p | integer/float | Sampling controls |
repeat_penalty, repeat_last_n | float/integer | Repetition controls |
frequency_penalty, presence_penalty | float | Token penalties |
mirostat, mirostat_eta, mirostat_tau | integer/float | Mirostat sampling controls |
tfs_z | float | Tail-free sampling value |
seed | integer | Sampling seed |
stop | list of strings | Sequences that stop generation |
use_mmap, use_mlock | boolean | Model memory-loading controls |
Cohere
Cohere has no additional model-group properties. Use the common fields.
Mistral
Mistral has no additional model-group properties. Use the common fields.
Perplexity
Perplexity has no additional model-group properties. Use the common fields.
Moonshot
Moonshot has no additional model-group properties. Use the common fields.
Mira
Mira has no additional model-group properties. Use the common fields.
Galadriel
Galadriel has no additional model-group properties. Use the common fields. It uses an OpenAI-compatible Chat Completions endpoint; when providers.galadriel.base_url is unset, Frona uses https://api.galadriel.com/v1/verified.
Hugging Face
Hugging Face has no additional model-group properties. Use the common fields.
Apps
Settings for agent-deployed applications.
app:
port_range_start: 4000
port_range_end: 4100
health_check_timeout_secs: 30
max_restart_attempts: 2
hibernate_after_secs: 259200| Field | Type | Default | Description |
|---|---|---|---|
port_range_start | integer | 4000 | Start of the port range for app allocation |
port_range_end | integer | 4100 | End of the port range for app allocation |
health_check_timeout_secs | integer | 30 | Maximum time to wait for an app to become healthy during deployment |
max_restart_attempts | integer | 2 | How many times to restart a crashed app before marking it as failed |
hibernate_after_secs | integer | 259200 (3 days) | Inactivity duration before auto-hibernating an app |
Cache
Entity caching settings.
cache:
entity_ttl_secs: 300
entity_max_capacity: 1000| Field | Type | Default | Description |
|---|---|---|---|
entity_ttl_secs | integer | 300 (5 min) | Time-to-live for cached entities |
entity_max_capacity | integer | 1000 | Maximum number of cached entities |
Channel
Default retry policy for channel connections. Per-channel overrides on the channel detail page take precedence. See Channels.
channel:
retry:
max_retries: 4294967295
initial_backoff_ms: 1000
backoff_multiplier: 2.0
max_backoff_ms: 60000| Field | Type | Default | Description |
|---|---|---|---|
retry.max_retries | integer | unlimited | Total retry attempts before a channel is marked Failed for good. |
retry.initial_backoff_ms | integer | 1000 (1s) | Delay before the first retry. |
retry.backoff_multiplier | float | 2.0 | Delay multiplier between attempts. |
retry.max_backoff_ms | integer | 60000 (60s) | Cap on the delay between attempts. |
Share
Short share links and preview pages. Channel adapters mint /s/{id} and /p/{id} URLs through this service when they need to point a user at a workspace file or chat snapshot — most visibly when an SMS reply overflows the segment limit and the overflow needs a stable link.
share:
ttl_secs: 2592000
cleanup_interval_secs: 21600| Field | Type | Default | Description |
|---|---|---|---|
ttl_secs | integer | 2592000 (30 days) | Lifetime of a newly-issued share row. Expired links return a non-leaking 404. |
cleanup_interval_secs | integer | 21600 (6 hours) | How often the scheduler deletes expired share rows. |
Signal
Safety caps for the signal matcher.
signal:
max_pending_per_user: 50
default_max_evaluations: 50
default_max_continuous_evaluations: 1000| Field | Type | Default | Description |
|---|---|---|---|
max_pending_per_user | integer | 50 | Maximum number of pending signal watches per user. |
default_max_evaluations | integer | 50 | Default safety cap on candidates a one-shot watch is evaluated against before auto-failing. |
default_max_continuous_evaluations | integer | 1000 | Default safety cap on fires a continuous-mode watch can absorb before auto-completing. |
MCP
MCP server hosting (see MCP).
mcp:
enabled: true
cache_path: data/system/mcp-cache
max_servers_per_user: 32
startup_timeout_secs: 30
health_check_interval_secs: 10
max_restart_attempts: 3
default_transport: stdio
port_range_start: 4100
port_range_end: 4200
bridge_mode: truePer-MCP-server workspaces live under {data_dir}/users/{user_handle}/mcps/{mcp_handle}/ and are not separately configurable. The package cache is shared across all users.
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable MCP server support. |
cache_path | string | {data_dir}/system/mcp-cache | Shared package cache directory (npm, uv). |
max_servers_per_user | integer | 32 | Maximum number of MCP servers a single user can install. |
startup_timeout_secs | integer | 30 | Seconds to wait for an MCP server's initialize handshake before failing. |
health_check_interval_secs | integer | 10 | Interval between MCP server liveness checks. |
max_restart_attempts | integer | 3 | Maximum process restart attempts before marking a server as failed. |
default_transport | string | stdio | Default transport for new MCP servers: stdio or http. |
port_range_start | integer | 4100 | Start of port range for local HTTP MCP servers. |
port_range_end | integer | 4200 | End of port range (exclusive) for local HTTP MCP servers. |
bridge_mode | boolean | true | Expose MCP tools via the mcpctl CLI bridge instead of individual tool definitions. Reduces LLM context token usage. See Bridge mode. |
Sensitive values
These fields are automatically redacted in logs: auth.encryption_secret, sso.client_secret, voice.twilio_account_sid, voice.twilio_auth_token, all vault.* credential fields, and all providers[*].api_key values.