数字员工不是一个更大的 Agent Loop

A Digital Employee Is Not a Bigger Agent Loop

早上 8 点整,没有人给「涌现」发消息,它已经起床干活了。

涌现是我的钉钉数字员工。每天早上 8 点整,任务消息准时到达,日程表上排着五项早读:读公众号后台、读 GA、digest 小红书、更新 token 消耗、扫一遍 aibase,预算一小时。中午 12:05,下一班任务照样准点到——它安静干完活,报告发进群,日志里一行 ok=True,一条兜底都没有。(这是我在 谁停掉了数字员工的早读? 里给它验完尸之后的日常。)

没有人 @ 它,没有人提问。它是被自己的日程叫醒的。

这个细节值得停一下:聊天机器人被消息召唤,员工被日程叫醒。而被日程叫醒只是起点——一个真正意义上的员工,还得记得昨天答应过什么,知道十点该跟进谁,干完活主动来汇报。这些都不是「回答得更聪明」的问题,是架构问题。

而这两年,全行业的力气都花在把 Agent Loop 做得更大、更聪明上。我的判断是:数字员工缺的不是一个更大的 Loop,是另一个 Loop。

A Digital Employee Is Not a Bigger Agent Loop

一、行业在造的 Loop,和数字员工缺的 Loop

打开任何一个主流 Agent 框架——Claude Code、Codex、OpenCode,或者 dsh(DeepSeek Harness)这类开源运行时——默认形态都是一个 全能 Agent:一个 loop、一套工具、一份记忆,收到目标就开始 reason → tool call → observe → reason,直到把事做完。我在 一切皆员工:我们在 DeepSeek Harness 上装了一支钉钉数字员工团队 里写过,这个形态对个人助理是优点,对企业员工是要第一个消灭的属性。

但当时我没把话说透。消灭「全能」靠的是制度裁剪,而更根本的问题是:这个 loop 回答的从来只是「这件事怎么做成」,从不回答「我现在应该做什么」。

前者是执行问题,后者是存在问题。把它们拆开,就是两个 Loop:

                    Digital Employee
                           │
              ┌────────────┴────────────┐
              │                         │
       Employee Loop              Execution Loop
       (存在)                    (生产)
              │                         │
      ┌───────┼───────┐          ┌─────┼─────┐
      │       │       │          │     │     │
    Chat   Calendar  Events     Sandbox Cloud  Code
      │       │       │          Agent Agent Agent
      │       │       │
      └───────┴───────┘
              │
        Coordinator
              │
       Task / Approval
              │
              ↓
       Execution Loop
# generated by hugo AI
  • Employee Loop 负责「像一个员工一样存在」:长生命周期、事件驱动,感知组织、维持关系、记住承诺、协调工作。它是神经系统、秘书和 Coordinator 的合体。
  • Task Execution Loop 负责「像一个 Agent 一样干活」:短生命周期、目标驱动,plan → act → observe → verify → retry,把一件事变成可验证的结果。

两者的差别不是「谁更聪明」,几乎每一项都相反:

Employee LoopTask Execution Loop
核心问题我现在应该做什么?这件事怎么做成?
角色员工 / CoordinatorWorker / Executor
生命周期长期存在一个 Task 一个生命周期
TriggerEvent(消息/日程/timer/组织事件)Task 派发
输出决策、回复、委派、提醒Result / Artifact
主要优化拟人化、关系、上下文、协调完成率、正确性、可靠性
状态Employee State(永久持续)Task State(做完归档)
典型工具Chat、Calendar、Org、ApprovalBrowser、Shell、Code、SQL、MCP
失败处理沟通 / 协调 / 升级Retry / Recover / Verify
结束条件没有真正结束完成 / 失败 / Cancel

看最后一行。Task Loop 有终止条件,Employee Loop 没有——员工不下班,只是睡着。 这是两个 Loop 在定义上的分界线,也解释了为什么把执行能力堆到天花板也堆不出一个员工:你造出来的是一个永远在等下一条消息的、很强的聊天机器人。

我在 SPEC 里给这个关系写了一句最狠的约束:

The Employee Loop is the Digital Employee. The Task Executor is merely a capability. Do not invert this relationship.

Employee Loop 才是数字员工本体,Task Executor 只是它借用的能力。Claude Code 再强,也只是员工手里的一件工具——工具可以换,员工不能散架。这个关系一旦倒置(用一个巨大的执行 loop 兼任员工),就会出现企业里最常见的那种数字员工:问一句答一句,答得极好,但从不记得昨天说过什么。

