# 功能配置

MCP 服务器、A2A 集成、备用提供商、用户管理、浏览器自动化、热重载、执行策略、审批流程、预算控制、思考模式、文本转语音、Docker 沙箱、画布、自动回复、广播、收件箱、绑定、配对、扩展、密钥库、Webhook 触发器、代理、会话管理和队列管理的配置。

---

### `[[mcp_servers]]`

MCP（模型上下文协议）服务器连接提供外部工具集成。每个条目是 `[[mcp_servers]]` 数组中的一个独立元素。

```toml
[[mcp_servers]]
name = "filesystem"
timeout_secs = 30
env = []

[mcp_servers.transport]
type = "stdio"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/docs"]
```

```toml
[[mcp_servers]]
name = "remote-api"
timeout_secs = 60
env = ["GITHUB_PERSONAL_ACCESS_TOKEN"]

[mcp_servers.transport]
type = "sse"
url = "https://mcp.example.com/sse"
```

```toml
[[mcp_servers]]
name = "my-http-backend"
timeout_secs = 30

[mcp_servers.transport]
type = "http_compat"
base_url = "https://tools.example.com"
headers = [{name = "Authorization", value_env = "MY_API_KEY"}]

[[mcp_servers.transport.tools]]
name = "search"
description = "Search documents"
path = "/search"
method = "post"
```

#### Streamable HTTP

```toml
[[mcp_servers]]
name = "remote-tools"

[mcp_servers.transport.Http]
url = "https://mcp.example.com/v1"
```

使用 Streamable HTTP 传输方式（MCP 规范 2025-03-26+）。与 SSE 不同，这是基于标准 HTTP POST 的更简单的请求/响应模式。

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `name` | string | *必填* | MCP 服务器的显示名称。工具以 `mcp_{name}_{tool}` 的命名空间注册。 |
| `timeout_secs` | u64 | `30` | 请求超时时间（秒）。 |
| `env` | list of strings | `[]` | 传递给子进程的环境变量名称（仅 stdio 传输方式）。 |

**传输方式变体**（基于 `type` 的标记联合体）：

| `type` | 字段 | 说明 |
|--------|------|------|
| `stdio` | `command`（string）、`args`（list of strings，默认 `[]`） | 启动子进程，通过 stdin/stdout 上的 JSON-RPC 通信。 |
| `sse` | `url`（string） | 连接到 HTTP Server-Sent Events 端点。 |
| `Http` | `url`（string） | Streamable HTTP 传输方式（MCP 规范 2025-03-26+）。基于 HTTP POST 的简单请求/响应。 |
| `http_compat` | `base_url`（string）、`headers`（header 配置列表）、`tools`（工具配置列表） | 内置兼容适配器，用于没有原生 MCP 服务器的纯 HTTP/JSON 工具后端。每个工具映射到一个 HTTP 端点。 |

**`http_compat` header 配置：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | HTTP 请求头名称（例如 `"Authorization"`）。 |
| `value` | string 或 null | 静态请求头值。 |
| `value_env` | string 或 null | 用作请求头值的环境变量名称（密钥推荐使用此方式）。 |

**`http_compat` 工具配置：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `name` | string | *必填* | 暴露给 LLM 的工具名称。 |
| `description` | string | `""` | 展示给 LLM 的工具描述。 |
| `path` | string | *必填* | HTTP 路径（例如 `"/search"`）。 |
| `method` | string | `"post"` | HTTP 方法：`get`、`post`、`put`、`patch`、`delete`。 |
| `request_mode` | string | `"json_body"` | 参数发送方式：`json_body`、`query`、`none`。 |
| `response_mode` | string | `"json"` | 响应解析方式：`json`、`text`。 |
| `input_schema` | object | `{"type":"object"}` | 工具输入参数的 JSON Schema。 |

---

### `[a2a]`

Agent 间协议（A2A）配置，实现跨 LibreFang 实例的 Agent 间通信。

```toml
[a2a]
enabled = true
name = "LibreFang Agent OS"
description = "My production agent OS"
listen_path = "/a2a"

[[a2a.external_agents]]
name = "research-agent"
url = "https://agent.example.com/.well-known/agent.json"

[[a2a.external_agents]]
name = "code-reviewer"
url = "https://reviewer.example.com/.well-known/agent.json"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 是否启用 A2A 协议。 |
| `name` | string | `"LibreFang Agent OS"` | 在 well-known Agent 名片中展示的服务级显示名称。 |
| `description` | string | `""` | 在 well-known Agent 名片中展示的服务级描述。 |
| `listen_path` | string | `"/a2a"` | A2A 端点的 URL 路径前缀。 |
| `external_agents` | list of objects | `[]` | 要发现和交互的外部 A2A Agent 列表。 |

**`external_agents` 条目：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | 外部 Agent 的显示名称。 |
| `url` | string | Agent 名片端点 URL（通常为 `/.well-known/agent.json`）。 |

---

### `[[fallback_providers]]`

后备提供商链。当主 LLM 提供商（`[default_model]`）失败时，按顺序尝试这些后备提供商。

```toml
[[fallback_providers]]
provider = "ollama"
model = "llama3.2:latest"
api_key_env = ""
# base_url = "http://localhost:11434"

