MD 更新:2026/6/8

Goose 架构分析

核心问题与约束

Goose 要解决的问题是:构建一个本地运行的通用 AI Agent,能连接任意 LLM 提供商、通过标准协议挂载工具扩展,并以桌面应用 / CLI / API 三种形态交付

这带来了几个硬约束:

  1. 多模型异构性:必须统一 Anthropic、OpenAI、Google、Ollama、Bedrock 等 15+ 提供商的 API 差异
  2. 扩展生态开放性:第三方工具(Extension)以独立进程运行,需要安全的隔离与标准化的通信协议
  3. 多形态交付:同一核心逻辑要支撑 CLI(终端交互)、Desktop App(Tauri GUI)、Server(HTTP/WebSocket API)三种前端
  4. 本地安全边界:Agent 持有用户权限执行 shell 命令、文件操作,必须有完善的权限审批机制

架构假设:这是一个插件式 + 分层的 Agent 系统,核心数据流是 用户指令 → Agent 调度 → Provider(LLM推理) → Tool(Extension执行) → 响应聚合 → 用户,最关键的设计决策在 Agent 循环、Provider 抽象和 Extension Manager 三处。

架构全景

graph TB
    subgraph "前端层 (Frontends)"
        CLI["goose-cli<br/>终端交互"]
        Desktop["UI / Tauri<br/>桌面应用"]
        Server["goose-server (goosed)<br/>HTTP/WS API"]
        Gateway["Gateway<br/>Telegram 等外部平台"]
    end

    subgraph "Agent 核心 (goose crate)"
        Agent["Agent<br/>调度循环 / 上下文管理"]
        PM["PromptManager<br/>系统提示词组装"]
        PM2["PermissionManager<br/>权限审批"]
        Retry["RetryManager<br/>错误重试"]
        Compact["ContextMgmt<br/>对话压缩"]
    end

    subgraph "Provider 抽象层 (goose-providers + goose/providers)"
        ProvTrait["Provider trait<br/>统一 LLM 接口"]
        Conv["Conversation<br/>消息格式标准化"]
        Canonical["CanonicalModel<br/>模型名映射"]
    end

    subgraph "工具扩展层 (Extensions)"
        EM["ExtensionManager<br/>MCP 客户端管理"]
        MCP["MCP Protocol (rmcp)<br/>工具通信协议"]
        BuiltIn["内置扩展<br/>memory / autovisualiser<br/>computercontroller"]
        External["外部扩展<br/>子进程 MCP Server"]
        SubAgent["SubAgent<br/>子 Agent 调度"]
    end

    subgraph "基础设施层"
        Session["SessionManager<br/>会话持久化 (SQLite)"]
        Config["Config<br/>全局配置管理"]
        Security["SecurityInspector<br/>安全检查 / 对抗检测"]
        Telemetry["OpenTelemetry<br/>可观测性"]
    end

    CLI --> Agent
    Desktop --> Agent
    Server --> Agent
    Gateway --> Agent

    Agent --> PM
    Agent --> PM2
    Agent --> Retry
    Agent --> Compact
    Agent --> ProvTrait
    Agent --> EM

    ProvTrait --> Conv
    ProvTrait --> Canonical

    EM --> MCP
    MCP --> BuiltIn
    MCP --> External
    EM --> SubAgent

    Agent --> Session
    Agent --> Config
    Agent --> Security
    Agent --> Telemetry

架构师注释:关键依赖方向是单向的——前端 → Agent → Provider / Extension → 基础设施。没有反向依赖。Agent 是唯一的调度中心,Provider 和 Extension 都是被动响应者。

架构风格:插件式 Agent 循环

Goose 采用了经典的 Agent Loop + 插件系统 架构,这在 AI Agent 领域是主流范式(类似 Claude Code、OpenAI Codex CLI),但 Goose 的独特之处在于:

设计维度Goose 的选择同类对比
语言Rust(性能 + 安全)Claude Code 用 TypeScript,Codex CLI 用 Rust
工具协议MCP(Model Context Protocol)Claude Code 也用 MCP,OpenAI 用 Function Calling
Agent 通信协议ACP(Agent Client Protocol)自研协议,已提交 Linux Foundation
多模型15+ Provider,Canonical Model 映射Claude Code 仅支持 Claude 系列
扩展形式子进程 MCP ServerClaude Code 同样是子进程
上下文管理自动 Compaction + 子 Agent 分流Claude Code 手动 /compact

