Easel 架构课程 · 第 3 课

Loop 的实现:agent 循环的真实代码长什么样

10 分钟 · 读完你能徒手写出 agent loop 的骨架

本课唯一结论:agent loop 没有魔法——它是一个 双层 while:while(还有工具要执行) { 调模型(流式) → 执行工具 → 结果回填 }, 外面再包一层管重试、压缩和排队的 while(true)。全部"智能"来自 stopReason 判定 + 结果回填这两个动作的循环。

一、loop 在哪(血统与坐标)

Easel 六件套的 ① 号(Harness)借 OpenClaw 实现;OpenClaw 的 loop 本体在 packages/agent-core/src/agent-loop.ts(1562 行),血统来自 badlogic(Mario Zechner)的 pi-mono——被 vendored 进仓库深度改造(THIRD_PARTY_NOTICES 明确致谢)。

gateway 收 /v1/chat/completions
 → agentCommand(准入)
  → runPreparedEmbeddedLoop        外层 while(true):重试/compaction/排队
    → runEmbeddedAttempt           装配工具 + 系统提示词 + 历史
     → runAgentLoop → runLoop      agent-loop.ts:214 ← 真正的双层 while

二、一次迭代做七件事(骨架)

while (hasMoreToolCalls):                # 内层:agentic 主循环
  ① abort 检查(用户喊停就收尾)
  ② pending/steering 消息提交进 transcript
  ③ streamAgentResponse 调 LLM           # 流式:text_delta 逐个发事件
       流中 toolcall_end → 工具提前入队   # 不等流结束就开始干活
  ④ stopReason 判定:
       toolUse → 执行工具 → 继续
       error / aborted → 终止
       stop → 看 endTurn / terminate 钩子
  ⑤ tool results 追加回 context.messages  # ← 整个"agentic"的秘密就在这行
  ⑥ turn_end 事件 → prepareNextTurn 钩子  # 可中途换模型/思维档
  # hasMoreToolCalls 为假才出内层
排空 followUp 队列;无新消息 → agent_end

⑤ 是第一性设计:工具失败不是抛异常,是构造 isError: true 的结果消息回填—— 模型看到失败原因,下一轮自我纠正。用户看到的是 agent"想了一下又试了一次",不是报错。

三、三个最容易误解的点

① compaction(上下文压缩)不是停止。它发生在 assistant 消息之后: tokens 超过 contextWindow − 16384 预留就触发,LLM 生成摘要,压缩条目 追加进 transcript(历史永不重写,可回放可审计),然后 continue() 续跑。

② 工具是进程内函数,不是子进程。形态统一为 execute(toolCallId, args, signal),MCP 工具也被包装成同形态;串行或并行按批次配置。

③ 同会话严格串行。每会话一个 lane(并发=1)+ Agent.prompt 重入保护; 不同会话不同 lane 天然并行。所以 Easel 才敢让多个浏览器标签页共享一条 raw-stream 文件。

四、Easel 怎么"接到"这个 loop(集成契约)

OpenClaw 的流走事件总线;对外部消费者另开一条旁路: 设 OPENCLAW_RAW_STREAM=1 后,所有 text/thinking delta 以 JSONL best-effort 追加到 /tmp/easel-raw-stream.jsonl(失败静默,绝不影响 run)。 Easel 的 Web 后端每轮开始记住文件尾偏移 → tail 新增行 → 用首个新事件的 runId 闩锁认领自己这轮(隔离并发会话)→ 转 SSE 推给浏览器。

另一处值得抄:Easel 的 supervisor/forward 分离——浏览器断开只断转发,agent 照跑到底, 结果落盘,回来经 /api/chat/last 取回(web/app.py:2064-2066 注释原文)。 长任务 agent 的 Web 集成,这是标准答案。

五、检索练习

六、下一步

一手源推荐: agent-loop.ts(GitHub) 本机也有浅克隆 /tmp/openclaw-src(临时目录)。先只读 runLoop(:214-436)这一段, 对照本课骨架逐行找七件事;再看 docs.openclaw.ai 的 agent-loop 概念文档交叉印证。配套速查:Loop 解剖速查表。