首页
/ Goose Recipes 实战:用可复用的"菜谱"把 Agent 工作流规模化

Goose Recipes 实战:用可复用的"菜谱"把 Agent 工作流规模化

2026-09-07 12:16:01作者:董灵辛Dennis

本指南以 Goose 官方博客《A Recipe for Success》中的思想为骨架,系统讲解 Goose 如何借助 Model Context Protocol(MCP)把大模型从"提建议的顾问"升级为"能动手的编排者",并通过 Recipe(菜谱)机制将一次成功的会话固化为可重跑、可混搭、可分享的可复用工作流。读完你将掌握 Recipe 的 YAML 结构、参数化、扩展装配、校验、分享与自动重试等完整实操能力,并能在真实场景中一键复现同一套 Agent 工作流。

Goose Recipes 主题博客封面:用厨房烹饪比喻可复用、可分享的 Agent 工作流

从《料理鼠王》说起:传统 AI Agent 的"三层角色"

原文档用电影《料理鼠王》里 Remy 与 Linguini 的关系类比 AI Agent:Remy 满腹厨艺却没有厨房使用权,Linguini 能在厨房自由行动却缺乏烹饪判断。二者合体后,Remy 观察厨房里有什么工具、给出一步步指令("拿起刀和砧板,把土豆切片"),Linguini 负责执行。

对应到智能体系统,就是三个核心角色:

角色 电影类比 职责
Large Language Model(LLM) Remy 拥有知识与推理能力,负责规划(用什么工具、按什么顺序)
Agent Linguini 能调用工具采取行动,但需要 LLM 的指导
Tools 厨房里的刀、灶台、食材 完成具体动作的能力入口,如 file.write()

典型流程是:用户说"写一些单元测试",LLM 分析代码后回复"这是 JavaScript,用 Jest,创建测试文件并导入模块",Agent 随后调用 file.write() 等工具落地执行。这是"LLM 规划、Agent 执行"的基础形态。

MCP:让 Agent 从被动执行者变成主动编排者

电影后半段,Linguini 不再需要每一道菜都依赖指令——搭档 Colette 教会他工具放在哪里、工位如何组织、如何在厨房里高效移动、缺东西时如何变通。此时的 Linguini 已经理解"厨房是一个系统"。

Goose 的思路与此一致:遵循 Model Context Protocol(MCP)的 AI Agent,会把智能体从被动执行者推向主动编排者——少依赖 LLM 的临场发挥,多感知自己运行所在的上下文。MCP 为 Agent 与外部数据、服务之间的交互提供了标准化协议,其三大核心组件是:

  • MCP Host:接收计划并协调任务的核心 Agent;
  • MCP Client:Host 用来连接外部服务的本地连接器;
  • MCP Servers:以结构化格式封装的工具、数据或提示词包——在 Goose 生态中,MCP Server 被称为扩展(Extension)

这套架构让 Goose 能动态发现工具、理解工具用法,并跨多个系统编排复杂工作流。Goose 本身就是一个本地运行的开源 AI Agent,其编排与扩展能力的实际使用方式见 Goose 扩展文档,MCP Host/Client/Server 的分层实现在 crates/goose/src/mcp_utils.rs 等源码中均有对应。

Goose 的编排与临场应变

当用户让 Goose"收集上周关于认证 bug 的所有讨论"时,Goose 会主动协调工具、管理执行、动态调整:

  • 识别该用哪些 MCP Server:Slack、GitHub、PostgreSQL;
  • 察觉某个工具运行异常(如 Slack 搜索没有返回上周消息);
  • 寻找替代路径("试试不同日期范围""PR 评论里也许有要点")。

"出错了不慌、先换方案"正是 Recipe 诞生前,Agent 单次会话中体现出的编排能力。

为什么需要 Recipe:把一次成功"烹饪"封装成可复用的菜谱

原文档指出了一个关键痛点:单纯分享 prompt 无法复现体验。AI 是非确定性的,不同人的扩展与上下文配置也不一致。Recipe 的解法是把整个 Goose 工作流打包:扩展、设置、目标、示例活动一并交付。一个 Recipe 相当于一张完整的烹饪菜谱——别人拿到手就知道开哪些火、放哪些料、最终端出什么菜。

