← 返回总览

🔄 主循环设计 — ReAct / Plan-Execute / State Machine

Agent 构建实战 · 模块 1 — 从 20 个项目中提炼的主循环实现细节与取舍
📋 本章目录 1. 所有主循环的本质 2. ReAct 循环 — 9/20 项目的选择 3. Plan-Execute — 全局规划型 4. State Machine — 精确控制流 5. Actor Model — 天然多 Agent 6. 混合架构 — 当今趋势 7. 事件驱动 — 可观测性的基础 8. 循环内部:6 个关键环节 9. 卡死检测与恢复 10. 并行执行与原子性 11. 全景对比表 12. 选型决策树 13. 实现检查清单

1. 所有主循环的本质

不管哪种架构,Agent 主循环的数学本质只有一个:

while not done: observation = get_state() # 感知:读环境 + 历史 thought = llm.think(observation) # 思考:LLM 推理 action = parse_action(thought) # 决策:文本解析 / Function Calling result = execute(action) # 行动:工具执行 history = update(history, result) # 更新:状态 / 事件追加 20 个项目的差异,全在「每个步骤怎么做」和「步骤之间怎么连」。
核心洞察:选择主循环模式,本质上是在选择「思考-行动」的粒度「状态转移」的确定性。ReAct 每步都问 LLM(灵活但贵),Plan-Execute 一次规划多步(省 token 但不适应变化),State Machine 精确控制(可靠但需要预定义)。

2. ReAct 循环 — 9/20 项目的选择

ReAct(Reasoning + Acting)是出现频率最高的主循环模式。核心思路:每一步都让 LLM 先推理、再决定行动、观察结果、继续推理。

ReAct 循环(9/20 采用) User Query │ ▼ ┌────────────────────────────────────────────────────────────────┐ │ Observation — 组装消息历史(system + 历史 + 用户输入) │ │ │ │ │ ▼ │ │ Thought — LLM 推理:分析当前状态,决定下一步 │ │ │ │ │ ├── 无工具调用 → MessageEvent(回复用户)→ 结束 │ │ │ │ │ ├── 工具调用 → ActionExecuteResult │ │ │ │ │ │ │ ├── 成功 → 追加 Observation → 回到顶部 │ │ │ ├── 失败 → 重试 / 报错 → 回到顶部 │ │ │ └── 需确认 → 等待用户 → 回到顶部 │ │ │ │ │ └── 空响应 / 仅推理 → 注入 followup → 回到顶部 │ │ │ │ 重复直到:完成 / 达到最大步数 / 用户终止 │ └────────────────────────────────────────────────────────────────┘

2.1 各项目的 ReAct 实现差异

项目循环实现终止条件特色
OpenHands Conversation.run()Agent.step() FinishTool / max 500 iter / StuckDetector Event Stream + Condenser 压缩 + ParallelToolExecutor
SWE-agent DefaultAgent.step()forward_with_handling() StepOutput.done=True / total_execution_timeout 8 种解析器 + 错误重查询(FormatError/BlocklistError 重试)
Aider Coder.run_one()send_message() + Reflection Loop 无 reflection message / max_reflections Reflection Loop(lint/test 失败自动重试)+ 15 种编辑格式
Codex CLI 内部 Agent loop + 三级审批 任务完成 / 用户取消 Auto-approve / Suggest / Full-confirm 三级安全模式
Agent Zero 嵌套 ReAct(主 Agent + 子 Agent) Agent 自行判断完成 层次化记忆 + 自发学习循环
Goose Session-based ReAct loop 任务完成 / 用户中断 Provider 抽象层 + Session 状态恢复
Browser Use ReAct over browser tabs LLM 判断完成 / max_steps Tab 管理 + 页面快照 + DOM 选择器
GPT Researcher Research + Report 双阶段 ReAct 信息充足度评估 Scraping + VectorStore + 评估器决定是否继续搜索
Hermes ReAct + Background Review Fork 工具返回完成标志 自进化:后台 fork 审查自身行为并优化提示词

2.2 OpenHands 的 ReAct:Event-Driven 变体(最佳实践)

OpenHands 在标准 ReAct 基础上做了两个关键创新:

① Event Stream — 不可变追加日志

