Andrew Ng开源OpenWorker:本地优先的桌面AI Agent,从"对话"到"交付成品"的范式转变

一、引言:AI助手的"最后一公里"困境

过去两年,大语言模型的能力突飞猛进。GPT-5系列、Claude Opus 4.8、Gemini 3.6——每个模型都能写出令人惊叹的回答,都能在基准测试中刷新纪录。但有一个问题始终没解决:AI停留在"说"的阶段,无法真正"做"。

你让AI"准备一份客户续约简报",它给你一段文字。你让AI"整理一下这周的日历冲突",它给你一个待办清单。你让AI"排查一下线上故障",它给你一份分析报告。然后呢?你还是要自己动手——打开文档编辑器、切换日历应用、登录Slack发消息。AI回复了你,然后把烂摊子留给你收拾。

2026年7月23日,Andrew Ng 联合 Alexa 前负责人 Rohit Prasad 开源了 OpenWorker,一个MIT协议的桌面AI Agent。GitHub上14.5k星,定位是"桌面AI同事"(desktop AI coworker)。它的核心承诺只有一句话:AI应该交付成品,而不是对话。

┌──────────────────────────────────────────────────────────────┐
│                    范式转变:从"对话"到"交付成品"              │
│                                                              │
│  传统AI助手(Chatbot范式)                                    │
│  ┌──────────┐    ┌──────────┐    ┌──────────────────┐       │
│  │ 用户提问  │ -> │ AI回复   │ -> │ 用户自己动手干活  │       │
│  └──────────┘    └──────────┘    └──────────────────┘       │
│         ↑                                                    │
│    "帮我写个报告"  →  一段文字  →  你打开Word自己排版        │
│                                                              │
│  OpenWorker(成品交付范式)                                    │
│  ┌──────────┐    ┌──────────────────┐    ┌──────────────┐   │
│  │ 用户描述  │ -> │ AI拆解执行+审批  │ -> │ 交付成品文件  │   │
│  │  目标成果  │    │ 跨工具全流程     │    │ 可直接使用    │   │
│  └──────────┘    └──────────────────┘    └──────────────┘   │
│         ↑                                                    │
│  "准备客户续约简报"  →  读CRM+查Slack+分析数据  →  HTML报告  │
│                        →  请求审批 →  发送给客户CTO         │
└──────────────────────────────────────────────────────────────┘

这不是一个简单的聊天机器人升级。这是AI产品设计哲学的深刻转变——从"优化回复质量"到"优化交付完整性"。本文将从架构设计、审批门控、连接器生态、模型路由等维度,深度剖析OpenWorker的技术实现。


二、项目背景:为什么是Andrew Ng

Andrew Ng 不需要过多介绍。斯坦福教授、Coursera联合创始人、Google Brain早期成员、百度前首席科学家、DeepLearning.AI创始人。和他一起做这个项目的 Rohit Prasad,是亚马逊Alexa的前负责人,拥有超过八年的大规模语音AI产品经验。

两人联手做OpenWorker,信号非常明确:AI Agent要从"玩具"变成"工具",产品化是最关键的一步。

OpenWorker于2026年7月20日创建,7月23日正式开源,8月广泛传播。截至本文撰写时,GitHub上已获得14.5k星,仓库包含:

  • coworker/:Python后端——约119个文件、32,400行代码(Agent引擎、模型提供者、连接器、MCP客户端、记忆系统、自动化调度)
  • surfaces/gui/:React UI + Tauri桌面壳——149个TypeScript/TSX文件
  • stt/:Rust语音识别sidecar(基于whisper.cpp)
  • packaging/:macOS DMG和Windows安装包构建、自动更新清单
  • tests/:78个后端测试模块

这不是一个Demo项目。这是一个可以直接下载、安装、使用的桌面应用。


三、核心设计哲学:不追求"多聪明",追求"把活干完"

OpenWorker 的 README 第一句话写得非常克制:“AI that gets your everyday tasks done.” 翻译过来就是"帮你把日常任务干完的AI。"

这句话的潜台词是:OpenWorker不和你比谁更聪明,它和你比谁更靠谱。

3.1 从"Prompt"到"Outcome"的转变

传统AI的使用方式是写Prompt。你写"给我写一份总结",AI给你一段总结。写得不好,你改Prompt重试。OpenWorker改变了这个交互模型——你给的是一个结果目标(outcome),不是一段提示词(prompt)。

你说"准备下周一客户续约会议的简报",它不会回你一段文字让你自己去整理。而是:

  1. 检查HubSpot CRM中的客户数据
  2. 读取相关的Slack对话记录
  3. 分析使用量趋势
  4. 生成一份HTML/PDF简报文件
  5. 请求你的审批后,将简报通过邮件发送给客户CTO

最终交付的是一个成品——一份可以直接打开的文档、一条已经发送的消息、一项已经更新的日历。

3.2 四种Agent角色,而不是一种万能Prompt

OpenWorker 在后端区分了四种Agent角色,每种角色有独立的工具集、系统提示词和行为模式:

# coworker/agent.py - 四种Agent角色定义(示意代码)
AGENT_ROLES = {
    "chat": {
        "description": "纯对话模式,没有文件和shell权限",
        "tools": ["web_search", "read_url"],
        "system_prompt": "你是一个友好的对话助手,只能提供信息和建议。"
    },
    "code": {
        "description": "编码专用Agent,带单目录工作区",
        "tools": [
            "read_file", "write_file", "shell",
            "git_clone", "git_commit", "git_push",
            "grep_search", "list_files"
        ],
        "system_prompt": (
            "你是一位资深工程师。先读懂代码再修改,"
            "改完必须验证。多个互不依赖的read/grep请求"
            "要在一个批次里并发发出,而不是一次一个。"
        ),
        "workspace": "single_dir"
    },
    "coworker": {
        "description": "知识工作Agent,交付具体成品",
        "tools": [
            "read_file", "write_file", "web_search",
            "connector:slack", "connector:gmail",
            "connector:calendar", "connector:github",
            "connector:jira", "connector:notion"
        ],
        "system_prompt": (
            "你的任务是交付可用的成品文件,而不是回复文字。"
            "在发送消息、修改日历、运行命令之前,"
            "必须请求用户审批。"
        ),
        "workspace": "multi_dir"
    },
    "myhelper": {
        "description": "长期在线个人助理,跨时间连续线程",
        "tools": ["read_file", "write_file", "web_search",
                  "connector:slack", "connector:gmail",
                  "connector:calendar", "scheduler"],
        "system_prompt": "你是一个长期助理,记住用户的重要事项并主动提醒。",
        "persistent": True
    }
}

四种角色,四套工具集,四套人格。不同工种配不同人格,比一个万能Prompt硬撑要清晰得多。这种设计也体现了软件工程中的**关注点分离(Separation of Concerns)**原则。


四、四层架构详解

OpenWorker 的架构是清晰的分层设计,全部运行在用户本机。

┌──────────────────────────────────────────────────────────────────┐
│                    OpenWorker 四层架构总览                        │
│                                                                  │
│  ┌────────────────────────────────────────────────────────┐     │
│  │   Layer 1: 桌面壳 (Tauri 2 + React 18)                │     │
│  │  ┌────────────────────────────────────────────────┐   │     │
│  │  │  React UI (Composer, Transcript, Onboarding)   │   │     │
│  │  ├────────────────────────────────────────────────┤   │     │
│  │  │  Tauri Rust Shell (进程管理, 系统托盘, 语音)    │   │     │
│  │  │  - 启动/监控Python sidecar                      │   │     │
│  │  │  - 本地语音识别 (ocw-stt, whisper.cpp)          │   │     │
│  │  │  - 系统托盘 & 保持唤醒 (caffeinate)             │   │     │
│  │  └────────────────────────────────────────────────┘   │     │
│  ├────────────────────────────────────────────────────────┤     │
│  │   Layer 2: 本地Agent服务 (Python FastAPI + uvicorn)   │     │
│  │  ┌────────────────────────────────────────────────┐   │     │
│  │  │  TurnEngine (核心执行循环)                      │   │     │
│  │  │  ├─ SessionManager (会话管理)                   │   │     │
│  │  │  ├─ PermissionEngine (审批门控引擎)             │   │     │
│  │  │  ├─ ToolRegistry (工具注册与调度)               │   │     │
│  │  │  └─ ProviderRouter (模型路由)                   │   │     │
│  │  └────────────────────────────────────────────────┘   │     │
│  │  绑定: 127.0.0.1:8765 · 默认12轮模型-工具迭代        │     │
│  ├────────────────────────────────────────────────────────┤     │
│  │   Layer 3: 能力与连接器层                              │     │
│  │  ┌────────────────────┬─────────────────────────────┐ │     │
│  │  │  本地工具            │  外部连接器                 │ │     │
│  │  │  ├─ 文件系统 (read/  │  ├─ Slack, GitHub, Jira   │ │     │
│  │  │  │   write/list)    │  ├─ Gmail, Outlook, Cal   │ │     │
│  │  │  ├─ Shell执行        │  ├─ Notion, Linear,      │ │     │
│  │  │  ├─ Git操作          │  │  HubSpot, Attio       │ │     │
│  │  │  ├─ ripgrep搜索      │  ├─ Google Drive, Dropbox│ │     │
│  │  │  ├─ 待办列表         │  ├─ Asana, Monday.com    │ │     │
│  │  │  └─ MCP Client      │  └─ MCP Server (任意)    │ │     │
│  │  └────────────────────┴─────────────────────────────┘ │     │
│  ├────────────────────────────────────────────────────────┤     │
│  │   Layer 4: 模型路由 (aisuite)                          │     │
│  │  ┌────────────────────────────────────────────────┐   │     │
│  │  │  ProviderRouter → ProviderDescriptor → Client  │   │     │
│  │  │  ├─ OpenAI / Anthropic / Google (原生)          │   │     │
│  │  │  ├─ DeepSeek / GLM / Kimi / Qwen / MiniMax     │   │     │
│  │  │  │  Mistral / Grok (兼容)                      │   │     │
│  │  │  ├─ Together / Fireworks (开源权重)             │   │     │
│  │  │  └─ Ollama (完全本地)                          │   │     │
│  │  └────────────────────────────────────────────────┘   │     │
│  └────────────────────────────────────────────────────────┘     │
│                                                                  │
│  全部运行在本机 · 唯一的云组件:OAuth握手中转服务                  │
└──────────────────────────────────────────────────────────────────┘

4.1 Layer 1: 桌面壳(Tauri 2 + React 18)

桌面壳是用户与OpenWorker交互的入口。Tauri 2提供了原生窗口、系统托盘、进程管理等功能。React 18提供了UI组件。

关键设计:Tauri壳负责管理Python sidecar的完整生命周期——启动、监控、终止。如果GUI崩溃,sidecar会自动检测到父进程消失并退出,防止产生僵尸进程。

# coworker/server/run.py - Sidecar进程管理(示意代码)
import os
import signal
import threading

def _exit_when_orphaned():
    """检测父进程是否存活,若已死则自行退出"""
    parent_pid = os.getppid()
    while True:
        try:
            # POSIX: os.kill(pid, 0) 检测进程存活
            os.kill(parent_pid, 0)
            threading.Event().wait(2.0)
        except ProcessLookupError:
            # 父进程已终止,自己退出
            os._exit(0)
        except Exception:
            threading.Event().wait(2.0)