Recipe 的三大核心组成

一个 Recipe 至少要围绕以下内容组织(详见 Recipes 文档):

  • Instructions(指令):定义 Agent 行为与能力边界,相当于 Agent 的"使命宣言",让 Agent 能胜任任何相关任务;若未提供 prompt 则必填;
  • Prompt(提示词,可选):自动开启会话的首条消息,适合"特定即时任务";若未提供 instructions 则必填;
  • Activities(活动,可选):以可点击气泡展示的示例任务,帮用户快速理解这个 Recipe 能做什么、从哪里开始。

动手示例:一个"404 风格个人主页"Recipe

原文档给出的示例 Recipe 会先询问用户选择 GitHub、Bluesky 还是 Dev.to,然后用该平台的公开内容,生成一个故事化的 404 错误页微站点。它可以借助桌面端 Recipe 链接一键启动——该链接本质上是 goose://recipe?config= 后跟一段 URL-safe Base64 编码的 Recipe JSON(Goose 桌面端安装方式见 installation.md,DeepLink 的解析逻辑可参考 crates/goose/src/recipe_deeplink.rs)。

把该链接中的 Base64 解码后,得到的正是如下 JSON(原文以 YAML 呈现,二者等价):

version: 1.0.0
title: "404Portfolio"
description: "Create personalized, creative 404 pages using public profile data"

instructions: |
  Create an engaging 404 error page that tells a creative story using a user's recent public content from **one** of the following platforms: **GitHub**, **Dev.to**, or **Bluesky**. You do not need to use all three—just the one selected by the user.

  The page should be fully built with **HTML, CSS, and JavaScript**, featuring:

  * Responsive design
  * Personal branding elements (e.g., name, handle, avatar)
  * Narrative-driven layout that turns the error into an opportunity for discovery

  Use platform-specific methods to fetch recent user content:

  * For **Dev.to**, use the public Dev.to API to retrieve recent articles, reactions, and profile information.
  * For **GitHub**, use the GitHub REST or GraphQL API to access recent repos, commits, and contributions.
  * For **Bluesky**, use public feed endpoints from the AppView API (e.g., `app.bsky.feed.getAuthorFeed`) to pull posts, replies, or likes.

  Incorporate the fetched data into a compelling narrative (e.g., "Looks like this page is missing, but \[username\] has been busy!"), and display it using engaging visuals like cards, timelines, or media embeds.

  Wrap the user's activity into a story  for example:

  "This page may be lost, but @username is building something amazing. Their latest open source journey involves a new repo that's gaining stars fast…"

  "You won't find what you're looking for here, but you will find @username's hot take on async/await in their latest Dev.to post."

  The result should be a small narrative-driven microsite that dynamically celebrates the user's presence online—even when the destination is missing.

  Ask the user:

  1. Which platform to use: GitHub, Dev.to, or Bluesky
  2. Their username on that platform

  Then generate the complete code in a folder called 404-story.


activities:
  - "Build error page from GitHub repos"
  - "Generate error page from dev.to blog posts"
  - "Create a 404 page featuring Bluesky bio"

extensions:
  - type: builtin
    name: developer
  - type: builtin
    name: computercontroller

这个例子清晰地展示了一个"真菜谱"长什么样:目标(instructions)告诉 Agent 要做什么、按什么平台逻辑取数、产出物放哪里;activities 给用户三个可点的入手任务;extensions 预先声明需要 developer(开发扩展)与 computercontroller(电脑控制扩展)两个内置工具。共享者只需把文件或链接发给对方,接收方就能在独立、私有的会话中复现完全一致的环境与目标。

Recipe 的文件结构与字段语义

Recipe 可以使用 .yaml(官方推荐,以及 .yml)或 .json 编写;注意 Goose CLI 不直接支持 .yml 后缀。完整字段对照表见 Recipe Reference Guide,核心字段如下:

字段 类型 必填 说明
title String 简短的 Recipe 标题
description String 详细描述该 Recipe 做什么
instructions String ✅* 模板化指令,可含参数替换
prompt String ✅* 模板化首条提示词;headless(非交互)模式必须提供
activities Array - 示例提示词列表,桌面端以可点击气泡呈现
extensions Array - Recipe 所需的扩展(MCP Server)配置列表
parameters Array - 动态 Recipe 的参数定义
response Object - 自动化场景的结构化输出 schema
retry Object - 带成功校验的自动重试配置
settings Object - 指定 provider、model 等运行时设置
sub_recipes Array - 子 Recipe 列表
version String - Recipe 格式版本,缺省为 1.0.0