顺带说一句,这个横向拆分和我在 数字员工背后的 Agent,是五层基础设施的叠加 里的纵向五层是互相解释的,不是两套说法硬凑:五层里的身份、上下文、学习三层,全部住在 Employee State 里;执行、验收两层,属于 Task Loop。纵向回答「要建什么」,横向回答「怎么跑」。

二、分界线是时间,不是智力

把两个 Loop 分开之后,最容易误解的一点是:以为 Employee Loop 是「更难的那个」,需要更强的模型。恰恰相反——它需要的不是智力,是记性。

两个 Loop 真正的分界线是时间状态:Employee Loop 是 Stateful Agent,Task Loop 是 Episodic Agent。

Task State 是任务期内的事:goal、plan、当前步骤、tool calls、artifacts、重试记录。任务结束,整个 state 归档,干干净净。

Employee State 是永远不归档的事:

Identity          我是谁,我的主管是谁,我的职责边界
Relationships     我和每个同事的关系、沟通偏好
Commitments       我答应过什么,什么时候到期
Calendar          我的日程,以及日程背后要准备什么
Pending Tasks     我派出去的活,哪些还没回来
Conversations     进行中的对话,谁在等我回复
# generated by hugo AI

它要能记住「我昨天答应 Alice 今天上午给她报告」这句话里的全部信息:答应过、对象是谁、期限、以及现在期限快到了。聊天机器人的记忆里只有 context window;员工的记忆住在窗口外面,是一个可查询、可重放的持久对象。

Anthropic 四月的工程博客《Scaling Managed Agents》从另一个方向走到了同一个结论:他们把 Agent 拆成 Session(append-only 的事件日志)+ Harness(调用模型的 loop)+ Sandbox(执行环境),把「大脑」和「双手」解耦,session 挂在窗口之外,harness 崩了可以用 wake(sessionId) 从日志续跑。他们管解耦前的形态叫「宠物」——容器一挂,session 就丢。数字员工的 Employee State 就是那只不能死的宠物:进程可以重启,员工不能失忆。

时间连续性具体怎么工程化?三样东西:

1. 承诺(Commitment)是一等对象。 「下午三点提醒我给张三打电话」不是一条聊天记录,是一个有生命周期的结构化对象——有 owner、有 due_at、有状态,由 timer 驱动:

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum


class CommitmentStatus(Enum):
    """承诺的生命周期:创建 → 到点触发 → 三种终态。"""

    PENDING = "pending"        # 还没到点
    TRIGGERED = "triggered"    # timer 已触发,等待员工跟进
    ACKNOWLEDGED = "acknowledged"  # 人确认了
    OVERDUE = "overdue"        # 到点没闭环,员工要主动解释
    CANCELLED = "cancelled"


@dataclass
class Commitment:
    """数字员工的「记性」:员工答应过的事,不随会话结束消失。"""

    id: str
    employee_id: str
    description: str           # "给张三打电话"
    owner: str                 # 这件事是谁的:提醒对象
    due_at: datetime           # 承诺期限——员工被它叫醒
    status: CommitmentStatus = CommitmentStatus.PENDING
    source_event_id: str = ""  # 从哪条消息里长出来的,可回溯


@dataclass
class EmployeeState:
    """窗口之外的持久员工:进程可以重启,这个对象不能失忆。"""

    employee: dict                       # 身份、角色、主管、工作时间
    status: str                          # AVAILABLE / BUSY / WAITING_HUMAN ...
    active_conversations: list[str] = field(default_factory=list)
    commitments: list[Commitment] = field(default_factory=list)
    pending_tasks: list[str] = field(default_factory=list)
    scheduled_followups: list[str] = field(default_factory=list)
    recent_events: list[dict] = field(default_factory=list)
    relationships: dict[str, dict] = field(default_factory=dict)
# generated by hugo AI

Commitment 里最容易被忽略的字段是 source_event_id——承诺必须能回溯到「从哪句话里长出来的」,否则审计时无法回答「它为什么认为该做这件事」。

2. 一切重要动作进事件日志。 chat.message.received、decision.made、task.created、followup.scheduled、message.sent——事件流是唯一事实源,EmployeeState 从事件重放恢复,而不是靠模型 context 续命。

