> ## Documentation Index
> Fetch the complete documentation index at: https://beige.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Config Reference

> Complete config.json5 reference — all fields, validation rules, and directory layout

Beige is configured with a single `~/.beige/config.json5` file. JSON5 is JSON with comments, trailing commas, and unquoted keys. You can also override the path with `--config`.

## Environment Variables

Any string value can reference environment variables using `${VAR_NAME}`. Variables are resolved at startup — if a referenced variable is not set and has no default, the gateway exits with an error.

```json5 theme={null}
apiKey: "${ANTHROPIC_API_KEY}",            // resolved from env at startup
apiKey: "${ANTHROPIC_API_KEY:-fallback}",  // uses "fallback" if env var is not set
```

The `${VAR_NAME:-default}` syntax provides a fallback value when the variable is not set. Without a default, missing variables cause a startup error.

## Plugin Path Resolution

Plugin `path` values are resolved relative to the config file's directory, unless they are absolute paths. Installed plugins (via `beige plugins install`) are auto-resolved.

***

## Full Config Reference

```json5 theme={null}
{
  // ── LLM Providers ────────────────────────────────────────────────────
  llm: {
    providers: {
      anthropic: {
        apiKey: "${ANTHROPIC_API_KEY}",
      },
      openai: {
        apiKey: "${OPENAI_API_KEY}",
      },
      google: {
        apiKey: "${GOOGLE_API_KEY}",
      },
      // Custom / OpenAI-compatible providers
      zai: {
        apiKey: "${ZAI_API_KEY}",
        baseUrl: "https://api.zai.com/v1",
        api: "openai-completions",
      },
      // Local (no apiKey needed)
      ollama: {
        baseUrl: "http://localhost:11434/v1",
        api: "openai-completions",
      },
    },
  },

  // ── Plugins ──────────────────────────────────────────────────────────
  // Plugins provide tools, channels, hooks, and skills.
  // Plugins installed via `beige plugins install` are added here automatically.
  plugins: {
    // Plugin with custom config (path auto-resolved if installed)
    github: {
      config: { allowedCommands: ["repo", "issue", "pr"] },
    },
    // Local plugin (path required)
    git: {
      path: "~/.beige/plugins/git",
      config: {},
    },
    // Channel plugin
    telegram: {
      config: {
        token: "${TELEGRAM_BOT_TOKEN}",
        allowedUsers: [123456789],
        agentMapping: { default: "assistant" },
        defaults: { verbose: false, streaming: true },
      },
    },
  },

  // ── Skills ────────────────────────────────────────────────────────────
  // Standalone skill packages (plugins can also register skills).
  skills: {
    "code-review": {
      path: "./skills/code-review",
    },
  },

  // ── Agents ───────────────────────────────────────────────────────────
  agents: {
    assistant: {
      model: {
        provider: "anthropic",
        model: "claude-sonnet-4-6",
        thinkingLevel: "off",
        // Trigger auto-compaction at 100k tokens instead of the default (~184k)
        compactionThreshold: 100000,
      },
      fallbackModels: [
        {
          provider: "anthropic",
          model: "claude-3-5-sonnet-20241022",
          compactionThreshold: 80000,  // per-fallback threshold
        },
      ],
      tools: ["git", "github"],
      skills: ["code-review"],
      pluginConfigs: {
        git: {
          denyCommands: ["del"],
        },
      },
      sandbox: {
        image: "beige-sandbox:latest",
        // Hard memory cap — container gets OOM-killed before it can exhaust host RAM.
        // Default is "3g". Use a lower value on memory-constrained hosts (e.g. Raspberry Pi).
        memoryLimit: "3g",
        extraMounts: {
          "/host/path": "/container/path",
        },
        extraEnv: {
          "NODE_ENV": "production",
        },
      },
    },
  },

  // ── Gateway ───────────────────────────────────────────────────────────
  gateway: {
    host: "127.0.0.1",
    port: 7433,
    logFile: "~/.beige/logs/gateway.log",
  },
}
```

***

## Field Reference

### `llm.providers.<name>`

| Field     | Required | Description                                                           |
| --------- | -------- | --------------------------------------------------------------------- |
| `apiKey`  | Yes\*    | API key — use `${VAR}` for env var. Not required for local providers. |
| `baseUrl` | No       | Custom API endpoint. Required for non-built-in providers.             |
| `api`     | No       | API type (see below). Auto-set for built-in providers.                |

**API types:**

| Value                  | Use for                                                    |
| ---------------------- | ---------------------------------------------------------- |
| `anthropic-messages`   | Anthropic Claude (default for `anthropic`)                 |
| `openai-completions`   | OpenAI, ZAI, Groq, Ollama, and most OpenAI-compatible APIs |
| `openai-responses`     | OpenAI Responses API                                       |
| `google-generative-ai` | Google Gemini (default for `google`)                       |

### `plugins.<name>`

| Field    | Required | Description                                                                |
| -------- | -------- | -------------------------------------------------------------------------- |
| `path`   | No       | Path to the plugin package directory. Auto-resolved for installed plugins. |
| `config` | No       | Arbitrary object passed to `createPlugin(config, ctx)`                     |

### `skills.<name>`

| Field  | Required | Description                         |
| ------ | -------- | ----------------------------------- |
| `path` | Yes      | Path to the skill package directory |

### `agents.<name>.model`

