Agent Loop 中文翻译版Agent Loop Module Overview

源文件:agent-loop.ts(695 行)→ 提炼为中文模块结构  |  已优化排版,支持 Ctrl+P 直接打印 / 保存 PDFSource: agent-loop.ts (695 lines) → distilled into modular structure  |  Print-optimized, Ctrl+P to print / save PDF

一、整个文件的模块结构1. Module Structure of the Entire File

文件:File: agent-loop.ts // 整个文件就做一件事:实现 agent 的核心循环// The entire file does one thing: implement the agent's core loop   ┌─ 导入声明(跳过)┌─ Import declarations (skip) ├─ 入口函数 × 4(外部调用的接口,最终都调用 ↓)├─ Entry functions × 4 (external API, all ultimately call ↓) ├─ ⭐ runLoop() — 核心循环引擎(下面展开)— Core loop engine (expanded below) ├─ streamAssistantResponse() — 被 runLoop 调用:负责调 LLM— Called by runLoop: responsible for calling the LLM └─ 工具执行相关函数 × 6└─ Tool execution functions × 6 — 被 runLoop 调用:负责执行工具— Called by runLoop: responsible for executing tools
Start 外层循环 (while true) Outer loop (while true) 注入插队消息 Inject queued msgs 队列管理 Queue mgmt 内层循环 Inner loop 调用 LLM Call LLM 需要工具 Needs tools 执行工具 Execute tools 返回结果 Feed results 取消 Cancel 报错 Error 不需要工具 No tools needed 安全阀检查 Safety valve check 防死循环 Anti-infinite-loop AI 回复 AI Response followUp 追加? followUp task? 有追加 → 继续 Has followUp → continue 无追加 No followUp End

runLoop() 完整流程:外循环 + 内循环 + 队列管理 + 安全阀runLoop() complete flow: outer loop + inner loop + queue management + safety valve

二、runLoop() 核心循环——模块化展开2. runLoop() Core Loop — Modular Breakdown

函数 runLoopfunction runLoop(核心循环引擎) (core loop engine)   // ── 原料 ──// ── Ingredients ── currentContext agent 的记忆(系统提示 + 全部对话历史 + 可用工具列表)The agent's memory (system prompt + full conversation history + available tools list) newMessages 收集器:本次运行新产生的消息(最终返回给调用者)Collector: new messages produced in this run (returned to caller) config 配置(模型、hooks、消息队列……)Configuration (model, hooks, message queue...) signal 取消按钮(外部随时可以按下中断)Cancel button (external can press to abort anytime) emit 广播器(每发生一件事就通知外部)Broadcaster (notifies external on every event) streamFn 调用 LLM 的函数(可替换成不同 AI)Function to call the LLM (swappable for different AIs)   // ── 开始 ──// ── Start ──   外层循环(while true)Outer loop (while true) // 处理 followUp 追加任务// handles followUp append tasks 内层循环(while 还有工具调用 或 有插队消息)Inner loop (while has tool calls OR has queued messages) │ │ │ │ // ── 一轮(turn)的完整流程 ──// ── Complete flow of one turn ── │ │ │ ├─ ❶ 注入插队消息Inject queued messages │ │ 如果用户在 AI 工作期间发了新消息If user sent new messages while AI was working │ │ 加入 context(AI 下次能看到) Add to context (AI sees it next call) │ │ 加入 newMessages(记录本次新增) Add to newMessages (record as new this run) │ │ [Pi 特有机制][Pi-specific mechanism] │ │ │ ├─ ❷ 调用 LLMCall LLM ← 循环的心跳← The loop's heartbeat │ │ 调用 streamAssistantResponse()(展开见下方)Calls streamAssistantResponse() (expanded below) │ │ 返回 AI 的回复(可能含文字、工具调用请求、或错误) Returns AI's response (may contain text, tool call requests, or errors) │ │ 回复自动加入 context + newMessages Response automatically added to context + newMessages │ │ │ ├─ ❸ 出错/取消?→ 立即结束Error/Cancel? → Exit immediately │ │ 如果 AI 回复的 stopReason 是 "error" 或 "aborted"If AI response's stopReason is "error" or "aborted" │ │ return(退出整个函数) return (exit entire function) │ │ │ ├─ ❹ 检查并执行工具Check and execute tools ← 决定循环是否继续的核心← The core that decides if loop continues │ │ 从 AI 回复中找出所有工具调用请求Extract all tool call requests from AI response │ │ 如果有 调用 executeToolCalls()(展开见下方)If found call executeToolCalls() (expanded below) │ │ 工具结果加入 context + newMessages Tool results added to context + newMessages │ │ 标记"还有工具调用" 内层循环继续 Mark "has tool calls" inner loop continues │ │ 如果没有 标记"没有更多工具调用" 内层循环将退出If none mark "no more tool calls" inner loop will exit │ │ │ ├─ ❺ 安全阀:强制停止检查Safety valve: forced stop check │ │ 调用 config.shouldStopAfterTurn()(可选)Calls config.shouldStopAfterTurn() (optional) │ │ 如果返回 true return(强制结束,防止死循环)If returns true return (force stop, prevents infinite loop) │ │ │ └─ ❻ 检查新的插队消息Check for new queued messages 下一轮处理;没有 内层循环条件判断Found process next turn; None inner loop condition check // ── 内层循环结束 ──// ── Inner loop ends ── ├─ ❼ 检查 followUp 追加任务Check followUp append tasks 重新进入内层循环Found re-enter inner loop 没有 break 退出外层循环None break out of outer loop 外层循环结束Outer loop ends   // 广播 agent_end 事件,函数返回// Emit agent_end event, function returns

