第2节:核心Agent循环与Query Engine

1 阅读8分钟

1. 核心Agent循环概述

核心Agent循环是Claude Code的大脑,负责处理用户输入、调用Claude API、执行工具操作并返回结果。这是整个系统的核心执行流程,也是理解Claude Code工作原理的关键。

基本原理

Agent循环的基本流程如下:

User --> messages[] --> Claude API --> response
                                      |
                            stop_reason == "tool_use"?
                           /                          \
                         yes                           no
                          |                             |
                    execute tools                    return text
                    append tool_result
                    loop back -----------------> messages[]

循环执行步骤

  1. 接收用户输入:获取用户的提示或命令
  2. 构建消息上下文:将用户输入添加到消息历史中
  3. 调用Claude API:发送消息上下文到Claude API
  4. 处理API响应
    • 如果是文本响应,直接返回给用户
    • 如果是工具调用请求,执行相应工具
  5. 工具执行:根据工具调用请求执行工具,获取执行结果
  6. 循环处理:将工具执行结果添加到消息上下文,再次调用API

2. Query Engine设计与实现

Query Engine是Claude Code的核心组件之一,负责管理查询的完整生命周期,包括消息处理、API调用、工具执行等。

主要功能

  • 消息处理:接收和处理用户输入,构建消息上下文
  • 系统提示构建:组装系统提示,包括工具定义、权限信息等
  • API调用:与Claude API进行交互,处理流式响应
  • 工具执行:管理工具的执行,包括权限检查、并行执行等
  • 结果流式返回:将API响应和工具执行结果流式返回给消费者

核心方法

方法功能描述重要性
submitMessage()提交用户消息,返回异步生成器核心入口
fetchSystemPromptParts()获取系统提示部分构建上下文
processUserInput()处理用户输入,解析命令输入处理
query()主查询循环,处理API调用和工具执行核心逻辑
autoCompact()自动压缩上下文,管理token预算性能优化
runTools()执行工具调用,管理工具执行流程工具处理

3. 消息处理流程

消息处理是Query Engine的核心功能之一,负责构建和管理消息上下文。

消息类型

Claude Code支持多种消息类型,包括:

  • 用户消息:用户输入的文本或命令
  • 助手消息:Claude API返回的响应
  • 工具使用消息:Claude请求执行工具的消息
  • 工具结果消息:工具执行的结果
  • 系统消息:系统生成的消息,如压缩边界标记

消息处理步骤

  1. 接收用户输入:通过CLI或SDK接收用户输入
  2. 解析命令:处理以/开头的命令,如/help/clear
  3. 构建用户消息:创建用户消息对象,包含输入内容和元数据
  4. 记录转录:将用户消息持久化到磁盘(JSONL格式)
  5. 归一化消息:处理消息格式,准备发送到API
  6. 添加系统提示:组装系统提示,包括工具定义、权限信息等

消息流转

USER INPUT (prompt / slash command)
     │
     ▼
 processUserInput()                ← parse /commands, build UserMessage
     │
     ▼
 fetchSystemPromptParts()          ← tools → prompt sections, CLAUDE.md memory
     │
     ▼
 recordTranscript()                ← persist user message to disk (JSONL)
     │
     ▼
 ┌─→ normalizeMessagesForAPI()     ← strip UI-only fields, compact if needed
 │   │
 │   ▼
 │   Claude API (streaming)        ← POST /v1/messages with tools + system prompt
 │   │
 │   ▼
 │   stream events                 ← message_start → content_block_delta → message_stop
 │   │
 │   ├─ text block ──────────────→ yield to consumer (SDK / REPL)
 │   │
 │   └─ tool_use block?
 │       │
 │       ▼
 │   StreamingToolExecutor         ← partition: concurrent-safe vs serial
 │       │
 │       ▼
 │   canUseTool()                  ← permission check (hooks + rules + UI prompt)
 │       │
 │       ├─ DENY ────────────────→ append tool_result(error), continue loop
 │       │
 │       └─ ALLOW
 │           │
 │           ▼
 │       tool.call()               ← execute the tool (Bash, Read, Edit, etc.)
 │           │
 │           ▼
 │       append tool_result        ← push to messages[], recordTranscript()
 │           │
 └─────────┘                      ← loop back to API call
     │
     ▼ (stop_reason != "tool_use")
 yield result message              ← final text, usage, cost, session_id

4. 流式响应机制

Claude Code采用流式响应机制,提供实时的用户体验,特别是在处理长响应或工具执行时。

流式处理的优势

  • 实时反馈:用户可以看到响应的生成过程,减少等待感
  • 内存优化:不需要等待完整响应,可以边生成边处理
  • 中断支持:用户可以在响应生成过程中中断操作
  • 工具执行可视化:实时显示工具执行状态和结果

