fischer-agentkit/docs/plans/2026-06-24-002-feat-skill-h...

21 KiB
Raw Permalink Blame History

title status date type origin
feat: Skill 激活前置条件 + 来源标记 + 风险守卫学习 active 2026-06-24 feat SkillHarness (arXiv:2606.20636) + Agent Skills survey (arXiv:2602.12430) 对比分析

Summary

借鉴 SkillHarness 论文Macro/Micro Skill 分离、风险守卫 R、监督偏差与 Agent Skills 综述4 层门控权限模型、渐进式披露、26.1% 社区 skill 漏洞率)的观点,为 AgentKit 的 Skill 子系统补齐三个当前缺失的能力:

  1. 激活前置条件preconditions+ 来源标记provenance 作为 SkillConfig 基础设施preconditions 通过 system_prompt 注入实现软检查。
  2. 16 个存量 Skill YAML 的 preconditions 全量审查与补充(引擎模板除外)。
  3. RiskGuardLearner 从失败轨迹学习风险守卫建议,强制人工审查后应用(不自动应用)。

明确做基于轨迹的 skill 创建或边界细化L2/L3——只做 L1 风险守卫学习——因为 AgentKit 的 skill 是人工编写的 YAML论文核心问题轨迹学习导致的监督偏差在此不存在。

Problem Frame

SkillHarness 论文的核心贡献是 Macro/Micro Skill 分离 + 风险守卫 R实验显示自动从轨迹学习的 skill 有 75% 不安全,引入风险守卫后不安全 skill 减少 57.1%。Agent Skills 综述指出 26.1% 的社区 skill 存在漏洞,并提出 4 层门控权限模型与 Artifacts vs In-use 区分。

对照 AgentKit 现状:

