Skill 沉淀策略调整方案
日期:2026-06-25
背景判断
当前用户大量使用 HiPilot 做查数、指标分析、数据口径确认等任务。这类任务很容易因为多轮查表、查 ontology、试错 SQL、字段匹配等原因触发大量 tool call,轻松超过 10 次。
但在数据字典和 ontology 还不够准确的阶段,tool call 数高并不代表这次流程值得沉淀。它很多时候反而说明:
- 数据口径不清
- 字段或指标匹配不稳定
- ontology 命中不准
- Agent 在多次 fallback / retry 后才得到一个看似合理的答案
- 用户并没有确认这个流程可长期复用
所以现在最大的问题是:现有逻辑容易把“复杂执行”误判成“可复用方法”。
Skill 不应该沉淀“这次查出来的结果”,而应该沉淀“稳定、可重复、可验证的工作方法”。查数类任务尤其不应该只因为 tool call 多就自动建议保存为 Skill。
核心原则
- tool call 数只能是弱信号
tool call 多只能说明过程复杂,不能说明过程正确。查数场景下,tool call 多经常是负向信号。
- 可验证正确性优先于复杂度
如果本次回答依赖不确定的数据口径、模糊字段匹配、低置信 ontology 或 SQL 多次修正,就不应该沉淀。
- 用户认可比 AI 自评更重要
模型觉得自己答对了不算。沉淀应该依赖明确用户信号,例如用户说“以后都按这个流程来”、点赞、复制、反复复用等。
- 查数沉淀应与通用 Skill 分开
查数更适合沉淀为 Query Recipe / Metric Recipe / Metric Contract,而不是直接沉淀为通用 Skill。
- 自动沉淀应先观察,再候选,再草稿
不应从一次复杂对话直接跳到 UserSkillDraft。中间应该有 observe / candidate 阶段。
- 策略不能依赖人工逐条标注
人工抽样可以作为以后校准手段,但不应成为主流程前置条件。新方案默认不要求人工给 observation 打指标,而是依赖自动信号、重复出现、无负向信号和用户自然反馈来推进候选。
负向 Gate
只要出现下面任一信号,就不应主动生成 Skill 草稿:
- 任务是查数、SQL、指标分析、数据口径确认、ontology 依赖任务
- ontology 命中低置信度
- ontology unmatched / ambiguous
- 数据字典字段靠猜测或 fuzzy match
- 表、字段、指标口径未明确确认
- SQL 多次报错或多次 retry
- 结果依赖 fallback schema
- 用户纠错过结果
- 最终回答包含“可能 / 大概 / 需要确认 / 未核到 / 口径不确定”
- 没有明确数据来源、指标口径、时间范围
- 用户只是一次性说“查一下 / 算一下 / 看一下”
正向信号
比较可靠的沉淀正向信号包括:
- 用户明确说“把这个沉淀成 Skill”
- 用户说“以后都按这个流程来”
- 用户点赞、采纳、复制、导出结果
- 同一个用户多次重复类似任务
- 多个用户在同类场景重复使用
- 后续调用结果稳定,没有被用户纠错
- 输出有清晰来源、口径、时间范围、步骤和失败兜底
当前状态
当前已经从止血态推进到“策略守门 + observe-only + 自动候选聚合 shadow mode + 用户主动沉淀灰度代码态 + 自动草稿低打扰代码态”:
USER_SKILL_ACTIVE_SEDIMENT_ENABLED=falseUSER_SKILL_REVIEWER_ENABLED=false- 被动 reviewer 不创建 review job / draft
- runtime 默认不暴露
propose_skill_from_recent_turns /my-skills/package禁止创建草稿- pending draft confirm 被拒绝
- SkillsTab 不展示空的 Agent 沉淀入口
- 旧卡保存会变为 expired
- 已新增
user_skill_sediment_policy.py - 已新增 observe-only observation 表
- QA 可通过
USER_SKILL_SEDIMENT_OBSERVE_ENABLED=true只记录策略判定 - observation 记录结构化信号,不存用户正文和 tool result 正文
- 已新增
user_skill_sediment_candidates候选聚合表 - observe-only worker 会在记录 observation 后同步更新 candidate
- candidate report 可查看
collecting / ready_for_review / suppressed候选分布 - candidate key 已包含
intent_signature_hash,只存 hash,不存用户原文 - Phase 4 主动沉淀代码已落地,但默认关闭;只有显式打开 active 开关且 policy allow 才创建
UserSkillDraft和聊天保存卡片 - Phase 5 自动草稿代码已落地,但默认关闭;只有 mature candidate 且存在正向信号时才创建低打扰草稿,不主动发聊天卡片
这一步是正确的,建议继续保持用户侧沉淀关闭。后续不要把“人工标注 observation”作为必经步骤;QA/灰度可以按需只开 observe 或 active 做验证,生产默认继续关闭。
从当前形态到长期形态的 Phase
Phase 0:保持关闭,止血态
目标:不再新增错误沉淀。
状态:已完成。
- 被动 reviewer 不启动
- 主动沉淀 tool 不暴露
- API 层阻断创建 UserSkillDraft
- 历史 pending 卡片保存时变为不可保存状态
- 已启用 Skill、官方 Skill、用户手动导入/编辑 Skill 不受影响
这一阶段不需要继续扩展功能,只需要确保开关默认关闭。
Phase 1:新增沉淀策略判定层,但不打开沉淀
目标:先把“什么不该沉淀”固化成代码和测试,不改变用户体验。
状态:已完成。
已新增纯策略模块:
app/services/user_skill_sediment_policy.py
输入:
- 最近 AgentRun
- tool trace
- final answer
- trigger source
- 用户 hint
输出:
{
"decision": "block" | "observe" | "allow",
"task_kind": "data_query" | "research" | "workflow" | "unknown",
"reasons": [...],
"signals": {...}
}
第一版只做 hard block,不做复杂评分:
- data query / SQL / metric / ontology 相关任务默认 block
- ontology unmatched / ambiguous block
- schema fallback / fuzzy match / unknown field block
- SQL 多次 error / retry block
- final answer 有不确定措辞 block
这一阶段不创建草稿、不展示卡片,只建立策略和测试。
Phase 2:自动 observation,不要求人工打标
目标:系统自动记录每次策略判定,作为后续候选聚合的事实输入,但不要求人工逐条标注。
实现方式:
- 新增
user_skill_sediment_observations - worker 在 observe-only 开启时记录 policy result
- 记录字段只包含结构化信号:
- tenant_id / user_id / agent_id / channel_id - trigger_source - policy_version - decision / task_kind / confidence - reasons_json / signals_json / tool_names_json - run_ids_json / run_ids_hash
- 不存用户消息正文
- 不存 tool result 正文
- 不创建
UserSkillReviewJob - 不创建
UserSkillDraft - 不展示
skill_proposal卡片
状态:已完成基础能力,QA 可打开 observe-only。
注意:原先考虑的“人工给 observation 标 good_candidate / bad_candidate / unsure”不再作为主方案要求。相关能力即使存在,也只作为可选调试工具,不进入日常流程。
Phase 3:自动候选聚合 shadow mode
目标:不依赖人工标注,从 observation 中自动聚合同类重复任务,形成候选模式,但不打扰用户。
状态:代码已完成,待部署后观察。
实现方式:
- 新增
user_skill_sediment_candidates - 按自动 fingerprint 聚合 observation,例如:
- tenant_id / user_id / agent_id - task_kind - stable tool pattern - reason profile - normalized intent signature hash(只存 hash,不存用户正文)
- 只接收
decision in ("observe", "allow")且无 hard risk 的 observation - hard risk 包括:
- data_query_tool_used - ontology_unmatched_or_ambiguous - data_query_error - tool_result_error - user_correction_seen
- candidate 记录:
- seen_count - first_seen_at / last_seen_at - supporting_observation_ids - positive_signal_count - negative_signal_count - status = collecting | ready_for_review | suppressed
seen_count >= 3且 negative_signal_count = 0 时,才进入ready_for_review- 本阶段只提供 report,不创建 draft/card
这一阶段已经完成代码实现。部署后只需要验证 candidate 是否按预期累计:查数类不生成 candidate,研究 / workflow 类重复稳定出现后进入 ready_for_review。
Phase 4:恢复用户主动沉淀,但必须经过 candidate / policy gate
目标:用户明确说“沉淀成 Skill”时,可以恢复路径,但不再直接打包最近一次对话。
状态:代码已完成,默认关闭,待 QA/灰度验证。
实现方式:
- 新增
USER_SKILL_ACTIVE_SEDIMENT_ENABLED独立开关 propose_skill_from_recent_turns继续调用 policydecision=block时不创建UserSkillDraftdecision=observe时只记录 / 更新 candidate,不创建草稿decision=allow也要检查:
- 不是查数 / ontology 风险任务 - 没有 tool error / data error / 用户纠错 - 最终回答没有“可能 / 大概 / 需要确认 / 未核到 / 口径不确定 / 待确认”等不确定性措辞 - 有明确用户意图或已有 ready candidate
- 满足条件才进入
generate_skill_from_context - 否则返回清晰解释:
这次流程还不适合保存为 Skill。我会先把它作为候选模式继续观察;
等同类流程多次稳定出现后,再建议沉淀。
这一阶段仍然不打开后台自动沉淀,只恢复用户主动要求的路径。
Phase 5:多次成功后才自动进入草稿
触发条件从:
tool_call >= 10
改为:
同类任务重复出现
+ 无负向信号
+ 有自动正向信号或用户自然正向信号
+ 多次输出稳定
只有满足这些条件时,才创建低打扰 UserSkillDraft,进入 SkillsTab「Agent沉淀」。本阶段不主动在聊天里发自动建议卡片。
状态:代码已完成,默认关闭,待 QA/灰度验证。没有人工标注数据时,自动草稿阈值必须更高:
- seen_count >= 5
- 最近 14 天内重复出现
- negative_signal_count = 0
- 存在
intent_signature_hash - 至少 1 个正向信号。当前代码第一版只认
allow/explicit_request;复制、导出、点赞等自然行为信号后续再接入
Phase 6:查数类任务独立为 Query Recipe / Metric Contract
目标:查数不要沉淀成通用 Skill,而是进入单独体系。
建议新增概念:
QueryRecipeMetricRecipeMetricContractDataWorkflowRecipe
它保存的不是通用方法,而是:
- 指标口径
- 数据源
- 表 / 字段映射
- 维度范围
- 时间口径
- SQL 模板
- 验证样例
- owner / reviewer
查数类任务最终应该进入这个体系,而不是直接进入 Skill。
推荐实施顺序
- Phase 0 + Phase 1:已完成
关闭用户侧沉淀,并把“查数 / ontology 不确定不能沉淀”的规则落代码和测试。
- Phase 2:已完成基础 observe-only
记录 observation,但不要求人工打标,不创建草稿。
- Phase 3:自动候选聚合 shadow mode 已完成代码实现
不依赖人工标注,从 observation 自动累计重复模式,只出 report,不打扰用户。待 QA/灰度打开 observe 后验证真实分布。
- Phase 4:恢复用户主动沉淀代码已完成
用户明确要求时,可以通过 policy + candidate gate 创建草稿;不符合条件则只进入候选观察。默认关闭,待 QA/灰度验证。
- Phase 5:自动草稿低打扰代码已完成
没有人工标注数据时,自动草稿阈值必须更高,且默认只对非查数、非 ontology 风险任务开放。默认关闭,待 QA/灰度验证。
- Query Recipe / Metric Contract 单独立项
这会牵涉 ontology、数据字典、SQL template、metric governance,边界比 Skill 沉淀更大,不建议和 Skill gate 混在一个 PR 里。
Phase 3 Implementation 状态
Phase 3 已按以下范围完成代码实现:
- 新增
user_skill_sediment_candidates表 - 新增 candidate 聚合服务
- observe-only worker 记录 observation 后同步更新 candidate
- 新增 candidate report 脚本
- 不打开
USER_SKILL_REVIEWER_ENABLED - 不恢复 runtime tool
- 不改 mobile UI
- 不创建
UserSkillDraft - 不展示
skill_proposal - 不影响已有 Skill 使用和用户手动导入
第一版 candidate gate 识别:
- 同一 user + agent 下重复出现的非查数研究 / workflow 模式
- 无 data_query / ontology / tool_error / correction hard risk
- 有
intent_signature_hash时才允许进入自动草稿 gate - seen_count >= 3 才进入
ready_for_review
验收标准:
- 查数任务即使多次出现,也不会成为 Skill candidate
- 普通研究型/流程型任务多次稳定出现后进入 ready candidate
- 只生成 candidate/report,不生成 draft/card
- 不需要人工标注 observation
- 现有用户侧沉淀关闭态不被破坏
当前代码态后的 QA / 灰度建议
下一步建议不要直接打开生产自动沉淀,而是分开验证三个开关:
- QA/灰度只开
USER_SKILL_SEDIMENT_OBSERVE_ENABLED=true USER_SKILL_REVIEWER_ENABLED=false保持关闭- 查数类 run 不生成 candidate
- 研究 / workflow 类重复 3 次后 candidate 进入
ready_for_review UserSkillDraft、聊天卡片、runtime tool 均没有恢复- 单独打开
USER_SKILL_ACTIVE_SEDIMENT_ENABLED=true验证:用户明确要求 + clean allow 才生成草稿和卡片;查数、tool error、ontology 风险、最终回答不确定都不生成草稿 - 只有在确认 candidate 分布可靠后,才考虑 QA 打开
USER_SKILL_REVIEWER_ENABLED=true验证低打扰自动草稿;自动草稿必须满足 seen_count >= 5、14 天内重复、无 negative、存在 intent hash、positive_signal_count >= 1
生产默认继续关闭 active/reviewer。observe 是否打开由部署侧单独决定。
结论
Skill 沉淀的核心不应该是“复杂度”,而应该是:
可验证正确
+ 可复用
+ 用户认可
+ 无数据口径不确定性
查数类任务尤其要谨慎。短期应继续关闭自动沉淀,先建立 policy gate;中期恢复用户主动沉淀但加拦截;长期把查数沉淀拆到 Query Recipe / Metric Contract,而不是塞进通用 Skill。
更新后策略:不再依赖人工 observation 标注。系统可以继续自动记录 observation,但下一步重点是自动候选聚合,而不是要求运营或产品逐条打 good_candidate / bad_candidate / unsure。