[[fallback_providers]]
provider = "groq"
model = "llama-3.3-70b-versatile"
api_key_env = "GROQ_API_KEY"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `provider` | string | `""` | 提供商名称（例如 `"ollama"`、`"groq"`、`"openai"`）。 |
| `model` | string | `""` | 该提供商的模型标识符。 |
| `api_key_env` | string | `""` | API Key 的环境变量名称。本地提供商（ollama、vllm、lmstudio）留空。 |
| `base_url` | string 或 null | `null` | 基础 URL 覆盖。为 null 时使用模型目录默认值。 |

---

### `[[users]]`

RBAC 多用户配置。用户可以被分配角色，并绑定到各通道平台的身份标识。

```toml
[[users]]
name = "Alice"
role = "owner"
api_key_hash = "sha256_hash_of_api_key"

[users.channel_bindings]
telegram = "123456"
discord = "987654321"
slack = "U0ABCDEFG"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `name` | string | *必填* | 用户显示名称。 |
| `role` | string | `"user"` | 用户在 RBAC 层级中的角色。 |
| `channel_bindings` | map of string to string | `{}` | 将通道平台名称映射到平台特定用户 ID，实现跨通道的用户身份绑定。 |
| `api_key_hash` | string 或 null | `null` | 用户个人 API Key 的 SHA256 哈希值，用于认证 API 访问。 |

**角色层级**（从最高到最低权限）：

| 角色 | 说明 |
|------|------|
| `owner` | 完全管理权限。可以管理所有 Agent、用户和配置。 |
| `admin` | 可以管理 Agent 和大多数设置。无法修改 owner 账户。 |
| `user` | 可以与 Agent 交互。管理能力有限。 |
| `viewer` | 只读访问。可以查看 Agent 回复，但无法发送消息。 |

---


### `[browser]`

配置 Agent 工具 `browser_*` 使用的无头浏览器自动化引擎。

```toml
[browser]
enabled = true
headless = true
viewport_width = 1280
viewport_height = 720
timeout_secs = 30
idle_timeout_secs = 300
max_sessions = 5
# chromium_path = "/usr/bin/chromium"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `true` | 启用内置 CDP 浏览器工具。设为 `false` 关闭所有 `browser_*` 工具。 |
| `headless` | bool | `true` | 以无头模式运行浏览器（不显示窗口）。 |
| `viewport_width` | u32 | `1280` | 浏览器视口宽度（像素）。 |
| `viewport_height` | u32 | `720` | 浏览器视口高度（像素）。 |
| `timeout_secs` | u64 | `30` | 每个操作的超时时间（秒）。 |
| `idle_timeout_secs` | u64 | `300` | 浏览器会话闲置超过此秒数后自动关闭。 |
| `max_sessions` | usize | `5` | 最大并发浏览器会话数。 |
| `chromium_path` | string 或 null | `null` | Chromium/Chrome 二进制文件路径。为 null 时自动检测。 |

---

### `[reload]`

控制配置文件的自动监控和热重载。

```toml
[reload]
mode = "hybrid"
debounce_ms = 500
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `mode` | string | `"hybrid"` | 重载模式。见下表。 |
| `debounce_ms` | u64 | `500` | 检测到文件变更后，重载前的防抖窗口时长（毫秒）。 |

**`mode` 值说明：**

| 值 | 说明 |
|----|------|
| `off` | 不自动重载。更改需手动重启。 |
| `restart` | 任何配置变更都进行完整守护进程重启。 |
| `hot` | 仅对安全的部分进行热重载（通道、技能、心跳）。 |
| `hybrid` | 尽可能热重载；对需要重启的部分标记提示（默认）。 |

**可热重载的配置段（无需重启）：**

以下配置段在 daemon 运行时修改 `config.toml` 后会自动生效（每 30 秒轮询检测）：

- `[channels]` — 添加、删除或重新配置渠道适配器
- `[[skills]]` — 技能注册表
- `[proxy]` — HTTP/HTTPS/SOCKS5 代理设置
- `[browser]` — 浏览器自动化设置
- `[web]` — 网页搜索/抓取配置
- `[approval]` — 审批策略
- `[cron]` — 定时任务设置
- `[webhook_triggers]` — Webhook 触发器
- `[extensions]` — 扩展配置
- `[[mcp_servers]]` — MCP 服务器连接
- `[a2a]` — Agent-to-Agent 协议配置
- `[fallback_providers]` — 备用提供商链
- `provider_urls` — 提供商 URL 覆盖
- `default_model` — 默认模型选择
- `tool_policy` — 工具过滤规则
- `proactive_memory` — 主动记忆阈值
- `provider_api_keys` — 提供商 API key（会刷新驱动缓存）
- `usage_footer` — 使用量页脚模式
- `sanitize` — 输入清理规则

**需要重启的配置段：** `home_dir`、`data_dir`、`api_listen`、`tls`、`telemetry`。这些字段的变更会记录警告日志，但只在重启后生效。

---

### `[exec_policy]`

控制 Agent 通过 `exec` 和 `shell` 工具允许执行的 Shell 命令。

```toml
[exec_policy]
mode = "allowlist"
allowed_commands = ["git", "python3", "node"]
timeout_secs = 30
max_output_bytes = 102400
no_output_timeout_secs = 30
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `mode` | string | `"allowlist"` | 安全模式。见下表。 |
| `safe_bins` | list of strings | `["sleep","true","false","cat","sort","uniq","cut","tr","head","tail","wc","date","echo","printf","basename","dirname","pwd","env"]` | 始终绕过白名单检查的命令（仅标准输入的 POSIX 工具）。 |
| `allowed_commands` | list of strings | `[]` | 当 `mode = "allowlist"` 时额外允许的命令。 |
| `timeout_secs` | u64 | `30` | 每条命令的最大挂钟执行时间（秒）。 |
| `max_output_bytes` | usize | `102400` | stdout+stderr 合并输出的最大大小（字节）。默认 100 KB。 |
| `no_output_timeout_secs` | u64 | `30` | 进程在此秒数内无输出则被终止。`0` = 禁用。 |