def _watch_parent_windows(parent_handle):
    """Windows平台:使用WaitForSingleObject监听父进程"""
    import ctypes
    kernel32 = ctypes.windll.kernel32
    while True:
        ret = kernel32.WaitForSingleObject(parent_handle, 2000)
        if ret == 0:  # 父进程已结束
            os._exit(0)

4.2 Layer 2: 本地Agent服务(Python FastAPI)

这是整个系统的"大脑"。FastAPI服务绑定在127.0.0.1:8765,提供约120个REST端点和一个WebSocket接口用于流式传输Agent事件。

核心组件是TurnEngine——实现了"模型在环"(model-in-the-loop)执行模式。一次用户请求可能涉及多轮模型推理和工具调用:

# coworker/engine.py - TurnEngine核心循环(示意代码)
class TurnEngine:
    """一次用户"turn"的执行引擎"""
    
    def __init__(self, provider_client, tool_registry, permission_engine):
        self.provider = provider_client
        self.tools = tool_registry
        self.permissions = permission_engine
        self.max_iterations = 12  # 默认最多12轮模型-工具迭代
    
    async def run(self, user_input: str, history: list[dict]):
        messages = history + [{"role": "user", "content": user_input}]
        
        for iteration in range(self.max_iterations):
            # 1. 模型推理
            response = await self.provider.complete(messages, tools=self.tools.schemas)
            
            if response.tool_calls:
                # 2. 并行执行低风险工具,串行执行高风险工具
                results = await self._execute_tools(response.tool_calls)
                messages.extend(results)
            else:
                # 3. 模型给出最终回复,结束循环
                return response.content
        
        raise MaxIterationsError(f"达到最大迭代次数 {self.max_iterations}")
    
    async def _execute_tools(self, tool_calls: list):
        """根据风险等级并行或串行执行工具"""
        read_calls = []
        write_calls = []
        
        for tc in tool_calls:
            risk = self.permissions.classify(tc)
            if risk == RiskLevel.READ:
                read_calls.append(tc)
            else:
                write_calls.append(tc)
        
        # 低风险:并行执行
        read_results = await asyncio.gather(
            *[self.tools.execute(tc) for tc in read_calls]
        )
        # 高风险:串行执行,每个都走审批门控
        write_results = []
        for tc in write_calls:
            outcome = await self.permissions.request_approval(tc)
            if outcome == ApprovalOutcome.APPROVED:
                write_results.append(await self.tools.execute(tc))
            else:
                write_results.append({"error": "用户拒绝执行"})
        
        return read_results + write_results

4.3 Layer 3: 能力与连接器层

这一层分为本地工具和外部连接器。本地工具包括文件系统操作(read_file/write_file/list_files)、Shell执行、Git操作、ripgrep搜索等。外部连接器是OpenWorker的核心能力——25+预置连接器 + MCP协议扩展。

4.4 Layer 4: 模型路由(aisuite)

最底层是基于aisuite的模型路由。aisuite是Andrew Ng团队之前开发的轻量级Python库,统一了多家大模型的调用接口。OpenWorker在此基础上增加了Agent能力——工具调用、状态管理、任务编排。

┌─────────────────────────────────────────────────────┐
│              ProviderRouter 模型路由流程              │
│                                                     │
│  用户选择模型: "Claude Fable 5"                      │
│         │                                            │
│         ▼                                            │
│  model_labels() 映射查找                              │
│         │                                            │
│         ▼                                            │
│  模型ID: "anthropic:claude-fable-5"                  │
│         │                                            │
│         ▼                                            │
│  ProviderRouter.get_client("anthropic")              │
│         │                                            │
│         ▼                                            │
│  registry.py: build_provider_client()                │
│         │                                            │
│         ▼                                            │
│  ProviderDescriptor.build()  →  AnthropicProvider    │
│         │                                            │
│         ▼                                            │
│  TurnEngine.process_turn() 开始执行                   │
└─────────────────────────────────────────────────────┘

五、审批门控机制:核心创新

这是OpenWorker最值得深入分析的部分。一个真的去动你文件、发你消息、跑你终端命令的Agent,最怕的就是它自作主张。大多数桌面Agent项目把审批当成UI层面的事后补丁,OpenWorker把它做成了一个类型系统

5.1 四类风险等级

每个工具调用在注册时就被标注了风险等级:

# coworker/permissions.py - 风险等级与审批门控(示意代码)
from enum import IntEnum

class RiskLevel(IntEnum):
    """工具调用风险等级"""
    READ = 1          # 只读:无副作用,永远放行
    WRITE_LOCAL = 2   # 写本地:改动工作区文件,按路径范围卡
    EXEC = 3          # 执行命令:运行Shell命令
    EXTERNAL = 4      # 外部操作:副作用发生在机器之外

# 工具风险注册表
TOOL_RISK_MAP = {
    # 只读操作 - 自动放行
    "read_file": RiskLevel.READ,
    "list_files": RiskLevel.READ,
    "grep_search": RiskLevel.READ,
    "web_search": RiskLevel.READ,
    "connector:slack_read": RiskLevel.READ,
    
    # 写本地操作 - 需审批(路径范围受限)
    "write_file": RiskLevel.WRITE_LOCAL,
    "create_file": RiskLevel.WRITE_LOCAL,
    "git_commit": RiskLevel.WRITE_LOCAL,
    
    # Shell执行 - 高风险,永远需审批
    "shell": RiskLevel.EXEC,
    "run_script": RiskLevel.EXEC,
    
    # 外部操作 - 需审批,但可设置"常驻规则"
    "connector:slack_send": RiskLevel.EXTERNAL,
    "connector:gmail_send": RiskLevel.EXTERNAL,
    "connector:calendar_update": RiskLevel.EXTERNAL,
}

5.2 五种运行模式