所有交互(LLM 调用、工具执行、用户消息)都记录为不可变 Event 对象,追加到 append-only 事件流。这意味着:

# 事件层级
Event (frozen Pydantic, append-only)
  ├─ LLMConvertibleEvent → 可转为 LLM Message
  │   ├─ ActionEvent        # Agent 工具调用
  │   ├─ ObservationEvent   # 工具返回结果
  │   ├─ MessageEvent       # 用户/Agent 文本消息
  │   └─ SystemPromptEvent  # 初始系统提示词
  ├─ Condensation           # 上下文压缩事件
  ├─ CondensationRequest    # 请求压缩(超出窗口时触发)
  ├─ TokenEvent             # 流式 token
  └─ AgentErrorEvent        # 错误

② Condenser Pipeline — 上下文窗口管理

事件流会无限增长,但 LLM 上下文窗口有限。Condenser 在 prepare_llm_messages() 时压缩历史:

class LLMSummarizingCondenser(Condenser):
    """将早期事件总结为一条摘要,保留近期事件不变"""
    
    def condense(self, events: list[Event]) -> list[Event]:
        if token_count(events) <= max_size:
            return events
        # 1. 保留最近 N 个事件
        recent = events[-keep_recent:]
        # 2. 对早期事件做 LLM 摘要
        summary = self.llm.summarize(events[:-keep_recent])
        # 3. 返回 [Condensation(summary), ...recent]
        return [Condensation(content=summary)] + recent

2.3 SWE-agent 的 ReAct:ACI + 错误重查询

SWE-agent 的 ReAct 循环有独特的 错误重查询 机制——当 LLM 输出格式错误或触发 blocklist 时,不是直接失败,而是将错误信息注入历史重新查询:

# forward_with_handling 伪代码
def forward_with_handling(self, history):
    n_format_fails = 0
    while n_format_fails < self.max_requeries:
        try:
            return self.forward(history)         # 正常 ReAct 步
        except FormatError as e:
            n_format_fails += 1
            history = requery_history(e)         # 把错误加入历史重问
        except BlocklistError as e:
            history = requery_history(e)         # 被禁命令也重问
        except BashSyntaxError as e:
            history = requery_history(e)         # Bash 语法错误也重问
        except AgentGaveUpError:
            return attempt_autosubmission()      # 放弃但尝试提交
💡 值得学习:SWE-agent 的 ACI 设计哲学——为 Agent 设计专用交互接口,而非复用人类接口。例如 str_replace_editor 命令比裸 bash sed 更适合 LLM 操作文件。你的 Agent 不应该像人类一样操作电脑,它应该有自己专用的交互方式。

2.4 Aider 的 ReAct:Reflection Loop

Aider 在标准 ReAct 之外增加了 Reflection Loop——每次编辑后自动检查 lint 和测试,失败则自我修正:

# Aider run_one 伪代码
def run_one(self, user_message):
    message = user_message
    while message:
        self.reflected_message = None
        self.send_message(message)           # 标准 ReAct 步
        
        if not self.reflected_message:
            break                            # 无问题,完成
        
        if self.num_reflections >= self.max_reflections:
            break                            # 超过最大反思次数
        
        self.num_reflections += 1
        message = self.reflected_message     # 用反思消息继续循环

reflected_message 可能来自:

3. Plan-Execute — 全局规划型

Plan-Execute 模式先让 LLM 规划完整步骤列表,再逐步执行。优势是能做出全局最优决策,劣势是计划可能过时。

Plan-Execute 循环 User Query │ ▼ ┌──────────────┐ │ PLAN 阶段 │ LLM 生成步骤列表 │ steps = [...] │ [1. 分析需求, 2. 搜索代码, 3. 修改文件, 4. 测试] └──────┬───────┘ │ ▼ ┌──────────────┐ │ EXECUTE 阶段│ for step in steps: │ 逐步执行 │ result = execute(step) │ │ if needs_replan: → 回到 PLAN └──────┬───────┘ │ ▼ 完成 / 重新规划

3.1 AutoGPT 的 Block 架构:DAG 图执行

AutoGPT 采用了 Block 流式架构,将 Plan-Execute 推向了极致——每个步骤是一个 Block,Block 之间通过 DAG 图连接:

AutoGPT Block 体系

# Block 是执行的最小单元
class Block:
    id: str
    input_schema: dict   # 输入数据定义
    output_schema: dict  # 输出数据定义
    
    def execute(self, input_data) -> dict:
        """执行 Block,返回输出数据"""

# 关键 Block 类型:
OrchestratorBlock     # ReAct 循环:LLM → 工具调用 → 观察 → 继续
AutoPilotBlock        # 嵌套子代理:创建子 Agent 执行子任务
LLMBlock              # 纯 LLM 调用(不执行工具)
CodeBlock             # 代码执行
ForLoopBlock          # 循环控制
IfElseBlock           # 条件分支

AutoGPT 的 OrchestratorBlock 本质上是一个 ReAct 循环,但嵌在 DAG 图执行引擎中。这意味着你可以把 ReAct 和 Plan-Execute 混合使用——这正是混合架构的趋势。

3.2 GPT Researcher 的双阶段

GPT Researcher 的 Plan-Execute 更加显式:

⚠️ Plan-Execute 的陷阱:计划一旦生成就可能过时。环境在执行过程中会变化,LLM 早期规划的步骤可能不再适用。最佳实践:每步执行后评估是否需要重新规划,而非盲目执行完整个计划。

4. State Machine — 精确控制流

State Machine(状态机)模式用显式的图定义控制流:每个状态是一个节点,状态之间的转移是边。LangGraph 是这一模式的集大成者。

LangGraph State Machine ┌─────────┐ ┌──────────┐ ┌──────────┐ │ START │───▶│ 分析需求 │───▶│ 选择工具 │ └─────────┘ └────┬─────┘ └────┬─────┘ │ │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ 直接回复 │ │ 执行工具 │ └────┬─────┘ └────┬─────┘ │ │ ▼ ▼ ┌─────────┐ ┌──────────┐ │ END │ │ 观察结果 │ └─────────┘ └────┬─────┘ │ ┌───────┴───────┐ │ 条件转移 │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ 继续分析 │ │ 结束回复 │ └──────────┘ └──────────┘ 关键:节点并行执行Reducer 合并结果条件边路由

4.1 LangGraph 的 Pregel 执行模型

LangGraph 不仅仅是一个状态机——它的执行引擎基于 Google Pregel 论文的 BSP(Bulk Synchronous Parallel) 超步模型:

每个超步(Superstep)的 4 个阶段

  1. READ — 每个节点从 Channel(通道)读取输入
  2. COMPUTE — 所有节点并行执行
  3. WRITE — 每个节点将结果写入 Channel
  4. CHECKPOINT — 保存状态快照(Time Travel 基础)
# 超步循环核心
while there_are_nodes_to_run:
    # 1. READ: 从 Channel 读取
    for node in nodes_to_run:
        node.read_channels(state)
    
    # 2. COMPUTE: 并行执行(asyncio.gather)
    results = await gather(*[node.execute() for node in nodes_to_run])
    
    # 3. WRITE: 写入 Channel(Reducer 合并)
    for result in results:
        for key, value in result.items():
            channel[key] = reducer(key, value)  # Reducer 决定合并策略
    
    # 4. CHECKPOINT: 保存快照
    await checkpointer.save(state, config)
    
    # 5. 确定下一轮要执行的节点(条件边路由)
    nodes_to_run = determine_next_nodes()
💡 为什么 Pregel 重要?它是唯一提供并行执行正确性保证的 Agent 框架。当两个节点同时写入同一个 state key 时,Reducer 函数决定如何合并(add_messages 追加、operator.add 求和、无 reducer 则覆盖)。没有这个机制,并行写入会导致不可预测的竞态条件。

4.2 StateGraph Builder 模式

from langgraph.graph import StateGraph, START, END
from typing import Annotated

class State(TypedDict):
    messages: Annotated[list, add_messages]  # Reducer: 追加消息
    next_action: str

graph = StateGraph(State)

# 添加节点
graph.add_node("analyze", analyze_fn)
graph.add_node("search", search_fn)
graph.add_node("respond", respond_fn)