**`mode` 值说明：**

| 值 | 别名 | 说明 |
|----|------|------|
| `deny` | `none`、`disabled` | 阻止所有 Shell 执行。 |
| `allowlist` | `restricted` | 仅允许 `safe_bins` 或 `allowed_commands` 中的命令（默认）。 |
| `full` | `allow`、`all`、`unrestricted` | 允许所有命令。不安全——仅限开发使用。 |

---

### `[approval]`

配置哪些工具在执行前需要明确的人工批准。引用 `ApprovalPolicy` 类型。

```toml
[approval]
require_approval = ["shell_exec"]
timeout_secs = 60
auto_approve_autonomous = false
auto_approve = false
second_factor = "none"
totp_issuer = "LibreFang"
totp_grace_period_secs = 300
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `require_approval` | list of strings | `["shell_exec"]` | 需要暂停执行并等待人工批准的工具名称列表。 |
| `timeout_secs` | u64 | `60` | 审批请求的超时时间（秒）。 |
| `auto_approve_autonomous` | bool | `false` | Agent 处于自主模式时自动批准工具执行。 |
| `auto_approve` | bool | `false` | 自动批准所有工具执行（不安全，仅限开发使用）。 |
| `second_factor` | string | `"none"` | 二次验证方式：`"none"` 或 `"totp"`。设为 `"totp"` 时，审批操作需要输入验证器应用的 6 位 TOTP 码。 |
| `totp_issuer` | string | `"LibreFang"` | 注册时显示在验证器应用中的发行者名称。 |
| `totp_grace_period_secs` | u64 | `300` | 成功验证 TOTP 后，在此时间窗口内跳过重复验证。设为 `0` 表示每次都要求输入验证码。最大值：`3600`。 |
| `totp_tools` | list of strings | `[]` | 需要 TOTP 验证的工具（支持 glob 模式）。为空时 `require_approval` 中的所有工具都需要 TOTP。示例：`["shell_exec"]`。 |

#### TOTP 设置

当 `second_factor = "totp"` 时，需要先注册验证器应用：

1. **生成密钥：** `POST /api/approvals/totp/setup` — 返回 base32 密钥、`otpauth://` URI、二维码（base64 PNG）和 8 个恢复码。
2. **添加到验证器：** 扫描二维码或在 Google Authenticator、1Password、Authy 等应用中手动输入密钥。
3. **保存恢复码：** 妥善保存 8 个恢复码——丢失验证器设备时可用恢复码代替 TOTP 码，每个恢复码只能使用一次。
4. **确认注册：** `POST /api/approvals/totp/confirm`，body 为 `{"code": "123456"}` — 验证应用生成的一次性密码。
5. **启用强制验证：** 在配置中设置 `second_factor = "totp"`（支持热重载）。

也可以在 Dashboard 的 **设置 > 安全** 中完成 TOTP 设置。

启用后，审批流程变更：
- **Dashboard：** 点击"批准"时会弹出 6 位验证码输入框。
- **频道（Telegram/Slack）：** 使用 `/approve <id> <6位验证码>` 代替 `/approve <id>`。
- **API：** 在 `POST /api/approvals/{id}/approve` 的 body 中发送 `{"totp_code": "123456"}`。
- **恢复码：** 可用恢复码（格式：`xxxx-xxxx`）代替 TOTP 码。每个恢复码使用后即失效。

撤销 TOTP：使用 `DELETE /api/approvals/totp`（body: `{"code": "..."}`）或在 Dashboard 中操作。重置需要验证当前 TOTP 或恢复码。

**频率限制：** 连续 5 次 TOTP 验证失败后锁定 5 分钟。

TOTP 密钥存储在加密保管库（`~/.librefang/vault.enc`）中，使用 AES-256-GCM 加密。

---

### `[budget]`

设置 LLM API 费用的全局支出限制。所有限制默认为 `0.0`（无限制）。

