拆.
主循环——AI 怎么'思考'一轮对话 · 第 01

主循环(runLoop)是什么

为什么 AI 不是'一问一答'

4500读完约 23 分钟craft:B+发布于 2026-06-21

一、原理:Chatbot 的 request/response 模式 vs Agent 的循环

你跟 ChatGPT 聊天时是这样的——你打字、按回车、它回复。一来一回。一次"对话"在结构上是一次完整的 HTTP 请求 + 一次响应。如果你想让它继续做点别的,你得再问一句。

这种模式叫 request/response——请求/响应。它的核心特征是同步:你的输入到它的输出之间没有"中间步骤"。

但 AI Agent 不一样。你跟 Cursor 或 opencode 说"修一下这个 bug",它的行为是这样的:

  • 先读几个文件(看代码结构)
  • 再 grep 几次(找 bug 相关的位置)
  • 再读细节(确认问题)
  • 改代码(edit 工具)
  • 跑测试(bash 工具)
  • 看测试结果(如果失败,回到改代码)
  • 都通过了,给你一个总结

中间发生了 5-10 次(甚至几十次)跟 LLM 的交互,每一次 LLM 都决定"下一步做什么"。这些中间交互你看不见——只看到最后一句"已修复,测试通过"。

这种模式叫 agentic loop——智能体循环。它的核心特征是多轮自主决策:LLM 不只是回答用户,它会自己决定下一步该做什么、调用什么工具、看到结果后下一步怎么走。

为什么需要循环?因为LLM 自己不能"做一连串事"。LLM 一次只能输出一段文字或一个 tool call 请求。它不能在一次响应里"既改代码又跑测试又看结果"。要做一连串事,必须有外部代理(Agent)反复调它,每一轮把上一轮的结果塞回去让它继续。

这个"反复调它的代理"就是主循环。它的核心逻辑是:

loop:
  1. 把当前消息历史发给 LLM
  2. 收到 LLM 响应
  3. 看响应里有没有 tool call 请求
  4. 如果没有 tool call → LLM 觉得任务完了 → 跳出循环
  5. 如果有 tool call → 执行那个工具 → 把结果塞回消息历史 → 回到步骤 1

5 行伪代码,但它是所有 AI Agent 的核心。Cursor 有、opencode 有、Devin 有、Claude Code 有。它们的差别不在"有没有主循环",在"主循环怎么实现"——怎么管理状态、怎么处理错误、怎么控制成本、怎么应对中断。

理解主循环你才能理解 AI Agent 的所有其他设计。tool 设计是为了让循环中的"执行步骤"有效;context 管理是为了让循环不超出 token 限额;permission 是为了让循环不做危险事;event stream 是为了让 UI 能看到循环的每一步。所有 Agent 机制都是围绕主循环转的

二、案例:opencode 的 runLoop 状态机

opencode 的主循环在 packages/opencode/src/session/prompt.tsrunLoop 函数。打开看,它的结构大致是这样:

while (true) {
  // 1. 检查是否需要 compaction(context 太满)
  if (compaction.isOverflow()) {
    compaction.create()
    continue
  }
  
  // 2. 拼装请求并发给 LLM
  const stream = llm.stream(messages, tools, ...)
  
  // 3. 消费流式响应
  for await (event of stream) {
    // 实时发布事件给 UI(每个 token 都触发)
    // 检测 tool call
  }
  
  // 4. 处理 tool calls
  if (toolCalls.length > 0) {
    for (call of toolCalls) {
      executeAndStreamBack(call)
    }
    continue  // 继续下一轮
  }
  
  // 5. 没 tool call,结束
  break
}

这是简化版。真实代码加了大量分支:错误处理、用户中断、max steps、permission 等待、background task 通知。但骨架就是这 5 步。

我们看几个 opencode 的具体设计选择。

选择 1:循环用 Effect FP 的 Stream 模式。opencode 用 Stream.tap().takeUntil().runDrain() 处理 LLM 流式响应。这跟传统的 for await 不一样——Stream 支持 cancellation、错误隔离、并行 tap。用户按 Ctrl+C 时,整个 Stream 被中断,所有副作用(tool 执行、UI 更新)自动 cleanup。

选择 2:tool 执行不阻塞主循环。当 LLM 输出 tool call 时,opencode 把 tool 执行 fork 到一个新的 fiber。LLM 可以继续输出(也许还要 call 别的 tool),fork 的 fiber 在后台跑实际工具。所有 tool 完成后再进入下一轮。