论文观点 AgentKit 现状 差距
Macro Skill 激活前置条件preconditions SkillConfig 无 preconditions 字段;@skill:xxx 命中即无条件执行 缺失
Skill 来源标记provenance / Artifacts vs In-use SkillLoader 三种加载路径YAML / SKILL.md / entry_points均不记录来源 缺失
危险能力告警 entry_points 加载第三方 Skill 时无危险能力 warning 缺失
风险守卫 R从失败轨迹学习 EvolutionMixin 只优化 promptreflect→optimize→AB test不学习 skill 级风险守卫 缺失
4 层门控权限模型 已有 alignment 守卫v5+ quality_gate部分覆盖 部分实现
渐进式披露 已有 disclosure_levelv3 已实现
监督偏差(轨迹学习 skill skill 是人工编写 YAML不从轨迹学习 不适用(问题不存在)

关键洞察:论文的监督偏差问题在 AgentKit 不存在(人工编写 skill因此不引入 L2skill 边界细化)和 L3从轨迹创建新 skill。只引入 L1从失败轨迹学习风险守卫建议且必须人工审查。

Requirements

  • R1SkillConfig 新增 preconditions: list[str] | Noneprovenance: str 字段,完全向后兼容(旧 YAML 无字段时取默认值),from_dict / to_dict 正确序列化。
  • R2build_skill_system_prompt 在拼装基础 prompt 后追加 preconditions 段落(软检查,不增加额外 LLM 调用preconditions 为空时不改变现有 prompt 输出。
  • R3SkillLoader 三条加载路径记录 provenance"yaml:<path>" / "skill_md:<path>" / "entry_point:<ep_name>"entry_points 加载时若 Skill 声明了危险能力terminal / code_execution / file_write / shell / system_admin发出 logger.warning
  • R410 个业务 Skill YAML 审查并补充 preconditions 字段6 个引擎模板react/direct/rewoo/reflexion/plan_exec/goal_driven不需要 preconditions。
  • R5RiskGuardLearnerExperienceStore 检索失败轨迹,经 LLM 分析生成 RiskGuardSuggestionpreconditions 候选 + 理由 + 置信度),不自动应用,输出供人工审查。
  • R6CLI 新增 agentkit skill learn-risk-guards 命令,触发 RiskGuardLearner 并以 Rich 表格打印建议清单,明确标注"待人工审查"。

Key Technical Decisions

KTD1preconditions 通过 system_prompt 注入(软检查),不做硬 LLM 调用

决策preconditions 作为提示词约束注入 system_prompt由 LLM 在执行时自行判断是否满足,而非在 skill 激活前发起一次额外 LLM 调用做硬校验。

理由:硬校验会在每次 skill 激活时增加一次 LLM 调用延迟(~500ms-2s与 token 成本。AgentKit 的 @skill:xxx 路由追求零成本显式匹配(见 RequestPreprocessor Layer 0。软检查符合"显式调用即信任用户意图"的现有设计哲学preconditions 更多是引导 LLM 在条件不满足时拒绝或澄清,而非阻断路由。

代价preconditions 不是强保证——LLM 可能忽略。可接受的边界preconditions 是"激活后行为约束",不是"激活前权限门控"(后者由 alignment 守卫 v5 负责)。

KTD2RiskGuardLearner 不自动应用,强制人工审查

决策RiskGuardLearner 只生成 RiskGuardSuggestion,不写入 SkillConfig必须由人工审查后手动编辑 YAML 应用。

理由SkillHarness 论文实验显示自动从轨迹学习的 skill 有 75% 不安全。AgentKit 虽然是"学习风险守卫建议"而非"学习新 skill",但自动写入 preconditions 仍可能引入错误约束(误判失败原因 → 错误 precondition → 阻断合法调用。human-in-the-loop 是最低成本的安全保证。

代价:无法闭环自动化。可接受:风险守卫学习是低频离线操作,不是实时路径。

KTD3provenance 是轻量字符串,不做 hash/签名

决策provenance 为简单字符串(如 "yaml:configs/skills/code_reviewer.yaml""entry_point:my_rag_skill"),不做内容 hash 或签名校验。

理由AgentKit 当前无供应链合规需求provenance 的用途仅是"在日志和 skill info 中区分来源",便于排查"哪个 skill 来自第三方 entry_point"。引入 hash/签名会增加加载路径复杂度且当前无消费者。

代价:无法检测第三方 skill 被篡改。升级路径:未来若有合规需求,可在 provenance 字符串中追加 :sha256=<hash> 后缀,向后兼容。


Scope Boundaries

In scope

  • SkillConfig 新增 preconditions / provenance 字段及序列化
  • build_skill_system_prompt 注入 preconditions
  • SkillLoader 三路径记录 provenance + entry_points 危险能力 warning
  • 10 个业务 Skill YAML 补充 preconditions
  • RiskGuardLearner 新模块(仅生成建议,不自动应用)
  • agentkit skill learn-risk-guards CLI 命令

Out of scope

  • 从轨迹学习创建新 skillL3——论文监督偏差问题在 AgentKit 不存在
  • 从轨迹细化 skill 边界L2——同上
  • preconditions 的硬校验 LLM 调用——见 KTD1
  • provenance 的 hash/签名——见 KTD3
  • 4 层门控权限模型的完整实现——alignment 守卫 v5 已部分覆盖,本次不扩展
  • RiskGuardLearner 自动应用闭环——见 KTD2

Deferred to follow-up work

  • skill info CLI 展示 preconditions / provenance 字段U6 之外的小增强,可后续补)
  • RiskGuardSuggestion 的持久化存储(当前只打印,未来可存入 ExperienceStore
  • 第三方 skill 的内容签名校验(见 KTD3 升级路径)

Implementation Units

U1. SkillConfig preconditions + provenance 字段基础设施

Goal:为 SkillConfig 新增 preconditionsprovenance 字段,完成 __init__ / from_dict / to_dict 三处改造,向后兼容。

RequirementsR1

Dependencies:无(基础设施单元,后续 U2/U3/U4 依赖此单元)

Files

  • Modify: src/agentkit/skills/base.py
  • Test: tests/unit/test_skill_config_preconditions.py

Approach

  • SkillConfig.__init__ 签名末尾新增 preconditions: list[str] | None = Noneprovenance: str = "" 两个参数(放在 v6 fallback_strategies 之后,作为 v7 字段)。
  • __init__ 体内赋值 self.preconditions = preconditionsself.provenance = provenance
  • from_dict 增加 preconditions=data.get("preconditions")provenance=data.get("provenance", "")
  • to_dict 增加 d["preconditions"] = self.preconditionsd["provenance"] = self.provenance
  • 不新增校验逻辑preconditions 是字符串列表provenance 是字符串,无合法值约束)。

Patterns to followv6 fallback_strategies 字段的添加方式(src/agentkit/skills/base.py__init__ 签名、from_dictto_dict 三处对称改造)。

Test scenarios

  • Happy pathSkillConfig(name="x", agent_type="y", preconditions=["用户已登录"], provenance="yaml:test.yaml") 构造成功,字段可读。
  • Happy pathSkillConfig.from_dict({"name":"x","agent_type":"y"}) 不传新字段时,preconditions 为 None、provenance""(向后兼容)。
  • Happy pathfrom_dict 传入 preconditions 列表与 provenance 字符串时正确解析。
  • Edge caseto_dict() 输出包含 preconditionsprovenance 键,值与构造时一致。
  • Edge casepreconditions=[](空列表)与 preconditions=Noneto_dict 中区分保留。

Verificationpython3 -m pytest tests/unit/test_skill_config_preconditions.py -x -q 通过;现有 tests/unit/ 中涉及 SkillConfig 的测试不回归。


U2. build_skill_system_prompt 注入 preconditions

Goalbuild_skill_system_prompt 在拼装基础 prompt 后,若 skill_config.preconditions 非空,追加 preconditions 段落,引导 LLM 在条件不满足时拒绝或澄清。

RequirementsR2

DependenciesU1

Files

  • Modify: src/agentkit/chat/skill_routing.py
  • Test: tests/unit/test_skill_system_prompt_preconditions.py

Approach

  • build_skill_system_prompt 现有 "\n\n".join(prompt_parts) 之后,检查 skill_config.preconditions
  • 若非空列表,追加一段格式化文本(标题如 ## Activation Preconditions,逐条列出 preconditions并附一句"若任一条件不满足,请拒绝执行或向用户澄清")。
  • preconditions 为空或 None 时,返回值与现状完全一致(不改变现有行为)。

Patterns to followbuild_skill_system_prompt 现有的 prompt_parts.append + "\n\n".join 模式(src/agentkit/chat/skill_routing.py)。

Test scenarios

  • Happy pathskill_config 有 preconditions=["需要代码仓库访问权限", "当前分支非 main"] 时,输出 prompt 包含 ## Activation Preconditions 段落与两条条件文本。
  • Happy pathskill_config.preconditions 为 None 时,输出 prompt 与不传 preconditions 时完全一致(字节级)。
  • Edge caseskill_config.preconditions 为空列表 [] 时,不追加 preconditions 段落。
  • Edge caseskill_config 无 prompt 字段时,函数返回 None现有行为不变
  • Integrationpreconditions 段落出现在 identity/context/instructions 等基础段落之后。

Verificationpython3 -m pytest tests/unit/test_skill_system_prompt_preconditions.py -x -q 通过。


U3. SkillLoader 三路径 provenance 记录 + entry_points 危险能力 warning

GoalSkillLoader 的三条加载路径(_load_skill_from_file / load_from_skill_md / load_from_entry_points)在加载后设置 config.provenanceentry_points 路径额外检查危险能力并 logger.warning

RequirementsR3

DependenciesU1

Files

  • Modify: src/agentkit/skills/loader.py
  • Test: tests/unit/test_skill_loader_provenance.py

Approach

  • 在模块顶部定义 _DANGEROUS_CAPABILITIES = frozenset({"terminal", "code_execution", "file_write", "shell", "system_admin"})
  • _load_skill_from_fileSkillConfig.from_yaml(path) 后设置 config.provenance = f"yaml:{path}"
  • load_from_skill_mdSkillMdParser.to_skill_config(...) 后设置 config.provenance = f"skill_md:{path}"
  • load_from_entry_points:每个 Skill 加载后设置 skill.config.provenance = f"entry_point:{ep.name}",并检查 skill.config.capabilitiesCapabilityTag 列表)中是否有 tag 命中 _DANGEROUS_CAPABILITIES,命中则 logger.warning
  • provenance 设置在 register 之前,确保注册到 registry 的 config 已带 provenance。

Patterns to followload_from_entry_points 现有的 logger.info 日志模式(src/agentkit/skills/loader.pyCapabilityTagtag 字段访问方式(src/agentkit/skills/schema.py)。

Test scenarios

  • Happy path_load_skill_from_file 加载 YAML 后,skill.config.provenance"yaml:<path>"
  • Happy pathload_from_skill_md 加载后,skill.config.provenance"skill_md:<path>"
  • Happy pathload_from_entry_points 加载后,skill.config.provenance"entry_point:<ep.name>"
  • Error pathentry_points 加载的 Skill 声明了 capabilities: [{tag: "shell"}] 时,logger.warning 被调用且包含 skill 名与危险能力名。
  • Edge caseentry_points 加载的 Skill 无 capabilities 或 capabilities 为空时,不触发 warning。
  • Edge caseYAML 中已有 provenance 字段时,加载路径的设置覆盖它(加载路径是权威来源)。

Verificationpython3 -m pytest tests/unit/test_skill_loader_provenance.py -x -q 通过。


U4. 10 个业务 Skill YAML 审查并补充 preconditions

Goal:审查 10 个业务 Skill YAML根据每个 skill 的实际语义补充 preconditions 字段6 个引擎模板不补充。

RequirementsR4

DependenciesU1字段必须先存在

Files

  • Modify: configs/skills/code_reviewer.yaml
  • Modify: configs/skills/geo_optimizer.yaml
  • Modify: configs/skills/content_generator.yaml
  • Modify: configs/skills/competitor_analyzer.yaml
  • Modify: configs/skills/benchmark_runner.yaml
  • Modify: configs/skills/trend_agent.yaml
  • Modify: configs/skills/monitor.yaml
  • Modify: configs/skills/citation_detector.yaml
  • Modify: configs/skills/schema_advisor.yaml
  • Modify: configs/skills/deai_agent.yaml

Approach

  • 逐个审查每个业务 skill 的 identity / instructions / tools / capabilities提炼出"激活此 skill 的前置条件"(如"需要可访问的代码仓库"、"需要网络连接"、"输入必须包含待审查的代码片段")。
  • preconditions 用中文短句2-4 条为宜,聚焦"条件不满足会导致 skill 无法正常工作或产生误导"的场景。
  • 引擎模板(react_agent / direct_agent / rewoo_agent / reflexion_agent / plan_exec_agent / goal_driven_agent)是通用执行模板,不补充 preconditions。
  • 不修改 YAML 的其他字段,只新增 preconditions 键。

Patterns to follow:现有 YAML 的字段缩进与风格(如 configs/skills/code_reviewer.yaml 的 2 空格缩进、字符串引号风格)。

Test scenarios

  • Test expectation: none -- 纯配置变更,无行为代码。验证方式:SkillConfig.from_yaml 对每个修改后的 YAML 加载成功且 preconditions 字段非空(引擎模板为 None

Verificationagentkit skill list 正常加载全部 16 个 skill 无报错10 个业务 skill 的 preconditions 字段非空。


U5. RiskGuardLearner 从失败轨迹学习风险守卫建议

Goal:新建 RiskGuardLearner 模块,从 ExperienceStore 检索失败轨迹,经 LLM 分析生成 RiskGuardSuggestion 列表preconditions 候选 + 理由 + 置信度),不自动应用。

RequirementsR5

DependenciesU1preconditions 字段概念)、ExperienceStore(已存在)

Files

  • Create: src/agentkit/evolution/risk_guard_learner.py
  • Test: tests/unit/test_risk_guard_learner.py

Approach

  • 定义 RiskGuardSuggestion dataclassskill_name: strprecondition: strreason: strconfidence: floatsource_experience_ids: list[str]
  • RiskGuardLearner 类:__init__(experience_store, llm_gateway, model="default")
  • async def learn(self, skill_name: str | None = None, top_k: int = 20) -> list[RiskGuardSuggestion]
    • ExperienceStore.search(query="failure", top_k=top_k, task_type=None) 检索失败轨迹(outcome == "failure")。
    • skill_name 指定,过滤属于该 skill 的轨迹。
    • 构建 LLM prompt输入失败轨迹摘要goal / steps_summary / failure_reasons / optimization_tips要求 LLM 输出"该 skill 应补充的 preconditions 候选"JSON。
    • 解析 LLM 响应为 RiskGuardSuggestion 列表。
    • LLM 失败时返回空列表并 logger.warning(不抛异常)。
  • 明确不做:不写入 SkillConfig、不修改 YAML、不调用任何"应用"方法。

Patterns to followLLMReflectorsrc/agentkit/evolution/llm_reflector.py)的 __init__(llm_gateway, model) 签名、_sanitize_for_prompt 提示词安全处理、LLM 失败时返回默认值的容错模式。

Test scenarios

  • Happy pathExperienceStore 返回 3 条失败轨迹LLM 返回合法 JSONlearn() 返回 3 条 RiskGuardSuggestion,字段完整。
  • Happy pathskill_name 过滤生效——只返回该 skill 的建议。
  • Error pathLLM 调用抛异常时,learn() 返回空列表且不抛异常。
  • Error pathLLM 返回非法 JSON 时,learn() 返回空列表并 logger.warning
  • Edge caseExperienceStore 返回空列表时,learn() 返回空列表(不调用 LLM
  • Edge caseconfidence 字段被 clamp 到 [0.0, 1.0] 区间。

Verificationpython3 -m pytest tests/unit/test_risk_guard_learner.py -x -q 通过;模块不导入任何"写入 SkillConfig"的路径。


U6. CLI 命令 learn-risk-guards

Goal:新增 agentkit skill learn-risk-guards 命令,触发 RiskGuardLearner,以 Rich 表格打印建议清单,明确标注"待人工审查"。

RequirementsR6

DependenciesU5

Files

  • Modify: src/agentkit/cli/skill.py
  • Test: tests/unit/test_cli_skill_learn_risk_guards.py

Approach

  • skill_app 下新增 @skill_app.command("learn-risk-guards") 命令。
  • 参数:--skill(可选,指定 skill 名)、--top-k(默认 20--server-url(可选,远程模式预留,本地模式优先)。
  • 本地模式:构造 ExperienceStore(需 PostgreSQL若无则提示"需要 PostgreSQL"并退出)+ LLMGateway,实例化 RiskGuardLearner,调用 learn()
  • 用 Rich Table 打印建议:列含 Skill / Precondition / Confidence / Reason。
  • 表格上方打印醒目提示:"以下为自动生成的风险守卫建议,必须人工审查后手动编辑 YAML 应用,不会自动生效。"
  • 无建议时打印"未从失败轨迹中学习到风险守卫建议"。

Patterns to followskill list 命令的 Rich Table 构造与 rprint 模式(src/agentkit/cli/skill.pyskill list 的本地/远程双模式结构。

Test scenarios

  • Happy pathRiskGuardLearner.learn() 返回 2 条建议时,命令输出包含 Rich 表格与 2 行建议,且包含"人工审查"提示文本。
  • Happy pathlearn() 返回空列表时,命令输出"未从失败轨迹中学习到风险守卫建议"。
  • Error pathPostgreSQL 不可用时,命令打印明确错误信息并以非零码退出。
  • Edge case--skill 参数透传给 learn(skill_name=...)

Verificationpython3 -m pytest tests/unit/test_cli_skill_learn_risk_guards.py -x -q 通过;agentkit skill learn-risk-guards --help 正常显示帮助。


Risks & Dependencies

  • 依赖 PostgreSQLU5/U6 依赖 ExperienceStorePostgreSQL + pgvector。单元测试需 mock ExperienceStore不依赖真实数据库。
  • LLM 成本U5 的 learn() 会发起一次 LLM 调用,但属低频离线操作,风险可控。
  • 向后兼容U1 新增字段必须不破坏现有 16 个 YAML 加载与现有 SkillConfig 测试——通过默认值保证。
  • preconditions 软检查的局限性KTD1 明确 preconditions 不是强保证;若未来需要硬保证,需在 RequestPreprocessor._resolve_explicit_skill 中增加校验逻辑(本次不做)。
  • YAML 审查的主观性U4 的 preconditions 内容依赖人工语义判断,需逐个 skill 阅读后提炼,无法自动化。

Sources & Research

  • SkillHarness 论文arXiv:2606.20636Macro/Micro Skill 分离、风险守卫 R、监督偏差、57.1% 不安全 skill 减少。核心借鉴preconditions 概念 + 风险守卫从失败学习 + 不自动应用。
  • Agent Skills 综述arXiv:2602.124304 层门控权限模型、渐进式披露、26.1% 社区 skill 漏洞率、Artifacts vs In-use 区分。核心借鉴provenance 来源标记 + 危险能力告警。
  • AgentKit 现状代码src/agentkit/skills/base.pySkillConfig v1-v6 字段演进)、src/agentkit/chat/skill_routing.pybuild_skill_system_promptsrc/agentkit/skills/loader.py(三路径加载)、src/agentkit/evolution/llm_reflector.pyLLM 分析器模式)、src/agentkit/evolution/experience_store.py(失败轨迹检索)。
  • 外部研究未运行:本计划基于论文观点与代码现状的直接对照,未发起额外外部研究(论文已在上一轮对话中深度学习)。