```toml
[budget]
max_hourly_usd = 1.00
max_daily_usd = 10.00
max_monthly_usd = 50.00
alert_threshold = 0.8
default_max_llm_tokens_per_hour = 0
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `max_hourly_usd` | f64 | `0.0` | 所有 Agent 每小时的最大 LLM 费用（美元）。`0.0` = 无限制。 |
| `max_daily_usd` | f64 | `0.0` | 所有 Agent 每天的最大 LLM 费用（美元）。`0.0` = 无限制。 |
| `max_monthly_usd` | f64 | `0.0` | 所有 Agent 每月的最大 LLM 费用（美元）。`0.0` = 无限制。 |
| `alert_threshold` | f64 | `0.8` | 各限额的告警阈值（0.0-1.0 的比例）。设为 0.8 时，达到限额 80% 即记录告警日志。 |
| `default_max_llm_tokens_per_hour` | u64 | `0` | 全局覆盖每个 Agent 的每小时 Token 预算。大于 `0` 时覆盖所有 Agent 自身的 Token 限制。`0` = 保持各 Agent 自身的限制。 |

#### 按提供商限额 (`[budget.providers.<id>]`)

当你同时使用免费的本地提供商（如 `litellm`、`ollama`）与付费提供商（如 `moonshot`、`openai`）时，可以只给付费方设置花销上限，而不影响免费方。提供商 ID 必须与 Agent `[model]` 中的 `provider` 字段一致。字段缺省或为 0 表示无限制。

```toml
[budget.providers.moonshot]
max_cost_per_day_usd = 2.0
max_tokens_per_hour = 500000

[budget.providers.openai]
max_cost_per_hour_usd = 1.0
max_cost_per_month_usd = 50.0

[budget.providers.litellm]
# 省略或全部为 0 = 无限制
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `max_cost_per_hour_usd` | f64 | `0.0` | 该提供商每小时费用上限。`0.0` = 无限制。 |
| `max_cost_per_day_usd` | f64 | `0.0` | 该提供商每天费用上限。`0.0` = 无限制。 |
| `max_cost_per_month_usd` | f64 | `0.0` | 该提供商每月费用上限。`0.0` = 无限制。 |
| `max_tokens_per_hour` | u64 | `0` | 该提供商每小时 Token 上限（输入+输出）。`0` = 无限制。 |

命中按提供商的上限时，调用将以 `QuotaExceeded` 错误返回，错误信息中包含提供商名；其他提供商的用量不受影响。

---

### `[thinking]`

配置支持扩展思维（思维链推理）的模型（例如启用了 `thinking` 模式的 Claude 3.7 Sonnet）。

```toml
[thinking]
budget_tokens = 10000
stream_thinking = false
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `budget_tokens` | u32 | `10000` | 分配给思维/推理阶段的最大 Token 数。 |
| `stream_thinking` | bool | `false` | 是否将思维 Token 流式传输给客户端（在 API 响应流中可见）。 |

---

### `[tts]`

配置语音合成（Text-to-Speech）功能。

```toml
[tts]
enabled = false
provider = "openai"          # openai | elevenlabs | google_tts
max_text_length = 4096
timeout_secs = 30

[tts.openai]
voice = "alloy"
model = "tts-1"
format = "mp3"
speed = 1.0

[tts.elevenlabs]
voice_id = "21m00Tcm4TlvDq8ikWAM"
model_id = "eleven_monolingual_v1"
stability = 0.5
similarity_boost = 0.75

