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

# 环境变量

> FIM One 的完整配置参考。

所有配置都通过 `.env` 完成。复制 `example.env` 并填入你的值：

```bash theme={null}
cp example.env .env
```

## 配置级别

每个集成都有一个配置级别，表示其重要性：

| 级别     | 含义      | 未配置时的行为                 |
| ------ | ------- | ----------------------- |
| **必需** | 核心系统依赖  | 系统将出错 — 聊天和主要功能将无法工作    |
| **推荐** | 重要功能启用器 | 优雅降级 — 该功能明显不可用，但系统继续运行 |
| **可选** | 增强功能    | 透明降级 — 系统运行正常，该功能不存在    |

> **注意**：管理员配置的模型（管理员 → 模型页面）可以替代 LLM 环境变量。健康检查会考虑两个来源。

***

## 前端（仅本地开发）

前端有一个仅用于本地开发的独立环境文件：`frontend/.env.local`。

> **此文件在 Docker 中不使用。** 在 Docker 容器内，Next.js 在内部将 `/api/*` 代理到 Python 后端（端口 8000 是容器内部的），因此不需要前端环境文件。

对于本地开发，默认设置开箱即用 — 除非你的后端运行在非默认端口，否则**不需要**创建 `frontend/.env.local`。

如果需要覆盖，请手动创建 `frontend/.env.local`：

```bash theme={null}
echo 'NEXT_PUBLIC_API_URL=http://localhost:9000' > frontend/.env.local
```

| 变量                    | 默认值                            | 描述                                                                                                |
| --------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_API_URL` | `http://localhost:8000` *（自动）* | **浏览器**用于直接 API 调用（OAuth 重定向、流式传输）的后端 URL。如果未设置，则从 `window.location` 自动检测 — 仅当后端在本地运行于非标准端口时才需覆盖。 |

> **构建时注意**：`NEXT_PUBLIC_*` 变量在 `pnpm build` 时被烘焙到 JS 包中。在运行时更改它们（例如通过根目录 `.env`）无效 — 这就是为什么它们仅存在于本地开发的 `frontend/.env.local` 中。

## LLM（必需）

| 变量                                | 必需    | 默认值                                   | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| --------------------------------- | ----- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `LLM_API_KEY`                     | **是** | —                                     | LLM 提供商的 API 密钥                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `LLM_BASE_URL`                    | 否     | `https://api.openai.com/v1`           | 任何 OpenAI 兼容 API 的基础 URL                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `LLM_MODEL`                       | 否     | `gpt-4o`                              | 主模型 — 用于规划、分析和 ReAct 智能体                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `FAST_LLM_MODEL`                  | 否     | *（回退到 `LLM_MODEL`）*                   | 快速模型 — 用于 DAG 步骤执行（更便宜、更快）                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `LLM_TEMPERATURE`                 | 否     | `0.7`                                 | 默认采样温度                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `LLM_CONTEXT_SIZE`                | 否     | `128000`                              | 主 LLM 的上下文窗口大小                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `LLM_MAX_OUTPUT_TOKENS`           | 否     | `64000`                               | 主 LLM 每次调用的最大输出 token 数                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `FAST_LLM_API_KEY`                | 否     | *（回退到 `LLM_API_KEY`）*                 | 快速模型提供商的 API 密钥。当快速模型由不同的提供商托管时使用                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `FAST_LLM_BASE_URL`               | 否     | *（回退到 `LLM_BASE_URL`）*                | 快速模型提供商的基础 URL                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `FAST_LLM_TEMPERATURE`            | 否     | *（回退到 `LLM_TEMPERATURE`）*             | 快速模型的采样温度                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `FAST_LLM_CONTEXT_SIZE`           | 否     | *（回退到 `LLM_CONTEXT_SIZE`）*            | 快速 LLM 的上下文窗口大小                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `FAST_LLM_MAX_OUTPUT_TOKENS`      | 否     | *（回退到 `LLM_MAX_OUTPUT_TOKENS`）*       | 快速 LLM 每次调用的最大输出 token 数                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `LLM_REASONING_EFFORT`            | 否     | *（禁用）*                                | 支持的模型的扩展思考级别（OpenAI o 系列、Gemini 2.5+、Claude）。值：`low`、`medium`、`high`。LiteLLM 会自动将其转换为每个提供商的原生格式。模型的思维链在 UI"思考"步骤中显示。                                                                                                                                                                                                                                                                                                                                                     |
| `LLM_REASONING_BUDGET_TOKENS`     | 否     | *（从努力级别自动计算）*                         | Anthropic 思考的显式 token 预算（最少 1024）。对于 OpenAI/Gemini，直接使用努力级别。仅在设置 `LLM_REASONING_EFFORT` 时有效。                                                                                                                                                                                                                                                                                                                                                                             |
| `LLM_JSON_MODE_ENABLED`           | 否     | `true`                                | `response_format=json_object` 的全局开关。如果您的提供商拒绝 LiteLLM 的助手预填充注入（例如 AWS Bedrock 中继 → 第 2+ 个智能体迭代上的 `ValidationException`），请设置为 `false`。禁用时，结构化调用跳过 JSON 模式，回退到纯文本正则表达式提取 — 无质量损失。适用于所有模型（ENV 配置和管理员配置）。                                                                                                                                                                                                                                                                    |
| `LLM_TOOL_CHOICE_ENABLED`         | 否     | `true`                                | 结构化输出提取中强制 `tool_choice` 的全局开关（级别 1 — 原生函数调用）。如果您的模型在强制工具选择时返回错误（例如拒绝 `tool_choice='specified'` 的思考模式模型），请设置为 `false`。禁用时，结构化调用跳过原生 FC，从 JSON 模式开始。在设置 → 模型 → 高级中提供按模型覆盖。                                                                                                                                                                                                                                                                                                |
| `REASONING_LLM_MODEL`             | 否     | *（回退到 `LLM_MODEL`）*                   | 推理层的模型名称。用于需要深度分析的任务（例如 DAG 规划、计划分析）                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `REASONING_LLM_API_KEY`           | 否     | *（回退到 `LLM_API_KEY`）*                 | 推理模型提供商的 API 密钥                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `REASONING_LLM_BASE_URL`          | 否     | *（回退到 `LLM_BASE_URL`）*                | 推理模型提供商的基础 URL                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `REASONING_LLM_TEMPERATURE`       | 否     | *（回退到 `LLM_TEMPERATURE`）*             | 推理模型的采样温度                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `REASONING_LLM_CONTEXT_SIZE`      | 否     | *（回退到 `LLM_CONTEXT_SIZE`）*            | 推理模型的上下文窗口大小                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `REASONING_LLM_MAX_OUTPUT_TOKENS` | 否     | *（回退到 `LLM_MAX_OUTPUT_TOKENS`）*       | 推理模型每次调用的最大输出 token 数                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `REASONING_LLM_EFFORT`            | 否     | *（回退到 `LLM_REASONING_EFFORT`）*        | 推理模型层的推理努力级别。值：`low`、`medium`、`high`                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `REASONING_LLM_BUDGET`            | 否     | *（回退到 `LLM_REASONING_BUDGET_TOKENS`）* | 推理的 token 预算（主要用于 Anthropic）。覆盖推理层的自动计算预算                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `LLM_SUPPORTS_VISION`             | 否     | `true` *（乐观）*                         | 控制是否尝试 ENV 模式文档 OCR（通过 MarkItDown + `markitdown-ocr`）。仅在**管理员 → 模型中未配置活跃模型组**时适用（纯 ENV 模式）。当默认 `true` 生效时，`convert_to_markdown` 和 RAG 摄取假设 `LLM_MODEL` 支持视觉并调用它进行图像 OCR — 这对所有常见选择（`gpt-4o`、`claude-3-5-sonnet`、`gemini-1.5-pro/flash`）都是正确的行为。当您的 ENV 配置的 `LLM_MODEL` **不**支持视觉时（例如 `deepseek-v3`、`qwen-chat`、`llama-3.1`、`gpt-3.5-turbo`、`o1-mini`），将其设置为 `false` 以跳过失败的视觉调用并直接进行纯文本提取。当管理员 → 模型面板中存在活跃模型组时，此标志被忽略，组的 `supports_vision` 标志接管 — 管理员策划的选择始终是数据库模式中的真实来源。 |