| Field                 | Required | Description                                                                                                                                                                                                 |
| --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`            | Yes      | Must match a key in `llm.providers`                                                                                                                                                                         |
| `model`               | Yes      | Model ID as the provider expects it                                                                                                                                                                         |
| `thinkingLevel`       | No       | `off` \| `minimal` \| `low` \| `medium` \| `high` — extended thinking budget                                                                                                                                |
| `compactionThreshold` | No       | Token count at which auto-compaction triggers for this model. Must be less than the model's context window. Defaults to `contextWindow − 16384`. Example: `100000` on a 200k model compacts at 100k tokens. |

### `agents.<name>.fallbackModels`

Optional array of `ModelRef` objects tried in order when the primary model fails or is rate-limited. Each fallback can carry its own `thinkingLevel` and `compactionThreshold`.

The gateway uses a **multi-pass retry loop**: it cycles through the model list up to 3 times, giving each model up to 3 chances per prompt. Rate-limited models (HTTP 429) are skipped immediately; transient errors (e.g. "overloaded") consume one of the 3 chances and the model is retried on the next pass. See [Model Fallback](/gateway/architecture#model-fallback) for details.

### `agents.<name>.sandbox`

| Field         | Required | Default                  | Description                                                                                                                                                                                              |
| ------------- | -------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image`       | No       | `"beige-sandbox:latest"` | Docker image name                                                                                                                                                                                        |
| `memoryLimit` | No       | `"3g"`                   | Hard memory cap for the container (e.g. `"3g"`, `"512m"`). The container is OOM-killed by the cgroup before it can exhaust host RAM. Swap is also capped to the same value, so the limit is always hard. |
| `extraMounts` | No       | —                        | `{ "/host/path": "/container/path" }` — reduces isolation                                                                                                                                                |
| `extraEnv`    | No       | —                        | `{ "KEY": "value" }` — visible to the agent, never use for secrets                                                                                                                                       |

<Note>
  **Why `memoryLimit` matters on constrained hosts.** When the Docker host has no per-container memory limit and `cgroup_disable=memory` is set in the kernel (common on Raspberry Pi), a runaway process inside the sandbox — multiple concurrent `npm install` runs, for example — can exhaust all available RAM. The kernel never gets to invoke the OOM killer, and a hardware watchdog fires a hard reboot instead. Setting `memoryLimit` gives the container a cgroup ceiling so Docker's OOM killer terminates the offending process inside the container, leaving the rest of the system intact.
</Note>

### `agents.<name>.workspaceDir`

Optional. Absolute or relative path for the agent's workspace directory.

* **Default**: `~/.beige/agents/<agentName>/workspace/`
* **Inside sandbox**: Always mounted at `/workspace`

### `agents.<name>.pluginConfigs`

Optional. Per-agent plugin config overrides. Each key must reference a plugin in `config.plugins`. Values are **deep-merged** with the top-level `plugins.<name>.config`.

<Warning>
  **Arrays are replaced, not merged.** The deep-merge recursively merges nested objects, but arrays and primitives from the agent override **replace** the base value entirely.
</Warning>

### `gateway`

| Field     | Default                     | Description                   |
| --------- | --------------------------- | ----------------------------- |
| `host`    | `"127.0.0.1"`               | HTTP API bind address         |
| `port`    | `7433`                      | HTTP API port                 |
| `logFile` | `~/.beige/logs/gateway.log` | Daemon stdout/stderr log file |

***

## Validation at Startup

| Check                                                 | Error if                                    |
| ----------------------------------------------------- | ------------------------------------------- |
| `llm.providers` exists                                | Missing or empty                            |
| `agents` exists                                       | Missing or empty                            |
| Each agent has `model.provider` + `model.model`       | Missing model config                        |
| Agent's `pluginConfigs` keys exist in `plugins`       | Unknown plugin in `pluginConfigs`           |
| Agent's tools resolve to registered plugin tools      | Unknown tool (checked after plugin loading) |
| Agent's skills exist in `skills` or plugin-registered | Unknown skill                               |
| All `${VAR}` references resolve                       | Environment variable not set                |

***

## Minimal Working Config

```json5 theme={null}
{
  llm: {
    providers: {
      anthropic: { apiKey: "${ANTHROPIC_API_KEY}" },
    },
  },
  agents: {
    bot: {
      model: { provider: "anthropic", model: "claude-sonnet-4-6" },
      tools: [],
    },
  },
}
```

This agent has no plugins but can still use the 4 core tools (`read`, `write`, `patch`, `exec`) inside its sandbox.

***

## Host Directory Structure

```
~/.beige/
├── config.json5                   # main config file
├── agents/
│   └── <agent>/
│       ├── workspace/             # mounted as /workspace (rw) in sandbox
│       └── launchers/             # generated launcher scripts → /tools/bin (ro)
├── sessions/
│   ├── session-map.json           # maps session keys → .jsonl file paths
│   ├── session-settings.json      # per-session setting overrides
│   └── <agent>/
│       └── <id>.jsonl             # pi conversation session files
├── sockets/
│   └── <agent>.sock               # Unix socket per agent
├── plugins/                       # installed plugin files
│   ├── github/

│   └── git/
├── packages/                      # intact multi-plugin packages
│   └── matthias-hausberger-beige-toolkit/
├── data/
│   ├── plugin-data.json
│   └── provider-health.json
└── logs/
    ├── audit.jsonl                # append-only audit log
    └── gateway.log                # daemon stdout/stderr
```