[tts.google]
voice = "en-US-Standard-F"
language_code = "en-US"
speaking_rate = 1.0
pitch = 0.0
format = "mp3"
```

**`[tts]` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用 TTS 合成。 |
| `provider` | string 或 null | `null` | 默认 TTS 提供商：`"openai"`、`"elevenlabs"` 或 `"google_tts"`。 |
| `max_text_length` | usize | `4096` | 单次 TTS 请求的最大文本长度（字符数）。 |
| `timeout_secs` | u64 | `30` | 每次 TTS 调用的请求超时时间（秒）。 |

**`[tts.openai]` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `voice` | string | `"alloy"` | 语音名称。可选：`alloy`、`echo`、`fable`、`onyx`、`nova`、`shimmer`。 |
| `model` | string | `"tts-1"` | TTS 模型：`"tts-1"`（快速）或 `"tts-1-hd"`（高质量）。 |
| `format` | string | `"mp3"` | 输出格式：`mp3`、`opus`、`aac`、`flac`。 |
| `speed` | f32 | `1.0` | 语速倍率（0.25 到 4.0）。 |

**`[tts.elevenlabs]` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `voice_id` | string | `"21m00Tcm4TlvDq8ikWAM"` | ElevenLabs 语音 ID（默认：Rachel）。 |
| `model_id` | string | `"eleven_monolingual_v1"` | ElevenLabs 模型 ID。 |
| `stability` | f32 | `0.5` | 语音稳定性（0.0-1.0）。越高越稳定，但表现力越低。 |
| `similarity_boost` | f32 | `0.75` | 语音相似度增强（0.0-1.0）。 |

**`[tts.google]` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `voice` | string | `"en-US-Standard-F"` | Google TTS 语音名称（如 `en-US-Standard-F`、`pl-PL-Wavenet-A`）。 |
| `language_code` | string | `"en-US"` | BCP-47 语言代码（如 `en-US`、`pl-PL`）。 |
| `speaking_rate` | f32 | `1.0` | 语速倍率（0.25 到 4.0）。 |
| `pitch` | f32 | `0.0` | 音高调整（半音，-20.0 到 20.0）。 |
| `format` | string | `"mp3"` | 输出格式：`mp3`、`opus`、`wav`。 |

需要设置 `GOOGLE_API_KEY` 或 `GOOGLE_CLOUD_API_KEY` 环境变量。

---

### `[docker]`

配置用于隔离代码执行的 Docker 容器沙箱。

```toml
[docker]
enabled = false
image = "python:3.12-slim"
container_prefix = "librefang-sandbox"
workdir = "/workspace"
network = "none"
memory_limit = "512m"
cpu_limit = 1.0
timeout_secs = 60
read_only_root = true
mode = "off"
scope = "session"
reuse_cool_secs = 300
idle_timeout_secs = 86400
max_age_secs = 604800
blocked_mounts = []
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用 Docker 沙箱用于代码执行。 |
| `image` | string | `"python:3.12-slim"` | 沙箱容器使用的 Docker 镜像。 |
| `container_prefix` | string | `"librefang-sandbox"` | 容器名称前缀。 |
| `workdir` | string | `"/workspace"` | 容器内的工作目录。 |
| `network` | string | `"none"` | 网络模式：`"none"`（隔离）、`"bridge"` 或自定义网络名称。 |
| `memory_limit` | string | `"512m"` | 内存限制（例如 `"256m"`、`"1g"`）。 |
| `cpu_limit` | f64 | `1.0` | CPU 限制（例如 `0.5`、`1.0`、`2.0`）。 |
| `timeout_secs` | u64 | `60` | 每条命令的最大执行时间（秒）。 |
| `read_only_root` | bool | `true` | 将根文件系统挂载为只读。 |
| `mode` | string | `"off"` | 激活模式。见下表。 |
| `scope` | string | `"session"` | 容器生命周期范围。见下表。 |
| `reuse_cool_secs` | u64 | `300` | 释放的容器在此秒数冷却后才可重用。 |
| `idle_timeout_secs` | u64 | `86400` | 容器闲置超过此秒数后被销毁（默认 24 小时）。 |
| `max_age_secs` | u64 | `604800` | 容器最大存活时间，超时后强制销毁（默认 7 天）。 |
| `blocked_mounts` | list of strings | `[]` | 禁止绑定挂载到容器的宿主机路径。 |
| `cap_add` | list of strings | `[]` | 添加到容器的 Linux 能力（例如 `["NET_ADMIN"]`）。请谨慎使用。 |
| `tmpfs` | list of strings | `["/tmp:size=64m"]` | 容器内的 tmpfs 挂载。每个条目格式为 `"path:options"`（例如 `"/tmp:size=128m"`）。 |
| `pids_limit` | u32 | `100` | 容器内的最大进程数。防止 Fork 炸弹。 |

**`mode` 值说明：**

| 值 | 说明 |
|----|------|
| `off` | 禁用 Docker 沙箱（默认）。 |
| `non_main` | 仅对非主（子）Agent 使用 Docker。 |
| `all` | 对所有 Agent 使用 Docker。 |

**`scope` 值说明：**

| 值 | 说明 |
|----|------|
| `session` | 每个会话一个容器，会话结束时销毁（默认）。 |
| `agent` | 每个 Agent 一个容器，跨会话重用。 |
| `shared` | 所有 Agent 共享容器池。 |

---

### `[canvas]`

配置 Canvas（Agent 到 UI）工具，允许 Agent 在仪表盘中渲染 HTML。

```toml
[canvas]
enabled = false
max_html_bytes = 524288
allowed_tags = []
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用 Canvas 工具。 |
| `max_html_bytes` | usize | `524288` | HTML 负载的最大大小（字节）。默认 512 KB。 |
| `allowed_tags` | list of strings | `[]` | 用于净化的允许 HTML 标签名称。空列表 = 允许所有安全标签。 |

---

### `[auto_reply]`

配置后台自动回复引擎，可以在无需人工交互的情况下自动回复传入消息。

```toml
[auto_reply]
enabled = false
max_concurrent = 3
timeout_secs = 120
suppress_patterns = ["/stop", "/pause"]
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用自动回复引擎。 |
| `max_concurrent` | usize | `3` | 最大并发自动回复任务数。 |
| `timeout_secs` | u64 | `120` | 每个自动回复任务的默认超时时间（秒）。 |
| `suppress_patterns` | list of strings | `["/stop", "/pause"]` | 抑制自动回复的传入消息匹配模式。 |

---

### `[broadcast]`

配置消息广播，将单条传入消息同时路由到多个 Agent。

```toml
[broadcast]
strategy = "parallel"
routes = { "announcement-channel" = ["agent-a", "agent-b", "agent-c"] }
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `strategy` | string | `"parallel"` | 投递策略。`"parallel"` = 同时发送给所有 Agent；`"sequential"` = 按顺序逐个发送。 |
| `routes` | map of string to list of strings | `{}` | 将对等方/通道标识符映射到接收消息的 Agent 名称列表。 |

---

### `[inbox]`

基于文件的异步外部命令输入收件箱。将文本文件放入监控目录后，文件内容会作为消息分发给 Agent。已处理的文件会被移动到 `processed/` 子目录以避免重复投递。

```toml
[inbox]
enabled = true
directory = "~/.librefang/inbox/"
poll_interval_secs = 5
default_agent = "assistant"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用收件箱目录监控。 |
| `directory` | string 或 null | `null` | 监控的目录。默认为 `$HOME_DIR/inbox/`。支持 `~` 展开。 |
| `poll_interval_secs` | u64 | `5` | 扫描目录新文件的间隔（秒）。最小值 1。 |
| `default_agent` | string 或 null | `null` | 文件中未找到 `agent:` 指令时路由到的 Agent 名称。 |