OpenWorker定义了五种运行模式,决定同一风险等级在不同场景下的处理方式:

# coworker/permissions.py - 运行模式(示意代码)
class Mode(IntEnum):
    DISCUSS = 0      # 纯对话,只读
    PLAN = 1         # 只读+规划,不做任何修改
    INTERACTIVE = 2  # 默认模式:读自动放行,写和命令要批准
    AUTO = 3         # 全放行,但写操作限制在路径范围内
    CUSTOM = 4       # 根据用户白名单自动放行

class PermissionEngine:
    """审批门控引擎"""
    
    def __init__(self, mode: Mode = Mode.INTERACTIVE):
        self.mode = mode
        self.standing_rules: dict[str, str] = {}  # 常驻规则
    
    def check_tool(self, tool_call: ToolCall) -> PermissionResult:
        """检查工具调用是否需要审批"""
        risk = TOOL_RISK_MAP.get(tool_call.name, RiskLevel.WRITE_LOCAL)
        
        # 只读操作:所有模式自动放行
        if risk == RiskLevel.READ:
            return PermissionResult.ALLOW
        
        # 检查常驻规则
        rule_key = f"{tool_call.name}:{tool_call.args.get('target', '')}"
        if rule_key in self.standing_rules:
            return PermissionResult.ALLOW
        
        # 根据模式判断
        if self.mode == Mode.DISCUSS or self.mode == Mode.PLAN:
            if risk > RiskLevel.READ:
                return PermissionResult.DENY
        
        if self.mode == Mode.INTERACTIVE:
            if risk >= RiskLevel.WRITE_LOCAL:
                return PermissionResult.NEEDS_USER
        
        if self.mode == Mode.AUTO:
            if risk == RiskLevel.EXEC:
                return PermissionResult.NEEDS_USER  # Shell永远需审批
            return PermissionResult.ALLOW
        
        return PermissionResult.NEEDS_USER

5.3 审批门控流程

┌─────────────────────────────────────────────────────────────────────┐
│                     审批门控执行流程                                   │
│                                                                      │
│  TurnEngine                        PermissionEngine                  │
│  ┌─────────────┐                   ┌───────────────┐                │
│  │ 模型请求     │                   │               │                │
│  │ 调用工具     │                   │               │                │
│  └──────┬──────┘                   │               │                │
│         │                          │               │                │
│         ▼                          │               │                │
│  ┌──────────────┐                  │               │                │
│  │ check_tool() │─────────────────►│ risk=EXEC     │                │
│  │ 检查风险等级  │                  │ needs_user?   │                │
│  └──────┬───────┘                  │               │                │
│         │                          │               │                │
│         ▼                          │               │                │
│  ┌──────────────────┐              │               │                │
│  │ Result: NEEDS_USER│             │               │                │
│  └────────┬─────────┘              │               │                │
│           │                        │               │                │
│           ▼                        │               │                │
│  ┌──────────────────────┐          │               │                │
│  │ 发射 PERMISSION_     │          │               │                │
│  │ REQUIRED 事件到UI     │          │               │                │
│  └──────────┬───────────┘          │               │                │
│             │                      │               │                │
│             ▼                      │               │                │
│  ┌──────────────────────┐          │               │                │
│  │ 用户选择:            │          │               │                │
│  │  ├─ ONCE: 仅此一次   │          │               │                │
│  │  ├─ ALWAYS_TOOL:     │          │               │                │
│  │  │  记住此工具+目标   │          │               │                │
│  │  └─ DENY: 拒绝      │          │               │                │
│  └──────────┬───────────┘          │               │                │
│             │                      │               │                │
│             ▼                      │               │                │
│  ┌──────────────────────┐          │               │                │
│  │ ApprovalOutcome.ONCE  │          │               │                │
│  │ → 执行工具调用        │          │               │                │
│  └──────────────────────┘          │               │                │
│                                                                      │
│  关键设计决策:                                                       │
│  • 常驻规则(standing rule)仅对EXTERNAL风险开放                        │
│  • Shell命令永远需要审批,一次都不放过                                │
│  • 无人值守模式不提升自主权,审批请求转到收件箱                        │
└─────────────────────────────────────────────────────────────────────┘

两个关键设计决策值得注意:

  1. 无人值守不提升自主权:当Agent在无人看管时遇到需要批准的动作,不会自作主张,而是把请求放进收件箱(Inbox),会话挂起直到你回来处理。Agent不会因为你走开了就悄悄获得更多权限。

  2. 常驻规则只对EXTERNAL开放:当一个外部动作(如"向Slack #checkout-alerts 频道发送消息")被你批准后,引擎可以记住"这个工具到这个目标",下次不再问你。但这条捷径只对EXTERNAL风险开放。Shell命令永远需要审批,一次都不放过。 安全的边界卡在最危险的动作上,而不是图省事全放开。


六、35个应用连接器架构

OpenWorker的另一个核心能力是其连接器生态。开箱即用支持25+预置连接器,加上MCP协议扩展,实际可达35个以上。