(*instructionsprompt 至少提供一个。)

该结构在源码中有精确对应:crates/goose/src/recipe/mod.rs 中的 Recipe 结构体定义了上述全部字段;RecipeBuildermod.rs)在 build() 时强制校验:titledescription 必填,且"promptinstructions 至少其一"。桌面端保存的 Recipe 还会包裹 recipe: 字段并附加 nameisGloballastModifiedisArchived 等元数据(这些元数据仅服务于桌面端的库管理,CLI 运行时会忽略)。

用参数让一个 Recipe 适配多种场景

Recipe 的复用价值很大程度上来自参数化:在内容中以 {{ variable_name }} 占位,并在 parameters 段定义每个参数。每个参数包含 keyinput_typerequirementdescription,可选 defaultoptions

  • input_typestring(默认)、numberbooleandatefileselect
  • requirementrequired(必填)、optional(可选,必须提供 default)、user_prompt(未提供时即使非交互模式也会提示用户输入);
  • file 类型的参数会把文件内容(而非路径)代入模板,且无论何种 requirement 都不允许默认值,以防无意导入敏感文件;
  • select 类型必须提供 options 候选列表。

一个带参数的典型 Recipe:

version: 1.0.0
title: "{{ project_name }} Code Review"
description: Automated code review for {{ project_name }} with {{ language }} focus
instructions: You are a code reviewer specialized in {{ language }} development.
prompt: |
   Apply the following standards:
   - Complexity threshold: {{ complexity_threshold }}
   - Required test coverage: {{ test_coverage }}%
   - Style guide: {{ style_guide }}
parameters:
- key: project_name
  input_type: string
  requirement: required
  description: name of the project
- key: language
  input_type: string
  requirement: required
  description: language of the code
- key: complexity_threshold
  input_type: number
  requirement: optional
  default: 20
  description: a threshold that defines the maximum allowed complexity
- key: test_coverage
  input_type: number
  requirement: optional
  default: 80
  description: the minimum test coverage threshold in percentage
- key: style_guide
  input_type: string
  requirement: user_prompt
  description: style guide name

标题若以模板语法开头,务必用引号包裹以避免 YAML 解析错误。参数替换底层由 MiniJinja 模板引擎实现,渲染逻辑见 crates/goose/src/recipe/template_recipe.rs:它会把合法变量代入参数、把不可解析的 {{...}}(如含空格的占位)自动按字面量保留,从而避免破坏 YAML。模板系统还支持:

  • 转义:用 {{'{{example_variable}}'}} 输出字面量花括号语法,适合生成含占位符的模板文件;
  • 模板继承{% extends "parent.yaml" %} + {% block ... %}{% endblock %}
  • indent() 过滤器{{ raw_data | indent(2) }} 让多行参数值缩进正确,可被当作合法 JSON/YAML 解析;
  • 内置参数 recipe_dir:自动指向 Recipe 所在目录,用于引用同目录伴生文件,例如 {{ recipe_dir }}/style-guide.md。注意其模板加载器会拒绝绝对路径与 ../ 目录穿越,防止模板越权读取文件(见 template_recipe.rs)。

为 Recipe 装配扩展:声明工具栈

Recipe 的 extensions 段声明运行所需的 MCP Server 等工具。每种扩展的子字段包括 typenamecmdargsenv_keystimeoutbundleddescriptionavailable_tools。扩展类型有 stdiobuiltin(内置扩展)、platform(在 Agent 进程内运行)与 streamable_http

env_keys 用于声明扩展所需的(秘密或非秘密)环境变量,goose 会依次从环境变量与 goose 密钥存储中解析;Recipe 加载时不会弹出补录,缺失则扩展报初始化错误。典型 stdio 扩展声明:

extensions:
  - type: stdio
    name: github-mcp
    cmd: github-mcp-server
    args: []
    env_keys:
      - GITHUB_PERSONAL_ACCESS_TOKEN
    timeout: 60
    description: "GitHub MCP extension for repository operations"