> **解析顺序**：用户偏好 → 管理员模型（数据库）→ ENV 回退。如果在管理员 → 模型中配置了角色为"通用"的管理员模型，这些 ENV 变量仅作为回退。健康检查考虑两个来源。

### MarkItDown OCR 分辨率

`convert_to_markdown` 内置工具和 RAG 摄取管道都使用 Microsoft 的 [MarkItDown](https://github.com/microsoft/markitdown) + 官方 [`markitdown-ocr`](https://github.com/microsoft/markitdown/tree/main/packages/markitdown-ocr) 插件从文档中提取文本 — 包括在有支持视觉的 LLM 可用时对嵌入图像和扫描 PDF 页面进行 OCR。

**视觉 LLM 分辨率顺序**（首次匹配获胜）：

| # | 来源                                           | 优先级原因                                                                              |
| - | -------------------------------------------- | ---------------------------------------------------------------------------------- |
| 1 | 智能体的**主要 LLM**（如果 `supports_vision=True`）    | 一致性：相同的 API 密钥、相同的计费桶、与对话相同的速率限制池。                                                 |
| 2 | 活跃的**模型组 → 快速模型**（如果 `supports_vision=True`） | 快速模型（`gpt-4o-mini`、`claude-haiku`、`gemini-1.5-flash`）是理想的 OCR 工具 — 便宜、低延迟、通常支持多模态。 |
| 3 | 活跃的**模型组 → 通用模型**（如果 `supports_vision=True`） | 当主要模型不在组中时的质量备选方案。                                                                 |
| 4 | **ENV 主要 LLM**（`LLM_MODEL`）                  | 纯 ENV 模式的乐观备选方案。仅在不存在活跃模型组时采用。由 `LLM_SUPPORTS_VISION` 控制。                          |

**推理模型永远不会被优先选择用于 OCR。** 推理层级（`o1`、`o3-mini`、`DeepSeek-R1`）历来缺乏视觉支持，本身也不是 OCR 的合适工具 — OCR 是一项感知任务，而非推理任务。如果工作区仅有一个支持视觉的推理模型（`supports_vision=True`），它仍会通过主要 LLM 路径被选中，但解析器不会主动将其排名高于快速/通用模型。

**零回归备选方案**：当在任何级别都找不到支持视觉的模型时，OCR 会被静默禁用，MarkItDown 以纯文本模式运行。Word/PowerPoint/Excel 嵌入图像 OCR 变为不可用（与此功能发布前相同），但所有其他文本提取（标题、表格、段落文本）继续正常工作。**不存在添加此功能使提取效果比之前行为更差的情况。**

**非 OpenAI 提供商（Anthropic、Google Gemini 等）** 得到透明支持：解析的 LLM 被包装在 `LiteLLMOpenAIShim` 中，该 shim 将 `chat.completions.create(...)` 调用路由通过 `litellm.completion()`，后者处理提供商特定的消息格式转换（例如 Anthropic 的 `source.type="base64"` 图像块）。一个 shim 覆盖 LiteLLM 支持的每个提供商 — 添加新提供商在 FIM One 中零代码更改成本。

### 扩展思维（推理）

当设置 `LLM_REASONING_EFFORT` 时，FIM One 启用模型的扩展思维能力，使内部思维链在 UI 的"思维"步骤中显示。FIM One 使用 [LiteLLM](https://github.com/BerriAI/litellm) 自动将推理努力参数转换为每个提供商的原生格式。

#### 支持的提供商

| 提供商                            | `LLM_BASE_URL`                                             | 工作原理                                           | 返回推理内容? |
| ------------------------------ | ---------------------------------------------------------- | ---------------------------------------------- | ------- |
| **OpenAI** (o1 / o3 / o4-mini) | `https://api.openai.com/v1`                                | `reasoning_effort` 原生发送                        | 是       |
| **Anthropic** (Claude 3.7+)    | `https://api.anthropic.com/v1/`                            | LiteLLM 通过原生 Anthropic API 路由，使用 `thinking` 参数 | 是       |
| **Google Gemini** (2.5+)       | `https://generativelanguage.googleapis.com/v1beta/openai/` | `reasoning_effort` 在兼容端点上发送                    | 是       |

LiteLLM 从 `LLM_BASE_URL` 自动检测提供商，并将其映射到正确的 API 格式。未知 URL 被视为 OpenAI 兼容。

#### 重要注意事项

<Warning>
  **第三方代理 / 自定义端点不保证兼容。**
  如果您的 `LLM_BASE_URL` 指向第三方 API 代理（例如 OpenRouter、one-api、自定义网关），LiteLLM 将尝试根据 URL 正确路由。但是，如果您的代理需要非标准格式，推理可能无法按预期工作。请查阅代理的文档以了解其预期的参数格式。
</Warning>

#### 推理时的温度约束

某些提供商在启用推理时会施加温度限制：

* **Anthropic**: 启用扩展思考时需要 `temperature=1`。如果使用 Anthropic 的扩展思考功能，你**必须**设置 `LLM_TEMPERATURE=1` — 当启用思考时，Anthropic 会拒绝其他值。
* **OpenAI GPT-5.x**: 始终仅支持 `temperature=1`。LiteLLM 的 `drop_params` 过滤会自动处理此问题 — 不支持的温度值会被静默丢弃。对于 GPT-5.x，无需用户采取任何操作。

#### `LLM_REASONING_BUDGET_TOKENS` 的工作原理

此变量**主要对 Anthropic 路径有意义**。设置时，它会覆盖自动计算的预算，并通过 LiteLLM 作为 `thinking` 参数中的 `budget_tokens` 发送。未设置时，预算从 `LLM_MAX_OUTPUT_TOKENS` x 努力比率派生：

| `LLM_REASONING_EFFORT` | 预算比率 | 示例 (max\_tokens = 64000) |
| ---------------------- | ---- | ------------------------ |
| `low`                  | 20%  | 12,800 tokens            |
| `medium`               | 50%  | 32,000 tokens            |
| `high`                 | 80%  | 51,200 tokens            |

最小预算为 1,024 tokens（Anthropic 的硬性最小值）。

对于 OpenAI 和 Gemini，提供商根据 `reasoning_effort` 级别在内部处理 token 分配 — `LLM_REASONING_BUDGET_TOKENS` 无效。

***

## 智能体执行

### ReAct 智能体

| 变量                                  | 必需 | 默认值     | 描述                                                                                                                                                                                          |
| ----------------------------------- | -- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `REACT_MAX_ITERATIONS`              | 否  | `20`    | 每个 ReAct 请求的最大工具调用迭代次数。值越高越彻底，但速度越慢且成本越高                                                                                                                                                    |
| `REACT_MAX_TURN_TOKENS`             | 否  | `0`     | 紧急断路器：单个 ReAct 轮次的最大累积令牌数（所有迭代的提示词 + 完成）。默认 `0` = 无限制。**这不是用于日常令牌控制的**——请使用按用户的 `token_quota`。这是针对极端场景（如智能体陷入无限工具调用循环）的最后手段安全阀。达到此限制会中止任务执行，浪费所有已消耗的令牌并返回不完整结果。除非您有特定的失控智能体问题需要控制，否则保持为 `0` |
| `REACT_TOOL_SELECTION_THRESHOLD`    | 否  | `12`    | 当注册的工具总数超过此阈值时，轻量级 LLM 调用会在每个请求前选择最相关的子集                                                                                                                                                    |
| `REACT_TOOL_SELECTION_MAX`          | 否  | `6`     | 智能选择后保留的最大工具数（仅当工具数超过 `REACT_TOOL_SELECTION_THRESHOLD` 时有效）                                                                                                                                 |
| `REACT_SELF_REFLECTION_INTERVAL`    | 否  | `6`     | 每 N 次工具调用后注入一次自我反思提示词，帮助智能体纠正方向并避免循环                                                                                                                                                        |
| `REACT_TOOL_OBS_TRUNCATION`         | 否  | `8000`  | 综合最终答案时每个工具观察的最大字符数。较高的值会保留更多结构化数据（JSON、表格），但会消耗更多令牌                                                                                                                                        |
| `REACT_TOOL_RESULT_BUDGET`          | 否  | `40000` | 单个会话中所有工具结果的聚合令牌预算。当工具结果令牌总数超过此上限时，新结果会被截断并显示通知。防止大型 API 响应（例如 5 个连接器调用各返回 8K）导致的上下文膨胀。设置为 `0` 禁用上限                                                                                         |
| `REACT_COMPLETION_CHECK_SKIP_CHARS` | 否  | `800`   | 当智能体的最终答案超过此字符数时，跳过答案后的完成检查 LLM 调用。长详细答案不需要"我是否遗漏了什么？"验证往返。设置较低值以更积极地跳过；设置为非常大的值以始终运行检查                                                                                                     |
| `REACT_CYCLE_DETECTION_THRESHOLD`   | 否  | `2`     | 当同一工具连续使用相同参数被调用此次数时，会注入确定性警告，告诉智能体尝试不同的方法。与依赖 LLM 注意到循环的自我反思不同，这是基于哈希的检查，无法被绕过。也适用于 DAG 步骤                                                                                                 |
| `REACT_COMPLETION_CHECK_MIN_TOOLS`  | 否  | `3`     | 完成检查清单触发前的最小工具调用数。简单任务（1-2 次工具调用）会跳过验证以避免不必要的延迟。设置为 `1` 以启用始终开启的验证。也适用于 DAG 步骤                                                                                                              |
| `REACT_TURN_PROFILE_ENABLED`        | 否  | `true`  | 发出按轮次的阶段级别计时日志（`memory_load`、`compact`、`tool_schema_build`、`llm_first_token`、`llm_total`、`tool_exec`）。每轮一行结构化日志。设置为 `false` 禁用分析（零开销）                                                       |
| `REACT_PLAN_TOOL_ENABLED`           | 否  | `true`  | 注册 `update_plan` 待办工具，以便智能体在多步骤任务中写下并维护计划检查清单。对于 DAG 步骤智能体和无工具的智能体会自动跳过                                                                                                                     |
| `REACT_PLAN_REMINDER_INTERVAL`      | 否  | `3`     | 在重新注入陈旧计划提醒前，未调用 `update_plan` 的工具轮次数（嵌入完整检查清单），以便计划在上下文压缩中保留                                                                                                                               |
| `REACT_MAX_CONTINUATIONS`           | 否  | `3`     | 当模型答案被提供商的输出令牌限制截断时的最大续接轮次（`finish_reason=length`）。截断的片段会被拼接成一个无缝答案，包括在智能体循环和流式合成中                                                                                                          |
| `REACT_BACKGROUND_TOOLS_ENABLED`    | 否  | `true`  | 在慢速工具（沙箱化 python/shell/node 执行）上提供 `run_in_background` 选项。智能体立即获得任务 id 并继续工作；工具完成时结果作为 `<task_notification>` 消息到达                                                                           |
| `REACT_BG_WAIT_TIMEOUT`             | 否  | `300`   | 当智能体想要最终确定答案时，等待仍在运行的后台工具的最大秒数。窗口内未完成的任务会被取消并显示明确的超时通知                                                                                                                                      |
| `DAG_CHECKPOINT_EVIDENCE_CHARS`     | 否  | `4000`  | DAG 崩溃恢复检查点文件（`data/dag_checkpoints/`）中的每步证据上限。步骤摘要以完整形式存储                                                                                                                                  |
| `DAG_CHECKPOINT_MAX_AGE_HOURS`      | 否  | `24`    | 超过此时间的 DAG 检查点在加载时被忽略，因此陈旧的崩溃遗留物永远不会恢复到新运行中                                                                                                                                                 |
| `LLM_RATE_LIMIT_PER_USER`           | 否  | `true`  | 使用按用户键控的速率限制桶而不是单个进程全局桶。防止一个嘈杂的用户在同一工作线程上饿死所有其他用户。底层速率硬编码为每个桶 60 请求/分钟和 100K 令牌/分钟——此设置仅控制桶是共享（全局）还是分区（按用户）。设置为 `false` 以恢复到旧版全局桶（不推荐）                                                      |

### DAG 规划器

| 变量                               | 必需 | 默认值     | 描述                                                                                                                                                                                                  |
| -------------------------------- | -- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MAX_CONCURRENCY`                | 否  | `5`     | DAG 执行器中的最大并行步骤数                                                                                                                                                                                    |
| `DAG_STEP_MAX_ITERATIONS`        | 否  | `15`    | 每个 DAG 步骤内的最大工具调用迭代次数                                                                                                                                                                               |
| `DAG_STEP_TIMEOUT`               | 否  | `600`   | 步骤执行超时时间（秒）。超过此时间的步骤标记为失败，其依赖步骤级联跳过                                                                                                                                                                 |
| `DAG_MAX_REPLAN_ROUNDS`          | 否  | `3`     | 当目标未达成时的最大自主重新规划尝试次数。用户中断（注入）次数不限，不计入此预算                                                                                                                                                            |
| `DAG_REPLAN_STOP_CONFIDENCE`     | 否  | `0.8`   | 当智能体确信目标无法达成的置信度超过此阈值时停止重试（`0.0` = 永不提前停止，`1.0` = 任何失败时停止）                                                                                                                                          |
| `DAG_VERIFY_TRUNCATION`          | 否  | `2000`  | 发送给步骤验证器 LLM 进行质量判断的步骤输出最大字符数                                                                                                                                                                       |
| `DAG_ANALYZER_TRUNCATION`        | 否  | `10000` | 格式化用于执行后分析器的每个步骤结果的最大字符数                                                                                                                                                                            |
| `DAG_STEP_EVIDENCE_CHARS`        | 否  | `16000` | 每个步骤保留的原始工具输出（网页抓取、搜索结果、文件读取）最大字符数，作为权威"源证据"。这些数据与步骤摘要一起提供给分析器和最终综合，以便可以根据源而非可能已静默丢弃或错误标记项目的摘要来验证答案的事实声明（总数、枚举、严重程度）。设置为 `0` 禁用证据捕获                                                                 |
| `DAG_REPLAN_RECENT_TRUNCATION`   | 否  | `500`   | 构建重新规划上下文时，来自最近一轮的每个步骤结果的最大字符数                                                                                                                                                                      |
| `DAG_REPLAN_OLDER_TRUNCATION`    | 否  | `200`   | 构建重新规划上下文时，来自较早轮次的每个步骤结果的最大字符数。较早的轮次会更激进地截断以节省上下文                                                                                                                                                   |
| `DAG_TOOL_CACHE`                 | 否  | `true`  | 在单个 DAG 执行中缓存相同的工具调用。仅缓存明确标记为 `cacheable` 的工具（搜索、知识检索等只读工具）。设置为 `false` 完全禁用缓存                                                                                                                      |
| `DAG_STEP_VERIFICATION`          | 否  | `false` | 每个 DAG 步骤后的通用 LLM 质量检查。失败时，步骤会根据反馈重试一次。**默认关闭**——在每个步骤上增加延迟，很少需要；大多数步骤输出无需重新检查即可接受。仅在观察到频繁的低质量步骤结果时使用                                                                                               |
| `DAG_CITATION_VERIFICATION`      | 否  | `true`  | 专业领域步骤的引文准确性检查。**前置条件**：查询必须首先由 LLM 领域分类器分类为专业领域（参见 `ESCALATION_DOMAINS`）。当检测到该领域且此标志为 `true` 时，每个完成的步骤会被扫描以查找法律/医学/财务引文并验证准确性——捕获幻觉的文章编号、虚构的案例参考和不正确的监管引文。如果领域分类返回 `null`（通用查询），则无论此设置如何，引文验证都不会运行 |
| `DAG_CITATION_VERIFY_TRUNCATION` | 否  | `6000`  | 发送给引文验证提示的步骤结果最大字符数                                                                                                                                                                                 |

### 领域分类

控制独立的基于LLM的领域检测层，在ReAct和DAG执行**之前**运行。当查询被分类为专家领域时，系统激活领域感知功能：升级到推理模型、领域特定的SOP指令和引用验证（仅DAG）。

| 变量                   | 必需 | 默认值                                             | 描述                                                                                                                                                           |
| -------------------- | -- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ESCALATION_DOMAINS` | 否  | `legal,medical,financial,tax,compliance,patent` | 专家领域的逗号分隔列表。快速LLM根据此列表对每个查询进行分类。匹配时，系统：(1) 升级到推理模型以获得更高的准确性，(2) 注入领域特定的SOP指令（例如在写入前通过搜索验证引用），(3) 为DAG步骤启用引用验证。根据需要添加自定义领域（例如 `legal,education,construction`） |

### 上下文守卫

控制自动上下文窗口管理，防止对话超过模型的限制。

| 变量                             | 必需 | 默认值     | 描述                                |
| ------------------------------ | -- | ------- | --------------------------------- |
| `CONTEXT_GUARD_DEFAULT_BUDGET` | 否  | `32000` | 上下文窗口管理的默认令牌预算。当对话超过此值时，较早的消息会被压缩 |
| `CONTEXT_GUARD_MAX_MSG_CHARS`  | 否  | `50000` | 任何单条消息的硬字符限制。超过此限制的消息会被截断作为安全网    |
| `CONTEXT_GUARD_KEEP_RECENT`    | 否  | `4`     | 压缩对话历史时保留的最近消息数                   |

### 内容护栏

逗号分隔的护栏名称，用于检查*内容*的输入或输出。独立于工具权限闸门（`core/hooks/*`）和安全层（`core/security/*`）。详见[内容护栏](/configuration/guardrails)。

| 变量                               | 必需 | 默认值         | 描述                                                                                  |
| -------------------------------- | -- | ----------- | ----------------------------------------------------------------------------------- |
| `FIM_GUARDRAILS_INPUT`           | 否  | `jailbreak` | 活跃的输入护栏。默认的`jailbreak`正则表达式检测器在检测到已知的提示词覆盖短语时会在花费任何LLM令牌之前中止该轮次。设置为空以禁用。未知名称会被记录并跳过 |
| `FIM_GUARDRAILS_OUTPUT`          | 否  | （空）         | 活跃的输出护栏。当前包含：`max_length`（限制答案字符数）。在智能体生成最终答案后运行                                    |
| `FIM_GUARDRAIL_MAX_OUTPUT_CHARS` | 否  | `50000`     | `max_length`输出护栏使用的字符上限。仅当`max_length`列在`FIM_GUARDRAILS_OUTPUT`中时有效                 |

### 智能体工作区

| 变量                            | 必需 | 默认值    | 描述                                          |
| ----------------------------- | -- | ------ | ------------------------------------------- |
| `WORKSPACE_OFFLOAD_THRESHOLD` | 否  | `8000` | 当工具输出超过这么多字符时，它会被保存到工作区文件中，并将截断的预览注入到对话上下文中 |
| `WORKSPACE_PREVIEW_CHARS`     | 否  | `2000` | 截断的工作区引用中包含的预览字符数                           |
| `WORKSPACE_CLEANUP_MAX_HOURS` | 否  | `72`   | 超过这么多小时的工作区文件符合自动清理的条件                      |

### 系统

| 变量                          | 必需 | 默认值 | 描述                                                                                                                                          |
| --------------------------- | -- | --- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| ~~`SYSTEM_PROMPT_RESERVE`~~ | —  | —   | **已移除。** 之前从上下文预算中减去固定的 4K 保留用于系统提示。这导致了重复计算，因为 ContextGuard 在估计消息列表令牌时已经包含了系统提示。预算公式现在简单为 `context_size - max_output_tokens`，系统提示的实际大小动态计算 |

***

## Web 工具（可选）

| 变量                    | 必需 | 默认值                        | 描述                                                                                  |
| --------------------- | -- | -------------------------- | ----------------------------------------------------------------------------------- |
| `JINA_API_KEY`        | 否  | —                          | Jina API 密钥。当未设置特定服务密钥时，作为**搜索、获取、嵌入和重排序**的共享备用方案。在 [jina.ai](https://jina.ai/) 获取  |
| `TAVILY_API_KEY`      | 否  | —                          | Tavily 搜索 API 密钥（如果设置且 `WEB_SEARCH_PROVIDER` 未设置，则自动选择）                             |
| `BRAVE_API_KEY`       | 否  | —                          | Brave 搜索 API 密钥（如果设置且 `WEB_SEARCH_PROVIDER` 未设置，则自动选择）                              |
| `EXA_API_KEY`         | 否  | —                          | Exa 搜索 API 密钥（如果设置且 `WEB_SEARCH_PROVIDER` 未设置，则自动选择）。在 [exa.ai](https://exa.ai/) 获取 |
| `WEB_SEARCH_PROVIDER` | 否  | `jina`                     | 搜索提供商选择器：`jina` / `tavily` / `brave` / `exa`                                        |
| `WEB_FETCH_PROVIDER`  | 否  | `jina`（如果密钥已设置，否则 `httpx`） | 获取提供商：`jina`（使用 Jina Reader API）/ `httpx`（直接 HTTP 请求，无需 API 密钥）                     |

> **快速开始提示**：仅设置 `JINA_API_KEY` 即可同时启用网页搜索、网页获取、嵌入和重排序——一个密钥，四项服务。您可以使用下面的变量单独覆盖每项服务。

***

## RAG 与知识库（推荐）

### 嵌入

嵌入将文本转换为向量以进行知识库搜索。FIM One 使用标准的 **OpenAI 兼容 `/v1/embeddings` 端点**，因此它适用于任何公开此接口的提供商 — 不仅仅是 Jina。

| 变量                    | 必需 | 默认值                      | 描述            |
| --------------------- | -- | ------------------------ | ------------- |
| `EMBEDDING_API_KEY`   | 否  | *(回退到 `JINA_API_KEY`)*   | 嵌入提供商的 API 密钥 |
| `EMBEDDING_BASE_URL`  | 否  | `https://api.jina.ai/v1` | 嵌入提供商的基础 URL  |
| `EMBEDDING_MODEL`     | 否  | `jina-embeddings-v3`     | 模型标识符         |
| `EMBEDDING_DIMENSION` | 否  | `1024`                   | 向量维度          |

**提供商示例** — 只需设置这三个变量即可切换：

| 提供商               | `EMBEDDING_BASE_URL`          | `EMBEDDING_MODEL`        | `EMBEDDING_DIMENSION` |
| ----------------- | ----------------------------- | ------------------------ | --------------------- |
| **Jina** *(默认)*   | `https://api.jina.ai/v1`      | `jina-embeddings-v3`     | `1024`                |
| **OpenAI**        | `https://api.openai.com/v1`   | `text-embedding-3-small` | `1536`                |
| **Voyage**        | `https://api.voyageai.com/v1` | `voyage-3`               | `1024`                |
| **Ollama** *(本地)* | `http://localhost:11434/v1`   | `nomic-embed-text`       | `768`                 |

<Warning>
  **更改嵌入模型或维度会使所有现有知识库向量失效。** 旧向量是在不同的嵌入空间中计算的 — 检索准确性将无声地降低。切换后，您必须**重建所有知识库索引**。
</Warning>

### 检索

| 变量               | 必需 | 默认值         | 描述                                            |
| ---------------- | -- | ----------- | --------------------------------------------- |
| `RETRIEVAL_MODE` | 否  | `grounding` | `grounding`（带引用和置信度评分的完整管道）或 `simple`（基础 RAG） |

### 重排器

重排器对检索到的文档重新评分以提高相关性。支持三个提供商 — 通过 `RERANKER_PROVIDER` 选择或让系统从可用的 API 密钥自动检测。

| 变量                      | 必需 | 默认值                                  | 描述                                                                             |
| ----------------------- | -- | ------------------------------------ | ------------------------------------------------------------------------------ |
| `RERANKER_PROVIDER`     | 否  | *(自动检测)*                             | `jina` / `cohere` / `openai`。如果未设置：如果设置了 `COHERE_API_KEY` 则使用 Cohere，否则使用 Jina |
| `RERANKER_MODEL`        | 否  | `jina-reranker-v2-base-multilingual` | 模型标识符（适用于 Jina 和 OpenAI 提供商）                                                   |
| `COHERE_API_KEY`        | 否  | —                                    | Cohere API 密钥（当设置且 `RERANKER_PROVIDER` 未设置时自动选择 Cohere 重排器）                    |
| `COHERE_RERANKER_MODEL` | 否  | `rerank-multilingual-v3.0`           | Cohere 特定的重排器模型                                                                |

> **Jina** 使用 `JINA_API_KEY`（来自上面的 Web 工具）。**OpenAI** 复用 `LLM_API_KEY` / `LLM_BASE_URL` — 无需额外密钥。**Cohere** 需要其自己的 `COHERE_API_KEY`。

> 重排器是**可选的** — 知识库搜索可以在不使用它的情况下使用融合评分。对于知识库功能，**推荐**使用嵌入。

### 向量存储

| 变量                 | 必需 | 默认值                   | 描述                             |
| ------------------ | -- | --------------------- | ------------------------------ |
| `VECTOR_STORE_DIR` | 否  | `./data/vector_store` | LanceDB 向量存储数据的目录（基于文件，无需外部服务） |

***

## 代码执行

| 变量                     | 必需 | 默认值                | 描述                                                                                                    |
| ---------------------- | -- | ------------------ | ----------------------------------------------------------------------------------------------------- |
| `CODE_EXEC_BACKEND`    | 否  | `local`            | `local`（直接主机执行）或 `docker`（隔离容器）                                                                       |
| `DOCKER_PYTHON_IMAGE`  | 否  | `python:3.11-slim` | Python 执行的 Docker 镜像                                                                                  |
| `DOCKER_NODE_IMAGE`    | 否  | `node:20-slim`     | Node.js 执行的 Docker 镜像                                                                                 |
| `DOCKER_SHELL_IMAGE`   | 否  | `python:3.11-slim` | shell 执行的 Docker 镜像                                                                                   |
| `DOCKER_MEMORY`        | 否  | *（Docker 默认值）*     | 每个容器的 RAM 上限（例如 `256m`、`512m`、`1g`）                                                                   |
| `DOCKER_CPUS`          | 否  | *（Docker 默认值）*     | 每个容器的 CPU 配额（例如 `0.5`、`1.0`）                                                                          |
| `SANDBOX_TIMEOUT`      | 否  | `120`              | 默认执行超时时间（秒）                                                                                           |
| `DOCKER_HOST_DATA_DIR` | 否  | *（未设置）*            | `./data` 卷挂载的主机端绝对路径。DooD（Docker-outside-of-Docker）部署需要此项；`docker-compose.yml` 通过 `${PWD}/data` 自动设置。 |

> **安全性**：`local` 模式直接在主机上运行 AI 生成的代码。对于面向互联网或多用户部署，始终设置 `CODE_EXEC_BACKEND=docker`。

***

## 工具制品

工具执行（代码执行、模板渲染、图像生成）产生的文件的大小限制。

| 变量                    | 必需 | 默认值                | 描述               |
| --------------------- | -- | ------------------ | ---------------- |
| `MAX_ARTIFACT_SIZE`   | 否  | `10485760` (10 MB) | 单个制品文件的最大大小（字节）  |
| `MAX_ARTIFACTS_TOTAL` | 否  | `52428800` (50 MB) | 每个会话的制品总大小上限（字节） |

***

## 文档处理（可选）

控制上传的 PDF/DOCX 文件如何被处理以供 LLM 使用。具有视觉能力的模型（GPT-4o、Claude 3/4、Gemini）可以接收渲染后的 PDF 页面作为图像，以获得更高的保真度。

| 变量                          | 必需 | 默认值    | 描述                                                   |
| --------------------------- | -- | ------ | ---------------------------------------------------- |
| `DOCUMENT_PROCESSING_MODE`  | 否  | `auto` | `auto`（如果模型支持则使用视觉），`vision`（始终渲染页面），`text`（始终仅提取文本） |
| `DOCUMENT_VISION_DPI`       | 否  | `150`  | PDF 页面渲染的 DPI。更高 = 更好的质量，更多 token                    |
| `DOCUMENT_VISION_MAX_PAGES` | 否  | `20`   | 每个 PDF 渲染为图像的最大页数                                    |

> **注意**：每个模型的视觉支持通过管理员 → 模型中的 `supports_vision` 开关进行配置。未明确设置时，系统会从模型名称自动检测视觉能力。

## 图像生成（可选）

| 变量                   | 必需 | 默认值                              | 描述                                                                                           |
| -------------------- | -- | -------------------------------- | -------------------------------------------------------------------------------------------- |
| `IMAGE_GEN_PROVIDER` | 否  | `google`                         | `google`（Gemini 原生 API）或 `openai`（OpenAI 兼容 `/v1/images/generations`）                        |
| `IMAGE_GEN_API_KEY`  | 否  | —                                | Google AI Studio 密钥（`google`）或代理/OpenAI API 密钥（`openai`）                                     |
| `IMAGE_GEN_MODEL`    | 否  | `gemini-3.1-flash-image-preview` | 图像生成模型（例如 `dall-e-3`、`gemini-nano-banana-2`）                                                 |
| `IMAGE_GEN_BASE_URL` | 否  | *（按提供商）*                         | Google：`https://generativelanguage.googleapis.com/v1beta`；OpenAI：`https://api.openai.com/v1` |

***

## 电子邮件（SMTP）（推荐）

当设置了 `SMTP_HOST`、`SMTP_USER` 和 `SMTP_PASS` 时，自动注册 `email_send` 内置工具。

| 变量                       | 必需 | 默认值                | 描述                                                                                             |
| ------------------------ | -- | ------------------ | ---------------------------------------------------------------------------------------------- |
| `SMTP_HOST`              | 条件 | —                  | SMTP 服务器主机名                                                                                    |
| `SMTP_PORT`              | 否  | `465`              | SMTP 端口                                                                                        |
| `SMTP_SSL`               | 否  | `ssl`              | TLS 模式：`ssl`（端口 465）/ `tls`（STARTTLS，端口 587）/ `none` 或 `""`（明文，凭证以明文发送）。任何其他值都会被拒绝，而不是静默回退到明文。 |
| `SMTP_USER`              | 条件 | —                  | SMTP 登录用户名                                                                                     |
| `SMTP_PASS`              | 条件 | —                  | SMTP 登录密码                                                                                      |
| `SMTP_FROM`              | 否  | *（使用 `SMTP_USER`）* | From 标头中显示的发件人地址                                                                               |
| `SMTP_FROM_NAME`         | 否  | —                  | From 标头中显示的显示名称                                                                                |
| `SMTP_REPLY_TO`          | 否  | —                  | Reply-To 地址；回复将发送到此处而不是 `SMTP_FROM`                                                            |
| `SMTP_ALLOWED_DOMAINS`   | 否  | —                  | 逗号分隔的域名允许列表（例如 `example.com,corp.io`）；阻止列表外域名的收件人                                              |
| `SMTP_ALLOWED_ADDRESSES` | 否  | —                  | 逗号分隔的精确地址允许列表；与 `SMTP_ALLOWED_DOMAINS` 结合使用；两者都不设置时允许任何收件人（不建议用于共享邮箱）                          |

***

## 连接器

| 变量                             | 必需 | 默认值           | 描述                                                                                                                                      |
| ------------------------------ | -- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `CONNECTOR_RESPONSE_MAX_CHARS` | 否  | `50000`       | 非数组 JSON / 纯文本连接器响应的最大字符数                                                                                                               |
| `CONNECTOR_RESPONSE_MAX_ITEMS` | 否  | `10`          | 当连接器响应为 JSON 数组时保留的最大数组项数                                                                                                               |
| `CREDENTIAL_ENCRYPTION_KEY`    | 否  | *(未设置)*       | 用于连接器凭证 blob 的 Fernet 加密密钥。设置后，存储在 `connector_credentials` 中的身份验证令牌将被加密存储。如果未设置，凭证将以纯文本 JSON 形式存储（向后兼容）。更改此密钥将使所有现有加密凭证失效。              |
| `CONNECTOR_TOOL_MODE`          | 否  | `progressive` | 连接器工具如何暴露给智能体。`progressive`：单个 `ConnectorMetaTool`，带有 `discover`/`execute` 子命令（\~30 tokens/连接器）。`classic`：每个操作一个工具（旧版，\~250 tokens/操作）。 |
| `DATABASE_TOOL_MODE`           | 否  | `progressive` | 数据库连接器工具如何暴露给智能体。`progressive`：单个 `DatabaseMetaTool`，带有 `list_tables`/`discover`/`query` 子命令。`legacy`：每个数据库连接器每个操作一个工具（3 个工具）。          |
| `MCP_TOOL_MODE`                | 否  | `progressive` | MCP 服务器工具如何暴露给智能体。`progressive`：单个 `MCPServerMetaTool`，带有 `discover`/`call` 子命令。`legacy`：每个 MCP 服务器操作一个工具（原始单个工具）。                      |

***

## 平台

| 变量                               | 必需 | 默认值                                     | 描述                                                                                                                                                                          |
| -------------------------------- | -- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`                   | 否  | `sqlite+aiosqlite:///./data/fim_one.db` | 数据库连接字符串。**SQLite**（零配置）：`sqlite+aiosqlite:///./data/fim_one.db`。**PostgreSQL**（生产环境）：`postgresql+asyncpg://user:pass@localhost:5432/fim_one`。Docker Compose自动配置PostgreSQL。 |
| `JWT_SECRET_KEY`                 | 否  | `CHANGE_ME`                             | JWT令牌签名的密钥。占位符值`CHANGE_ME`（或任何旧版默认值）会在首次启动时触发自动生成安全的256位随机密钥，并写回`.env`。在生产环境中显式设置以保持令牌在重启和副本间的有效性。                                                                          |
| `FIM_BCRYPT_COST`                | 否  | `12`                                    | bcrypt密码哈希的工作因子，范围限制在4-31。默认值12在现代CPU上每次哈希耗时约200ms；在弱硬件上降低该值，在安全加固的部署中提高该值。                                                                                                 |
| `CORS_ORIGINS`                   | 否  | —                                       | 逗号分隔的额外允许CORS源列表，超出默认localhost条目。当前端运行在非localhost域名上时必需（例如`https://app.example.com`）。                                                                                       |
| `UPLOADS_DIR`                    | 否  | `./uploads`                             | 上传文件的目录                                                                                                                                                                     |
| `MAX_UPLOAD_SIZE_MB`             | 否  | `50`                                    | 最大文件上传大小（单位：MB，后端强制执行）                                                                                                                                                      |
| `NEXT_PUBLIC_MAX_UPLOAD_SIZE_MB` | 否  | `50`                                    | 前端UI中显示的最大文件上传大小。**构建时变量**——必须与`MAX_UPLOAD_SIZE_MB`匹配。                                                                                                                      |
| `MCP_SERVERS`                    | 否  | —                                       | MCP服务器配置的JSON数组（需要`uv sync --extra mcp`）                                                                                                                                    |
| `ALLOW_STDIO_MCP`                | 否  | `false`                                 | 允许stdio MCP服务器。仅在可信的本地部署中设置为`true`                                                                                                                                          |
| `ALLOWED_STDIO_COMMANDS`         | 否  | `npx,uvx,node,python,python3,deno,bun`  | stdio MCP服务器允许的基础命令的逗号分隔列表。仅在`ALLOW_STDIO_MCP=true`时生效                                                                                                                      |
| `LOG_LEVEL`                      | 否  | `INFO`                                  | 日志级别：`DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL`                                                                                                                    |
| `REDIS_URL`                      | 否  | —                                       | Redis连接URL，用于跨工作进程中断中继。**当`WORKERS>1`时必需**——没有它，中途中断/注入请求可能会命中不同的工作进程并无声地失败。由Docker Compose自动配置。                                                                            |
| `WORKERS`                        | 否  | `1`                                     | Uvicorn工作进程数。`1`是安全的，不需要外部服务。对于生产环境多工作进程，使用PostgreSQL（SQLite是单写入器）。SQLite在轻负载下适合本地开发。身份验证、OAuth和文件操作完全支持多工作进程（基于JWT）。Docker Compose自动配置PostgreSQL和Redis。                    |

<Warning>
  **多工作进程检查清单**（`WORKERS>1`）：

  * **停止（中止流式传输）**——总是有效的，无需额外配置（信号在同一TCP连接上传输）。
  * **注入（中途后续操作）**——**需要`REDIS_URL`**。没有Redis，注入请求可能会落在不同的工作进程上，该进程对运行中的执行一无所知，导致无声地失败。
  * **生产环境**：使用PostgreSQL（`DATABASE_URL`）。SQLite的单写入器锁在并发写入下可能导致争用。
  * **本地开发**：SQLite+多工作进程在轻度使用下是可以的；如果使用注入功能，只需添加`REDIS_URL`。
</Warning>

## 工作流运行保留

自动清理旧工作流运行的后台任务。按工作流的覆盖设置（在工作流设置UI中配置）优先于这些全局默认值。

| 变量                                    | 必需 | 默认值   | 描述                       |
| ------------------------------------- | -- | ----- | ------------------------ |
| `WORKFLOW_RUN_MAX_AGE_DAYS`           | 否  | `30`  | 删除早于此天数的工作流运行            |
| `WORKFLOW_RUN_MAX_PER_WORKFLOW`       | 否  | `100` | 每个工作流最多保留此数量的运行（最旧的优先删除） |
| `WORKFLOW_RUN_CLEANUP_INTERVAL_HOURS` | 否  | `24`  | 后台清理任务运行的频率，单位为小时        |

### 通道确认请求过期

后台清理程序，将陈旧的待审批请求（由通道钩子如 `FeishuGateHook` 或审批演练场产生）标记为已过期。确保稍后点击被遗忘的卡片不会翻转已被拆除的智能体状态。

| 变量                                            | 必需 | 默认值    | 描述                         |
| --------------------------------------------- | -- | ------ | -------------------------- |
| `CHANNEL_CONFIRMATION_TTL_MINUTES`            | 否  | `1440` | 超过此时间的待确认请求将自动过期（默认值：24小时） |
| `CHANNEL_CONFIRMATION_SWEEP_INTERVAL_SECONDS` | 否  | `600`  | 过期清理程序运行的频率（默认值：每10分钟）     |

## OAuth（可选）

当为提供商同时设置 `CLIENT_ID` 和 `CLIENT_SECRET` 时，登录页面会自动显示相应的 OAuth 按钮。

| 变量                      | 必需       | 默认值                         | 描述                                                                                                                                    |
| ----------------------- | -------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `GITHUB_CLIENT_ID`      | 否        | —                           | GitHub OAuth 应用客户端 ID。在 [github.com/settings/developers](https://github.com/settings/developers) → OAuth Apps 创建                      |
| `GITHUB_CLIENT_SECRET`  | 否        | —                           | GitHub OAuth 应用客户端密钥                                                                                                                  |
| `GOOGLE_CLIENT_ID`      | 否        | —                           | Google OAuth 客户端 ID。在 [console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials) 创建               |
| `GOOGLE_CLIENT_SECRET`  | 否        | —                           | Google OAuth 客户端密钥                                                                                                                    |
| `DISCORD_CLIENT_ID`     | 否        | —                           | Discord OAuth2 客户端 ID。在 [discord.com/developers](https://discord.com/developers/applications) 创建                                      |
| `DISCORD_CLIENT_SECRET` | 否        | —                           | Discord OAuth2 客户端密钥                                                                                                                  |
| `FEISHU_APP_ID`         | 否        | —                           | 飞书（Lark）应用 ID。在 [open.feishu.cn](https://open.feishu.cn/app) 创建。需要 `contact:user.email:readonly` 权限                                   |
| `FEISHU_APP_SECRET`     | 否        | —                           | 飞书（Lark）应用密钥                                                                                                                          |
| `FRONTEND_URL`          | **生产环境** | `http://localhost:3000`     | OAuth 完成后浏览器跳转的位置。在生产环境中必须设置（例如 `https://yourdomain.com`）                                                                             |
| `API_BASE_URL`          | **生产环境** | `http://localhost:8000`     | 外部可访问的后端 URL，用于构建 OAuth 回调 URL。在生产环境中必须设置                                                                                             |
| `NEXT_PUBLIC_API_URL`   | **生产环境** | *（自动检测为 `<hostname>:8000`）* | 浏览器端 API 基础 URL，用于 OAuth 重定向。**这是前端构建时变量** — 在本地开发时在 `frontend/.env.local` 中设置，或在自定义生产部署时作为 Docker 构建参数传递。自动检测适用于标准反向代理设置（端口 80/443）。 |

> **生产环境** = 本地可选（使用默认值），但对于任何面向互联网的部署都**必需**。

### 需要向每个提供商注册的 OAuth 回调 URL

后端构造回调 URL 为：`{API_BASE_URL}/api/auth/oauth/{provider}/callback`

| 提供商     | 要注册的回调 URL                                               |
| ------- | -------------------------------------------------------- |
| GitHub  | `https://yourdomain.com/api/auth/oauth/github/callback`  |
| Google  | `https://yourdomain.com/api/auth/oauth/google/callback`  |
| Discord | `https://yourdomain.com/api/auth/oauth/discord/callback` |

***

## Cloudflare Tunnel（可选）

通过 Cloudflare 的网络路由所有流量，而不是直接暴露端口。无需 Nginx、SSL 证书和开放防火墙规则。有关设置说明，请参阅[生产部署](/quickstart#cloudflare-tunnel)部分。

<Warning>
  **中国大陆用户**：Cloudflare Free/Pro/Business 计划在中国大陆没有 PoP。流量被路由到海外边缘节点，导致频繁出现 502 错误。除非您拥有带有中国网络的 Cloudflare Enterprise，否则如果您的主要用户在中国大陆，请勿使用此功能。
</Warning>

| 变量                        | 必需                 | 默认值 | 描述                                                                                                                                                 |
| ------------------------- | ------------------ | --- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLOUDFLARE_TUNNEL_TOKEN` | **是**（如果使用 Tunnel） | —   | 来自 Cloudflare Zero Trust → Networks → Tunnels → 您的 tunnel → Configure 的令牌。以 `eyJ...` 开头。由 `docker-compose.tunnel.yml` 中的 `cloudflared` sidecar 所需。 |

***

## 分析（可选）

所有分析提供商都是可选的。设置任意组合——所有活跃的提供商同时加载。全部留空可禁用分析（建议用于本地开发）。

| 变量                                 | 必需 | 默认值                                 | 描述                                                                                                   |
| ---------------------------------- | -- | ----------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `NEXT_PUBLIC_GA_MEASUREMENT_ID`    | 否  | —                                   | Google Analytics 4 测量ID（例如 `G-XXXXXXXXXX`）。在 [analytics.google.com](https://analytics.google.com) 获取 |
| `NEXT_PUBLIC_UMAMI_SCRIPT_URL`     | 否  | —                                   | Umami 分析脚本URL（例如 `https://your-umami.com/script.js`）。自托管、隐私友好的替代方案——[umami.is](https://umami.is)     |
| `NEXT_PUBLIC_UMAMI_WEBSITE_ID`     | 否  | —                                   | Umami 网站ID。设置 `NEXT_PUBLIC_UMAMI_SCRIPT_URL` 时必需                                                     |
| `NEXT_PUBLIC_PLAUSIBLE_DOMAIN`     | 否  | —                                   | Plausible 分析域名（例如 `yourdomain.com`）。轻量级、隐私友好——[plausible.io](https://plausible.io)                   |
| `NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL` | 否  | `https://plausible.io/js/script.js` | 自托管实例的自定义Plausible脚本URL                                                                              |

> 所有 `NEXT_PUBLIC_*` 分析变量都是**构建时**的——更改需要前端重新构建才能生效。

## Stripe 计费（可选）

Stripe 为 Pro 订阅提供支持。将所有三个变量留空可禁用计费——FIM One 的其余部分保持不变。**必须**同时设置 `STRIPE_SECRET_KEY` **和** `STRIPE_WEBHOOK_SECRET`；部分配置会在首次使用时引发错误。

| 变量                          | 必需 | 默认值                                          | 描述                                                                                                                                                         |
| --------------------------- | -- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `STRIPE_SECRET_KEY`         | 否  | —                                            | Stripe API 密钥。必须以 `sk_test_` / `sk_live_`（完全访问权限）或 `rk_test_` / `rk_live_`（受限密钥）开头。从 Stripe Dashboard → Developers → API keys 获取。切勿将 `sk_live_*` 密钥提交到源代码。 |
| `STRIPE_WEBHOOK_SECRET`     | 否  | —                                            | Stripe webhook 签名密钥（`whsec_*`）。在 Stripe Dashboard → Developers → Webhooks → Add endpoint 中注册 webhook 端点时创建。验证入站 webhook 负载所需。                              |
| `STRIPE_BILLING_RETURN_URL` | 否  | `http://localhost:3000/settings?tab=billing` | Stripe 在 Checkout / Customer Portal 会话后重定向用户的 URL。将其设置为生产环境计费设置页面（例如 `https://your-domain.com/settings?tab=billing`）。                                      |