# 添加边
graph.add_edge(START, "analyze")
graph.add_conditional_edges("analyze", route_fn, {  # 条件路由
    "search": "search",
    "respond": "respond",
})
graph.add_edge("search", "analyze")     # 搜索后回到分析
graph.add_edge("respond", END)

# 编译(加入 Checkpoint、中断点等)
app = graph.compile(
    checkpointer=SqliteSaver("checkpoints.db"),
    interrupt_before=["respond"],  # 人机协作中断点
)

4.3 Checkpoint 与 Time Travel(独有优势)

LangGraph 是唯一原生支持 Time Travel 的框架:

实用价值:Checkpoint + Time Travel 让 Agent 可以安全地回滚错误决策,这是其他框架做不到的。在需要人机协作的场景下,interrupt_before + resume 提供了最优雅的中断-恢复机制。

4.4 PydanticAI 的 GraphAgent

PydanticAI 也提供了状态机模式,但更轻量:

# PydanticAI GraphAgent
class MyGraph(GraphAgent):
    node_a = Node(handler=analyze, next="node_b")
    node_b = Node(handler=execute, next=END_or_loop)

与 LangGraph 的区别:PydanticAI 没有 Pregel 并行模型,没有 Checkpoint,但集成度更高(类型安全 + 依赖注入 + result_type)。

5. Actor Model — 天然多 Agent

Actor Model 把每个 Agent 视为一个独立的 Actor,通过消息传递通信。AutoGen 和 MetaGPT 是这一模式的代表。

Actor Model(AutoGen) ┌──────────┐ message ┌──────────┐ message ┌──────────┐ │ Agent A │──────────────▶│ Agent B │──────────────▶│ Agent C │ │ (Actor) │◀──────────────│ (Actor) │◀──────────────│ (Actor) │ └──────────┘ response └──────────┘ response └──────────┘ ▲ │ │ ┌──────────┐ │ └──────────────────────│ Runtime │◀──────────────────────┘ message routing │ (Router) │ message routing └──────────┘ 通信模式: RPC (点对点):send_message() → 等待返回值 (asyncio.Future) Event (发布/订阅):publish_message() → Topic → 所有订阅者

5.1 AutoGen 的双层架构

AutoGen 的精妙之处在于双层解耦

Core Runtime — 纯 Actor

# 每个 Agent 是一个 Actor
class Agent(Protocol):
    @property
    def metadata(self) -> AgentMetadata: ...
    
    async def on_message(self, message, ctx) -> Response:
        """收到消息时的处理逻辑"""

# 两种通信
result = await runtime.send_message(msg, recipient=AgentId("agent_b"))
runtime.publish_message(event, topic_id=TopicId("news"))

5.2 AutoGen 的 5 种群组编排

Actor Model 的真正威力在于群组编排——多个 Agent 如何协作完成同一个任务:

编排模式原理适用场景
RoundRobinGroupChat Agent 轮流发言 简单讨论、头脑风暴
SelectorGroupChat LLM 选择下一个发言者 需要智能路由的任务
Swarm Handoff 机制:Agent 自主转移控制权 多专业技能协作
DiGraphGroupChat DAG 图定义执行流程 有明确依赖关系的流水线
MagenticOne Ledger 编排:协调者维护任务清单 复杂多步任务

5.3 MetaGPT 的 SOP 流水线

MetaGPT 用 SOP(Standard Operating Procedure) 模式——模拟软件团队的标准化流程:

MetaGPT Watch-Publish 模式

class Role:
    """每个 Role 监听特定消息,发布处理结果"""
    
    def _watch(self, actions: list[Type[Action]]):
        """订阅特定 Action 的输出"""
        self._watching = set(actions)
    
    async def _observe(self) -> int:
        """从 MessageQueue 取出自己关心的消息"""
        news = self.rc.msg_queue.pop()
        return len(news)
    
    async def run(self):
        """Role 主循环:Observe → Think → Act → Publish"""
        await self._observe()           # 1. 取消息
        reaction = await self._react()  # 2. 思考+行动
        await self._publish(reaction)   # 3. 发布结果

典型的 SOP 流水线:ProductManager 写 PRD → Architect 写设计 → ProjectManager 拆任务 → Engineer 写代码 → QaEngineer 测试。每个 Role 通过 _watch 订阅上游的输出,实现松耦合的流水线

