~/.fluffbuzz/fluffbuzz.json.
The active config path must be a regular file. Symlinked fluffbuzz.json
layouts are unsupported for FluffBuzz-owned writes; an atomic write may replace
the path instead of preserving the symlink. If you keep config outside the
default state directory, point FLUFFBUZZ_CONFIG_PATH directly at the real file.
If the file is missing, FluffBuzz uses safe defaults. Common reasons to add a config:
- Connect channels and control who can message the bot
- Set models, tools, sandboxing, or automation (cron, hooks)
- Tune sessions, media, networking, or UI
Minimal config
Editing config
- Interactive wizard
- CLI (one-liners)
- Control UI
- Direct edit
Strict validation
fluffbuzz config schema prints the canonical JSON Schema used by Control UI
and validation. config.schema.lookup fetches a single path-scoped node plus
child summaries for drill-down tooling. Field title/description docs metadata
carries through nested objects, wildcard (*), array-item ([]), and anyOf/
oneOf/allOf branches. Runtime plugin and channel schemas merge in when the
manifest registry is loaded.
When validation fails:
- The Gateway does not boot
- Only diagnostic commands work (
fluffbuzz doctor,fluffbuzz logs,fluffbuzz health,fluffbuzz status) - Run
fluffbuzz doctorto see exact issues - Run
fluffbuzz doctor --fix(or--yes) to apply repairs
fluffbuzz.json later fails validation (or drops gateway.mode, shrinks
sharply, or has a stray log line prepended), FluffBuzz preserves the broken file
as .clobbered.*, restores the last-known-good copy, and logs the recovery
reason. The next agent turn also receives a system-event warning so the main
agent does not blindly rewrite the restored config. Promotion to last-known-good
is skipped when a candidate contains redacted secret placeholders such as ***.
Common tasks
Set up a channel (WhatsApp, Telegram, Discord, etc.)
Set up a channel (WhatsApp, Telegram, Discord, etc.)
Each channel has its own config section under
channels.<provider>. See the dedicated channel page for setup steps:- WhatsApp —
channels.whatsapp - Telegram —
channels.telegram - Discord —
channels.discord - Feishu —
channels.feishu - Google Chat —
channels.googlechat - Microsoft Teams —
channels.msteams - Slack —
channels.slack - Signal —
channels.signal - iMessage —
channels.imessage - Mattermost —
channels.mattermost
Choose and configure models
Choose and configure models
Set the primary model and optional fallbacks:
agents.defaults.modelsdefines the model catalog and acts as the allowlist for/model.- Use
fluffbuzz config set agents.defaults.models '<json>' --strict-json --mergeto add allowlist entries without removing existing models. Plain replacements that would remove entries are rejected unless you pass--replace. - Model refs use
provider/modelformat (e.g.anthropic/claude-opus-4-6). agents.defaults.imageMaxDimensionPxcontrols transcript/tool image downscaling (default1200); lower values usually reduce vision-token usage on screenshot-heavy runs.- See Models CLI for switching models in chat and Model Failover for auth rotation and fallback behavior.
- For custom/self-hosted providers, see Custom providers in the reference.
Control who can message the bot
Control who can message the bot
DM access is controlled per channel via
dmPolicy:"pairing"(default): unknown senders get a one-time pairing code to approve"allowlist": only senders inallowFrom(or the paired allow store)"open": allow all inbound DMs (requiresallowFrom: ["*"])"disabled": ignore all DMs
groupPolicy + groupAllowFrom or channel-specific allowlists.See the full reference for per-channel details.Set up group chat mention gating
Set up group chat mention gating
Group messages default to require mention. Configure patterns per agent:
- Metadata mentions: native @-mentions (WhatsApp tap-to-mention, Telegram @bot, etc.)
- Text patterns: safe regex patterns in
mentionPatterns - See full reference for per-channel overrides and self-chat mode.
Restrict skills per agent
Restrict skills per agent
Use
agents.defaults.skills for a shared baseline, then override specific
agents with agents.list[].skills:- Omit
agents.defaults.skillsfor unrestricted skills by default. - Omit
agents.list[].skillsto inherit the defaults. - Set
agents.list[].skills: []for no skills. - See Skills, Skills config, and the Configuration Reference.
Tune gateway channel health monitoring
Tune gateway channel health monitoring
Control how aggressively the gateway restarts channels that look stale:
- Set
gateway.channelHealthCheckMinutes: 0to disable health-monitor restarts globally. channelStaleEventThresholdMinutesshould be greater than or equal to the check interval.- Use
channels.<provider>.healthMonitor.enabledorchannels.<provider>.accounts.<id>.healthMonitor.enabledto disable auto-restarts for one channel or account without disabling the global monitor. - See Health Checks for operational debugging and the full reference for all fields.
Configure sessions and resets
Configure sessions and resets
Sessions control conversation continuity and isolation:
dmScope:main(shared) |per-peer|per-channel-peer|per-account-channel-peerthreadBindings: global defaults for thread-bound session routing (Discord supports/focus,/unfocus,/agents,/session idle, and/session max-age).- See Session Management for scoping, identity links, and send policy.
- See full reference for all fields.
Enable sandboxing
Enable sandboxing
Run agent sessions in isolated sandbox runtimes:Build the image first:
scripts/sandbox-setup.shSee Sandboxing for the full guide and full reference for all options.Enable relay-backed push for official iOS builds
Enable relay-backed push for official iOS builds
Relay-backed push is configured in CLI equivalent:What this does:
fluffbuzz.json.Set this in gateway config:- Lets the gateway send
push.test, wake nudges, and reconnect wakes through the external relay. - Uses a registration-scoped send grant forwarded by the paired iOS app. The gateway does not need a deployment-wide relay token.
- Binds each relay-backed registration to the gateway identity that the iOS app paired with, so another gateway cannot reuse the stored registration.
- Keeps local/manual iOS builds on direct APNs. Relay-backed sends apply only to official distributed builds that registered through the relay.
- Must match the relay base URL baked into the official/TestFlight iOS build, so registration and send traffic reach the same relay deployment.
- Install an official/TestFlight iOS build that was compiled with the same relay base URL.
- Configure
gateway.push.apns.relay.baseUrlon the gateway. - Pair the iOS app to the gateway and let both node and operator sessions connect.
- The iOS app fetches the gateway identity, registers with the relay using App Attest plus the app receipt, and then publishes the relay-backed
push.apns.registerpayload to the paired gateway. - The gateway stores the relay handle and send grant, then uses them for
push.test, wake nudges, and reconnect wakes.
- If you switch the iOS app to a different gateway, reconnect the app so it can publish a new relay registration bound to that gateway.
- If you ship a new iOS build that points at a different relay deployment, the app refreshes its cached relay registration instead of reusing the old relay origin.
FLUFFBUZZ_APNS_RELAY_BASE_URLandFLUFFBUZZ_APNS_RELAY_TIMEOUT_MSstill work as temporary env overrides.FLUFFBUZZ_APNS_RELAY_ALLOW_HTTP=trueremains a loopback-only development escape hatch; do not persist HTTP relay URLs in config.
Set up heartbeat (periodic check-ins)
Set up heartbeat (periodic check-ins)
every: duration string (30m,2h). Set0mto disable.target:last|none|<channel-id>(for examplediscord,matrix,telegram, orwhatsapp)directPolicy:allow(default) orblockfor DM-style heartbeat targets- See Heartbeat for the full guide.
Configure cron jobs
Configure cron jobs
sessionRetention: prune completed isolated run sessions fromsessions.json(default24h; setfalseto disable).runLog: prunecron/runs/<jobId>.jsonlby size and retained lines.- See Cron jobs for feature overview and CLI examples.
Set up webhooks (hooks)
Set up webhooks (hooks)
Enable HTTP webhook endpoints on the Gateway:Security note:
- Treat all hook/webhook payload content as untrusted input.
- Use a dedicated
hooks.token; do not reuse the shared Gateway token. - Hook auth is header-only (
Authorization: Bearer ...orx-fluffbuzz-token); query-string tokens are rejected. hooks.pathcannot be/; keep webhook ingress on a dedicated subpath such as/hooks.- Keep unsafe-content bypass flags disabled (
hooks.gmail.allowUnsafeExternalContent,hooks.mappings[].allowUnsafeExternalContent) unless doing tightly scoped debugging. - If you enable
hooks.allowRequestSessionKey, also sethooks.allowedSessionKeyPrefixesto bound caller-selected session keys. - For hook-driven agents, prefer strong modern model tiers and strict tool policy (for example messaging-only plus sandboxing where possible).
Configure multi-agent routing
Configure multi-agent routing
Run multiple isolated agents with separate workspaces and sessions:See Multi-Agent and full reference for binding rules and per-agent access profiles.
Split config into multiple files ($include)
Split config into multiple files ($include)
Use
$include to organize large configs:- Single file: replaces the containing object
- Array of files: deep-merged in order (later wins)
- Sibling keys: merged after includes (override included values)
- Nested includes: supported up to 10 levels deep
- Relative paths: resolved relative to the including file
- FluffBuzz-owned writes: when a write changes only one top-level section
backed by a single-file include such as
plugins: { $include: "./plugins.json5" }, FluffBuzz updates that included file and leavesfluffbuzz.jsonintact - Unsupported write-through: root includes, include arrays, and includes with sibling overrides fail closed for FluffBuzz-owned writes instead of flattening the config
- Error handling: clear errors for missing files, parse errors, and circular includes
Config hot reload
The Gateway watches~/.fluffbuzz/fluffbuzz.json and applies changes automatically — no manual restart needed for most settings.
Direct file edits are treated as untrusted until they validate. The watcher waits
for editor temp-write/rename churn to settle, reads the final file, and rejects
invalid external edits by restoring the last-known-good config. FluffBuzz-owned
config writes use the same schema gate before writing; destructive clobbers such
as dropping gateway.mode or shrinking the file by more than half are rejected
and saved as .rejected.* for inspection.
If you see Config auto-restored from last-known-good or
config reload restored last-known-good config in logs, inspect the matching
.clobbered.* file next to fluffbuzz.json, fix the rejected payload, then run
fluffbuzz config validate. See Gateway troubleshooting
for the recovery checklist.
Reload modes
| Mode | Behavior |
|---|---|
hybrid (default) | Hot-applies safe changes instantly. Automatically restarts for critical ones. |
hot | Hot-applies safe changes only. Logs a warning when a restart is needed — you handle it. |
restart | Restarts the Gateway on any config change, safe or not. |
off | Disables file watching. Changes take effect on the next manual restart. |
What hot-applies vs what needs a restart
Most fields hot-apply without downtime. Inhybrid mode, restart-required changes are handled automatically.
| Category | Fields | Restart needed? |
|---|---|---|
| Channels | channels.*, web (WhatsApp) — all built-in and plugin channels | No |
| Agent & models | agent, agents, models, routing | No |
| Automation | hooks, cron, agent.heartbeat | No |
| Sessions & messages | session, messages | No |
| Tools & media | tools, browser, skills, audio, talk | No |
| UI & misc | ui, logging, identity, bindings | No |
| Gateway server | gateway.* (port, bind, auth, tailscale, TLS, HTTP) | Yes |
| Infrastructure | discovery, canvasHost, plugins | Yes |
gateway.reload and gateway.remote are exceptions — changing them does not trigger a restart.Reload planning
When you edit a source file that is referenced through$include, FluffBuzz plans
the reload from the source-authored layout, not the flattened in-memory view.
That keeps hot-reload decisions (hot-apply vs restart) predictable even when a
single top-level section lives in its own included file such as
plugins: { $include: "./plugins.json5" }. Reload planning fails closed if the
source layout is ambiguous.
Config RPC (programmatic updates)
For tooling that writes config over the gateway API, prefer this flow:config.schema.lookupto inspect one subtree (shallow schema node + child summaries)config.getto fetch the current snapshot plushashconfig.patchfor partial updates (JSON merge patch: objects merge,nulldeletes, arrays replace)config.applyonly when you intend to replace the entire configupdate.runfor explicit self-update plus restart
Control-plane writes (
config.apply, config.patch, update.run) are
rate-limited to 3 requests per 60 seconds per deviceId+clientIp. Restart
requests coalesce and then enforce a 30-second cooldown between restart cycles.config.apply and config.patch accept raw, baseHash, sessionKey,
note, and restartDelayMs. baseHash is required for both methods when a
config already exists.
Environment variables
FluffBuzz reads env vars from the parent process plus:.envfrom the current working directory (if present)~/.fluffbuzz/.env(global fallback)
Shell env import (optional)
Shell env import (optional)
If enabled and expected keys aren’t set, FluffBuzz runs your login shell and imports only the missing keys:Env var equivalent:
FLUFFBUZZ_LOAD_SHELL_ENV=1Env var substitution in config values
Env var substitution in config values
Reference env vars in any config string value with Rules:
${VAR_NAME}:- Only uppercase names matched:
[A-Z_][A-Z0-9_]* - Missing/empty vars throw an error at load time
- Escape with
$${VAR}for literal output - Works inside
$includefiles - Inline substitution:
"${BASE}/v1"→"https://api.example.com/v1"
Secret refs (env, file, exec)
Secret refs (env, file, exec)
For fields that support SecretRef objects, you can use:SecretRef details (including
secrets.providers for env/file/exec) are in Secrets Management.
Supported credential paths are listed in SecretRef Credential Surface.Full reference
For the complete field-by-field reference, see Configuration Reference.Related: Configuration Examples · Configuration Reference · Doctor