**文件格式：** 纯文本文件（`.txt`、`.md`、`.json`、`.py` 等）。第一行可以包含 `agent:<name>` 指令以指定目标 Agent；其余部分作为消息正文发送。没有指令的文件使用 `default_agent`。

**安全限制：** 大于 1 MB 的文件会被跳过。二进制文件（非文本扩展名）会被跳过。空文件会被移动到 `processed/` 但不发送。

**使用示例：**

指定目标 Agent：

```bash
cat > ~/.librefang/inbox/task.txt << 'EOF'
agent:code-reviewer
Please review this code for security issues:

def login(user, password):
    query = f"SELECT * FROM users WHERE name='{user}' AND pass='{password}'"
    return db.execute(query)
EOF
```

发送到默认 Agent：

```bash
echo "Summarize today's system logs" > ~/.librefang/inbox/summarize.txt
```

定时任务：

```bash
# crontab -e
0 9 * * * grep ERROR /var/log/app.log > ~/.librefang/inbox/daily_errors.txt
```

CI/CD 构建后处理：

```bash
echo "agent:devops
Build failed, please analyze:
$(tail -100 build.log)" > ~/.librefang/inbox/build_$(date +%s).txt
```

批量处理：

```bash
for doc in ~/reports/*.md; do
  cp "$doc" ~/.librefang/inbox/
done
```

检查收件箱状态：

```bash
curl -s http://127.0.0.1:4545/api/inbox/status
# {"enabled":true,"pending_count":3,"processed_count":12,...}
```

---

### `[[bindings]]`

Agent 绑定将特定的通道/账号/对等方组合路由到特定的 Agent。更具体的绑定（非空字段越多）优先级越高。

```toml
[[bindings]]
agent = "support-agent"
[bindings.match_rule]
channel = "telegram"
guild_id = "123456"

[[bindings]]
agent = "vip-agent"
[bindings.match_rule]
channel = "discord"
peer_id = "987654321"
roles = ["premium"]
```

**顶层字段：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `agent` | string | 匹配的消息路由到的目标 Agent 名称或 ID。 |
| `match_rule` | object | 匹配条件。所有指定的（非空）字段必须全部匹配。 |

**`match_rule` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `channel` | string 或 null | `null` | 要匹配的通道类型（例如 `"discord"`、`"telegram"`、`"slack"`）。 |
| `account_id` | string 或 null | `null` | 通道内特定的 Bot 账号 ID（用于多 Bot 场景）。 |
| `peer_id` | string 或 null | `null` | 用于私聊路由的用户/对等方 ID。 |
| `guild_id` | string 或 null | `null` | 服务器/Guild ID（Discord/Slack）。 |
| `roles` | list of strings | `[]` | 基于角色的路由；用户必须拥有其中至少一个角色。 |

**具体度评分**（分值越高越先匹配）：`peer_id`（+8）> `guild_id`（+4）> `roles`（+2）= `account_id`（+2）> `channel`（+1）。

---

### `[pairing]`

配置 LibreFang 移动端伴侣应用的设备配对和推送通知。

```toml
[pairing]
enabled = false
max_devices = 10
token_expiry_secs = 300
push_provider = "ntfy"
ntfy_url = "https://ntfy.sh"
ntfy_topic = "my-librefang-notifications"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用设备配对。 |
| `max_devices` | usize | `10` | 最大配对设备数。 |
| `token_expiry_secs` | u64 | `300` | 配对令牌有效期（秒）。默认 5 分钟。 |
| `push_provider` | string | `"none"` | 推送通知提供商：`"none"`、`"ntfy"` 或 `"gotify"`。 |
| `ntfy_url` | string 或 null | `null` | ntfy 服务器 URL（当 `push_provider = "ntfy"` 时使用）。 |
| `ntfy_topic` | string 或 null | `null` | 推送通知的 ntfy 主题。 |

---

### `[extensions]`

配置 MCP 服务器的重连行为和健康监控。

```toml
[extensions]
auto_reconnect = true
reconnect_max_attempts = 10
reconnect_max_backoff_secs = 300
health_check_interval_secs = 60
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `auto_reconnect` | bool | `true` | MCP 服务器断开连接时自动重连。 |
| `reconnect_max_attempts` | u32 | `10` | 放弃前的最大重连尝试次数。 |
| `reconnect_max_backoff_secs` | u64 | `300` | 重连尝试之间的最大退避时间（秒）。 |
| `health_check_interval_secs` | u64 | `60` | 已连接扩展的健康检查间隔（秒）。 |

---

### `[vault]`

配置用于存储敏感密钥的加密凭据库。

