# 扪心自问（FBR）——机制规格

英文版：[English](./fbr.md)

> 本文是 **FBR 规范**（以本文为准）。实现细节见：[`fbr-implementation.zh.md`](./fbr-implementation.zh.md)。

## 1. 这是什么

**扪心自问（FBR, Fresh Boots Reasoning）** 是 Dominds 的一种工作机制：在诉请者推进过程中，智能体可以把一个边界清晰的子问题“拆出去”，以 **更干净的上下文** 重新推理一次，然后把结论回贴到诉请者中。

在 Dominds 里，FBR 通过专用函数工具 `freshBootsReasoning({ tellaskContent: "...", effort?: N })` 触发；FBR 的核心是运行时对该支线对话施加的一组强制约束与串行语义。

## 2. 设计原则与取舍（为什么这样做）

### 2.1 可预期优先：FBR 在最终收口前不得使用普通工具

FBR 的价值来自“把推理拉回文本”：让被诉请者只围绕诉请正文进行独立推理，而不是在工具、环境、副作用里游走。为此，FBR 支线对话必须满足：

- **发散/收敛阶段与普通工具隔离**（不能 tellask、读文件、跑 shell、浏览、访问 rtws；provider 请求可使用 `tool_choice: "none"` 或等价禁用模式）
- **最终收口阶段只开放两个结论函数**
- **上下文以诉请正文为权威**（不是“默认继承诉请者一侧历史”）

这两点让 FBR 更像一个可控的“推理试算器”，而不是另一个会自行探索环境的智能体。

### 2.2 不搞隐式魔法：禁用就要明确失败

如果团队配置禁用了 FBR（例如 `fbr-effort: 0`），运行时必须 **对用户可见且清晰地拒绝** `freshBootsReasoning({ tellaskContent: "..." })`，避免“看起来发了诉请、实际上被静默忽略”的隐性失败。

### 2.3 串行多轮推理，而不是“多代理协作”

`fbr-effort` 是 FBR 的力度设置。运行时会把力度 `N` 解释为在**单一支线对话窗口**内先执行 `N` 轮发散，再执行 `N` 轮收敛，并要求 FBR 支线对话自己完成去噪和正式收口后再回贴诉请者。

## 3. 用户语法

### 3.1 触发语法

触发 FBR 的语法只有一种：

- `freshBootsReasoning({ tellaskContent: "...", effort?: N })`

说明：

- FBR 不使用 `targetAgentId`、`sessionSlug`、`mentionList`。
- `tellaskContent` 是 FBR 支线的权威任务上下文。
- `effort` 为可选，用于设置本次调用的 FBR 力度；未传时运行时回退到当前成员 `fbr-effort`。
- 力度 `N` 会映射为同一 FBR 支线窗口内的 `N` 轮发散 + `N` 轮收敛，并以最多 `N` 次最终收口重试结束。

### 3.2 作用域

本文档只定义 **FBR 机制**，并说明其通过 `freshBootsReasoning({ tellaskContent: "...", effort?: N })` 触发的行为契约。一般的队友诉请（`tellaskSessionless({ targetAgentId: "<teammate>", tellaskContent: "..." })`）仍按 [`dialog-system.zh.md`](./dialog-system.zh.md) 的诉请分类与能力模型执行。

如果你需要“同人设但可用工具”的支线对话，请使用一般队友诉请路径，并显式指定队友身份。

## 4. 运行时契约（必须做到什么）

本节使用“必须/不得/应/可”描述运行时的强制要求。

### 4.1 隔离与上下文

当运行时驱动由 `freshBootsReasoning({ tellaskContent: "..." })` 创建的 FBR 支线对话时，必须强制满足：

- **不依赖诉请者一侧上下文**：
  - 被诉请者不得假设能访问**诉请者一侧的对话历史**
  - 被诉请者必须把诉请正文当作主要且权威的任务上下文
- **FBR 轮次共享窗口**：
  - 同一次 `freshBootsReasoning` 启动的全部轮次共享同一套 FBR 约束上下文（无工具、无诉请上下文注入）
  - 所有轮次在同一 FBR 支线对话内连续推理，形成一段共享上下文历史，同时继续与主线对话历史隔离
