octomind-config · diff
v1.0 to v1.1
92 added, 88 removed. Audit A to A.
---
name: octomind-config
title: "Octomind Configuration Reference"
- description: "Field-by-field reference for octomind's config.toml: root settings, performance and spending limits, [capabilities] and [taps] overrides, [[roles]] and [roles.mcp], [mcp] servers (builtin, http, stdio), [[hooks]], [[layers]], [[commands]], [[agents]], [[prompts]], [skills], [compression], [registry], multi-file merge, and template variables. Activate when a user asks how to configure, tune, validate, or upgrade octomind, add a role or MCP server, set limits or spending caps, or debug a config parse error."
+ description: "Field-by-field reference for octomind's config.toml: the [model] profile and its per-boundary overrides, limits and spending caps, [capabilities] and [taps] overrides, [[roles]] with [roles.model] and [roles.mcp], [mcp] servers (builtin, http, stdio), [[hooks]], [[layers]], [[commands]], [[agents]], [[prompts]], [skills], [timing], [compression], [registry], multi-file merge, project guardrails, and template variables. Activate when a user asks how to configure, tune, validate, or upgrade octomind, add a role or MCP server, set limits or spending caps, or debug a config parse error."
license: Apache-2.0
compatibility: "Requires: octomind binary for `octomind config --validate`. macOS/Linux/Windows."
domains: octomind
rules:
- match((?i)\bconfig\.toml\b)
- match((?i)octomind config\b)
- - match((?i)\[\[?(roles|mcp\.servers|layers|commands|agents|prompts|hooks|compression|registry|capabilities|taps|skills)\]\]?)
+ - match((?i)\[\[?(model|roles|roles\.model|mcp\.servers|layers|commands|agents|prompts|hooks|compression|registry|capabilities|taps|skills|timing)\]\]?)
- semantic(configure octomind settings in config.toml)
metadata:
- version: "1.0"
+ version: "1.1"
tags: "octomind config toml roles mcp"
---
## Overview
- Octomind's configuration lives at `~/.local/share/octomind/config/config.toml` (`%LOCALAPPDATA%\octomind\config\config.toml` on Windows), overridable with `OCTOMIND_CONFIG_PATH`. This skill documents every section and field, so config answers cite real field names and defaults rather than plausible-sounding ones.
+ Octomind's configuration lives at `~/.local/share/octomind/config/config.toml` (`%LOCALAPPDATA%\octomind\config\config.toml` on Windows), overridable with `OCTOMIND_CONFIG_PATH` or relocated with `OCTOMIND_DATA_DIR`. This skill documents the sections and fields so config answers cite real names and defaults. The shipped template (`config-templates/default.toml` in the octomind source, also what `octomind config --show` reflects) is the authority when this page and the binary disagree.
- Supervisor tuning has its own skill (`octomind-supervisor`); this one covers everything else in the file.
+ Supervisor tuning has its own skill (`octomind-supervisor`).
## Mental model
- The file has three kinds of section, and they fail differently:
+ The file is strict. Octomind owns the schema and fails loudly instead of degrading silently:
- - Scalars with defaults — omit them and you get the default.
- - Strict sections — `[supervisor]` and its required keys are a hard parse error when missing. Octomind owns that schema and fails loudly instead of degrading silently.
- - Required-field tables — `[[layers]]` and `[[commands]]` require `input_mode`, `output_mode`, and `output_role`; omitting any fails config loading.
+ - Required sections — `[model]`, `[skills]`, `[timing]`, `[compression]`, `[supervisor]` and its mechanic tables, plus the root scalars. A missing one is a parse error; `octomind config --upgrade` migrates older files (the template is at `version = 21`; never edit `version` by hand).
+ - One model contract — `[model]` is the complete baseline profile. Roles (`[roles.model]`), `[compression.model]`, and `[supervisor.model]` are partial overrides: omitted fields inherit from `[model]`.
+ - Required-field tables — `[[layers]]` and `[[commands]]` require `name`, `description`, `command`, `input_mode`, `output_mode`, `output_role`; only `workdir` is optional.
- So a config error is usually a missing required key, not a wrong value. Validate after every edit: `octomind config --validate`. Never modify `version` — it drives `--upgrade`.
+ So a config error is usually a missing key, not a wrong value. Validate after every edit: `octomind config --validate`.
## Rules
- ### Root-level settings
-
- | Field | Type | Default | Meaning |
- |-------|------|---------|---------|
- | `version` | u32 | template ships `8` | Schema version. Do not modify. |
- | `log_level` | string | `"info"` | `none`, `info`, `debug` |
- | `model` | string | `"octohub:auto"` | Default model, `provider:model` |
- | `default` | string | `"assistant:concierge"` | Default TAG for `run`/`acp`/`server` |
- | `max_tokens` | u32 | `32768` | Global max tokens |
- | `sandbox` | bool | `false` | Restrict writes to CWD; Linux Landlock 5.13+, macOS Seatbelt |
- | `telemetry` | bool | `true` | Anonymous usage counts; never code, prompts, or paths |
- | `auto_capabilities` | bool | `true` | Automatic capability activation on user messages |
- | `system` | string | none | Legacy global system-prompt fallback; prefer per-role `system` |
-
- `default = "assistant:concierge"` is a tap agent from the built-in tap, not a role in this file — searching for a `concierge` role finds nothing. A bare tag without a colon resolves against `[[roles]]`; `category:variant` resolves against taps.
-
- ### Performance and limits
+ ### Root settings
| Field | Default | Meaning |
|-------|---------|---------|
- | `mcp_response_tokens_threshold` | `20000` | Hard truncation ceiling for MCP responses; `0` = unlimited |
- | `max_session_tokens_threshold` | `200000` | Session ceiling, also the hard compression ceiling; validation fails above 2,000,000 |
- | `max_retries` | `1` | API retry attempts |
- | `retry_timeout` | `30` | Exponential-backoff base, seconds |
- | `request_timeout_seconds` | `300` | Per-request HTTP timeout; `0` = none |
- | `reasoning_effort` | `"medium"` | `low`/`medium`/`high`/`xhigh`/`max`; ignored by non-thinking models |
- | `cache_keepalive_enabled` | `false` | Idle cache pings; provider-aware, currently Anthropic only |
- | `cache_keepalive_max_idle_seconds` | `1800` | Stop pinging after this idle time; validation fails above 86400 |
+ | `log_level` | `"info"` | `none`, `info`, `debug` |
+ | `default` | `"assistant:concierge"` | Tag used when `run`/`acp`/`server` get none |
+ | `sandbox` | `false` | Restrict writes to CWD; Linux Landlock 5.13+, macOS Seatbelt |
+ | `telemetry` | `true` | Anonymous usage counts; never code, prompts, paths, or env values |
+ | `auto_capabilities` | `true` | Capability auto-activation on fresh user messages |
+ | `mcp_response_tokens_threshold` | `20000` | Hard truncation ceiling per MCP response; `0` = unlimited |
+ | `max_session_tokens_threshold` | `200000` | Session ceiling; validation fails above 2,000,000 |
+ | `cache_keepalive_enabled` | `false` | Idle cache pings, currently Anthropic only |
+ | `cache_keepalive_max_idle_seconds` | `1800` | Stop pinging after this idle time; max 86400, `0` = until session ends |
+ | `enable_markdown_rendering` / `markdown_theme` | `true` / `"default"` | Themes: default, dark, light, ocean, solarized, monokai |
+ | `max_session_spending_threshold` | `0.0` | USD; prompts before continuing when exceeded |
+ | `max_request_spending_threshold` | `0.0` | USD; stops the current request when exceeded |
+ | `system` | unset | Legacy global prompt fallback; prefer per-role `system` |
- ### User interface and spending
+ `default = "assistant:concierge"` is a tap agent, not a role in this file. A tag without a colon resolves against `[[roles]]`; `domain:spec` resolves against taps.
- `enable_markdown_rendering` (`true`), `markdown_theme` (`default`, `dark`, `light`, `ocean`, `solarized`, `monokai`), `max_session_spending_threshold` and `max_request_spending_threshold` (USD, `0.0` = no limit). Session threshold prompts before continuing; request threshold stops execution.
+ ### `[model]`
+ ```toml
+ [model]
+ name = "octohub:auto" # provider:model
+ reasoning_effort = "medium" # none, low, medium, high, xhigh, max
+ max_tokens = 32768 # 0 = provider default
+ temperature = 0.3 # 0.0–2.0
+ top_p = 0.7 # 0.0–1.0
+ top_k = 20 # 0–1000
+ max_retries = 1
+ retry_timeout = 30 # backoff base, seconds
+ request_timeout_seconds = 300 # 0 = none
+ ```
+
+ These fields used to be root scalars (`model`, `max_tokens`, `reasoning_effort`, ...); `--upgrade` moves them. Sampling values are sent only where the provider accepts them — the provider layer drops them for models that reject sampling parameters and while extended thinking is on.
+
### `[capabilities]` and `[taps]`
```toml
[capabilities]
- codesearch = "octocode" # picks capabilities/codesearch/octocode.toml
+ websearch = "brave" # use capabilities/websearch/brave.toml instead of default.toml
[taps]
- "developer:general" = "ollama:glm-5"
+ "developer:general" = "ollama:glm-5" # model name only
```
- `[capabilities]` routes a capability name to a non-default provider. `[taps]` sets a model per tap agent, acting at the `config.model` tier — it applies only when neither `--model` nor the agent's own role model is set, and only to tags containing a colon.
+ Model priority, highest first: runtime override (`--model`, `/model`), the role's model, the `[taps]` entry, then `[model].name`. A `[taps]` value replaces only the model name; the rest of the profile is inherited.
### `[[roles]]`
- Fields: `name` (required), `model`, `system`, `welcome`, `temperature` (0.0–2.0), `top_p` (0.0–1.0), `top_k` (1–1000). Roles in config override tap-provided agents of the same name.
+ Fields: `name`, `system`, `welcome` (all required), optional `[roles.model]` override table (or `model = "provider:model"`), and `[roles.mcp]`. Flat `temperature`/`top_p`/`top_k` on a role are still accepted (tap manifests use them) and folded into the role's model override. Roles in config override tap agents of the same name.
```toml
[[roles]]
name = "assistant"
- temperature = 0.3
- system = "You are a helpful assistant. Working directory: {{CWD}}"
+ system = "You are a helpful assistant."
+ welcome = "Ready. Working in {{CWD}}"
+ [roles.model]
+ reasoning_effort = "high"
+
[roles.mcp]
- server_refs = ["core", "runtime", "filesystem", "agent"]
- allowed_tools = ["core:*", "runtime:*"]
+ server_refs = ["core", "orchestration", "runtime", "filesystem", "agent"]
+ allowed_tools = ["core:*", "orchestration:*", "runtime:*", "filesystem:*", "agent:*"]
```
- `[roles.mcp].server_refs` lists servers to enable; `allowed_tools` filters them, empty meaning all, wildcards supported.
+ `server_refs` lists servers to enable; `allowed_tools` filters them, empty meaning all, `server:*` and trailing-`*` prefixes supported.
### `[mcp]` and `[[mcp.servers]]`
- `[mcp].allowed_tools` is a global fallback used when a role does not specify its own.
+ `[mcp].allowed_tools` is a global fallback when a role does not specify its own.
- Builtin servers need no process: `core` (`recall`), `orchestration` (`tap`, `schedule`, `monitor`), `runtime` (`mcp`, `agent`, `skill`, `capability`), `agent` (one `agent_<name>` tool per `[[agents]]` entry). The `filesystem` server that default roles reference is not a builtin — it is an external stdio server backed by `octofs`, supplied by the built-in tap, exposing `view`, `text_editor`, `batch_edit`, `extract_lines`, `shell`, `workdir`.
+ Builtin servers need no process: `core` (`recall`, only advertised when `[compression.attention]` or its governance is enabled), `orchestration` (`tap`, `schedule`, `monitor`), `runtime` (`mcp`, `agent`, `skill`, `capability`), `agent` (one `agent_<name>` tool per `[[agents]]` entry). The `filesystem` server default roles reference is the external octofs server supplied by the built-in tap.
- Common server fields: `name`, `type` (`builtin`|`http`|`stdio`), `timeout_seconds` (required; per-operation, reset by tool-call progress), `tools` (filter, wildcards ok), `auto_bind` (role names to auto-include for). HTTP adds `url` (required) and `headers` (values support `{{ENV:KEY}}`). Stdio adds `command` (required) and `args`.
+ Every server needs `name`, `type` (`builtin`|`http`|`stdio`), `timeout_seconds` (1–3600; an idle deadline that MCP progress notifications reset), and `tools` (filter list, `[]` = all). Optional `auto_bind = ["role"]` includes the server for those roles without a `server_ref`. HTTP adds `url` (required) and `headers`; stdio adds `command` (spawned directly, no shell), `args`, `env` (passed to the child), and `cwd`. Values in `headers` and `env` support `{{ENV:KEY}}`.
Authentication: a static `Authorization` header carries a bearer token and disables OAuth discovery. Without one, Octomind uses MCP Authorization Discovery (RFC 9728), registers via CIMD/DCR, and authenticates with PKCE.
### `[[hooks]]`
- Webhook listeners: `name`, `bind` (e.g. `"0.0.0.0:9876"`), `script`, `timeout` (default 30, range 1–3600). Activate with `octomind run --daemon --hook <name>`.
+ Webhook listeners: `name`, `bind` (e.g. `"0.0.0.0:9876"`, unique per hook), `script` (stdin = HTTP body, stdout = message to inject), `timeout` (default 30, 1–3600). Activate with `octomind run --daemon --format jsonl --hook <name>`.
### `[[layers]]`, `[[commands]]`, `[[agents]]`, `[[prompts]]`
- `[[layers]]` and `[[commands]]` share one schema: `name`, `description`, `command` (`"octomind acp <role>"`), `input_mode` (`last`|`all`|`summary`), `output_mode` (`none`|`append`|`replace`|`last`|`restart`), `output_role` (`assistant`|`user`), and optional `workdir`. The three modes have no defaults — omitting any fails loading. Model and prompt live in the referenced `[[roles]]` entry, never in the layer. Layers are ACP orchestration units; commands are typed as `/run <name>`.
+ `[[layers]]` and `[[commands]]` share one schema: `name`, `description`, `command` (`"octomind acp <role>"`), `input_mode` (`last`|`all`|`summary`), `output_mode` (`none`|`append`|`replace`|`last`|`restart`), `output_role` (`assistant`|`user`), optional `workdir`. Model and prompt live in the referenced role, never in the layer. Commands run as `/run <name>`.
- Multi-step AI pipelines are not config — they are `octomind workflow <file.toml>`.
+ `[[agents]]`: `name`, `description`, `command` (any ACP server command), optional `workdir` (default `.`). Each becomes an MCP tool `agent_<name>` on the `agent` server.
- `[[agents]]`: `name`, `description`, `command`, optional `workdir`. Each becomes an MCP tool `agent_<name>`.
+ `[[prompts]]`: `name`, `prompt`, optional `description`. Inserted via `/prompt <name>`.
- `[[prompts]]`: `name`, `description`, `prompt`. Injected verbatim via `/prompt <name>`; no variable substitution.
+ Multi-step AI pipelines are not config — they are `octomind workflow <file.toml>`.
### `[skills]`
- `auto_activation` (`true`) evaluates declarative rules on every user message. `auto_validation` (`false`) runs skill `validate` scripts at end of turn — it gates only SKILL.md validators, not guardrail `[[validator]]` entries, which always run. Also `activation_timeout` (reserved), `validation_timeout` (`60`, `0` = unlimited), `max_retries` (`3`).
+ `auto_activation` (`true`) evaluates declarative rules on fresh user messages. `auto_validation` (`false`) runs tap skills' `validate` scripts at the end of each assistant turn. `validation_timeout` (`60`, `0` = unlimited), `max_retries` (`3`), `activation_timeout` (reserved, kept for compatibility).
+ ### `[timing]`
+
+ Per-person calibration for `/report`'s human-time and energy estimate: `think_overhead_min`, `deliberation_factor`, `attention_window_min`, `review_weight`, `wait_weight`, `switch_cost_dhe`.
+
### `[compression]`
- `knowledge_retention` (`25`), `analysis_findings_max_tokens` (`6000`, `0` disables), `threshold` (`70000` absolute tokens, `0` disables). Depth is computed, not configured: once past `threshold`, the ratio derives per cycle from measured growth and the context ceiling, always landing in [2.0, 16.0].
+ `threshold` (`70000` absolute tokens, `0` disables), `knowledge_retention` (`25`), `analysis_findings_max_tokens` (`6000`, `0` disables). Depth is computed per cycle from measured growth and the context ceiling, not configured. Keep scalar keys above the nested tables, or TOML assigns them to the table.
- `[compression.decision]` picks the model doing the work: `model` (`openai:gpt-5-mini`), `max_tokens` (`16000`), `temperature` (`0.3`), `top_p`, `top_k`, `max_retries`, `retry_timeout`. Cheap and fast is the right choice.
+ `[compression.model]` overrides the profile for folds; the template uses `reasoning_effort = "none"` because thinking models otherwise spend the output budget reasoning. `[compression.attention]` (`enabled = false`, `validator`, `telemetry`, `[compression.attention.governance]`) is the evidence-grounded compaction layer that also enables the `recall` tool.
### `[registry]`
- `cache_ttl_hours` (`24`) governs tap manifest caching. Within the TTL the cache is served; once stale, the cached copy is still served while a background refresh runs.
+ `cache_ttl_hours` (`24`) governs tap manifest caching.
### Multi-file configuration
- All `*.toml` in the config directory merge: `config.toml` first, then others alphabetically, with arrays of tables concatenated, same-name entries deduplicated (last wins), and scalars overridden by later files. Files matching `mcp-*.toml` load last regardless of alphabetical order, so they reliably override servers defined in `mcp.toml`. The `mcp persist` command relies on this, writing `<config_dir>/mcp-<name>.toml` with `auto_bind`.
+ All `*.toml` in the config directory merge: `config.toml` first, then other files alphabetically, then `mcp-*.toml` last. Arrays of tables concatenate with same-name entries deduplicated (last wins); scalars are overridden by later files. Runtime `mcp` persistence writes `<config_dir>/mcp-<name>.toml` with `auto_bind`.
+ ### Project guardrails (not config.toml)
+
+ `<workdir>/.agents/guardrails.toml` holds `[[pipe]]` (transform or reject user input), `[[guard]]` (block a tool call), `[[hook]]` (script after a tool result), and `[[validator]]` (script after the final reply). It loads at session start; a parse error means no authored rules, never a crash. Validators there always run, independent of `[skills] auto_validation`.
+
### Template variables
- Substituted in role `system` and `welcome` at prompt-expansion time: `{{CWD}}`, `{{ROLE}}`, `{{DATE}}`, `{{SHELL}}`, `{{OS}}`, `{{BINARIES}}`, `{{GIT_STATUS}}`, `{{GIT_TREE}}`, `{{README}}`, plus `{{CONTEXT}}` and `{{SYSTEM}}` for layers. `{{HOME}}` is not substituted in prompts — it only appears in the `octomind vars` listing, so it stays literal in a role prompt. Use an absolute path or `{{CWD}}`.
+ Expanded in role `system` and `welcome`: `{{CWD}}`, `{{ROLE}}`, `{{DATE}}`, `{{SHELL}}`, `{{OS}}`, `{{BINARIES}}`, `{{GIT_STATUS}}`, `{{GIT_TREE}}`, `{{README}}`, `{{CONTEXT}}`, `{{SYSTEM}}`. `octomind vars` lists them with live values. Anything else stays literal.
## Examples
### Example 1: layer missing required modes
❌ Bad:
```toml
[[layers]]
name = "task_refiner"
description = "Refines requests"
command = "octomind acp task_refiner"
```
✅ Good:
```toml
[[layers]]
name = "task_refiner"
description = "Refines requests"
command = "octomind acp task_refiner"
input_mode = "last"
output_mode = "none"
output_role = "assistant"
```
- What changed: the three mode fields have no defaults — the first version fails config loading outright.
+ What changed: the three mode fields have no defaults — the first version fails loading.
- ### Example 2: model and prompt in the wrong place
+ ### Example 2: model settings at the root
❌ Bad:
```toml
- [[layers]]
- name = "reduce"
- model = "openai:gpt-5-mini"
- system = "Compress the transcript."
+ model = "openai:gpt-5"
+ reasoning_effort = "high"
```
✅ Good:
```toml
- [[roles]]
- name = "reduce"
- model = "openai:gpt-5-mini"
- system = "Compress the transcript."
-
- [[commands]]
- name = "reduce"
- description = "Compress session history"
- command = "octomind acp reduce"
- input_mode = "all"
- output_mode = "replace"
- output_role = "assistant"
+ [model]
+ name = "openai:gpt-5"
+ reasoning_effort = "high"
+ # remaining profile fields as in the template
```
- What changed: layers delegate over ACP; model, prompt, and MCP config belong to the role the command references.
+ What changed: model settings live in the `[model]` profile; root scalars are the pre-upgrade layout.
### Example 3: overriding a server from a separate file
- Put the override in `mcp-github.toml`, not `zz-github.toml`. Only the `mcp-*.toml` prefix guarantees loading after `mcp.toml`; any other name risks being overwritten by alphabetical order.
+ Put the override in `mcp-github.toml`, not `zz-github.toml`. Only the `mcp-*.toml` prefix guarantees loading after every regular file.
## Checklist
- [ ] `octomind config --validate` run after the edit and passing?
- - [ ] `version` left untouched?
- - [ ] Every `[[layers]]`/`[[commands]]` entry has `input_mode`, `output_mode`, `output_role`?
- - [ ] Every `[[mcp.servers]]` has `timeout_seconds`, plus `url` for http or `command` for stdio?
- - [ ] `server_refs` names resolve to a builtin, a tap-provided server, or a declared `[[mcp.servers]]`?
- - [ ] No API key written into the file — environment or `.env` instead?
+ - [ ] `version` untouched; older layouts migrated with `--upgrade` rather than by hand?
+ - [ ] Model settings in `[model]`, `[roles.model]`, `[compression.model]`, or `[supervisor.model]` — not at the root?
+ - [ ] Every `[[layers]]`/`[[commands]]` entry has `description` and all three modes?
+ - [ ] Every `[[mcp.servers]]` has `timeout_seconds` and `tools`, plus `url` for http or `command` for stdio?
+ - [ ] Secrets referenced as `{{ENV:KEY}}` or set in `.env`, never written into the file?
- [ ] Override files that must win named `mcp-*.toml`?
- - [ ] Model, system prompt, and MCP config placed in `[[roles]]`, not in a layer or command?
## Composition / References
- Pairs with `octomind-cli` for the `octomind config` flags that mutate this file.
- - Pairs with `octomind-supervisor` for `[supervisor]`, which is strict and documented separately.
+ - Pairs with `octomind-supervisor` for `[supervisor]`, which is documented separately.
- Pairs with `octomind-runtime` for how capabilities and taps resolve into a role's tool surface.
- - Octomind docs: `doc/reference/03-config-reference.md`, `config-templates/default.toml`, `doc/usage/03-configuration.md`, `doc/usage/06-roles.md`, `doc/usage/10-commands-and-layers.md`
+ - Octomind docs: `doc/reference/03-config-reference.md`, `doc/usage/03-configuration.md`, `doc/usage/06-roles.md`, `doc/usage/10-commands-and-layers.md`, `doc/usage/18-guardrails.md`