```toml
[vault]
enabled = true
# path = "~/.librefang/vault.enc"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `true` | 启用凭据库。如果 `vault.enc` 已存在则自动检测。 |
| `path` | path 或 null | `null` | 自定义凭据库文件路径。默认为 `~/.librefang/vault.enc`。 |

---

### `[webhook_triggers]`

允许外部系统通过经过认证的 HTTP Webhook 在 `/hooks/wake` 和 `/hooks/agent` 端点触发 Agent 操作。

```toml
[webhook_triggers]
enabled = true
token_env = "LIBREFANG_WEBHOOK_TOKEN"
max_payload_bytes = 65536
rate_limit_per_minute = 30
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 启用 Webhook 触发器端点。 |
| `token_env` | string | `"LIBREFANG_WEBHOOK_TOKEN"` | 存放 Bearer 令牌的环境变量名称（不是令牌本身）。令牌长度必须大于等于 32 个字符。`enabled = true` 时必填。 |
| `max_payload_bytes` | usize | `65536` | 入站负载的最大大小（字节）。默认 64 KB。 |
| `rate_limit_per_minute` | u32 | `30` | 每个来源 IP 每分钟的最大 Webhook 请求数。 |

---

### `[proxy]`

配置所有出站连接（LLM API、网页搜索、MCP 服务器等）使用的 HTTP 代理。环境变量 `HTTP_PROXY`、`HTTPS_PROXY` 和 `NO_PROXY` 也作为后备选项被识别。

```toml
[proxy]
http_proxy = "http://proxy.corp.example:8080"
https_proxy = "http://proxy.corp.example:8080"
no_proxy = "localhost,127.0.0.1,.internal.corp"
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `http_proxy` | string 或 null | `null` | HTTP 代理 URL。回退到 `HTTP_PROXY` / `http_proxy` 环境变量。URL 中的凭据在日志中会被脱敏。 |
| `https_proxy` | string 或 null | `null` | HTTPS 代理 URL。回退到 `HTTPS_PROXY` / `https_proxy` 环境变量。 |
| `no_proxy` | string 或 null | `null` | 绕过代理的主机/域名逗号分隔列表。回退到 `NO_PROXY` / `no_proxy` 环境变量。 |

---



### `[session]`

配置空闲或多余会话的自动清理。

```toml
[session]
retention_days = 30
max_sessions_per_agent = 100
cleanup_interval_hours = 24
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `retention_days` | u32 | `0` | 空闲会话在自动清理前的最大保留天数。`0` = 无限制。 |
| `max_sessions_per_agent` | u32 | `0` | 每个 Agent 的最大会话数（最旧的优先清理）。`0` = 无限制。 |
| `cleanup_interval_hours` | u32 | `24` | 后台清理任务的运行间隔（小时）。 |

---

### `[queue]`

配置 Agent 命令队列，包括深度限制、TTL 和分通道并发度。

```toml
[queue]
max_depth_per_agent = 100
max_depth_global = 1000
task_ttl_secs = 3600

[queue.concurrency]
main_lane = 3
cron_lane = 2
subagent_lane = 3
```

**`[queue]` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `max_depth_per_agent` | u32 | `0` | 每个 Agent 的最大排队任务数。队列满时新任务被拒绝。`0` = 无限制。 |
| `max_depth_global` | u32 | `0` | 所有 Agent 的最大排队任务总数。`0` = 无限制。 |
| `task_ttl_secs` | u64 | `3600` | 未处理的任务在此秒数后过期。`0` = 无限制。 |

**`[queue.concurrency]` 字段：**

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `main_lane` | usize | `3` | 并发用户消息任务数。 |
| `cron_lane` | usize | `2` | 并发定时任务数。 |
| `subagent_lane` | usize | `3` | 并发子 Agent 调用任务数。 |

---

### `[tool_budget]`

**源码：** `librefang-runtime/src/tool_budget.rs`

工具预算执行器限制单次 agent 轮次中工具调用返回的数据大小，防止意外的大体积工具输出填满上下文窗口并推高 token 成本。

#### 工作原理

每个工具结果在放入上下文之前都要经过三层大小检查：

| 层级 | 阈值 | 行为 |
|---|---|---|
| **内联** | ≤ 50 KB | 结果直接嵌入上下文。 |
| **溢出** | 50 KB – 200 KB | 结果写入 `/tmp/librefang-results/` 下的临时文件，并在上下文中用包含溢出路径和字节数的简短摘要替换。 |
| **截断** | > 200 KB | 仅保留前 200 KB，剩余内容静默丢弃，并输出包含工具名和原始大小的 `WARN` 日志。 |

#### 溢出文件命名

溢出文件命名为 `<agent_id>_<tool_call_id>_<timestamp>.txt`，写入 `/tmp/librefang-results/`。轮次之间不自动清理；守护进程重启时清除该目录。

Agent 可在后续轮次中读取溢出文件——注入上下文的摘要中包含完整路径。

#### 配置

当前版本不支持按 agent 配置工具预算。50 KB 和 200 KB 阈值在编译时固定。

#### 为什么是这两个限制？

50 KB 内联文本约合 12 500 个 token——已是大多数模型上下文窗口的相当大一部分。超过此限制后，结果对 agent 的边际价值递减，而提示词成本线性增加。200 KB 硬上限防止单次失控工具调用耗尽整个上下文窗口。

---

### `[context_compression]`

上下文压缩可在 Agent 上下文窗口的 token 用量增长过大时自动缩减，防止达到硬性上下文限制而出错，无需手动管理会话。

#### 工作原理

在即将发送 LLM 调用时，`ContextEngine` 会估算已组装上下文（系统提示 + 会话历史 + 工具 schema）的 token 数。若用量超过**模型上下文窗口的 80%**，引擎会在发送请求前触发一次压缩。

