Fabric agility_story 模式解析:基于结构化提示词生成敏捷用户故事与验收标准
Fabric 项目中的 agility_story 是一个专注于敏捷开发(Agile)场景的 Prompt 模式(Pattern)。它的作用是把一个业务主题(Topic)转化为规范的「用户故事(User Story)+ Given/When/Then 验收标准(Acceptance Criteria)」,并且强制以固定 Schema 的 JSON 格式输出,便于下游工具直接消费。读完本文,你将理解这个模式提示词的逐段结构与设计意图、Fabric 是如何把 system.md 与用户输入拼装成最终提示词的底层调用链,以及如何查看、验证和参照它编写自己的模式。
一、agility_story 模式的完整提示词内容
模式定义位于 data/patterns/agility_story/system.md,全文很短但结构完整,由三个章节和一个输入占位段构成。下面按原文结构完整给出并逐段解读。
1. IDENTITY and PURPOSE:角色设定
# IDENTITY and PURPOSE
You are an expert in the Agile framework. You deeply understand user story and
acceptance criteria creation. You will be given a topic.
Please write the appropriate information for what is requested.
这一段完成两件事:
- 角色锚定(Role Anchoring):将模型设定为「敏捷框架专家」,并强调其对用户故事与验收标准编写的深度理解。这是 Fabric 模式体系的典型写法——对照官方的模式编写模板 data/patterns/official_pattern_template/system.md,其
# IDENTITY一节的标准句式就是 "You are _______ that specializes in _______"。agility_story正是该模板的一个精简落地实例。 - 任务边界:明确输入是一个 topic(主题),输出是「被要求的信息」,避免模型发散去写别的内容。
2. STEPS:执行步骤
# STEPS
Please write a user story and acceptance criteria for the requested topic.
agility_story 只规定了一个原子步骤:针对给定主题,写出用户故事和验收标准。这体现了 Fabric 模式的一种设计风格——对于单一目标的任务,不堆砌"思考多次、多轮迭代"之类的复杂步骤(official_pattern_template 中展示的那种"读 218 遍输入、在脑中画白板"的重型步骤在这里是不必要的),保持提示词短小直接。
3. OUTPUT INSTRUCTIONS:JSON 输出契约
这是该模式最关键的部分。原文要求:
# OUTPUT INSTRUCTIONS
Output the results in JSON format as defined in this example:
{
"Topic": "Authentication and User Management",
"Story": "As a user, I want to be able to create a new user account so that I can access the system.",
"Criteria": "Given that I am a user, when I click the 'Create Account' button, then I should be prompted to enter my email address, password, and confirm password. When I click the 'Submit' button, then I should be redirected to the login page."
}
这个示例本身就是一个输出 Schema 定义,包含三个字段:
| 字段 | 语义 | 示例值体现的规范 |
|---|---|---|
Topic |
原始输入主题的回显 | "Authentication and User Management" |
Story |
用户故事 | 严格套用 "As a <role>, I want <capability> so that <benefit>" 三要素模板 |
Criteria |
验收标准 | 采用 Given/When/Then 句式,可串联多个场景("Given that I am a user, when …, then …") |
注意示例中 Story 和 Criteria 的写法分别对应敏捷领域的两种经典约定:用户故事三要素(角色/诉求/价值)与 Gherkin 风格的验收标准。通过「用一个具体示例代替文字描述 Schema」的方式约束输出,这是少样本(few-shot)提示中保证结构化输出稳定性的常用技巧——模型会模仿示例的字段名、句式与粒度。
4. INPUT 段:输入哨兵
# INPUT:
INPUT:
文件末尾的 INPUT: 是提示词的输入锚点。运行时,Fabric 会把用户的实际输入(例如一段文件内容或管道传入的文本)拼接到模式文本之后。在 Fabric 的模式体系里,system.md 的正文即完整提示词,用户输入以追加方式接入;如果模式需要更精细的变量替换,还可以使用 {{input}} 模板变量(见下文模板引擎部分)。此外该模式目录下还有一个 user.md 文件,当前为空文件,属于 Fabric 模式目录的可选组件(用于在独立的用户消息中承载额外输入模板),对 agility_story 而言并不承载内容。
该模式的一句话官方描述可在 data/patterns/pattern_explanations.md 中查到:
agility_story: Generate a user story and acceptance criteria in JSON format based on the given topic.
二、Fabric 如何把 system.md 变成一次真实调用
理解这个模式的实际行为,需要看 Fabric 的三条源码链路:模式加载、变量替换、会话构建。
1. 模式目录与 system.md 常量
Fabric 约定「一个模式 = 一个目录,目录内以 system.md 作为提示词主体」。这一约定在源码中是硬编码常量:
- internal/plugins/db/fsdb/db.go(第 23 行)在初始化 Patterns 实体时设置
SystemPatternFile: "system.md",即每个模式目录下唯一被读取的主文件就是system.md; - internal/plugins/db/fsdb/patterns.go(第 148 行)在按名称取模式时执行
patternPath := filepath.Join(o.Dir, name, o.SystemPatternFile),然后os.ReadFile(patternPath)读取全文作为提示词。
因此 agility_story 模式名与目录名 data/patterns/agility_story/ 一一对应,模式名可以直接出现在 CLI 命令中(如 fabric chat 时指定 -p agility_story)。
模式本身的来源由 internal/tools/patterns_loader.go 管理:DefaultPatternsGitRepoFolder 常量默认为 data/patterns(第 20 行),PopulateDB() 会创建临时目录、从 Git 仓库拉取 data/patterns 内容、把本地自定义模式(主目录中存在而远端不存在的目录)合并保留后,整体写入用户配置目录,并生成 unique_patterns.txt 供列举使用。也就是说,agility_story/system.md 这类文件是随 Fabric 的 patterns 库一起分发、可离线落盘到本地配置目录的。
2. {{input}} 的哨兵保护机制
虽然 agility_story 的正文里用的是显式的 INPUT: 锚点而非 {{input}} 变量,但 Fabric 的模板引擎对所有模式统一处理 {{input}}。其实现值得注意:
- internal/plugins/db/fsdb/patterns.go(第 102–122 行)的
applyVariables()会先把提示词中的{{input}}替换为哨兵令牌template.InputSentinel(定义在 internal/plugins/template/constants.go:__FABRIC_INPUT_SENTINEL_TOKEN__),让模板引擎解析其余模板变量(如{{ext:...}}扩展调用),最后再把哨兵令牌替换为真实用户输入。 - 这样做的目的是防止用户输入内容里恰好包含
{{...}}之类文本时触发二次模板解析——从源码结构看,这是一种针对提示注入/模板逃逸的防御性设计。
3. 从模式到供应商消息的组装
真正发起请求的是核心聊天器:internal/core/chatter.go 的 Chatter.Send() 会先 BuildSession() 把请求组装为会话(含模式正文与用户输入的拼接结果),再调用 session.GetVendorMessages() 得到供应商消息列表,随后根据 Stream 选项选择流式或非流式发送给选定的 AI 供应商插件(internal/plugins/ai/ 下包含 openai、anthropic、gemini、ollama 等多种实现)。这意味着 agility_story 的提示词最终会作为系统消息的一部分发给任意已配置的供应商,而其「必须输出 JSON」的约束是否被遵守,取决于模型对该提示词的遵循能力——这正是 Fabric 把「输出格式指令」写成可审阅文本而非代码的原因:格式契约与供应商解耦。
4. 安全边界测试
值得注意的是,仓库对「按名称读取模式」这一环节有专门的安全测试。internal/server/path_traversal_test.go 验证了不能通过构造 ../ 之类模式名在模式目录外写入/读取 system.md;internal/plugins/db/fsdb/patterns_test.go 则覆盖了符号链接逃逸、名称合法性校验等场景。这保证了 agility_story 这类模式只能通过合法的模式名(目录名)被加载,而不能借模式机制越权访问仓库内任意文件。
三、该模式的设计要点与可复用经验
把 agility_story 放回 Fabric 的整个模式库(data/patterns/ 下有数百个模式)中看,它的写法浓缩了几个可复用的提示工程要点:
- 短而完整的章节骨架。参照 official_pattern_template/system.md,一个完整模式可包含 IDENTITY、GOALS、STEPS、OUTPUT、POSITIVE/NEGATIVE EXAMPLES 等章节;
agility_story只保留了 IDENTITY、STEPS、OUTPUT INSTRUCTIONS 三段——对单目标任务做了恰当裁剪,而不是机械套用模板全量章节。 - 用示例定义 Schema。相比文字描述"请输出包含 Topic、Story、Criteria 三个字段的 JSON",直接给出一个填好真实内容的 JSON 示例,模型模仿的确定性更高。
Story字段演示了 "As a … I want … so that …" 句式,Criteria字段演示了可串联的 Given/When/Then 段落——读者拿到输出后无需再解析自由文本。 - 输出可机读。JSON 输出意味着下游脚本可以直接
jq或程序化提取Story/Criteria字段,把生成结果灌入 Jira、GitHub Issue 等工单系统。这与模式库中其他结构化输出模式(如analyze_prose_json的 JSON 评分输出)是同一种"提示词即接口"的思路。 - 模式即文件,可审阅可 diff。由于提示词就是仓库里的 Markdown 文件,任何对
agility_story行为的不满都可以直接定位到 system.md 的具体行来修正(例如补充"Criteria 至少覆盖正反两个场景"之类的约束),改动即生效、可版本化追溯。
四、如何查看与运行这个模式
以当前仓库的实际结构为准,使用路径如下(前提是已按 Fabric 常规方式安装并配置好 AI 供应商凭据,模式库已下载落盘到本地配置目录):
- 查看原始提示词:直接阅读 data/patterns/agility_story/system.md;
- 列举可用模式名:
agility_story作为模式名会出现在本地配置目录生成的unique_patterns.txt中(生成逻辑见 patterns_loader.go 的createUniquePatternsFile()); - 在会话中调用:通过 Fabric CLI 的 chat 流程指定模式
agility_story并传入一个业务主题(例如"订单导出功能"),得到的预期输出即上述三字段 JSON:
{
"Topic": "Order Export",
"Story": "As a store admin, I want to export all orders from a date range to CSV so that I can reconcile payments in our accounting system.",
"Criteria": "Given that I am logged in as a store admin, when I select a date range and click 'Export CSV', then I should receive a downloadable CSV file containing every order in that range. Given that no orders exist in the range, when I click 'Export CSV', then I should see a message indicating that the range has no orders."
}
(上面的 JSON 为按该模式 Schema 构造的示意输出,用于说明字段格式,并非仓库内固化的数据。)
- 参照它编写自己的模式:以 official_pattern_template/system.md 为骨架新建一个目录与
system.md,放入自定义模式目录(由CUSTOM_PATTERNS_DIRECTORY环境变量指定,加载逻辑见 internal/plugins/db/fsdb/db.go 第 58–68 行),同名时会覆盖主库中的模式(见 patterns.go 第 135–145 行先查自定义目录的取值顺序)。
五、小结
agility_story 展示了 Fabric 模式体系的一个完整样本:一个目录、一个 system.md、三段式提示词(身份—步骤—JSON 输出示例)、末尾的输入锚点。它的价值不在篇幅,而在于把「用户故事 + Given/When/Then 验收标准」的领域规范和一个可机读的 JSON 契约压缩进了模型每次都能稳定遵循的提示词结构里。源码层面,SystemPatternFile 常量、哨兵保护的 {{input}} 替换、以及针对模式名越权的测试用例,共同保证了这个纯文本文件能够安全、确定性地参与真实的 AI 会话组装流程。对于希望让 AI 稳定产出结构化敏捷工件的读者,这个模式既可以直接使用,也可以作为编写自己结构化输出模式的范例。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00