实现方式

  • AsyncGenerator:使用异步生成器模式,逐个yield响应片段
  • API流式调用:使用Claude API的流式接口,接收实时响应
  • 事件处理:处理API返回的各种事件,如message_start、content_block_delta、message_stop等
  • 进度更新:在工具执行过程中,实时发送进度更新

流式响应流程

  1. 建立流式连接:与Claude API建立流式连接
  2. 接收事件流:接收API返回的事件流
  3. 处理事件:根据事件类型进行处理
  4. 生成响应片段:将事件转换为响应片段,yield给消费者
  5. 处理工具调用:如果收到工具调用事件,执行工具并流式返回结果
  6. 完成响应:当收到message_stop事件时,完成响应

5. 工具调用处理

工具调用是Claude Code的核心特性之一,允许Claude执行各种操作,如文件操作、搜索、执行命令等。

工具调用流程

  1. 识别工具调用:从API响应中识别tool_use类型的内容块
  2. 权限检查:检查用户是否允许执行该工具
  3. 工具执行:调用工具的call方法执行操作
  4. 结果处理:获取工具执行结果,构建tool_result消息
  5. 循环处理:将工具执行结果添加到消息上下文,再次调用API

工具执行器

Claude Code使用StreamingToolExecutor来管理工具执行,支持:

  • 并行执行:对于并发安全的工具,可以并行执行
  • 串行执行:对于非并发安全的工具,串行执行
  • 进度跟踪:实时跟踪工具执行进度
  • 错误处理:处理工具执行过程中的错误

工具调用示例

// 工具调用消息示例
const toolUseMessage = {
  type: "tool_use",
  tool_call_id: "tool_123",
  tool_name: "FileReadTool",
  input: {
    file_path: "/path/to/file.txt",
    limit: 100,
    offset: 0
  }
};

// 工具执行结果示例
const toolResultMessage = {
  type: "tool_result",
  tool_call_id: "tool_123",
  output: {
    content: "File content here...",
    status: "success"
  }
};

6. 上下文管理

上下文管理是Query Engine的重要功能,确保消息历史在token预算范围内,同时保持对话的连贯性。

上下文压缩

当消息历史超过token预算时,Query Engine会自动压缩上下文:

  • 自动压缩:使用Claude API对旧消息进行总结
  • 标记管理:移除僵尸消息和过时标记
  • 上下文重组:优化上下文结构,提高效率

压缩策略

  1. 自动压缩:当token计数超过阈值时触发
  2. 智能总结:使用Claude API对旧消息进行总结
  3. 边界标记:在压缩后的消息和新消息之间添加边界标记
  4. 选择性保留:保留重要消息,如工具调用和结果

7. 错误处理与重试

Query Engine实现了完善的错误处理和重试机制,确保系统的稳定性和可靠性。

错误类型

  • API错误:Claude API返回的错误
  • 工具执行错误:工具执行过程中发生的错误
  • 网络错误:网络连接问题导致的错误
  • 权限错误:权限检查失败导致的错误

重试机制

  • 指数退避:失败后使用指数退避策略重试
  • 错误分类:根据错误类型决定是否重试
  • 用户提示:对于需要用户干预的错误,显示提示信息

8. 性能优化

Query Engine实现了多种性能优化策略,确保系统的响应速度和资源使用效率。

优化策略

  • 异步处理:使用异步操作,避免阻塞主线程
  • 并行执行:并发安全的工具并行执行
  • 缓存机制:缓存系统提示和常用结果
  • 流式处理:边生成边处理,减少内存使用
  • 惰性加载:按需加载资源,减少启动时间

性能指标

  • 响应时间:从用户输入到首次响应的时间
  • 吞吐量:单位时间内处理的请求数量
  • 内存使用:系统运行时的内存占用
  • API调用次数:减少不必要的API调用

9. 代码分析

核心文件

  • src/query.ts:主代理循环,包含核心的AI代理逻辑
  • src/QueryEngine.ts:SDK/无头查询生命周期引擎
  • src/services/api/claude.ts:Claude API客户端
  • src/services/tools/StreamingToolExecutor.ts:工具执行器

关键代码片段

主查询循环

async function* query(/* 参数 */) {
  // 初始化
  // 主循环
  while (true) {
    // 构建消息
    // 调用API
    // 处理响应
    // 执行工具
    // 检查是否结束
  }
}

工具执行

async function runTools(/* 参数 */) {
  // 分组工具(并发安全 vs 串行)
  // 执行工具
  // 处理结果
  // 返回工具执行结果
}

10. 小结

核心Agent循环与Query Engine是Claude Code的核心组件,负责处理用户输入、调用Claude API、执行工具操作并返回结果。通过流式响应机制和高效的上下文管理,Claude Code提供了流畅的用户体验和强大的功能。

理解这些核心组件的工作原理,对于掌握Claude Code的架构和开发自定义AI代理系统都具有重要意义。下一节我们将深入探讨工具系统的设计与实现。