首页
/ Fabric agility_story 模式解析:基于结构化提示词生成敏捷用户故事与验收标准

Fabric agility_story 模式解析:基于结构化提示词生成敏捷用户故事与验收标准

2026-09-05 19:12:50作者:钟日瑜

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 …")

注意示例中 StoryCriteria 的写法分别对应敏捷领域的两种经典约定:用户故事三要素(角色/诉求/价值)与 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.goChatter.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.mdinternal/plugins/db/fsdb/patterns_test.go 则覆盖了符号链接逃逸、名称合法性校验等场景。这保证了 agility_story 这类模式只能通过合法的模式名(目录名)被加载,而不能借模式机制越权访问仓库内任意文件。

三、该模式的设计要点与可复用经验

agility_story 放回 Fabric 的整个模式库(data/patterns/ 下有数百个模式)中看,它的写法浓缩了几个可复用的提示工程要点:

  1. 短而完整的章节骨架。参照 official_pattern_template/system.md,一个完整模式可包含 IDENTITY、GOALS、STEPS、OUTPUT、POSITIVE/NEGATIVE EXAMPLES 等章节;agility_story 只保留了 IDENTITY、STEPS、OUTPUT INSTRUCTIONS 三段——对单目标任务做了恰当裁剪,而不是机械套用模板全量章节。
  2. 用示例定义 Schema。相比文字描述"请输出包含 Topic、Story、Criteria 三个字段的 JSON",直接给出一个填好真实内容的 JSON 示例,模型模仿的确定性更高。Story 字段演示了 "As a … I want … so that …" 句式,Criteria 字段演示了可串联的 Given/When/Then 段落——读者拿到输出后无需再解析自由文本。
  3. 输出可机读。JSON 输出意味着下游脚本可以直接 jq 或程序化提取 Story/Criteria 字段,把生成结果灌入 Jira、GitHub Issue 等工单系统。这与模式库中其他结构化输出模式(如 analyze_prose_json 的 JSON 评分输出)是同一种"提示词即接口"的思路。
  4. 模式即文件,可审阅可 diff。由于提示词就是仓库里的 Markdown 文件,任何对 agility_story 行为的不满都可以直接定位到 system.md 的具体行来修正(例如补充"Criteria 至少覆盖正反两个场景"之类的约束),改动即生效、可版本化追溯。

四、如何查看与运行这个模式

以当前仓库的实际结构为准,使用路径如下(前提是已按 Fabric 常规方式安装并配置好 AI 供应商凭据,模式库已下载落盘到本地配置目录):

  • 查看原始提示词:直接阅读 data/patterns/agility_story/system.md
  • 列举可用模式名agility_story 作为模式名会出现在本地配置目录生成的 unique_patterns.txt 中(生成逻辑见 patterns_loader.gocreateUniquePatternsFile());
  • 在会话中调用:通过 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 稳定产出结构化敏捷工件的读者,这个模式既可以直接使用,也可以作为编写自己结构化输出模式的范例。

登录后查看全文
热门项目推荐
相关项目推荐