选择 3:每个 turn 完整重新拼 system prompt。第 0.4 章我们提过,每次进入"步骤 2"(发给 LLM)时,opencode 都会重新拼一份完整 system prompt。这意味着 mode 切换、环境变化、用户改了 AGENTS.md 这些都能在下一轮反映出来。代价是 prompt caching 命中率下降——opencode 做了 trade-off 接受这个代价换实时性。

选择 4:循环没有显式的"最大轮数"上限。理论上 opencode 可以无限循环——只要 LLM 一直返回 tool call。实际上有 max-steps 机制(1.9 章讲过)作为安全网,但这是个软上限,不是循环本身的硬限制。

选择 5:循环跟 Session 解耦。一个 session 里可以有多个 turn,每个 turn 调用一次 runLoop。runLoop 是 stateless 的——它的所有状态都在 session 和 messages 里,runLoop 本身不持久化任何东西。这让循环可以 abort、resume、fork 都不影响其他 session。

这 5 个选择叠加,让 opencode 的主循环既灵活又健壮。但它的复杂度也不小——runLoop 函数和它依赖的 processor.ts 加起来大概 2000 行 TypeScript,是 opencode 最复杂的模块之一。

为什么这么复杂?因为主循环是 AI Agent 的"核心反应器"——所有的产品行为都从这里发出。让它健壮值得花这个工程量。

三、设计启示:什么场景需要循环 / 什么场景不需要

这一章的核心论点:主循环是 AI Agent 区别于 Chatbot 的本质特征——但不是所有 AI 产品都需要主循环

什么场景需要主循环?

1. 用户的需求需要多步骤完成。"修这个 bug"涉及读、改、测、复查;"加这个功能"涉及设计、写、测;"解释这段代码"涉及读多个文件理解依赖。这类需求不能一次性完成,需要循环。

2. 中间步骤的结果影响下一步。读了文件 A 才知道要读文件 B;跑了测试才知道改没改对。这种"动态决策"必须有循环承载——LLM 看到上一步结果才能决定下一步。

3. 任务的边界不清晰。用户说"优化下这个函数",没有清晰的"完成标准"。LLM 可能改一次试试、看效果不够再改一次。这种探索性任务需要循环。

什么场景不需要主循环?

1. 输入到输出是确定的。"翻译这段话"、"把这个 JSON 转成 YAML"、"写一段 README"——一次请求一次响应就够。加循环只是浪费 token。

2. 用户期望即时响应。聊天产品、客服产品——用户敲一句话期待 1-2 秒回复。循环可能跑几十秒,不适合即时场景。

3. 没有工具集。如果 LLM 不能调用工具(纯文本生成场景),循环没意义——它每一轮都只是输出更多文字。

设计 AI 产品时关于主循环你要做的几件事:

1. 明确"循环边界"。一个 turn 是一个"用户问 → AI 完成"的单元。turn 内部可以有很多轮 LLM 调用,但 turn 边界要清晰——用户能感知到"这件事完了"。

2. 给循环一个软 + 硬退出条件。软退出是 LLM 自己觉得完了(finish_reason);硬退出是 max-steps、用户中断、context overflow。两者都要有——光软退出可能死循环,光硬退出可能太早砍。

3. 循环要能被中断。用户按 Ctrl+C 必须立刻停。这要求所有 fork 的 fiber、tool 执行、stream 消费都支持 cancellation。不支持中断的循环是不可用的——用户会忍受 30 秒卡死后再也不用了。

4. 循环的每一步要可观测。事件总线、日志、UI 更新——每一轮 LLM 调用、每一次 tool 执行都要发事件。用户看不到内部步骤会失去信任——觉得 AI 在"黑箱乱搞"。

5. 循环要无副作用 fail-safe。如果第 5 轮 tool 调用失败了,前 4 轮的工作不能全废。每一轮的结果应该是独立可见的——LLM 已经改的文件不要因为后面错了就回滚到改之前(除非用户明确要求)。

最后一个观察。主循环这个抽象在 AI Agent 设计里是相对新的——5 年前没人讨论这种东西。它的标准化(每家 Agent 产品都长这样)大概是 2023-2024 年发生的——ReAct 论文 + LangChain 早期版本推动了这个模式的普及。现在主循环已经是 AI Agent 设计的"事实标准"——任何新出现的 Agent 产品几乎肯定有类似的循环结构。

理解这个事实标准,你就能快速看懂任何 Agent 产品的核心架构。下一章 2.2 我们看主循环内部的"一个 turn"长什么样——这是更细的颗粒度。