三、streamAssistantResponse()——调用 LLM 的具体步骤3. streamAssistantResponse() — Steps for Calling the LLM

函数 streamAssistantResponsefunction streamAssistantResponse(调用 LLM 获取 AI 回复) (call LLM to get AI response)   ├─ ❶ transformContext 对消息列表做预处理:压缩旧对话、删不重要的、裁剪到窗口大小以内Preprocess message list: compress old conversations, remove unimportant ones, trim to context window size (可选步骤——如果配置了才执行)(Optional step — only runs if configured) ├─ ❷ convertToLlm agent 内部格式 → LLM API 要求的格式Agent internal format → LLM API required format (过滤掉 LLM 不需要看的内部字段:时间戳、元数据等)(Filter out internal fields the LLM doesn't need: timestamps, metadata, etc.) ├─ ❸ 组装完整请求Assemble full request 把三样东西打包在一起发给 LLM:Bundle three things together and send to LLM: • systemPrompt — "你是谁、怎么行为"的总指令 • systemPrompt — master instruction for "who you are and how to behave" • messages — 全部对话历史(用户消息 + AI回复 + 工具结果) • messages — full conversation history (user messages + AI replies + tool results) • tools — 可用工具的说明书列表(名字 + 参数定义) • tools — list of available tool specs (name + parameter definitions) ├─ ❹ 调用 LLM APICall LLM API 通过 streamFn 发送请求,开始接收流式响应Send request via streamFn, begin receiving streaming response └─ ❺ 处理流式响应Process streaming response AI 一个字一个字回复,每收到新内容就通知外部(emit)AI responds word by word; each new chunk triggers a notification (emit) 最终返回一条完整的 AI 回复消息Finally returns one complete AI response message

补充说明:context 和 newMessages 的关系Supplementary: Relationship Between context and newMessages

循环中每产生一条新消息(AI 回复、工具结果、插队消息),都会做两件事:

Every time a new message is produced in the loop (AI response, tool result, queued message), two things happen:

它们是重叠的:newMessages 里的内容也在 context 里,但 context 还包含"本次运行之前的历史消息"。

They overlap: everything in newMessages is also in context, but context also includes "messages from before this run."

四、executeToolCalls()——执行工具的具体步骤4. executeToolCalls() — Steps for Executing Tools

函数 executeToolCallsfunction executeToolCalls(执行 AI 请求的工具调用) (execute tool calls requested by AI)   ├─ 判断执行方式Determine execution mode 多个工具并行执行(快,默认)还是顺序执行(安全)Multiple tools in parallel (fast, default) or sequential (safe) └─ 对每个工具调用执行三步:For each tool call, execute three steps:   ├─ ❶ 准备 preparePrepare 找到工具 → 校验参数 → 问 beforeToolCall "允许执行吗?"Find tool → validate params → ask beforeToolCall "allow execution?" 如果被拦截 直接返回错误结果,不执行If blocked return error result directly, don't execute (权限系统的接入点:Claude Code 的 "Allow?" 弹窗就在这里)(Permission system hook: Claude Code's "Allow?" dialog lives here) ├─ ❷ 执行 executeExecute 真正运行工具代码(读文件 / 搜索 / 写代码……)Actually run tool code (read files / search / write code...) └─ ❸ 收尾 finalizeFinalize 调用 afterToolCall → 格式化结果 → 返回Call afterToolCall → format result → return