压缩自动发生——无需任何配置即可启用。`[context_compression]` 章节为未来可调参数预留；当前所有阈值均在内部固定。

#### 三层保护

| 层级 | 触发条件 | 机制 |
|------|---------|------|
| **LLM 摘要压缩** | ≥ 上下文窗口的 80% | 内部 LLM 调用将会话历史中最早的部分压缩为紧凑摘要消息，并注入回历史中替换原始轮次。 |
| **强制截断** | 摘要后仍超出限制 | 直接删除最旧的非系统消息，直到上下文适合窗口。仅在摘要本身体积过大无法解决问题时应用。 |
| **上下文守护** | 最终安全兜底 | 硬编码上限，确保构建的提示词永远不超过模型声明的最大值。超出的 token 被截断，并在 `ERROR` 级别记录警告。 |

#### 摘要保留与迭代精炼

摘要消息以带有内部特殊标签的普通 `assistant` 轮次存入会话历史。后续压缩时，现有摘要会被纳入待重新摘要的内容，而非原样保留。这意味着长时间运行的会话会经历迭代精炼——较旧的摘要会被折叠进更新、更紧凑的摘要中。

压缩器 system prompt 现在指示 LLM **用对话中用户在用的语言写摘要**。中文对话产出中文摘要；阿拉伯语对话产出阿语摘要。这条指令同时作用于单次的 `summarize_messages` 路径和 `summarize_in_chunks` 的合并步骤，分块压缩也覆盖到 — 长的非英文 session 不再夹带意外的英文摘要。

#### 可插拔 `ContextEngine`

压缩算法实现于 `ContextEngine` trait 之后。当前实现使用基于 LLM 的摘要器。LibreFang 未来版本将支持配置替代压缩算法——包括基于 DAG 的压缩和 LCM（Latent Context Modeling）——等实现稳定后开放配置。

#### 无需配置

上下文压缩对所有 Agent 始终启用，当前在 `config.toml` 中没有任何开关或可调参数。80% 阈值、强制截断回退和上下文守护上限均由运行时自动执行。

---

### Cron 调度器

按 agent 的定时任务（interval、一次性、或 5 字段 cron 表达式）触发 agent 回合、system event 或 workflow 运行。调度器支持多目标分发带失败隔离、pre-script 把数据注入 LLM prompt，以及 silent marker 在运行时抑制分发。

完整 schema、扇出目标变体（channel / webhook / local file / email）、Webhook URL 的 SSRF 防护、pre-script 的 `<home_dir>/scripts/` 路径白名单、以及 wake-gate vs pre-script 的取舍，见 [Cron 调度器](/zh/configuration/features/cron)。

---

### 可观测性 — Tempo + 业务 span

LibreFang 自带可选的可观测性栈，一条 `docker compose` 起栈。捕获 HTTP 请求**和** LibreFang 自己的工作 — agent 回合、tool 调用、channel 发送、cron 触发 — 作为可搜索的 Tempo trace。

**栈组件**（全部捆绑进二进制，不需要外部下载）：

- `librefang-otel-collector` — `:4317` 上的 OTLP/gRPC 收集器。daemon 把 span 导出到这。
- `librefang-tempo` — 单二进制 Grafana Tempo，本地文件系统存储，24 小时保留。内部 `:4317` 接收，查询 API 在 `:3200`。
- `librefang-grafana` — 预配置的 Grafana，Tempo 数据源已接好。

**自动启动是 opt-in 的。** 可观测性栈**不**会跟着 `librefang start` 自动起 —— 想让 daemon 帮你管理生命周期就在 `config.toml` 设 `[telemetry] auto_start = true`。否则用 `librefang observability up` / `down` 显式管理。捆绑的容器按 `home_dir` 加 Docker label，同一台机器上多个 LibreFang 安装不会抢同名容器；拆栈用 RAII 风格清理，daemon 异常退出时也能回收。

**起栈：**

```bash
librefang observability up      # 起捆绑的 compose 栈
librefang observability status  # 各容器健康检查
librefang observability down    # 拆栈
```

**配置 daemon 导出到那里：**

```toml
[telemetry]
otlp_endpoint = "http://localhost:4317"
service_name = "librefang"
sample_rate = 1.0           # 0.0–1.0；高量生产环境降低
prometheus_enabled = true   # 同时暴露 /api/metrics
```

**Trace 搜索：** 在 `http://localhost:3000` 打开 Grafana，把 Explore tab 切到 Tempo 数据源，按 trace ID、span 名、或属性搜。业务级 span 包括 `agent.turn`、`tool.call`、`channel.send`、`cron.fire`、`provider.request`，每个带 agent id、channel 名、model、结果作为可搜索属性。

**`cache_hit_ratio` 指标：** runtime 给每个 `agent.turn` span 计算

```
cache_hit_ratio = cache_read / (cache_read + cache_creation)   # 取值 [0.0, 1.0]
```

`Some(1.0)` 是完美前缀缓存命中；`Some(0.0)` 是 cold start，缓存激活但没命中；`None` 是 run 完全没启用缓存。出现在 trajectory 导出（`metadata.cache_hit_ratio`）和 Grafana per-agent 面板。

---