┌─────────────────────────────────────────────────────────────────────┐
│                    OpenWorker 连接器架构                              │
│                                                                      │
│                        连接器管理器 (ConnectorManager)                │
│                         ┌──────────────────────┐                    │
│                         │  OAuth Token Manager  │                    │
│                         │  Credential Vault     │                    │
│                         │  Connector Registry   │                    │
│                         └──────────┬───────────┘                    │
│                                    │                                  │
│     ┌──────────┬──────────┬────────┼──────────┬──────────┬────────┐ │
│     │          │          │        │          │          │        │ │
│     ▼          ▼          ▼        ▼          ▼          ▼        │ │
│  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐     │
│  │Slack │  │GitHub│  │ Jira │  │Gmail │  │Calendar│  │Notion│     │
│  ├──────┤  ├──────┤  ├──────┤  ├──────┤  ├───────┤  ├──────┤     │
│  │消息  │  │PR    │  │Issue │  │读取  │  │读取   │  │读取  │     │
│  │发送  │  │创建  │  │创建  │  │发送  │  │创建   │  │写入  │     │
│  │读取  │  │读取  │  │搜索  │  │搜索  │  │更新   │  │搜索  │     │
│  └──────┘  └──────┘  └──────┘  └──────┘  └───────┘  └──────┘     │
│                                                                      │
│  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐     │
│  │Linear│  │HubSpot│  │Outlook│  │Drive │  │Dropbox│  │Asana │     │
│  ├──────┤  ├───────┤  ├───────┤  ├──────┤  ├───────┤  ├──────┤     │
│  │Issue │  │CRM   │  │邮件  │  │文件  │  │文件  │  │任务  │     │
│  │管理  │  │数据  │  │日历  │  │操作  │  │同步  │  │管理  │     │
│  └──────┘  └───────┘  └───────┘  └──────┘  └───────┘  └──────┘     │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  MCP Client (Model Context Protocol)                        │   │
│  │  任何MCP Server都可以接入,带per-tool控制                      │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │   │
│  │  │ 数据库   │  │ 浏览器   │  │ 自定义API │  │ 文件系统  │    │   │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘    │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  凭证存储:全部在本地SecretStore,唯一云组件是OAuth握手中转服务        │
│  使用Auth0授权码+PKCE流程,Token直接交给本机,绝不在云端存储          │
└─────────────────────────────────────────────────────────────────────┘

连接器的设计遵循统一的接口协议。每个连接器暴露一组工具(如Slack连接器暴露slack_send_messageslack_read_channelslack_search),这些工具被注册到ToolRegistry中,供Agent引擎调用。

关键设计决策:连接器凭证全部存在本地SecretStore。唯一的云组件是一个可选的OAuth中转服务,使用Auth0授权码+PKCE流程处理一键连接握手。Token直接交给本机,绝不在云端存储。用户也可以完全不登录,手动粘贴API密钥来使用连接器。


七、模型无关设计

OpenWorker是真正的模型无关(model-agnostic)。它不依赖任何特定模型提供商,也不运行自己的推理服务。你自带API Key,或者用Ollama完全本地跑。

7.1 30个精选模型 + 自定义扩展

# coworker/providers/matrix.py - 模型矩阵(示意代码)
from dataclasses import dataclass

@dataclass
class ModelCapabilities:
    tools: bool = True
    vision: bool = False
    parallel_tool_calls: bool = True
    streaming: bool = True
    pdf: bool = False

# 精选模型矩阵
MATRIX = {
    # OpenAI 原生
    "gpt-5.6-sol":       ModelEntry("GPT-5.6 Sol · OpenAI",       _AGENTIC_VISION),
    "gpt-5.6-terra":     ModelEntry("GPT-5.6 Terra · OpenAI",     _AGENTIC_VISION),
    "gpt-5.5":           ModelEntry("GPT-5.5 · OpenAI",           _AGENTIC_VISION),
    
    # Anthropic 原生
    "anthropic:claude-fable-5":   ModelEntry("Claude Fable 5 · Anthropic",  _AGENTIC_VISION),
    "anthropic:claude-opus-4.8":  ModelEntry("Opus 4.8 · Anthropic",        _AGENTIC_VISION),
    "anthropic:claude-sonnet-4.6":ModelEntry("Sonnet 4.6 · Anthropic",      _AGENTIC_VISION),
    
    # Google 原生
    "gemini:gemini-3.6-flash": ModelEntry("Gemini 3.6 Flash · Google", _AGENTIC_VISION),
    "gemini:gemini-3.1-pro":   ModelEntry("Gemini 3.1 Pro · Google",   _AGENTIC_VISION),
    
    # OpenAI 兼容供应商
    "zai:glm-5.2":        ModelEntry("GLM-5.2 · Z AI",        _AGENTIC),
    "deepseek:deepseek-v4": ModelEntry("DeepSeek V4",          _AGENTIC),
    "moonshot:kimi-k2.6": ModelEntry("Kimi K2.6 · Moonshot",  _AGENTIC),
    "minimax:m2.5":       ModelEntry("MiniMax M2.5",           _AGENTIC),
    "qwen:qwen3-max":     ModelEntry("Qwen3 Max · Alibaba",    _AGENTIC_VISION),
    "xai:grok-4.3":       ModelEntry("Grok 4.3 · xAI",        _AGENTIC),
    "mistral:mistral-large": ModelEntry("Mistral Large",       _AGENTIC),
    
    # 开源权重 (通过 Together / Fireworks)
    "together:thinkingmachines/Inkling": ModelEntry("Inkling · via Together", _AGENTIC),
    
    # 完全本地 (Ollama)
    "ollama:llama-4":     ModelEntry("Llama 4 · Ollama",       _AGENTIC),
}

7.2 ProviderRegistry 工厂模式

模型路由使用工厂模式,通过ProviderDescriptor将UI配置映射到具体的ProviderClient:

# coworker/providers/registry.py - Provider注册与工厂(示意代码)
from dataclasses import dataclass, field

@dataclass
class ProviderField:
    """定义单个配置输入字段"""
    key: str
    label: str
    type: str = "string"       # string, password, select
    secret: bool = False
    required: bool = True
    placeholder: str = ""

@dataclass
class ProviderDescriptor:
    """Provider描述符:包含配置字段和构建函数"""
    name: str
    label: str
    fields: list[ProviderField] = field(default_factory=list)
    build: callable = None  # (profile, secrets) -> ProviderClient