五、读完应该带走的认知5. Key Takeaways

5 条核心认知5 Core Insights

  1. Agent = 一个循环,不是一次问答
    调 LLM → 有工具调用?→ 是 → 执行 → 结果喂回 → 再调 LLM → … → 没有工具了 → 结束
  2. Agent = a loop, not a single Q&A
    Call LLM → tool calls? → yes → execute → feed results back → call LLM again → ... → no more tools → done
  3. 停止条件有三层保护
    ① 出错/取消 → 立即停
    ② 外部强制(安全阀:max turns / token limit)→ 兜底保护
    ③ AI 自然完成(没有更多工具调用)→ 正常结束
  4. Stop conditions have three layers of protection
    ① Error/cancel → stop immediately
    ② External force (safety valve: max turns / token limit) → fallback protection
    ③ AI finishes naturally (no more tool calls) → normal end
  5. 调 LLM 前有"变换管道"
    原始消息 → transformContext(压缩/裁剪)→ convertToLlm(格式转换)→ 组装三件套(systemPrompt + messages + tools)→ 发给 LLM
    这就是"上下文工程"的实现位置,后续章节会深入学
  6. A "transform pipeline" runs before calling the LLM
    Raw messages → transformContext (compress/trim) → convertToLlm (format conversion) → assemble the trio (systemPrompt + messages + tools) → send to LLM
    This is where "context engineering" lives — deeper study in later chapters
  7. 工具执行前有"权限关卡"
    beforeToolCall hook 可以拦截任何工具调用 → Claude Code 的"Allow?"弹窗就是这个机制
  8. A "permission checkpoint" exists before tool execution
    The beforeToolCall hook can intercept any tool call → Claude Code's "Allow?" dialog is exactly this mechanism
  9. 事件系统让外部观察循环状态
    agent_start → turn_start → message_start → tool_execution_start → … → agent_end
    UI、日志、监控都靠 emit 事件来知道"agent 在干嘛"
  10. The event system lets the outside world observe loop state
    agent_start → turn_start → message_start → tool_execution_start → ... → agent_end
    UI, logs, and monitoring all rely on emit events to know "what the agent is doing"

和你日常体验的对应Mapping to Your Daily Experience

你看到 Claude Code 在做的事What You See Claude Code Doing对应模块Corresponding Module
AI 说"我要读文件" → 读了 → "要编辑" → 编辑了 → "完成了"runLoop 内层循环的多次迭代(每次 = 一轮 turn)
AI says "I'll read this file" → reads → "I'll edit" → edits → "done"Multiple iterations of runLoop's inner loop (each = one turn)
弹出"Allow Read file X?"对话框工具执行 ❶准备 里的 beforeToolCall
"Allow Read file X?" dialog appearsbeforeToolCall in tool execution step ❶ Prepare
AI 一个字一个字打出来streamAssistantResponse ❺处理流式响应
AI types out word by wordstreamAssistantResponse step ❺ Process streaming response
你在 AI 工作时打字补充指令runLoop ❶注入插队消息
You type additional instructions while AI is workingrunLoop step ❶ Inject queued messages
AI 说"完成了"然后停下来runLoop ❹没有工具调用 → 内层循环退出 → ❼没有 followUp → break
AI says "done" and stopsrunLoop ❹ no tool calls → inner loop exits → ❼ no followUp → break