3. 重启测试是验收项,不是健壮性加分项。 我在 PoC SPEC 里写了一条硬 Eval:创建一个未到期的 follow-up,杀掉进程,重启,等 timer 到点——提醒必须照常发生。过了这条,才有资格说自己「持续存在」。

这三样加起来,就是那个杀手级 demo。我特意在 SPEC 里写明,PoC 不许用「AI 帮我订会议」做演示——任何 chatbot 都能订会议。必须演示的是:

10:00  人:「下午三点提醒我给张三打电话。」
       ↓
       Employee Loop 创建 Commitment + Timer
       ↓
       ……五个小时,它什么都不做,它在睡觉……
       ↓
15:00  timer.triggered
       ↓
       Employee Loop 被唤醒
       ↓
       它主动发来消息:「现在是下午三点,该给张三打电话了。」
# generated by hugo AI

没有人发消息,它先开口。一个 timer,就划开了员工和聊天机器人。

有人会说:定时提醒,cron 加个 chatbot 就能做。差别在 timer 的前后两头。前一头,「下午三点提醒我」是自然语言里长出来的 Commitment 对象——谁答应的、答应给谁、从哪句话里来的,全部结构化;cron 里只有一行 crontab。后一头,到点唤醒的不是一个固定脚本,而是一个带着全部 Employee State 醒来的员工——它知道这个提醒的上下文,知道你十分钟前刚说过「张三那个事不用催了」,于是它可以决定不提醒,或者换个说法提醒。cron 触发的是动作,Employee Loop 触发的是判断。

三、把副作用从模型手里收走

存在循环要 7×24 无人值守地跑,就不能让 LLM 直接碰副作用。这是 Employee Loop 最重要的一条工程纪律:模型只返回结构化决策,一切动作过 Coordinator 校验执行。

决策合同长这样:

{
  "decision": "CREATE_TASK",
  "reason": "用户要求分析客户流失原因,属于复杂分析任务,应由 Task Executor 完成",
  "actions": [
    {
      "type": "CREATE_TASK",
      "title": "分析客户近 30 天流失原因",
      "assigned_to": "analysis-executor",
      "correlation_id": "conv-8821"
    },
    {
      "type": "SEND_MESSAGE",
      "conversation_id": "conv-8821",
      "content": "收到,我开始分析,预计一小时内给你结论。"
    }
  ]
}
// generated by hugo AI

决策是一个封闭集合:REPLY / CREATE_TASK / UPDATE_TASK / SCHEDULE_FOLLOWUP / ASK_HUMAN / WAIT / IGNORE / DELEGATE。动作也是封闭集合:SEND_MESSAGE、SCHEDULE_TIMER、REQUEST_APPROVAL、UPDATE_COMMITMENT 等。LLM 永远不直接调外部 API,所有副作用走 typed action。

主循环因此非常朴素:

while employee_is_alive:
    event = await next_event()          # 没事件就睡,不轮询模型
    context = build_context(event, employee_state)  # 只装相关上下文
    decision = await agent.decide(context)          # 返回结构化决策
    actions = validate(decision)        # ← 权力搬到了这一行,下文细说
    for action in actions:
        execute_action(action)          # Coordinator 执行,不是模型执行
    persist_state()                     # 落事件日志
    emit_events()
# generated by hugo AI

注意第一行:事件驱动,没有事件就睡。存在循环的成本模型因此和 Task Loop 完全不同——它一天被唤醒几十次,每次只做分类和决策;昂贵的长推理只发生在它派出去的 Task 里。

Task Executor 在 PoC 阶段是一个 Mock:接口只有 create / cancel / get 三个方法,异步模拟任务从 CREATED 到 RUNNING 再到 COMPLETED(偶尔 FAILED),完成后把结果作为事件发回 Employee Loop。这个抽象是整个架构的承重墙——Mock 之后可以整体换成 Sandbox Agent、Cloud Agent、SQL Agent,甚至换成一个真人,Employee Loop 一行不改。员工不换,手里的工具随便换。

四、两个反直觉

反直觉一:Employee Loop 不需要最聪明的模型

「老板在群里 @ 我」这个事件的第一层处理,根本不需要深度推理:

@我
 ↓
Intent Classification(规则 + 小模型)
 ↓
Need Action?
 ├── No  → REPLY(「好的」「收到」级别的回应)
 └── Yes → CREATE_TASK(昂贵的推理留给 Task Loop)
# generated by hugo AI