# 注册所有Provider
DESCRIPTORS = {
    "openai": ProviderDescriptor(
        name="openai",
        label="OpenAI",
        fields=[
            ProviderField(key="api_key", label="API Key", secret=True),
            ProviderField(key="base_url", label="Base URL", 
                         required=False, 
                         placeholder="https://api.openai.com/v1"),
        ],
        build=lambda p, s: OpenAIProvider(api_key=s["api_key"], 
                                          base_url=p.get("base_url")),
    ),
    "anthropic": ProviderDescriptor(
        name="anthropic",
        label="Anthropic",
        fields=[
            ProviderField(key="api_key", label="API Key", secret=True),
        ],
        build=lambda p, s: AnthropicProvider(api_key=s["api_key"]),
    ),
    "ollama": ProviderDescriptor(
        name="ollama",
        label="Ollama (Local)",
        fields=[
            ProviderField(key="base_url", label="Base URL", 
                         required=False,
                         placeholder="http://localhost:11434/v1"),
        ],
        build=lambda p, s: OllamaProvider(base_url=p.get("base_url", 
                                          "http://localhost:11434/v1")),
    ),
}

def build_provider_client(provider_name: str, profile: dict, secrets: dict):
    """工厂函数:根据provider名称构建客户端"""
    desc = DESCRIPTORS.get(provider_name)
    if not desc:
        raise ValueError(f"Unknown provider: {provider_name}")
    return desc.build(profile, secrets)

7.3 本地优先的配置存储

# config.toml - OpenWorker 配置文件示例
# 全局配置: ~/.config/coworker/config.toml
# 工作区配置: <project>/.coworker/config.toml (覆盖全局)

model = "anthropic:claude-sonnet-4.6"   # 默认模型
mode = "interactive"                     # 默认审批模式
max_iterations = 12                      # 每轮最大迭代次数

# 无需审批的Shell命令前缀
allowed_commands = [
    "ls",
    "cat",
    "pwd",
    "git status",
    "git diff",
]

# 自定义模式下自动放行的工具
auto_allow = [
    "write_file:reports/",
    "connector:slack_read",
]

[server]
host = "127.0.0.1"
port = 8765

八、Slack集成:从消息到成品的完整链路

Slack是OpenWorker最重要的入口之一。在Slack频道里@OpenWorker,一个会话在你的桌面端打开,工作在你的本地工具上运行,结果以线程回复形式送回。

┌─────────────────────────────────────────────────────────────────────┐
│                 Slack → Agent → 连接器 → 交付 完整链路                │
│                                                                      │
│  你: @OpenWorker checkout API is 500ing                              │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │  Slack (线程回复)                                           │    │
│  │  "收到,正在排查..."                                         │    │
│  └─────────────────────────────────────────────────────────────┘    │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │  OpenWorker 桌面端(本地Agent引擎)                          │    │
│  │                                                              │    │
│  │  步骤1: 检查最近部署记录 (GitHub Connector)                    │    │
│  │  └─→ 读取: github.com/org/repo/deployments                   │    │
│  │      ← 发现: 2:02am 部署 payment-migration v3.8              │    │
│  │                                                              │    │
│  │  步骤2: 检查错误日志 (本地Shell)                               │    │
│  │  └─→ 执行: grep "500" /var/log/app/error.log                  │    │
│  │      ← 发现: 错误从2:04am开始,峰值18.4%                       │    │
│  │                                                              │    │
│  │  步骤3: 对照Runbook (本地文件)                                 │    │
│  │  └─→ 读取: docs/runbook.md                                   │    │
│  │      ← 确认: 回滚条件匹配                                     │    │
│  │                                                              │    │
│  │  步骤4: 生成事故时间线 (成品文件)                               │    │
│  │  └─→ 写入: reports/checkout-incident-timeline.md              │    │
│  └─────────────────────────────────────────────────────────────┘    │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │  审批门控: "发送此报告到 #checkout-alerts 频道?"              │    │
│  │  [Approve] [Not now]                                         │    │
│  └─────────────────────────────────────────────────────────────┘    │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │  Slack (线程回复)                                           │    │
│  │  ┌─────────────────────────────────────────┐                │    │
│  │  │  事故时间线报告 (已发送)                  │                │    │
│  │  │  服务: checkout                           │                │    │
│  │  │  峰值错误率: 18.4%                        │                │    │
│  │  │  影响时长: 10分钟                         │                │    │
│  │  │  根因: payment-migration v3.8 连接池回归   │                │    │
│  │  │  建议操作: 回滚v3.8,监控10分钟            │                │    │
│  │  └─────────────────────────────────────────┘                │    │
│  └─────────────────────────────────────────────────────────────┘    │
│                                                                      │
│  关键特性:Slack作为入口,但Agent运行在本地,凭证和模型调用都在本机   │
└─────────────────────────────────────────────────────────────────────┘

这个链路展示了OpenWorker区别于传统AI助手的核心:它不是"回复"你,而是"完成"任务。你只说了"checkout API is 500ing",它自己完成了部署检查、日志分析、Runbook对照、文档生成、审批请求、消息发送——整个闭环。


九、定时任务与无人值守

OpenWorker内置了一个常驻调度器,支持定时自动化任务:早间简报、每周报告、频道盯守。