- **不得通过工具补上下文**：
  - 不得读文件/跑命令/浏览
  - 不得读取 Memory 或 rtws（运行时工作区）状态

直觉上：FBR 的“初心”不是“忘掉一切系统规则”，而是“相对诉请者不继承历史”。运行时仍可能无条件注入基础规则（安全、格式、少量只读摘要等），但 **推理依据必须以诉请正文为主**。

### 4.2 无工具（提示词 + 技术强制）

FBR 的阶段性约束必须同时满足两类要求：

1. **提示词契约**：运行时必须把当前阶段的能力边界表达得明确无歧义。
2. **API/传输层契约**：发散/收敛阶段不得暴露任何可调用的 Dominds 工具；最终收口阶段只允许两个结论函数。

#### 4.2.1 system prompt 的要求（不得包含工具说明）

FBR 支线对话的 system prompt 必须明确包含（措辞可不同，但语义必须到位）：

- 这是一次 FBR 支线对话，诉请正文是主要任务上下文
- 不要假设能访问诉请者一侧的对话历史
- 若诉请正文缺少关键上下文，需要列出缺失信息与阻塞原因
- 不得发起任何诉请（包括 `tellaskBack` 或 `askHuman`）

同时，**system prompt 本体不得包含任何工具说明**（不得出现“有哪些工具/如何用工具/例子命令/白名单”等）。

#### 4.2.2 附加“无工具提示”（唯一允许的工具相关文本）

关于工具可用性的所有表达必须收敛到单独附加的一段“无工具提示”，并且：

- 该提示必须 **简短、固定、不可扩展**
- 必须明确声明：
  - 没有任何工具，不能调用工具
  - 不能访问 rtws / 文件 / 浏览器 / shell
- 不得包含任何工具清单、允许列表、示例命令或执行指导

如果提供方集成通常会注入工具提示（或工具结构），那么对 FBR 必须二选一：

- 完全不注入工具提示，或
- 仅注入与“无工具提示”**完全一致**的文本

无论如何，FBR 支线对话都不应看到任何工具定义。

#### 4.2.3 发散/收敛阶段的 LLM 请求不得暴露可调用工具

发起 `freshBootsReasoning` FBR 支线对话的发散/收敛请求必须做到没有可调用的 Dominds 工具：

- 请求 payload 中不得包含任何 tool/function 定义（有效工具列表必须为空）
- provider 工具调用/函数调用模式应使用 `none` 或最接近的禁用模式

最终收口阶段，运行时只可开放以下两个函数：

- `presentLowNoiseHighlyInformativeConclusion({ content })`
- `presentUnreasonableSituation({ content })`

并且：如果模型尝试发出其它任何 tool/function call，运行时必须视为违规并硬拒绝（见 4.5）。

### 4.3 诉请限制：一律禁止

FBR 支线对话不得发起任何 tellask 调用（包括 `tellaskBack({ tellaskContent: "..." })`、`tellask({ ... })`、`tellaskSessionless({ ... })` 或 `askHuman({ tellaskContent: "..." })`）。
若关键上下文缺失，应**列出缺口与阻塞原因**，然后直接回复。

### 4.4 输出契约（在 FBR 内部完成去噪）

FBR 支线对话应在内部完成去噪与收口，只向诉请者回贴一个最终结果。

1. **发散阶段**：对离谱、少数派、反直觉想法保持开放，不急于压成共识。
2. **收敛阶段**：自主去噪，只保留跨轮稳定共识与正文可支撑内容。
3. **最终收口**：必须以 `presentLowNoiseHighlyInformativeConclusion` 或 `presentUnreasonableSituation` 二选一结束。
4. **诉请者交付**：诉请者只接收低噪高信息结论，或“当前现状无法被合理看待”的最终结论。

### 4.5 违规与报错（必须“响亮可调试”）

- 若 FBR 支线对话尝试发起任意队友诉请，或尝试 tool/function call，运行时必须硬拒绝该次驱动。
- 反馈必须 **对用户可见、语义清晰**，并且日志/事件中应包含可检索的错误原因字符串，避免静默吞掉。

## 5. 串行语义：`fbr-effort`

`fbr-effort` 是 **按队友成员（member）配置** 的整数参数，也可以放在 `member_defaults` 里作为 rtws 默认值。

