跳到主要内容

goose — 架构与原理

30 秒导读: goose 是一个跑在你机器上的通用 AI agent(不只是写代码——研究、写作、自动化、数据分析都行),有桌面 App、CLI 和 API 三种壳,内核用 Rust 写。它把「让模型反复调工具直到任务完成」这件事做成一个可流式输出的循环,所有工具都通过 MCP(Model Context Protocol)这一开放标准接入,并且在每个工具真正执行之前,串了一条安全/权限检查链。

1. 这是什么(零基础也能懂)

一句话定义: goose 是一个开源的「AI agent 运行时」——你给它一个目标,它自己反复地「想一步、调一个工具、看结果、再想下一步」,直到把事做完。

解决什么问题 / 给谁用。 假设你在终端里说「帮我把这个项目的测试都修绿」。光有一个聊天模型不够:模型只会说话,不会真的读文件、跑命令、改代码。goose 补上的就是这套「手脚 + 大脑调度」:

  • 它把你的话发给某个大模型(Anthropic / OpenAI / Google / Ollama / …);
  • 模型回一句「我要运行 cargo test」(这叫一次工具调用);
  • goose 真的去执行,把输出再发回给模型;
  • 如此往复,直到模型说「做完了」。

它能做什么(功能):

  • 多家模型提供商:15+ 家,既可用 API key,也能复用你已有的 Claude/ChatGPT/Gemini 订阅。
  • 70+ 扩展:通过 MCP 接入文件系统、shell、浏览器、记忆、自定义 server 等。
  • 三种交互壳:桌面 App、CLI(goose)、HTTP 服务(goosed)。
  • 安全护栏:权限审批、prompt-injection 检测、数据外泄(egress)检测、生命周期 hooks。
  • 长任务支撑:上下文自动压缩、子 agent、会话持久化、recipe(可复用任务模板)。

用起来什么样。 最小的 CLI 体感:

# 安装后,在项目目录里:
goose session
# 然后用自然语言下指令:
> 看一下 src/ 里有哪些 TODO,挑最关键的一个修掉
# goose 会:列目录 → 读文件 → 提议改动 → (按权限模式)征求同意 → 写文件 → 报告

一句话直觉 / 类比。 把 goose 想成一个项目经理 + 一双手:大模型是会出主意的「大脑」,但只会说话;goose 负责把大脑说的每句「去做 X」翻译成真实动作、拿回结果、再递回给大脑,并在动手前过一遍「这步安全吗、要不要先问主人」的安检。

2. 顶层全景(它大概怎么转)

仓库结构(只列主线相关)

goose 是一个 Rust workspace,核心逻辑集中在 crates/goose:

crate干什么
goose核心:agent 循环、工具分发、扩展管理、安全检查、上下文管理
goose-providers各家模型的接入(Anthropic / OpenAI / OpenAI-compatible),统一成 Provider trait
goose-mcpgoose 自带的内置 MCP 扩展(computercontroller、memory、tutorial 等)
goose-cli命令行入口 goose
goose-serverHTTP 后端,二进制名 goosed,桌面 App 连它
ui/desktopElectron 桌面应用(TypeScript)

核心类型 Agent 定义在 crates/goose/src/agents/agent.rs:237(struct Agent)。

主部件与职责

部件干什么在哪
Agent持有 provider、扩展管理器、各种 manager,提供 reply() 入口agents/agent.rs:237
Provider (trait)把「一组消息 + 工具定义」发给模型,流式返回goose-providers/src/base.rs:381
ExtensionManager管理所有 MCP 扩展、聚合工具、按前缀路由 dispatch_tool_callagents/extension_manager.rs:186
ToolInspectionManager工具执行前的检查器流水线(安全/egress/权限/重复)tool_inspection.rs:57
PromptManager组装系统提示(扩展信息 + hints + 模式)agents/prompt_manager.rs:22
SessionManager会话与消息持久化session/
context_mgmt上下文超限时的压缩 / 工具对摘要context_mgmt/mod.rs

主线走一遍(高层,不进代码)

用户的一条消息进来后,大致经过:

用户消息


Agent::reply ──── 先跑斜杠命令? 先处理 elicitation 回复? 先看要不要自动压缩?


reply_internal ────────────────────────────────────┐
│ (一个 async 流,内部是一个 loop = 一「回合」一圈) │
▼ │
① 问模型 (stream_response_from_provider) │
│ 模型流式吐:文本 / thinking / 工具调用 │
▼ │
② 分类工具 (categorize_tool_requests) │
│ 分成「前端工具」「其它工具」 │
▼ │
③ 安检 + 权限 (ToolInspectionManager.inspect_tools) │
│ 每个工具:Allow / Deny / 需审批 │
▼ │
④ 执行 (dispatch_tool_call → ExtensionManager) │
│ 按工具名前缀路由到对应 MCP 扩展 │
▼ │
⑤ 把工具结果作为 user 消息写回 conversation │
│ │
└── 这一圈如果调了工具 → 回到 ①(再问模型) ──────────┘
如果没调工具 → 收尾(goal/grind 提醒、retry、stop hook)→ 退出

关键直觉:「调了工具就继续循环,没调工具就准备结束」。这就是所有 agent 的心跳。goose 在这条主线上挂满了护栏和长任务机制,这正是它和「裸调 API」的区别。

3. 阅读地图(建议顺序)

想真正读懂 goose,按下面顺序看分章:

  1. 01-agent-loop.md —— 先看心跳。reply_internal 那个 loop 是整个项目的主算法,搞懂它你就懂了 80%。
  2. 02-tools-and-mcp.md —— 工具从哪来、怎么命名、调用时怎么找到对的扩展。MCP 是 goose 的「插槽标准」。
  3. 03-safety-chain.md —— goose 相对其它框架最用心的地方:工具执行前的检查器链 + 四种权限模式 + prompt-injection / egress 检测 + 生命周期 hooks。
  4. 04-context-management.md —— 长任务怎么不撑爆上下文:阈值触发的整体压缩、后台的工具对摘要、消息「可见性」双轨制。
  5. 05-clever-and-boundaries.md —— 巧妙之处(流式 + 工具的并发收集、tool_call_id 去重、思考内容回放抑制等)、边界局限、与兄弟项目对比、代码地图总表。

如果你是 agent,只想低成本判断相关性:goose = 「Rust 版的 MCP-原生通用 agent 内核 + 重安全护栏」。要找「主循环」看第 1 章;找「工具/MCP 接线」看第 2 章;找「权限/安全」看第 3 章。