┌─────────────────────────────────────────────────────────────────────┐
│                     定时任务调度架构                                  │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────┐     │
│  │  Scheduler (常驻调度器)                                     │     │
│  │  ┌────────────────────┐  ┌──────────────────────────────┐  │     │
│  │  │  Cron表达式解析器    │  │  任务队列 (SQLite持久化)      │  │     │
│  │  └────────────────────┘  └──────────────────────────────┘  │     │
│  └────────────────────────────────────────────────────────────┘     │
│       │                                                              │
│       ▼  (调度触发)                                                   │
│  ┌────────────────────────────────────────────────────────────┐     │
│  │  任务执行器                                                   │     │
│  │  ├─ 创建新会话 (SessionManager.create_session())              │     │
│  │  ├─ 注入用户预设的Prompt                                      │     │
│  │  ├─ 运行TurnEngine                                            │     │
│  │  ├─ 遇到审批请求 → 放入收件箱(Inbox)                          │     │
│  │  │  └─ 用户不在线时,会话挂起等待                              │     │
│  │  └─ 执行完成后 → 保存完整Transcript到本地                      │     │
│  └────────────────────────────────────────────────────────────┘     │
│       │                                                              │
│       ▼                                                              │
│  ┌────────────────────────────────────────────────────────────┐     │
│  │  收件箱 (Inbox)                                            │     │
│  │  ┌──────────────────────────────────────────────────┐     │     │
│  │  │  ⏰ 08:00 早间简报 → 待审批: 发送Slack摘要        │     │     │
│  │  │  ⏰ 09:30 每日站会报告 → 待审批: 更新Jira任务     │     │     │
│  │  │  👀 频道盯守: #alerts → 待审批: 发送告警通知     │     │     │
│  │  └──────────────────────────────────────────────────┘     │     │
│  └────────────────────────────────────────────────────────────┘     │
│                                                                      │
│  宕机期间错过的任务:下次启动时自动补跑                               │
│  keep-awake: 通过caffeinate(macOS)/SetThreadExecutionState(Win)      │
│              确保系统在任务执行期间不休眠                               │
└─────────────────────────────────────────────────────────────────────┘

定时任务的强大之处在于它和审批门控机制的结合。即使任务在无人值守时运行,需要审批的操作不会自动执行,而是放入收件箱等待用户处理。宕机期间错过的任务,下次启动时自动补跑。系统还通过caffeinate(macOS)或SetThreadExecutionState(Windows)确保任务执行期间系统不休眠。


十、本地优先设计

OpenWorker的本地优先(local-first)设计是它的核心安全承诺。

10.1 什么存在本地

┌─────────────────────────────────────────────────────────────────────┐
│                     本地优先:数据驻留边界                              │
│                                                                      │
│  ✅ 存在本机 (绝不离开)                  ❌ 可能离开本机                │
│  ┌────────────────────────────┐        ┌────────────────────────┐   │
│  │ Agent循环 (TurnEngine)     │        │ 模型API调用            │   │
│  │ 对话记录 (ConversationStore)│        │ (到你选择的LLM提供商)   │   │
│  │ 连接器凭证 (SecretStore)    │        │ 连接器数据读写          │   │
│  │ 模型API Key (SecretStore)  │        │ (到你集成的SaaS工具)    │   │
│  │ 生成的文件 (本地文件系统)    │        │ OAuth握手 (仅中转)      │   │
│  │ 配置文件 (config.toml)     │        └────────────────────────┘   │
│  │ SQLite会话数据库            │                                      │
│  │ 定时任务队列                │                                      │
│  └────────────────────────────┘                                      │
│                                                                      │
│  SecretStore安全设计:                                                 │
│  • 密钥永远不会进入模型上下文、prompt或trace                          │
│  • 所有敏感信息存于本地加密存储                                     │
│  • 可完全离线使用(手动粘贴API Key)                                  │
│                                                                      │
│  OAuth握手流程:                                                      │
│  用户 → OAuth Provider → 中转服务 → 直接交给本机 (不在云端停留)      │
│  使用 Auth0 授权码 + PKCE 流程                                       │
└─────────────────────────────────────────────────────────────────────┘

10.2 为什么本地优先重要

在企服领域,数据主权是硬门槛。很多企业不敢用AI Agent,因为数据要上传到云端。OpenWorker的本地优先设计解决了这个问题:

  • 模型调用直接走你的机器到LLM提供商,没有中间代理服务器
  • 连接器Token直接交给本机,绝不在OpenWorker的服务器上停留
  • 完全离线可用:手动粘贴API Key和凭证,不需要任何云服务
  • OAuth中转服务使用Auth0授权码+PKCE,Token握手后直接交给本机

唯一的云组件是一个可选的OAuth中转服务,用于一键连接时的握手流程。Token直接交给本机,不在云端存储。


十一、与同类工具对比

OpenWorker 诞生的时间点(2026年7月),桌面AI Agent已经有不少选择。但它们的定位各不相同。

┌─────────────────────────────────────────────────────────────────────┐
│                  同类工具对比:定位决定设计                            │
│                                                                      │
│   工具              │ 目标用户    │ 核心场景    │ 运行方式    │ 模型     │
│  ─────────────────────────────────────────────────────────────────   │
│  OpenWorker         │ 知识工作者  │ 跨工具任务  │ 本地桌面    │ 任意    │
│                     │ (全员)      │ 成品交付    │ (Tauri)    │         │
│  ─────────────────────────────────────────────────────────────────   │
│  Claude Code        │ 开发者     │ 代码编辑    │ 本地终端    │ Claude  │
│                     │            │ 仓库级操作  │ + VS Code  │ 仅     │
│  ─────────────────────────────────────────────────────────────────   │
│  Codex CLI          │ 开发者     │ 代码编辑    │ 云端沙箱    │ OpenAI │
│                     │            │ 沙箱执行    │ + 本地     │ 仅     │
│  ─────────────────────────────────────────────────────────────────   │
│  DeepSeek Harness   │ 开发者     │ 插件化     │ 本地CLI    │ 任意    │
│                     │            │ 一切皆插件  │            │         │
│  ─────────────────────────────────────────────────────────────────   │
│  Hermes Agent       │ 全栈自动   │ 内容流水线  │ CLI+消息   │ 任意    │
│                     │ 化         │ 服务器运维  │ 平台驱动   │         │
│  ─────────────────────────────────────────────────────────────────   │
│                                                                      │
│  OpenWorker 与 Claude Code / Codex 的核心差异:                       │
│  • Claude Code 擅长"改代码"——在仓库里读懂、修改、测试                  │
│  • Codex 擅长"沙箱执行"——隔离环境中运行代码                          │
│  • OpenWorker 擅长"填缝隙"——跨Jira+GitHub+Slack+日历                 │
│    拉通数据,合成文档,审批后执行                                    │
│                                                                      │
│  它们不是竞争关系,而是面向不同场景的互补工具                          │
└─────────────────────────────────────────────────────────────────────┘

