关于 resolve-before-asking
Resolve Before Asking 是一项 Agent 技能,要求在询问用户某人的身份或角色前,先检查知识系统和外部来源。它规定了逐步查找流程;若仍无法确认,提问必须说明已查到的内容并给出假设。
主要功能
- 01按顺序跨来源查找身份
- 02搜索脑库和已挂载来源
- 03检查时间线与关系图
- 04向用户求助前进行外部搜索
- 05未解决时提出带假设的问题
- 06摄取时清理占位内容
适用场景
- 01确认草稿中提到的人物身份
- 02在创建实体页面时确定人物角色
- 03仅在查找无果后询问用户身份信息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ garrytan/ gbrain --skill resolve-before-asking安装后在 Claude Code 中输入/resolve-before-asking确认已加载。
附带文件routing-eval.jsonl
详细介绍
在询问用户前先解决问题——先彻底挖掘大脑,再打扰用户
**约定:**有关基础查找链(search → query → get_page → 外部 API),请参见 conventions/brain-first.md。此技能将这条链再延伸一步,直至人类边界:询问用户是最后的手段,只有在查过大脑并完成外部升级之后才可采用,不能把它当作绕过这些步骤的捷径。
**约定:**请参见 _brain-filing-rules.md——摄取解析部分涉及的页面按主要主题归档(
people/、companies/)。
目的
如果大脑中已经有答案,就绝不要问用户“X 是谁?”。
记忆应先给出答案,不必打扰人类——这是产品承诺。本技能规定了在向用户提出任何实体识别问题之前必须运行的查找链,以及确有理由询问时应采用的升级格式。
本技能要消除的问题
常见模式:Agent 遇到某个实体,而大脑中已有内容丰富的页面——包含时间线条目、会议记录和导入的消息存档——却不去阅读,反而问用户“X 是谁?”。这是懒惰的升级。它浪费用户的注意力,去问系统本可自行回答的问题。
问题示例(已匿名化):
- alice-example——她的大脑页面已记录职位(“acme-example 的幕僚长”)和详尽的会议记录 → Agent 仍然提问。
- charlie-example——一封篇幅很长的导入邮件线程,其主题行都指向同一个共享项目 → Agent 仍然提问。
何时触发
这是一项框架路由约定,并非机械保证:满足以下任一条件时,都应路由至此——
- 回复草稿中包含“谁是 [姓名]?”或类似表述。
- 草稿询问某人的职位、关系或身份。
- 你即将将某个实体描述为“未知”或“身份不明”。
- 大脑页面中含有
[To be filled by content analysis]或类似占位文本。 - 你正在编写人物列表,却将任何人的关系标为“未知”。
查找链(按顺序运行;首次得到明确答案时即停止)
步骤 1:think——跨大脑综合(可解决大多数情况)
gbrain think "Who is {entity}? What is their relationship to the user? What role do they play? Use all available context — meetings, timeline, imported archives, facts."
think 会综合所有大脑数据。如果该实体有页面,其中包含导入活动统计、时间线条目和会议记录,think 就会将这些线索联系起来。通过 MCP,entity("{entity}") 会先返回一张零 LLM 卡片(别名、最近修改时间、主要关联);如果卡片信息不足,synthesize 则会给出跨页面的深度答案。
如果此步骤返回明确答案 → 停止。使用该答案。不要询问用户。
步骤 2:search + 完整阅读页面
gbrain search "{entity}" --limit 5
gbrain get {entity-slug}
需要查看的内容:
- Frontmatter 中的
relationship字段——已填写即表示关系已确定。 - 时间线条目中反复出现的职位线索(“顾问”、“acme-example 的同事”、“幕僚长”)。
- 事实表——任何职位或关系事实。
- 会议记录——此人参加过什么会议?与谁一起参加?
如果时间线条目反复显示一致的职位 → 停止。职位已显而易见。不要询问用户。
步骤 3:查询大脑实际挂载的每个来源
不要对渠道进行硬编码。先检查大脑中有什么,再进行查询:
gbrain sources list
gbrain query "emails with {entity}" --limit 10
gbrain query "meetings with {entity}" --limit 5
无论挂载的是什么——邮件存档、日历导入、聊天记录还是会议笔记——浏览少数几条主题行或会议标题,通常就能看出双方关系:
- 发票/日程安排/账单主题 → 专业服务关系。
- 定期的一对一会议标题,且共同参会者固定 → 同事关系。
- 晚餐/周末计划消息 → 私人朋友关系。
步骤 4:遍历时间线和关系图
gbrain timeline {entity-slug} --limit 20
gbrain backlinks {entity-slug}
gbrain graph {entity-slug} --depth 2
查看有日期的事件、引用此实体的人,以及它与哪些内容相关联。从公司页面和三个会议页面反向链接到某人的,就不能算作未知人物。
第 5 步:网络搜索(外部升级,遵循脑优先原则)
仅当步骤 1–4 都没有找到有用信息时才进行。使用
"{entity name} {company/domain hints accumulated in steps 1-4}" 进行通用网络搜索。使用搜索到的任何信息前,先将其补充到大脑页面中(遵循 brain-ops 的读取、补充、写入循环),以免下次查找时重复劳动。
第 6 步:升级给用户(最后手段)——带着假设提问
仅当之前所有步骤都没有得出确定结论时:
- 说明你搜索了什么。
- 说明你找到了什么——即使只是部分线索。
- 提出一个具体、可确认的问题:不要问“X 是谁?”,而要问“{entity} 是 {best guess assembled from partial signals} 吗?”
使用 ask-user 处理选择环节的机制(2–4 个选项、提供退出选项、结束本轮)。
置信度阈值
- 高置信度(不要提问):
think/synthesize给出了明确答案,或有 3 条以上时间线记录对角色的描述一致,或页面的关系字段已填写。 - 低置信度(提问,以最佳猜测开头): 线索相互矛盾或数据极少。应当提问,但问题开头要先说出你的假设;如果存在矛盾,也要说明。
没有第三种情况。要么大脑给出了答案(使用它),要么没有(完成整个流程,然后带着假设提问)。
摄取时不得保留占位内容
当任何摄取管道(邮件导入、日历信息补充、聊天记录、会议摄取)创建或显著更新个人或公司的页面时,应立即确认实体身份和关系——绝不能留下占位文本。以下页面内容都是缺陷:
[To be filled by content analysis]> Contact from the user's personal network.- 空的
## Context部分
尤其是在摄取批次本身包含数百条有关此人身份的线索时。对批次创建或更新的每个页面执行摄取后检查:
- 检查占位内容。 扫描已修改的页面,查找标记(
[To be filled、Unknown relationship、TBD)。没有占位内容且关系字段已填写 → 跳过,表示已解决。 - 运行流程(上述步骤 1–4;在摄取时,通常只需步骤 1,因为批次刚刚写入了
think所需的线索)。 - 提取信息: 关系类型(朋友/同事/顾问/家人/创始人)、职业角色(职位 + 公司)、关键信息(如何认识用户、哪个时期)。
- 更新页面(
put_page):填写relationshipfrontmatter 字段,将占位描述替换为真实的一句话描述,并更新## Context或介绍段落。 - 提高批量处理效率,适用于批量运行(100 个以上页面):每批处理 10–20 个;按捕获的活动量优先处理(活动越多,用户越可能在简报中遇到这个名字);跳过内容已充实的页面。
邮件域名捷径(用于生成假设,而非证明)
运行流程前,发件人的域名通常可以作为假设的起点:
| 域名形式 | 假设 |
|---|---|
@acme-example.com — 大脑中已有的公司 | 很可能是 acme-example 的员工。对照公司页面和共同参加的会议进行确认,然后填写信息。 |
| 大脑中没有的企业域名 | 新公司。运行流程;考虑创建 companies/ 页面。 |
| 个人域名(gmail 等) | 没有捷径——运行完整流程。 |
质量标准
通过验证的页面应满足以下标准:如果用户在简报、分诊或会议准备中遇到这个名字,页面的第一行就能说明此人是谁,用户无需再询问。
- 不好:
> Contact from the user's personal network. - 好:
> Operations lead at acme-example — handles invoicing and vendor onboarding for the user.
约定
此技能保证:
- 在针对该实体运行完查找链(步骤 1–5)之前,不会向用户提出任何身份、角色或关系问题。
- 每次升级都会说明搜索了什么、发现了什么,并以假设开头——绝不会只问一句“X 是谁?”。
- 此技能涉及的页面在一次摄取批次结束后不会残留任何占位文本;关系/角色字段会在写入时填好。
- 写入内容只会落在
writes_to:目录下,并根据_brain-filing-rules.md按主要对象归档。 - 保留隐私约定:示例中不出现真实姓名、特定分支的文件系统路径字面量或上游分支引用。
输出格式
有两种可能的输出:
(a) 静默解析——在当前流程中使用该身份;如果页面上有占位内容,则将其填好(put_page)作为副作用。不向用户发送有关查找的消息。
(b) 带有假设的升级——按照询问用户的选择门控格式:
🔀 **Is {entity} the {best guess}?**
Searched: think, search + page read, mounted sources, timeline/graph, web.
Found: recurring invoices from @widget-co.com; two meetings alongside the
acme-example team. Nothing names their role directly.
1. **Confirm** — {entity} is {best guess}
2. **Correct me** — it's someone else (tell me who)
3. **Skip** — leave unresolved for now
发出门控后,结束本轮(参见 ask-user)。
失败时的处理
遇到任何 gbrain 错误 code、退出码、[AGENT] 块或通知块时,遵循Agent 操作者协议。此技能的具体处理方式:
- 所有查找结果均为空且带有降级通知:仅关键词搜索可能无法找到该实体。应在可确认的问题中说明这一点,而不是直接冷不丁地问“X 是谁?”。
- 对猜测的 slug 调用
get_page返回page_not_found:在判断该实体未知之前,先尝试按标题和别名搜索。 - 填写页面时返回
revision_conflict:重新读取并合并。
反模式
- ❌ 未事先查找就问“X 是谁?”。
- ❌ 脑中的页面已有数十条时间线记录,却问“他们和你的关系是什么?”。
- ❌ 未对每个未知对象逐一运行查找链,就列出一串未知项。
- ❌ 页面对应的摄取批次已有数百条信号,却仍留下
[To be filled by content analysis]。 - ❌ 询问某个电子邮件地址已透露其雇主的人(
[email protected])。 - ❌ 使用
memory_search查找实体——记忆工具搜索的是会话笔记,而不是脑知识图谱;brain-first.md 明令禁止这样做。应使用search/query/entity。 - ❌ 将
search的非零命中数视为查找链已完成——应阅读页面;在断定“脑中没有此信息”之前,先用query搜索同义表述。 - ❌ 带着不实的确信升级:部分信号只是一个假设,并非结论。若信号相互矛盾,升级内容应说明矛盾之处。
去重(明确边界)
- query — 负责查找操作的机制(3 层搜索、综合、引用),用于回答用户的问题。本技能使用相同的工具,但负责的是一项决策,而非查找:是否允许就身份问题向用户提问。
- brain-ops — 负责每次与脑库交互时通用的读取-补充-写入流程。本技能把守该流程的一个特定出口:向用户询问身份问题。
- ask-user — 负责如何提问(选择门格式、选项限制、结束本轮)。本技能负责判断提问是否合理,以及问题必须包含什么(已搜索/已发现/假设)。
- enrich — 负责按照分层补充协议创建和更新实体页面。本技能中的“摄取时不留占位符”一节是这些写入必须达到的验收标准;需要填补占位符时,执行本技能的流程链,然后按照 enrich/brain-ops 约定写入。
- conventions/brain-first.md — 负责所有查找中优先查询脑库、再调用外部 API 的顺序。本技能沿用这一顺序,并增加最后一道边界:先查外部信息,再询问用户。
- 创建实体前的去重防护(创建新页面前进行语音匹配/别名匹配)属于不同的故障类别——该防护在写入时防止重复页面;本技能在提问时防止不必要的问题。如果/当其发布时,应交叉引用,而不是合并。
标准
用户看到这个人的脑库页面——导入的档案、暴露雇主信息的电子邮件域名、反复提及同一职位的时间线条目——会觉得 Agent 询问这个人是谁是合理的吗?
如果答案是否定的,就说明没有执行这条流程链。执行它。