5.4 CrewAI 的 Process-Driven 编排

CrewAI 的模式介于 AutoGen 和 MetaGPT 之间:

6. 混合架构 — 当今趋势

2024-2025 年的 Agent 架构趋势:ReAct 内核 + 外层编排。单一模式已经不够用,混合架构成为主流。

混合架构(趋势) ┌─────────────────────────────────────────────────────────┐ │ 编排层(State Machine / Actor Model) │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │Node1│→│Node2│→│Node3│→│Node4│→│Node5│ │ │ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ │ │ │ │ │ │ │ │ └─────┼────────┼────────┼────────┼────────┼──────────────┘ │ │ │ │ │ ┌─────▼────────▼────────▼────────▼────────▼──────────────┐ │ ReAct 内核(每个 Node 内部) │ │ while not done: │ │ think → act → observe → think → ... │ └────────────────────────────────────────────────────────┘

6.1 各项目的混合架构

项目外层编排内层循环混合方式
AutoGPT DAG 图 + Block 流式 OrchestratorBlock 内部 ReAct Block 是 DAG 节点,OrchestratorBlock 自身是 ReAct
AutoGen Actor Model Runtime 每个 Agent 内部 ReAct Agent 是 Actor,通过 Handoff 转移控制权
MetaGPT SOP Watch-Publish Role._react() 内部 ReAct Watch-Publish 流水线,每个 Role 内部 ReAct
CrewAI Process Sequential/Hierarchical Agent 内部 ReAct 外层 Process 编排,内层 Agent 自主
LangGraph Pregel 超步图执行 每个 Node 可以是 ReAct Agent Node 内部嵌套子图(子 ReAct 循环)
Aider ArchitectCoder 两阶段 Architect 思考 + Editor 编辑 双模型分离:强模型推理 + 经济模型执行
SWE-agent RetryAgent 多尝试 DefaultAgent 内部 ReAct 外层多尝试 + Reviewer 评分,内层标准 ReAct
架构趋势总结:

7. 事件驱动 — 可观测性的基础

事件驱动不是一种主循环模式,而是任何主循环都应采用的实现方式。OpenHands 和 OpenClaw 是最佳实践。

为什么需要事件驱动?

OpenClaw 的事件驱动实现

OpenClaw 的整个 Gateway 是事件驱动的——每个 session 是一个事件流:

8. 循环内部:6 个关键环节

不管哪种循环模式,内部都有 6 个必须正确实现的环节:

📥
1. 状态收集
MUST
从环境/历史中收集当前状态,组装为 LLM 输入。OpenHands 用 prepare_llm_messages() + Condenser,SWE-agent 用 HistoryProcessor 链(Cache + LastN + ClosedWindow + RemoveRegex)。
🧠
2. LLM 调用
MUST
调用 LLM 获取推理结果。关键细节:重试逻辑(OpenHands 5 次指数退避)、流式处理、多模型 fallback。几乎所有项目都用 LiteLLM 做统一接口。
🔍
3. 输出解析
MUST
将 LLM 输出转为结构化动作。两条路线:Function Calling(12/20 项目,如 OpenHands、AutoGen)vs 文本解析(8/20,如 Aider SEARCH/REPLACE、SWE-agent 8 种解析器)。
4. 动作执行
MUST
执行工具/动作。关键:并行执行(OpenHands ParallelToolExecutor + 资源锁)、安全审批(Codex CLI 三级审批)、沙箱隔离(OpenHands Docker、SWE-agent SWE-ReX)。
📊
5. 结果处理
MUST
将执行结果反馈到循环。细节:错误重查询(SWE-agent)、Reflection Loop(Aider)、CriticMixin 自评(OpenHands)、Action Sampler 多路径(SWE-agent)。
🔄
6. 终止判断
MUST
决定循环是否继续。方式:显式完成工具(OpenHands FinishTool)、LLM 自行判断(GPT Researcher 评估器)、最大步数限制(几乎所有项目)、卡死检测(OpenHands StuckDetector)。

9. 卡死检测与恢复

Agent 循环最大的运行时风险是卡死——Agent 在同一个错误上反复尝试,永远无法逃脱。只有 OpenHands 实现了完整的卡死检测系统。

9.1 OpenHands StuckDetector — 5 种检测