需要 subagent 委派(delegate/load 工具)时须显式加入 summon platform 扩展——因为一旦写了 extensions 段,默认平台扩展不会自动带入。而定义 sub_recipes 的 Recipe 会被自动注入 summon;从源码看,加载时还会对含旧版 developer 内置扩展的 Recipe 自动补齐 analyze 平台扩展(见 crates/goose/src/recipe/mod.rs)。前面的 404 Recipe 声明了 developercomputercontroller 两个 builtin 扩展,二者都属于 Goose 自带的本地 MCP Server 工具集,保证收到 Recipe 的人不必额外安装任何第三方 MCP 服务。

创建、运行与校验 Recipe

创建

  • Goose Desktop:在会话中点击底部的厨师帽按钮,把当前会话保存为 Recipe(支持从"当前会话"或"模板"新建);编辑字段后可选择 Create Recipe(存入 Recipe 库)或 Create & Run Recipe(保存并立即在新会话运行)。注意:不能从"运行中的 Recipe 会话"再创建 Recipe,只能查看或编辑它。
  • Goose CLI:在会话内执行斜杠命令生成 recipe.yaml
/recipe                # 在当前目录生成 recipe.yaml
/recipe my-custom-recipe.yaml

Goose 如何把对话转成 Recipe 字段,由 crates/goose/src/prompts/recipe.md 这个提示词模板决定——它要求模型产出 titledescriptioninstructions(更高层、可泛化的措辞)与 3~5 个 activities 的合法 JSON;你可以编辑该模板自定义生成行为。

运行

Recipe 可放在本地文件系统(当前目录或 GOOSE_RECIPE_PATH 指定目录),也可配置 GitHub 仓库统一拉取(配置项 GOOSE_RECIPE_GITHUB_REPO,要求安装并认证 GitHub CLI gh)。仓库中每个 Recipe 应独占一个目录,目录名即命令中使用的 Recipe 名,文件名为 recipe.yamlrecipe.json

# 本地文件
goose run --recipe recipe.yaml
goose run --recipe ./recipes/my-recipe.yaml
goose run --recipe recipe.yaml --interactive        # 交互模式,逐个提示必填参数
goose run --recipe recipe.yaml --params language=Python

# GitHub 仓库按名运行(目录名即 recipe 名)
goose run --recipe code-review

桌面端则通过 Recipe 库、手动输入链接或自定义斜杠命令启动;首次运行会弹出信任确认(展示标题、描述与指令),确认 Trust and Execute 后同版本 Recipe 不再重复询问;含参数时在 Recipe Parameters 弹窗中填写(必填项带红色星号,可选项展示可改默认值)。无论桌面还是 CLI,每次运行都是彼此隔离的私有会话——数据不跨用户共享,也不影响创建者原会话。

校验

CLI 提供了 goose recipe validate 命令,用于排障、验证手工修改、接入 CI/CD 自动化:

goose recipe validate recipe.yaml

校验器会检查必填字段、参数格式、扩展是否存在有效、YAML/JSON 语法。源码实现见 crates/goose/src/recipe/validate_recipe.rs,其校验规则包括:instructions/prompt 至少其一、response.json_schema 合法、可选参数必须有默认值、文件参数禁止默认值、模板变量与参数定义一一对应(无未定义变量、无未使用参数)、retry 配置合法等。

分享与定时

  • 分享链接:桌面端 Recipe 库点复制链接;CLI 用 goose recipe deeplink <FILE> 生成,也可用 --param key=value 预填参数;接收者点击后会用该配置打开 Goose Desktop,并可导入为可复用的本地 Recipe(详见 storing-recipes.md)。
  • 分享文件:桌面端可 Export to File 导出 .yamlCopy YAML;CLI 用户可直接发送文件,接收方用 goose run --recipe <FILE> 运行。
  • 定时调度:桌面端 Scheduler 视图可创建/暂停/编辑/立即运行定时 Recipe;CLI 用 goose schedule add --schedule-id daily-report --cron "0 0 9 * * *" --recipe-source ./recipes/daily-report.yaml,支持 5/6/7 位 cron 表达式。

