Configuration
Swarm uses a centralized configuration file at ~/.swarm/settings.json that defines projects, agents, providers, permissions, and more. The config system distinguishes between raw (as-written) and resolved (fully-defaulted) types.
Settings File Location
~/.swarm/settings.json
Created automatically by swarm init, or manually. The file uses JSON format with a required version field and project entries keyed by absolute path.
File Structure
{
"version": 2,
"/absolute/path/to/project": {
"providers": { ... },
"agents": [ ... ],
"supervisor": { ... },
"defaults": { ... },
"permissions": { ... },
"hooks": { ... },
"mcpServers": { ... },
"wasm_tools": [ ... ],
"sub_agent_defaults": { ... }
}
}
Version
The version field must be 1 or 2. Version 2 is the current schema. Versions above the supported maximum are rejected.
Providers
Named provider blocks describe how to reach an LLM API:
"providers": {
"default": {
"type": "anthropic",
"api_key_env": "ANTHROPIC_API_KEY",
"base_url": null,
"max_retries": null,
"timeout": null
}
}
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type | String | Yes | — | Provider type (currently only "anthropic") |
api_key_env | String | No | "ANTHROPIC_API_KEY" | Environment variable holding the API key |
base_url | String | No | null | Custom API base URL |
max_retries | u32 | No | null | Max retries for transient failures |
timeout | u64 | No | null | Request timeout in seconds |
If no providers block is defined, an implicit "default" Anthropic provider is created.
Agents
An array of agent definitions (at least one required):
"agents": [
{
"name": "backend",
"prompt": "You are a backend engineer. Focus on API and data layer.",
"model": "sonnet",
"provider": "default",
"permissions": { ... },
"delegate_mode": false,
"mode": "code"
}
]
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | String | Yes | — | Unique name matching [a-z][a-z0-9-]* |
prompt | String | Yes | — | System prompt text, or @path/to/file to load from file |
model | String | No | defaults.model or "sonnet" | Model identifier |
provider | String | No | defaults.provider or "default" | Provider name |
permissions | PermissionsConfig | No | null | Agent-level permission overrides |
delegate_mode | bool | No | false | Legacy flag for delegate mode |
mode | String | No | See resolution | Agent execution mode |
Prompt resolution: If the prompt starts with @, the remainder is treated as a file path relative to the project root, and the file contents are loaded as the prompt.
Mode resolution priority: agent.mode > defaults.mode > delegate_mode compat ("delegate" if true) > "code"
Supervisor
Optional supervisor configuration:
"supervisor": {
"prompt": "Custom supervisor prompt",
"model": "sonnet"
}
| Field | Type | Required | Default |
|---|---|---|---|
prompt | String | No | Built-in merge-focused supervisor prompt |
model | String | No | defaults.model |
Defaults
Project-wide defaults applied when agent-level values are not specified:
"defaults": {
"model": "sonnet",
"provider": "default",
"session_timeout": null,
"commit_interval": 300,
"max_consecutive_errors": 5,
"max_total_errors": 20,
"mode": "code",
"liveness": { ... }
}
| Field | Type | Default | Description |
|---|---|---|---|
model | String | "sonnet" | Default model for agents and supervisor |
provider | String | "default" | Default provider name |
session_timeout | u64 | null | Session timeout in seconds (none = no timeout) |
commit_interval | u64 | 300 | Auto-commit interval in seconds |
max_consecutive_errors | u32 | 5 | Consecutive errors before agent stops |
max_total_errors | u32 | 20 | Total errors before agent stops |
mode | String | null | Default agent mode |
liveness | LivenessConfig | See below | Liveness monitoring settings |
Liveness Configuration
Controls idle detection, nudging, and stall monitoring:
"liveness": {
"enabled": true,
"idle_nudge_after_secs": 120,
"idle_nudge_interval_secs": 300,
"max_nudges": 3,
"idle_warn_after_secs": 600,
"stall_timeout_secs": 900,
"auto_interrupt_stalled": false
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable/disable liveness monitoring |
idle_nudge_after_secs | u64? | 120 | Seconds idle before first nudge |
idle_nudge_interval_secs | u64? | 300 | Seconds between subsequent nudges |
max_nudges | u32 | 3 | Maximum nudge messages per idle episode |
idle_warn_after_secs | u64? | 600 | Seconds idle before warning hook fires |
stall_timeout_secs | u64? | 900 | Seconds without heartbeat before stall detection |
auto_interrupt_stalled | bool | false | Auto-interrupt stalled agents |
Permissions
Project-level permission rules (also available per-agent):
"permissions": {
"allow": ["Bash(npm run *)"],
"ask": ["Bash(rm *)"],
"deny": ["Bash(curl *)"],
"default_mode": "ask"
}
See Permissions for full details.
Resolution Cascade
When the configuration is loaded, raw values are resolved into fully-defaulted types:
Agent model = agent.model ?? defaults.model ?? "sonnet"
Agent provider = agent.provider ?? defaults.provider ?? "default"
Agent mode = agent.mode ?? defaults.mode ?? (delegate_mode ? "delegate" : "code")
The ResolvedConfig struct has no Option fields — every value is filled in.
Validation Rules
The config loader validates:
- Version — Must be 1 or 2 (no higher)
- At least one agent — The
agentsarray cannot be empty - Agent names — Must match
[a-z][a-z0-9-]*and be unique - Provider references — All
agent.provideranddefaults.providervalues must reference a defined provider - Provider types — Cannot be empty strings
- WASM tool names — Must match
[a-z][a-z0-9_-]*, be unique, have non-empty paths - WASM capabilities — Must be one of:
Logging,WorkspaceRead,HttpRequest,ToolInvoke,SecretCheck
Related
- Config Schema — Complete field reference
- Writing Agents — Practical configuration guide
- Permissions — Permission rules and modes
- Environment Variables — Runtime environment