class StuckDetector:
    """5 种卡死模式检测"""
    
    def is_stuck(self, events: list[Event]) -> bool:
        # 1. Action-Observation Loop:同一动作重复 N 次
        #    例:反复搜索同一个文件,结果相同
        if self._detect_action_observation_loop(events):
            return True
        
        # 2. Action-Error Loop:同一失败动作重复 N 次
        #    例:反复尝试同一个语法错误的命令
        if self._detect_action_error_loop(events):
            return True
        
        # 3. Monologue:Agent 自说自话,不调用任何工具
        if self._detect_monologue(events):
            return True
        
        # 4. Alternating Pattern:两个动作来回切换
        #    例:搜索 → 编辑 → 搜索 → 编辑(编辑总被撤销)
        if self._detect_alternating_pattern(events):
            return True
        
        # 5. 上下文膨胀:Condensation 请求过于频繁
        if self._detect_excessive_condensation(events):
            return True
        
        return False

9.2 其他项目的卡死处理

项目卡死处理详细
SWE-agent total_execution_timeout + 自动提交 超时后 attempt_autosubmission(),尝试提取当前 patch
Aider max_reflections 限制 Reflection Loop 最多 N 轮,超过则强制结束
AutoGPT max_iterations 硬性上限,到达后停止
LangGraph recursion_limit 图的最大递归深度(默认 25),超过抛异常
AutoGen TerminationCondition 可组合的终止条件(MaxMessageCount、TextMention、TokenUsage)
💡 最佳实践:实现至少两层保护——1) 智能卡死检测(检测重复模式)+ 2) 硬性上限(最大步数/时间)。只有智能检测才能让 Agent 在真正需要多次尝试时不被误杀,而硬性上限是最后的安全网。

10. 并行执行与原子性

当 LLM 返回多个工具调用时(Parallel Function Calling),如何并行执行?核心问题是原子性——多个工具调用应该全部成功还是允许部分失败?

10.1 OpenHands _ActionBatch — 原子批处理

@dataclass(frozen=True, slots=True)
class _ActionBatch:
    action_events: list[ActionEvent]
    has_finish: bool
    blocked_reasons: dict[str, str]     # Hook 拦截的动作
    results_by_id: dict[str, list[Event]]

    @classmethod
    def prepare(cls, action_events, state, executor, tool_runner, tools):
        # 1. 如果包含 FinishTool,截断后续调用
        # 2. 分区:blocked(Hook 拦截)vs executable
        # 3. ParallelToolExecutor 批量执行
        #    - 声明相同资源的工具串行执行
        #    - 不同资源的工具并行执行
        # 4. 返回不可变批次结果

关键:ParallelToolExecutor 使用资源键锁机制——工具通过 declared_resources() 声明它要访问的资源(如文件、URL),声明相同资源的工具串行执行,不同资源的并行执行。

10.2 LangGraph — Pregel 并行保证

LangGraph 的并行更根本——在 Pregel 超步模型中,所有节点天然并行执行,Reducer 保证写入合并的正确性:

class State(TypedDict):
    messages: Annotated[list, add_messages]  # 并行写入 → 追加合并
    score: Annotated[int, operator.add]       # 并行写入 → 求和

10.3 对比

策略代表项目优势劣势
资源键锁并行 OpenHands 细粒度控制,避免竞态 工具必须声明资源依赖
Pregel + Reducer LangGraph 形式化正确性保证 仅限 State Machine 模式
串行执行 大多数项目 简单,无竞态 性能差

11. 全景对比表