- 类型：整数
- 默认：`3`
- `0`：该成员默认禁用 FBR（当有效力度为 `0` 时必须明确报错拒绝）
- `1..100`：力度取值范围（有效力度来自显式 `effort`，未传时回退 `fbr-effort`）
- `> 100` / 非整数 / 负数：配置错误（直接报错，不做 clamp）

当 `fbr-effort = N`：

- 运行时必须把一条 `freshBootsReasoning({ tellaskContent: "..." })` 扩展为单一 FBR 支线对话内的 **N 轮发散 + N 轮收敛 + 最多 N 次最终收口重试**
- 发散轮必须切换不同视角，允许大胆但可能最终被丢弃的候选想法
- 收敛轮必须自主去噪，只保留稳定共识
- 只有完成发散轮与收敛轮之后，运行时才开放两个结论函数
- 如果模型在最终收口阶段连续 `N` 次仍不调用规定函数，运行时必须程序化地产出 `presentUnreasonableSituation` 的结果
- 诉请者最终只接收低噪结论，或“不合理现状”结论

## 6. 模型参数覆盖：`fbr_model_params`

`fbr_model_params` 用于只在驱动 FBR 支线对话时覆盖模型参数：

- 结构：与 `model_params` 完全一致（参考 `dominds/main/llm/defaults.yaml` 的 `model_param_options`）
- 作用域：仅对 `freshBootsReasoning({ tellaskContent: "..." })` FBR 生效
- 合并：建议在成员的有效 `model_params` 之上做深合并覆盖（便于只改少数字段，如 `temperature`）
- `max_tokens` 允许写成顶层 `max_tokens`，也允许写成 `general.max_tokens`；二选一，禁止同时设置

## 7. 配置示例

### 7.1 诉请正文必须自给自足

坏例（依赖外部上下文与工具）：

```text
freshBootsReasoning({ tellaskContent: "把 bug 找出来并修掉。" })
```

好例（把关键上下文写进正文）：

```text
freshBootsReasoning({ tellaskContent: "你正在做无工具的 FBR。请只使用下方文本推理。\n\n目标：判断最可能的根因，并给出 2–3 个可行修复方向。\n\n现象：\n- 点击 \"Run\" 偶发卡死 ~10 秒。\n\n约束：\n- 不能改后端协议。\n\n线索（日志/片段）：\n<粘贴相关日志或代码片段>" })
```

### 7.2 `.minds/team.yaml`

```yaml
member_defaults:
  # 默认每次 `freshBootsReasoning({ tellaskContent: "..." })` 在单一 FBR 支线对话内串行执行 3 轮。
  fbr-effort: 3

members:
  ux:
    # 每次 `freshBootsReasoning({ tellaskContent: "..." })` 在单一 FBR 支线对话内串行执行 5 轮。
    fbr-effort: 5

    # 让 FBR 更“发散”，但不影响诉请者风格。
    fbr_model_params:
      codex:
        temperature: 0.9
        reasoning_effort: medium
      general:
        max_tokens: 1200
```

## 8. 与一般支线对话的关系（避免混用）

- `freshBootsReasoning({ tellaskContent: "..." })` 的 FBR 支线对话是 **特例**：无工具、正文优先、诉请受限、可串行扩展。
- 一般的 `tellaskSessionless({ targetAgentId: "<teammate>", tellaskContent: "..." })` 支线对话仍是“完整能力”的（可按配置拥有工具与工具集）。
- 若你需要“同人设 + 可用工具”的支线，请使用显式队友身份（`tellask` / `tellaskSessionless`）。

## 9. 验收清单（实现检查点）

- `freshBootsReasoning({ tellaskContent: "..." })` 触发 FBR：发散/收敛阶段不得暴露可调用工具；最终收口阶段必须调用两个结论工具之一。
- system prompt 本体不含工具说明；工具相关文本只能来自独立、固定的“无工具提示”。
- FBR 支线对话不得发起队友诉请（包括 `tellaskBack`）。
- `fbr-effort` 默认 `3`，接受 `0..100`，禁用时明确报错拒绝。
- `fbr_model_params` 仅对 FBR 生效，且与 `model_params` 同结构、按深合并覆盖。