存在循环追求的是便宜、稳定、永远在线;执行循环才追求聪明。把两个目标塞进一个 Loop,代价是用最贵的模型维持心跳——每次「好的,收到」都烧一遍旗舰模型的推理。分开之后,系统明显更便宜,也更稳:心跳层只做分类和路由,错误面小,出了错还有 validator 兜底。

拟人化的大头也不在推理,在 State。「好的,我下午 3 点前给你」这句话背后没有任何复杂思考,但它需要知道自己是谁、和你什么关系、承诺意味着什么、到点要主动回来。这些全是 Employee State 的供给,不是模型智商的供给。推到底:Employee Loop 的护城河全在组织侧——关系、日程、审批链、职责边界,这些数据只有组织平台给得起。模型再强,也推理不出「张三是谁、归谁管、什么事要他审批」。

反直觉二:validate 那一行,是新的权力中心

决策合同把副作用从 LLM 手里收走了,但权力没有消失,只是搬家了——搬进了 validate(decision) 这一行。

哪个 action 允许直接执行、哪个要升级人工审批、哪个无论如何不许发生,全部由 validator 的规则决定。模型再聪明,出不了这个闸口;validator 一松,前面所有约束形同虚设。而 SPEC 写完我发现自己没有回答一个问题:validator 归谁管?

它的配置权、变更权、审计归属,必须有明确的人。按我在 数字员工的第一准则不是可控性 里立的主管负责制,validator 必须挂在数字员工的主管名下,每次变更进审计日志——否则架构里出现了一个没有主人的新权限层:出了问题,模型的决策有据可查,放行决策的闸口却无人认领。

把权力从模型手里收走是对的;收走之后不给权力找到主人,等于把风险从可见的地方挪到了不可见的地方。

五、模型会吞掉双 Loop 吗

写到这里必须正面回应一个反方,而且是我自己论证过的反方:我在 模型正在吞噬 Agent 框架 里说过,模型每强一代,框架的能力层就被吃掉一层。长记忆、自主规划、事件感知,迟早都是模型内置的。那双 Loop 会不会也是过渡产物——一个足够强的 Agent,为什么不能既是员工又是执行者?

我的回答分两层。

第一层,#403 里已经立过的分界:被模型吞掉的永远是 能力层(loop、调度、上下文压缩),吞不掉的是 职责层(对谁负责、谁审批、出错找谁)。就算未来的模型自带完美记忆和主动性,「这个员工的承诺由谁验收、validator 归谁管」仍然是组织问题,不是模型问题。

第二层是本文新增的:两个 Loop 的优化目标冲突,合并不掉。 存在循环要便宜、稳定、永不宕机;执行循环要聪明、能失败、可重试。合并成一个 Loop,意味着用最贵的组件承载心跳、用最不可控的组件承载承诺。这不是能力问题,是账本问题——账本问题不会因为模型变强而消失,就像电力再便宜,工厂的照明电路和动力电路也不会并成一路。

所以我的预期是:Task Loop 会被模型和运行时持续吞噬,越来越薄;Employee Loop 会持续变厚,因为它沉淀的全是组织供给的状态——那部分不是技术,是资产。

结尾:它睡着的时候,还是不是员工

最后把授权线合拢。Employee Loop 的本质是无人值守运行,而 Anthropic 上个月给 Claude Tag 加的权限体系(我在 权限跟着人走,还是跟着工号走 里拆过)恰好从反面印证了这个架构:个人借给 Agent 的权限(personal connector)明确 不允许无人值守,一切定时例程和自主发起的动作,只能走组织授予的共享权限。

翻译过来:一个 7×24 存在、会被 timer 叫醒、会主动开口的 Loop,天然要求组织级授权——独立身份、service account、管理员划的边界、可审计的日志。这不是巧合。「敢不敢给数字员工发工号」的工程实质,就是敢不敢让一个 Employee Loop 无人值守地存在。

回到开头那个 8 点整的场景。涌现被日程叫醒时,没有任何人在场——那一刻支撑它「是员工而不是聊天机器人」的,不是模型多聪明,而是它的承诺在数据库里、它的权限在组织的授权里、它的动作在 validator 的闸口后面、它的历史在可重放的事件日志里。

所以检验一个数字员工,别问「它回答得够不够聪明」,问一个更狠的问题:

它睡着的时候,还是不是员工?

你在给数字员工做架构时,把「存在」和「执行」分开了吗?欢迎留言聊聊你的拆法。


See also