Skill 技能系统(ai-engine)
本页以 ai-engine 当前实现为准,解释:
- Skill 在仓库中长什么样(目录结构)
- Skill 如何被选择与执行
- Skill 输出如何被强校验(不合法即失败)
- 如何触发“卡片中断(ask_user)”
1) Skill 的目录结构
ai-engine 的技能都在 .skills/ 目录下,每个技能是一个目录:
ai-engine/.skills/<skill-name>/
SKILL.md # 提示词与业务规则(人读/可审查)
skill.meta.json # 机器可读元信息(触发/依赖/工具/模型配置)
assets/output_schema.json # 输出 schema(约束 data 字段;profile 字段由 provides 收敛)
scripts/ # 可选:preprocess / postprocess / validate 等
cases.yaml # 可选:技能用例(回归/评测)
references/ # 可选:知识参考(markdown,按 token 预算截断加载)
一个典型技能(示例:litigation-intake)具备:
skill.meta.json:声明 tools、outputs.provides、execution_config(model/provider/temperature/…) 等assets/output_schema.json:声明data.*允许的字段与类型
2) skill.meta.json:声明式元信息
技能的核心元信息示例(摘录,具体以仓库为准):
{
"name": "litigation-intake",
"description": "诉讼案件受理:抽取当事人/事实/诉请/证据线索;信息不足则发起补问卡片。",
"triggers": {
"contexts": ["matter"],
"state_conditions": ["state.profile.intake_status != 'completed'"]
},
"requires": {
"all": ["state.matter_id != null"]
},
"tools": ["file__get_info", "file__parse", "element__extract"],
"outputs": {
"provides": [
"profile.summary",
"profile.plaintiff",
"profile.defendant",
"profile.facts",
"profile.claims",
"profile.intake_status"
]
},
"execution_config": {
"provider": "openrouter",
"model": "qwen/qwen3-32b",
"temperature": 0.2
}
}
关键点:
tools决定该技能允许调用哪些工具(tool handler)。outputs.provides是 profile 可写字段的单点真源(禁止在 schema 漂移)。execution_config决定该 skill 用哪个模型/网关与采样参数(按技能可差异化)。
3) output_schema.json:输出 schema(强收敛)
assets/output_schema.json 主要用于约束 data 部分(data 叶子字段),示例(摘录):
{
"properties": {
"data": {
"properties": {
"evidence_list": {
"type": "array",
"items": { "type": "object" }
}
}
}
}
}
实现上的收敛规则(重要):
data字段:以output_schema.json为唯一真源profile字段:以skill.meta.json.outputs.provides为唯一真源(加载 schema 时会把 profile.properties 重写为 provides 列表)
这能避免“提示词/文档更新导致写入字段漂移”,保证工作流门控(gate/checkpoints)不被悄悄破坏。
4) 统一输出契约:四段结构(无兜底)
每个技能最终必须输出一个 JSON 对象,且顶层必须且仅包含四段:
{
"response": "给用户/律师看的自然语言回复",
"profile": { "..." : "画像增量(合并到 state.profile)" },
"data": { "..." : "业务数据增量(合并到 state 顶层字段)" },
"control": {
"action": "continue|retry|ask_user|finish",
"review_type": "clarify|select|confirm|phase_done",
"questions": [
{
"question": "问题文本",
"field_key": "回填字段(支持点路径,如 profile.plaintiff.name)",
"input_type": "text|select|multi_select|boolean|file_ids",
"required": true,
"options": [{"label": "选项", "value": "xxx"}]
}
],
"retry_prompt": "retry 时的重试提示"
}
}
约束:输出不满足 schema/契约时,技能直接失败,外层不会做“自动修正/兜底拼接”。
5) 执行流程(简化)
flowchart TB
P[Workflow Router 选择 next_skill] --> R[SkillRunner 执行]
R --> C[构建上下文: state + SKILL.md + references]
C --> L[LLM 调用 + tool calls]
L --> V[输出校验: schema + validate.py]
V -->|pass| O[产出 skill_result]
V -->|fail retry| L
V -->|fail ask_user| H[中断/卡片]
校验链路(典型):
assets/output_schema.json(通用结构校验)scripts/validate.py(可选:业务规则校验;返回 continue/retry/ask_user)
6) 工具系统(tool handlers)
技能通过 tool calls 访问外部世界。当前常见工具前缀:
file__*:文件信息/解析(对接 files-service)matters__*:事项读写(对接 matter-service)knowledge__*:知识检索(对接 knowledge-service)element__*:要素/案由相关的结构化能力(对接 knowledge-service internal element 工具)memory__*:记忆与事实(对接 memory-service)
每个技能可用哪些工具由 skill.meta.json.tools 显式声明。
7) ask_user:卡片中断的唯一入口
当技能需要用户/律师补充信息或做选择时:
- 技能输出
control.action = "ask_user" - ai-engine 发出
event=card - 上游(consultations-service)将其转发给前端
- 前端提交
/resume后继续执行
协议与事件转发参见:implementation/card-interaction.md。
8) 测试与回归(ai-engine)
ai-engine 的 pytest markers(来自 pyproject.toml):
L1:Prompt 渲染测试L2:脚本逻辑测试L3:语义评估测试integration:需要真实 LLM 调用的集成测试
建议在变更 skills/workflow_graph 后至少跑 L1/L2,避免输出契约漂移导致流程卡死。