为什么选 Rust:Agent 需要(1)在用户本地持续运行、(2)安全地执行子进程管理、(3)处理流式 LLM 响应的并发。Rust 的零成本异步(tokio)和内存安全使得一个进程可以同时管理数十个 MCP 子进程连接而不泄露资源。

代价:Rust 编译慢、Feature Flag 爆炸(goose 核心 crate 有 20+ feature flags),对社区贡献者门槛高。

核心模块解析

1. goose crate — Agent 核心引擎

职责:实现 Agent 调度循环、上下文管理、权限控制、会话持久化

关键模块

模块职责
agents/agent.rsAgent struct — 主循环,管理 Provider 调用 → 工具执行 → 响应聚合
agents/extension_manager.rsExtensionManager — 管理所有 MCP Extension 的生命周期
agents/prompt_manager.rsPromptManager — 组装系统提示词(含工具描述、模式指令)
agents/retry.rsRetryManager — 工具调用失败时的重试策略
agents/tool_execution.rs工具调用的实际执行与结果路由
agents/subagent_handler.rs子 Agent 拆解(将复杂任务分发给子 Agent)
context_mgmt对话历史过长时自动 Compaction(压缩)
session/SessionManager — 基于 SQLite 的会话持久化
config/全局配置(Goose Mode、Extension 启用状态、Provider 配置)
security/AdversaryInspector + EgressInspector — 对抗性检测与出站流量审查
permission/PermissionInspector + PermissionJudge — 工具调用前的权限审批
gateway/Gateway trait — 外部平台接入(如 Telegram)

耦合点

  • Agent → Provider:通过 Provider trait 解耦,运行时动态选择
  • Agent → Extension:通过 ExtensionManager + MCP 协议解耦
  • Agent → Session:通过 SessionManager trait 解耦

Agent 循环核心流程(从 agent.rs 源码推导):

loop (max_turns = 1000) {
    1. PromptManager 组装 system_prompt + tools + conversation
    2. check_if_compaction_needed → 若对话过长则 compact_messages
    3. Provider::stream() → 获取 LLM 流式响应
    4. 解析响应中的 tool_calls
    5. ToolConfirmationRouter → 权限检查
       ├── frontend tools → 路由到前端执行
       ├── platform tools → 内部直接执行
       └── extension tools → ExtensionManager 分发
    6. 执行工具,收集结果
    7. RetryManager 判断是否重试
    8. 检查 CancellationToken
    9. 若无 tool_call 或触发 FinalOutputTool → 结束循环
}

2. goose-providers crate — LLM 提供商抽象

职责:定义 Provider trait,统一所有 LLM 提供商的调用接口

核心 trait

// 每个 Provider 必须实现的核心方法
pub trait Provider: Send + Sync {
    fn get_name(&self) -> &str;
    async fn stream(
        &self,
        model_config: &ModelConfig,
        session_id: &str,
        system: &str,
        messages: &[Message],
        tools: &[Tool],
    ) -> Result<MessageStream, ProviderError>;
}

// Provider 工厂 trait — 从环境变量创建 Provider 实例
pub trait ProviderDef: Send + Sync {
    type Provider: Provider + 'static;
    fn metadata() -> ProviderMetadata;
    fn from_env(model, extensions) -> BoxFuture<Result<Self::Provider>>;
}

设计亮点

  • stream() 是唯一必须实现的方法,complete() 有默认实现(收集流)
  • complete_fast() 先尝试 fast model,失败回退到主模型 — 这是一种优雅的降级策略
  • ProviderDef trait 提供工厂模式,支持从环境变量自动配置

Canonical Model 机制canonical/ 模块维护了一个模型名映射表,将用户输入的模型别名(如 gpt-4)映射到提供商的特定模型 ID。这使得跨 Provider 切换模型时无需记忆各家的命名规则。

3. goose-mcp crate — MCP 工具扩展

职责:实现 MCP(Model Context Protocol)的 Server 端能力,提供内置工具扩展