详细对比表

维度OpenWorkerClaude CodeCodex CLIDeepSeek Harness
桌面GUI✅ Tauri原生❌ 仅终端❌ 终端+VS Code❌ 仅终端
模型无关✅ 30+模型❌ Anthropic仅❌ OpenAI仅✅ 任意
工具集成25+连接器+MCPMCP+文件系统+浏览器沙箱+文件系统一切皆插件
本地优先✅ 全部本地
审批门控✅ 类型化风险系统✅ 审批✅ 审批⚠️ 基本
定时任务✅ 内置调度器
语音输入✅ Rust STT
开源协议MIT闭源Apache 2.0MIT
主要定位知识工作者跨工具任务代码编辑代码编辑插件化Agent框架

十二、局限性

客观评价一个技术项目,必须看它的局限性。OpenWorker目前处于open beta阶段,以下问题值得注意:

12.1 生产环境需谨慎

OpenWorker虽然是MIT协议开源,但项目创建不到1个月(截至本文撰写时),社区生态仍处于早期阶段。虽然仓库已经有179个Issues和250个Pull Requests,但代码成熟度、文档完整性、社区支持都还在快速演进中。

12.2 Windows版无代码签名

Windows 10/11 x64版本可以下载使用,但由于尚未完成代码签名,Windows SmartScreen会弹出安全警告。对于企业用户来说,这是一个需要认真评估的风险点。macOS版本已签名并公证,自动更新功能正常。

12.3 无Linux桌面构建

目前只有macOS(Apple Silicon)和Windows(x64)的构建版本。Linux用户需要从源码构建,或者通过浏览器模式(npm run dev)运行UI。

12.4 集成权限需自行配置

虽然OpenWorker提供了25+连接器,但每个连接器的OAuth认证和权限范围需要用户自行配置。对于非技术用户来说,理解不同工具的权限模型(如Slack的Bot Token作用域、Google API的OAuth范围)可能有一定门槛。

12.5 本地小模型的任务拆解质量

OpenWorker的模型无关设计让它可以使用Ollama本地模型。但实际测试表明,本地小模型(如7B-13B参数级别)在任务拆解、工具调用规划等复杂场景下的质量明显下降。这是当前小模型能力的天花板,不是OpenWorker本身的问题,但用户需要了解这个限制。


十三、行业意义与展望

13.1 审批门控作为默认设计

OpenWorker最持久的贡献,可能是把审批门控做成了AI Agent的默认设计

在OpenWorker之前,大多数Agent框架把安全当成事后补丁——先让Agent能干活,再考虑怎么防止它干坏事。OpenWorker反过来:安全是架构的第一公民。每个工具调用在注册时标注风险等级,五种运行模式定义不同场景下的行为,shell命令永远需要审批,无人值守不提升自主权。

这个设计哲学应该成为所有"能干活"的AI Agent的参考标准。没有闸门的Agent,能力越强越危险。

13.2 从"对话"到"交付"的范式转变

OpenWorker真正的创新,不是技术架构(虽然架构确实做得好),而是产品哲学的转变

它重新定义了"AI完成一个任务"的标准——不是AI回复了一段话,而是AI交付了一个可用的成品。这个标准听起来简单,但它对产品设计、架构设计、安全设计都产生了深远的影响:

  • 对产品设计:交互从"写Prompt"变成"描述目标成果"
  • 对架构设计:需要连接器、审批门控、本地存储、文件系统集成
  • 对安全设计:需要类型化风险系统、运行模式、驻留规则

13.3 本地优先 = 信任优先

在AI Agent的信任危机日益严重的今天(数据泄露、Prompt注入、权限滥用),OpenWorker的本地优先设计给出了一个清晰的答案:信任不是靠承诺,而是靠架构。当Agent循环、对话记录、连接器凭证、模型密钥全部存在本机,当模型调用直接走你的机器到LLM提供商,当唯一的云组件只是一个OAuth握手中转——信任就不再是一个需要"相信我们"的承诺,而是一个可以验证的事实。


十四、总结

OpenWorker 不是一个划时代的模型,也不是一个颠覆性的技术突破。它是一个把正确的事情做对了的产品——安全当架构设计、成品当交付标准、本地当默认部署、模型当可替换组件。

在AI Agent的"战国时代",OpenWorker可能不是最终的赢家。但它定义了一个新的基线:AI Agent应该交付成品,而不是对话;应该先问再干,而不是先干再问;应该跑在本机,而不是被锁在云端。

对于开发者来说,OpenWorker的代码是一个值得深入研究的参考实现——尤其是它的PermissionEngine、TurnEngine、ProviderRegistry和连接器框架。对于知识工作者来说,它是一个值得尝试的桌面AI同事——虽然还在beta阶段,但方向已经足够清晰。

Andrew Ng 和 Rohit Prasad 做了一个微妙但重要的选择:把AI从"聊天工具"升级为"执行工具"。 这个选择,可能比任何模型能力的提升都更能改变我们与AI的协作方式。


本文基于OpenWorker GitHub仓库(https://github.com/andrewyng/openworker)及公开技术文档撰写,代码片段为示意性实现,完整源码请参考仓库。