项目 主循环 编排方式 终止条件 卡死检测 并行执行 特色
OpenHands ReAct Event Stream FinishTool / 500 iter / StuckDetector 5 种检测 资源键锁 Condenser + CriticMixin
LangGraph State Machine Pregel BSP END 节点 / recursion_limit recursion_limit Pregel + Reducer Checkpoint / Time Travel
Aider ReAct + Reflection Strategy Pattern 无 reflection / max_reflections max_reflections ArchitectCoder 双模型
AutoGen Actor Model 5 种群组编排 TerminationCondition 组合 MaxMessageCount Actor 天然并行 Handoff + SocietyOfMind
AutoGPT DAG + ReAct Block 流式 + DAG 图 max_iterations 硬性上限 DAG 并行 AutoPilotBlock 子代理
MetaGPT Actor + SOP Watch-Publish SOP 流程完成 Role 天然并行 ActionNode Review-Revise
CrewAI Process-driven Sequential / Hierarchical / Flow 任务完成 Flow 并行 Flow 装饰器
SWE-agent ReAct + Retry RetryAgent 包装 done=True / total_execution_timeout 超时自动提交 ACI + 8 种解析器
Agent Zero 嵌套 ReAct 主 Agent → 子 Agent Agent 自行判断 子 Agent 并行 层次化记忆
GPT Researcher Plan-Execute Research + Report 信息充足度 搜索并行 VectorStore + 评估器
Browser Use ReAct Tab 管理 LLM 判断 / max_steps max_steps 多 Tab 并行 DOM 选择器
Hermes ReAct + 自进化 76 工具 + Toolset 工具返回完成 Background Review Fork
OpenClaw Event-driven ReAct Session + Channel 完成 / 用户终止 超时保护 Policy Pipeline Cache Boundary + 14 平台
Codex CLI ReAct 三级审批 任务完成 / 用户取消 Auto-approve/Suggest/Confirm
Smolagents ReAct CodeAgent / ToolCallingAgent Final Answer 极简实现
CAMEL Role-playing Role-playing + Knowledge Graph 对话轮数 / 任务完成 Inception Prompting
Google ADK ReAct Runner + Session Agent 自行判断 A2A 协议
PydanticAI ReAct / Graph Agent + GraphAgent result_type 返回 类型安全 + 依赖注入
Goose ReAct Session-based 任务完成 Provider 抽象
Agno ReAct Agent + Toolkit + Session Agent 自行判断 极简 API

12. 选型决策树

🤔 我该选哪种主循环? ❓ 你的 Agent 是单 Agent 还是多 Agent? │ ├── 单 Agent │ │ │ ├── ❓ 任务步骤是否固定? │ │ ├── 固定 → State Machine (LangGraph) │ │ │ 需要回滚?→ LangGraph + Checkpoint │ │ │ 需要人机协作?→ LangGraph + interrupt_before │ │ │ │ │ ├── 不固定 → ReAct │ │ │ 需要错误恢复?→ ReAct + Reflection Loop (Aider) │ │ │ 需要多尝试?→ ReAct + RetryAgent (SWE-agent) │ │ │ 需要上下文管理?→ ReAct + Event Stream (OpenHands) │ │ │ │ │ └── 部分固定 → 混合架构 │ │ 外层 State Machine + 内层 ReAct │ │ │ └── ❓ 需要双模型分工? │ └── → ArchitectCoder 模式 (Aider) │ 强模型推理 + 经济模型执行 │ ├── 多 Agent │ │ │ ├── ❓ Agent 角色是否固定? │ │ ├── 固定 → SOP 流水线 (MetaGPT) │ │ │ 需要 DAG 控制?→ Process-driven (CrewAI) │ │ │ │ │ └── 动态 → Actor Model (AutoGen) │ │ 需要 Handoff?→ Swarm (AutoGen) │ │ 需要智能路由?→ SelectorGroupChat (AutoGen) │ │ 需要 Ledger 编排?→ MagenticOne (AutoGen) │ │ │ └── ❓ 需要形式化保证? │ └── → Pregel 图执行 (LangGraph) │ 并行执行 + Reducer 合并 + Checkpoint │ └── 不确定 └── 从 ReAct 开始,需要时再升级 ReAct 是最灵活的起点,几乎所有项目都以它为基础

13. 实现检查清单

不管选择哪种模式,一个完整的主循环需要覆盖以下所有项:

基础(必须)

健壮性(应该)

进阶(可选)

🎯 最终建议:如果你的项目从零开始,从 Event-Driven ReAct 开始。它在简单场景下表现良好,在复杂场景下可以无缝升级为混合架构(外层 State Machine + 内层 ReAct)。确保实现 Condenser(上下文管理)和 StuckDetector(卡死检测)——这两个是生产环境最关键的保障。
Agent 构建实战 · 主循环设计 · 基于 20 个项目源码分析 · 2026-05-17