内置扩展(通过 BUILTIN_EXTENSIONS 宏注册):

扩展名功能
autovisualiser自动将内容可视化
computercontroller计算机控制(GUI 自动化)
memory持久化记忆存储
tutorial教程引导

扩展模型

  • 内置扩展:同一进程内通过 tokio::io::DuplexStream 双向管道通信
  • 外部扩展:通过子进程启动 MCP Server,使用 rmcp 库的 stdio 或 HTTP 传输
  • 平台扩展platform_tools):Agent 自身提供的工具(如 manage_extensionsmanage_schedule

4. goose-acp — Agent Client Protocol

职责:实现 ACP 协议,让 Goose 作为一个可被外部程序调用的 Agent 服务

ACP 是 Goose 团队主导的开放协议(已提交 Linux Foundation 的 AAIF),定义了:

  • Agent 如何通过 stdio / HTTP 接受请求
  • 消息格式(custom_requests / custom_notifications
  • 权限路由(PermissionDecision

这使得 Goose 可以被嵌入到任何 IDE、应用或工作流中。

5. goose-server crate (goosed) — HTTP/WebSocket API

职责:将 Agent 能力暴露为 HTTP API 和 WebSocket 流式接口

关键设计

  • 使用 axum Web 框架 + WebSocket 支持流式响应
  • 支持 TLS(rustls 或 native-tls 二选一)
  • 自动生成自签名证书(rcgen
  • 跨平台文件锁(fs2)确保单实例运行
  • OpenAPI 文档自动生成(utoipa

6. goose-cli crate — 命令行界面

职责:终端交互入口

默认启用的 features 暴露了产品定位

default = [
    "code-mode",      # 代码模式(PCTX 集成)
    "local-inference", # 本地推理(Whisper 语音转文字、llama.cpp)
    "tui",             # TUI 交互界面
    "aws-providers",   # AWS Bedrock/SageMaker
    "telemetry",       # 遥测
    "nostr",           # Nostr 协议集成
    "otel",            # OpenTelemetry
    "rustls-tls",      # 纯 Rust TLS
    "system-keyring",  # 系统密钥环
    "update",          # 自动更新(Sigstore 验签)
]

数据流分析

flowchart LR
    subgraph "用户输入"
        U1["文本指令"]
        U2["语音输入"]
        U3["外部平台消息"]
    end

    subgraph "预处理"
        P1["PromptManager<br/>组装系统提示"]
        P2["Dictation<br/>Whisper 语音转文字"]
        P3["Gateway<br/>平台消息标准化"]
    end

    subgraph "Agent 循环"
        A1["Provider.stream()<br/>LLM 推理"]
        A2["ThinkFilter<br/>分离 reasoning/content"]
        A3["Tool 解析<br/>提取 tool_calls"]
        A4["PermissionCheck<br/>权限审批"]
        A5["ToolExecution<br/>工具执行"]
        A6["RetryManager<br/>失败重试"]
        A7["Compaction<br/>上下文压缩"]
    end

    subgraph "输出"
        O1["流式文本响应"]
        O2["工具执行结果"]
        O3["子 Agent 报告"]
    end

    U1 --> P1 --> A1
    U2 --> P2 --> P1
    U3 --> P3 --> P1

    A1 --> A2 --> A3
    A3 -->|有工具调用| A4 --> A5 --> A6 --> A1
    A3 -->|无工具调用| O1
    A5 --> O2
    A5 --> O3

    A1 -.->|上下文过长| A7
    A7 -.-> A1

架构师注释:数据流的核心特征是流式优先——从 LLM Provider 到最终输出,全程使用 BoxStream<Message> 流式传递。这意味着用户可以在 LLM 生成过程中实时看到响应,同时工具调用在流结束后解析执行。Compaction 是唯一的异步中断点。

请求链路

以「用户在 CLI 中输入指令,Agent 调用外部工具并返回结果」为例:

sequenceDiagram
    participant User as 用户 (CLI)
    participant Agent as Agent
    participant PM as PromptManager
    participant Provider as Provider (LLM)
    participant Perm as PermissionInspector
    participant EM as ExtensionManager
    participant MCP as MCP Server (子进程)

    User->>Agent: 输入 "帮我创建一个 React 项目"
    Agent->>PM: 组装 prompt (system + history + tools)
    PM-->>Agent: 完整 prompt
    Agent->>Agent: check_if_compaction_needed()
    Agent->>Provider: stream(prompt, tools)
    Provider-->>Agent: 流式响应 (text + tool_calls)

    Note over Agent: 解析出 shell 工具调用

    Agent->>Perm: 检查 shell 权限
    Perm-->>Agent: PermissionCheckResult

    alt 需要用户确认
        Agent->>User: 请求权限确认
        User-->>Agent: 批准
    end

    Agent->>EM: dispatch_tool_call("shell", args)
    EM->>MCP: CallToolRequest (stdio)
    MCP-->>EM: CallToolResult
    EM-->>Agent: ToolCallResult

    Agent->>Provider: stream(带工具结果的 prompt)
    Provider-->>Agent: 流式响应 (最终文本)
    Agent-->>User: 渲染输出

关键架构决策

ADR-1: 使用 MCP 作为工具扩展协议

  • 背景:Agent 需要调用外部工具(文件操作、Shell、数据库等),这些工具由不同开发者提供
  • 决策:采用 Model Context Protocol(MCP)作为工具通信协议,使用 rmcp Rust 库实现
  • 原因:MCP 是 Anthropic 主导的开放标准,已有丰富生态(70+ 扩展);它天然支持子进程隔离、Capability 声明、资源发现
  • 代价:每个扩展是一个独立进程,有启动开销和内存占用;MCP 的 stdio 传输不支持双向流式通知
  • 风险:MCP 协议仍在快速迭代,breaking changes 可能影响扩展兼容性

ADR-2: 自研 ACP(Agent Client Protocol)

  • 背景:需要一种标准化的方式让外部程序(IDE、应用)调用 Goose Agent
  • 决策:设计 ACP 协议,而非复用 MCP 的 client 模式
  • 原因:MCP 是「工具协议」(tool use),ACP 是「Agent 协议」(agent interaction)—— 两者抽象层级不同。ACP 支持 session 管理、权限路由、自定义通知等 Agent 语义
  • 代价:自研协议需要独立维护,社区接受度未知
  • 风险:如果 OpenAI/Claude 推出类似的 Agent 交互标准,ACP 可能被边缘化

ADR-3: Feature Flag 矩阵控制编译变体

  • 背景:Goose 要在不同平台(macOS/Linux/Windows)、不同交付形态(CLI/Server/Desktop)下运行,且支持可选功能(CUDA 加速、本地推理、AWS、遥测等)
  • 决策:使用 Cargo Feature Flags 构建编译矩阵
  • 原因:Rust 的零成本抽象使 feature gate 成为天然的条件编译手段
  • 代价:Feature 组合爆炸——10 个 crate × 20+ features = 难以穷举测试所有组合;portable-default feature 的存在说明组合管理已是痛点
  • 风险:某个 feature 组合可能有编译错误但未被 CI 覆盖

ADR-4: 子 Agent 分流处理复杂任务

  • 背景:单个 Agent 的上下文窗口有限,复杂任务需要拆解
  • 决策:实现 SubAgentHandler,允许主 Agent 将子任务分发给独立的子 Agent 执行
  • 原因:子 Agent 有独立的上下文窗口和工具集,可以并行处理不相关的子任务
  • 代价:增加了系统复杂度(子 Agent 的生命周期管理、结果聚合)
  • 风险:子 Agent 的错误传播和超时管理需要精心设计

架构质量评估

质量属性设计手段评估潜在风险
可扩展性MCP 协议 + ExtensionManager + 内置/外部扩展双轨制★★★★★扩展生态极度开放,新增扩展只需实现 MCP Server
可维护性10 个 crate 分层解耦,Provider/Extension trait 隔离★★★★☆核心 goose crate 仍然过重(40+ 模块)
性能Rust + tokio 异步 + 流式处理 + tree-sitter 代码解析★★★★☆每个 MCP 扩展是独立进程,N 个扩展 = N+1 进程
安全性PermissionInspector + AdversaryInspector + EgressInspector + Sigstore 签名验证★★★★☆Agent 可执行任意 shell 命令,权限粒度是「批准/拒绝」而非细粒度 ACL
可移植性rustls 纯 Rust TLS + 跨平台编译 + Feature Flag★★★★☆macOS 独占扩展(peekaboo)、平台特定密钥环实现
可观测性OpenTelemetry 全链路追踪 + tracing 结构化日志★★★☆☆遥测和 OTel 都是可选 feature,默认未启用
开发体验Feature Flag 矩阵 + workspace 依赖统一管理★★★☆☆编译时间长、Feature 组合测试覆盖不全

架构风险与改进建议

风险 1: 核心 Crate 膨胀

goose crate 承担了过多职责(Agent 循环、上下文管理、权限、安全、会话、配置……),源码中有 40+ 模块。随着功能增长,这会成为维护瓶颈。

建议:将 securitypermissioncontext_mgmt 抽取为独立 crate,goose 只保留 Agent 循环和协调逻辑。

风险 2: Feature Flag 爆炸

当前 Feature Flag 之间有隐式依赖(如 cuda 依赖 local-inferenceportable-default 是多个 feature 的组合),但没有编译时强制校验。

建议:引入 feature 依赖声明(cuda = ["local-inference"] 已有,但缺少互斥检查)和 CI 矩阵测试。

风险 3: MCP 子进程管理

每个外部扩展启动一个子进程,长时间运行可能积累僵尸进程或内存泄漏。

建议:实现扩展进程健康检查 + 自动重启 + 资源限制(cgroup / job object)。

风险 4: Session 持久化的 SQLite 依赖

会话持久化依赖 SQLite(通过 sqlx),在大量历史会话场景下可能成为性能瓶颈。

建议:实现会话归档/过期清理机制,或提供可选的远程存储后端。

可复用架构经验

✅ 值得借鉴的模式

  1. Canonical Model 映射(适用条件:多 LLM 提供商接入场景)

    • 用统一的模型别名映射到各提供商的具体模型 ID,消除 API 差异
    • 让用户用 gpt-4 一个名字就能在 OpenAI / Azure / Bedrock 间切换
  2. Agent 循环的 Tool Confirmation Router(适用条件:需要权限控制的 Agent 系统)

    • 工具调用先经过权限检查,区分 frontend / platform / extension 三类工具分别路由
    • 实现了「工具执行前必须获得授权」的安全模型
  3. 内置扩展的 DuplexStream 模式(适用条件:同一进程内的插件系统)

    • 通过 tokio::io::DuplexStream 在进程内模拟 MCP 通信,内置扩展享受与外部扩展相同的接口
    • 避免了内置/外部扩展的双轨代码路径
  4. 自动 Compaction(适用条件:长对话 Agent 场景)

    • 当对话历史超过阈值时,自动调用 LLM 进行摘要压缩
    • 相比 Claude Code 的手动 /compact,对用户更透明

⚠️ 值得警惕的反模式

  1. Feature Flag 矩阵(出现场景:需要多种编译变体的 Rust 项目)

    • goose crate 有 portable-defaultcode-modelocal-inferencecudavulkanaws-providersrustls-tlsnative-tlssystem-keyringnostrtelemetryotel 等 12+ 个 feature
    • rustls-tlsnative-tls 同时启用时直接 compile_error!,但其他冲突组合呢?
  2. Agent 循环中的硬编码常量(出现场景:快速迭代的 Agent 系统)

    • DEFAULT_MAX_TURNS = 1000DEFAULT_COMPACTION_THRESHOLD 等核心参数以常量形式硬编码
    • 虽然可通过环境变量覆盖部分,但缺乏统一的配置层

关联概念

  • MCP — Model Context Protocol,Goose 的工具扩展通信协议
  • AI Agent — Agent 系统的通用架构模式
  • ACP — Agent Client Protocol,Goose 主导的 Agent 交互协议
  • ReAct Pattern — Agent 循环的推理-行动模式
  • Tool Use — LLM 调用外部工具的设计模式
  • Compaction — 对话历史压缩策略
  • Feature Flag — Rust 条件编译的 Feature Gate 机制
  • Tauri — Goose Desktop App 使用的跨平台 GUI 框架
  • Goose vs oh-my-pi — 与 oh-my-pi 的对比分析