☰
pi agent源码阅读之`agent_loop` 的两层循环
2026/10/3 7:38:10 网站建设 项目流程

agent_loop的两层循环

核心实现位于:

  • packages/agent/src/agent-loop.ts:162-320
  • 入口runAgentLoop():agent-loop.ts:101-125
  • Agent对 loop 的配置:packages/agent/src/agent.ts:467-504

结构如下:

while(true){lethasMoreToolCalls=true;while(hasMoreToolCalls||pendingMessages.length>0){// 发送请求、处理 assistant response、执行工具、处理 steering}// 检查 follow-up 或显式 continuation}

可以先用一句话概括:

  • 内层循环:当前 agent run 中,只要还有工具调用或 steering 消息,就继续推进下一个 turn。
  • 外层循环:内层循环认为 agent 可以停止后,再检查是否有 follow-up,或者是否需要无新消息地继续一轮。

1. 为什么需要两层循环

一次用户 prompt 不一定只产生一次模型请求:

用户:请修复这个 bug ↓ 模型:调用 read ↓ 工具:返回文件内容 ↓ 模型:调用 edit ↓ 工具:返回编辑成功 ↓ 模型:调用测试工具 ↓ 工具:返回测试结果 ↓ 模型:给出最终回答

这里发生了多个模型请求和多个工具执行,但它们都属于同一次 agent run。

如果用户在 agent 运行期间输入了新指令:

用户:不要改这个文件,改另一个文件

这条消息可能作为 steering message 插入当前 run。

如果 agent 原本已经准备结束,但队列里又有新任务:

用户:顺便更新一下 README

这条消息可能作为 follow-up,在 agent 原本要结束后触发下一轮。

因此需要区分:

当前 turn 内继续推进 vs. 当前 run 本来要结束,但又有新的后续操作

2. 外层循环

外层循环位于:

  • packages/agent/src/agent-loop.ts:177-178
  • 结束逻辑位于agent-loop.ts:300-319

代码逻辑可以抽象为:

while(true){run inner loop;constfollowUpMessages=awaitgetFollowUpMessages();if(followUpMessages.length>0){pendingMessages=followUpMessages;continue;}if(explicitContinuation){explicitContinuation=false;continue;}break;}

外层循环的职责不是直接执行工具,而是决定:

当前内层循环结束后,整个 agent run 是否真的结束。


2.1 外层循环的第一次进入

进入runLoop()时:

letcurrentContext=initialContext;letconfig=initialConfig;letlastCompletedTurn:PrepareNextTurnContext|undefined;letexplicitContinuation=false;letpendingMessages=awaitconfig.getSteeringMessages?.()||[];

位置:

  • agent-loop.ts:170-175

随后立即进入外层循环:

while(true){lethasMoreToolCalls=true;while(hasMoreToolCalls||pendingMessages.length>0){...}...}

hasMoreToolCalls初始为true,这是为了确保第一次一定发送模型请求,而不是直接跳到外层循环末尾。

第一次请求通常来自:

初始 user message ↓ 内层循环 ↓ 模型请求

2.2 外层循环检查 follow-up

内层循环退出后,说明:

没有待处理工具调用 并且没有待处理 steering message

但这还不代表 agent 一定结束。

外层循环会调用:

constfollowUpMessages=(awaitconfig.getFollowUpMessages?.())||[];

位置:

  • agent-loop.ts:300-301

如果存在 follow-up:

if(followUpMessages.length>0){explicitContinuation=false;pendingMessages=followUpMessages;continue;}

位置:

  • agent-loop.ts:302-306

这里的continue是针对外层循环的。下一次外层循环开始后:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询