技能
技能打包可重用的专业知识——用 markdown 编写的指令,可选地带有支持文件——智能体仅在需要时加载它。工具执行应用程序代码,而技能教授程序。
技能遵循开放的智能体技能格式,因此为 Flue 编写的技能可以在其他支持该格式的运行时中工作,第三方技能可以原样放入你的智能体中。
什么是技能?
每个技能有三个部分:
name— 短标识符(refunds、review-pr),模型用它来激活它。description— 一两句话说明技能做什么_以及何时使用它_。这是模型始终看到的唯一部分,因此它承载整个路由决策。instructions— 完整的程序,仅在激活时加载。
技能还可以携带支持文件——清单、模板、参考文档——这些文件保持未加载状态,直到模型显式读取其中一个。
技能是渐进式披露的:每个挂载的技能在系统提示中只占用一行始终存在的目录行(名称 + 描述),直到模型判断手头的任务匹配时才会有更多内容。然后它激活技能,接收完整的指令,并仅在需要时读取支持文件。智能体可以携带数十个技能,而无需在每个回合为它们的内容付费。
编写技能目录
磁盘上的技能是一个包含 SKILL.md 文件的目录。frontmatter 包含名称和描述;markdown 正文是指令。目录中的任何其他内容都成为支持文件:
src/skills/refunds/
├─ SKILL.md # frontmatter + 指令
└─ POLICY.md # 支持文件,仅在读取时加载
---
name: refunds
description: 端到端处理客户退款请求。当客户要求退款或对收费提出异议时使用。
---
对每个退款请求遵循此程序:
1. 确认订单 ID 和退款原因。
2. 读取 `POLICY.md` 并检查该原因的资格规则。
3. 如果符合资格,使用 `issue_refund` 工具处理退款并向客户确认金额。
4. 如果不符合资格,解释适用的规则并提供政策中列出的替代方案。描述是模型在判断技能是否适用时读取的内容——说明能力和触发条件(“当…时使用”)。保持 SKILL.md 专注于程序,并将大量参考资料移入指令指向的支持文件中。
Frontmatter 字段
Flue 根据智能体技能规范验证每个 SKILL.md,无论技能是导入的还是在工作空间中发现的:
name(必需)— 小写字母、数字和连字符;不能有前导、尾随或连续的连字符;最多 64 个字符;必须与技能目录名称匹配。description(必需)— 非空,最多 1024 个字符。告诉智能体技能做什么以及何时使用它。license(可选)— 接受;仅供参考。compatibility(可选)— 接受;最多 500 个字符;仅供参考。metadata(可选)— 接受;字符串到字符串的映射;Flue 不解释。allowed-tools(可选)— 接受,不强制执行。该字段在智能体技能规范中是实验性的,支持可能因实现而异;Flue 为兼容性携带它但不对其采取行动。
安全说明:
allowed-tools列出了技能作者期望使用的工具。它不限制技能可以调用什么,因此请在你自己的工具和审批门中强制执行授权。
未知的 frontmatter 字段会被忽略,因此携带额外主机特定字段的技能仍然可以加载。如果你想要更严格的编写检查,规范的 skills-ref 验证器会标记未知字段。
导入和挂载技能
通过其模块说明符导入 SKILL.md 文件,就像任何其他模块一样。在构建时,Flue 识别导入,验证 frontmatter,并将整个目录与你的应用程序打包在一起。导入的值是类型化的 SkillReference;使用 useSkill hook 挂载它:
'use agent';
import { useModel, useSkill } from '@flue/runtime';
import refunds from '../skills/refunds/SKILL.md';
export function SupportAgent() {
useModel('anthropic/claude-haiku-4-5');
useSkill(refunds);
return '清晰准确地回答客户支持问题。';
}没有注册步骤,没有运行时文件复制——导入就是声明,它在你的项目构建的任何地方都有效:开发服务器、vite build 和 flue run。SKILL.md 和 .md 导入的类型声明随 @flue/runtime 一起提供,在开发中,编辑技能目录中的任何文件会自动获取更改。
从包导入的工作方式相同:
import review from '@acme/review-skills/review/SKILL.md';
包必须发布 SKILL.md 及其支持文件;如果它定义了包导出,它必须导出导入的 SKILL.md 子路径。
一些需要知道的规则:
- 技能导入必须是静态的——动态的
import('./skills/x/SKILL.md')是构建错误。 - 每个技能名称每渲染挂载一次;挂载同名两次会抛出异常。
- 打包会跳过仓库噪音(
node_modules、.git、dist及类似内容),对超过 1MB 的文件发出警告,并拒绝打包密钥——.env文件、私钥、凭据存储和符号链接是硬错误。
挂载可以是条件性的,像每个资源 hook 一样——用持久化状态控制 useSkill(...) 以在对话中途解锁技能。运行时向模型宣布目录更改而不使你的缓存提示失效;请参阅动态资源了解机制。
使用 defineSkill 的内联技能
当内容很短、生成的或从数据组装时,使用 defineSkill(...) 在代码中声明技能:
import { defineSkill } from '@flue/runtime';
export const escalation = defineSkill({
name: 'escalation',
description:
'将未解决的案例升级给人工专家。当客户要求人工服务或问题超出范围时使用。',
instructions:
'总结到目前为止的案例,用升级原因标记对话,并使用 `escalate_case` 工具进行交接。',
});将结果传递给 useSkill(escalation),就像导入一样。定义等同于技能目录:instructions 是 SKILL.md 正文,可选的 files 映射携带按相对路径键控的支持资源:
const reviewSkill = defineSkill({
name: 'review-pr',
description: '根据团队清单审查拉取请求。当被要求审查代码时使用。',
instructions: '读取 CHECKLIST.md,然后根据每个项目审查差异。',
files: { 'CHECKLIST.md': checklistText },
});
defineSkill 验证定义并返回冻结的版本——定义时不会发生打包。当技能首次需要时,运行时将其打包成与 SKILL.md 导入产生的相同形状,自己编写规范有效的 frontmatter。
defineSkill 也可以转换不命名为 SKILL.md 的 markdown。裸的 .md 导入作为普通字符串加载——没有任何东西被打包——因此通过 defineSkill 传递它以使其成为技能:
import { defineSkill } from '@flue/runtime';
import runbook from './incident-runbook.md'; // 普通 markdown 文本
export const incidents = defineSkill({
name: 'incidents',
description:
'运行事件响应程序。当报告中断或安全事件时使用。',
instructions: runbook,
});
useSkill(...) 也接受直接在调用中编写的定义对象,具有相同的验证。请参阅 SkillDefinition 了解每个字段和约束。
激活如何工作
挂载的技能出现在系统提示的可用技能部分——每个技能一行,名称和描述。与此同时,运行时提供一个 activate_skill 工具。当模型判断任务匹配技能的描述时,它用技能的名称调用工具,并接收完整的指令作为工具结果。
因为指令作为工具结果到达,当技能激活时系统提示永远不会改变,提供商的缓存提示前缀得以保存。激活未知名称不是错误——结果列出了可用的技能。
因为激活是工具调用,你的指令可以引导它:
useSkill(refunds);
return '在处理任何退款请求之前激活 `refunds` 技能。';
相同的工作也可以从应用程序代码完成。运行时工具的 harness.prompt(...) 使用智能体的渲染配置运行——相同的系统提示、技能目录和工具——因此在提示文本中命名技能就足以让模型在那里激活它,包括工作空间发现的技能。
对于智能体应该_始终_拥有的内容,不要使用技能:将 markdown 作为字符串导入并折叠到你的指令中,或传递给 useInstruction(...)。
运行时的支持文件
打包技能的支持文件在你的应用程序包中传输,而不是在智能体的工作空间中。没有任何东西被复制到沙盒中:运行时在虚拟路径以只读方式提供每个文件,激活简报列出每个资源及其读取的确切路径。模型的文件读取工具透明地解析这些路径——包括运行时在挂载技能携带支持文件时添加的 read_skill_resource 工具——而工作空间本身保持不变。
相同的包在你的笔记本电脑上、Node.js 中或 Cloudflare 上提供相同的文件——无需每个环境的文件系统设置,智能体永远不能意外编辑自己的技能内容。
工作空间技能
带有沙盒的智能体还有一种获取技能的方式:从其工作空间发现。在会话开始时,运行时扫描沙盒工作目录中的 .agents/skills/,它找到的每个有效的 <name>/SKILL.md 都会加入目录,与你声明的技能并列——无需导入,无需 useSkill(...) 调用:
<cwd>/.agents/skills/
└─ greet/
└─ SKILL.md
工作空间技能留在工作空间中。它们的指令在激活时从磁盘读取——因此会话中的编辑会被获取——它们的支持文件是模型直接读取的普通工作空间文件。格式错误的工作空间 SKILL.md 会被跳过并发出警告,而不是使会话失败(相比之下,导入的技能在构建时被严格验证,其中错误是可操作的)。名称与声明技能冲突的工作空间技能是错误的。
当专业知识随工作空间一起提供时使用工作空间技能——仓库签出、CI 环境或为任何在其中工作的智能体准备的运行时工作空间——当它属于你的应用程序时使用声明技能。