让 Recipe 更可靠:自动重试与结构化输出

针对无人值守场景,Recipe 提供两个"高级武器":

retry:自动重试 + shell 成功校验

retry:
  max_retries: 3
  timeout_seconds: 30
  on_failure_timeout_seconds: 60
  checks:
    - type: shell
      command: "curl -f http://localhost:8080/health"
    - type: shell
      command: "pgrep -f 'web-service' > /dev/null"
  on_failure: "systemctl stop web-service || killall web-service"

执行流程为:Recipe 正常运行 → 结束后按序执行所有 checks(shell 命令退出码 0 才算成功)→ 若失败且重试次数未耗尽,执行可选的 on_failure 清理、将 Agent 消息历史重置为初始状态并重新执行 → 直到全部校验通过或达到 max_retries。全局超时可用环境变量 GOOSE_RECIPE_RETRY_TIMEOUT_SECONDSGOOSE_RECIPE_ON_FAILURE_TIMEOUT_SECONDS 配置(Recipe 内配置优先)。

response:强制结构化 JSON 输出

在 Recipe 中声明 response.json_schema 后,Goose 会通过一个 final_output 工具要求 Agent 产出与 schema 匹配的 JSON,经校验后作为最后一行输出,方便脚本直接提取:

response:
  json_schema:
    type: object
    properties:
      build_status:
        type: string
        enum: ["success", "failed", "warning"]
      tests_passed:
        type: number
      deployment_ready:
        type: boolean
    required: [build_status, tests_passed, deployment_ready]

配合 CLI 即可管道化消费:

goose run --recipe analysis.yaml --params project_path=./src > output.log
RESULT=$(tail -n 1 output.log)
echo "Analysis Status: $(echo $RESULT | jq -r '.build_status')"

注意:该功能在 CLI 与 Desktop 运行均支持,但 json_schema 目前需要手动在 Recipe 文件中创建与编辑。

Recipe 打包了什么,又刻意排除了什么

打包范围(详见 session-recipes.md):

  • AI 指令(目标/目的);
  • 建议活动(用户可点击的示例);
  • 启用的扩展及其配置;
  • 项目文件夹或文件上下文;
  • 初始设置(不含完整对话历史);
  • 运行所用模型与 provider(可选);
  • 重试逻辑与成功校验配置(如配置)。

隐私与安全边界——Recipe 会主动排除:全局与本地记忆、API 密钥与个人凭证、系统级 goose 设置。因此如果 Recipe 依赖个人凭证,接收者需要自行提供。源码中还有一道防线:加载时会扫描 instructions/prompt/activities 中的 Unicode 私用区标签,检出有害内容即告警(mod.rs)。

规模化使用场景

  • 新同事入职:与其花几小时解释环境搭建、平台选型与团队潜规则,不如直接发一个 Recipe——自动完成本地配置、呈现相关文档、带他走一遍团队工作流,全程无需屏幕共享;
  • 办工作坊:不同机器、不同环境最容易翻车。丢一个 Recipe 链接,每个参会者都能拉起相同的环境、相同的工具、相同的目标与示例,把时间省给教学而不是排障;
  • 放大团队产出:有人做好了内部仪表盘、有人摸熟了工单分级、有人自动化了 changelog 生成——用 Recipe 把这些"孤品"转成团队共享的复用资产,沉淀成 Goose 流程库。仓库中的 workflow_recipes/release_risk_check/recipe.yamlscripts/test-subrecipes-examples 就是真实存在的 Recipe 与子 Recipe 范例,可当作阅读参照。

小结

正如 Colette 教会 Linguini"把厨房当系统来理解",MCP 让 Goose 从被动的执行者成长为能动态发现工具、编排多系统、遇错即换路的编排者;而 Recipe 则更进一步——把某一次成功的"烹饪"固化成包含工具栈、设置、目标与示例活动的完整菜谱,用 DeepLink、文件或共享仓库一键分发。想要编写或调试自己的 Recipe,可从 Recipe Reference Guide 的完整字段规范入手,配合 goose recipe validate 迭代;想进一步拆解子任务、并行执行,可阅读 subrecipes.md。从你的下一次成功会话开始,把它存成一张菜谱——未来的你和团队都会感谢现在的你。

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