十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

拆解AI Agent核心循环:从ReAct范式到Claude Code的queryLoop实现

拆解AI Agent核心循环:从ReAct范式到Claude Code的queryLoop实现 1. 从“黑盒”到“白盒”为什么我们需要拆解AI Agent的核心循环如果你最近在尝试构建或使用AI Agent大概率会陷入一种困惑你给了它一个任务比如“帮我分析这个代码仓库”然后它就开始“思考”了。你看着它输出的“Thought: ...”、“Action: ...”、“Observation: ...”感觉它像模像样但心里总有个疑问——它到底在“想”什么为什么这一步要调用这个工具下一步又去读那个文件这个决策过程对我们来说就像一个黑盒。这正是理解“核心循环”的价值所在。把AI Agent想象成一个高级的自动驾驶程序核心循环就是它的“驾驶决策系统”。它不断感知环境读取你的指令、工具返回的结果、历史对话进行“思考”决定下一步做什么然后执行“动作”调用工具、输出回答。拆解这个循环就等于打开了自动驾驶系统的决策日志你能看到它每一次转向、加速背后的计算和理由。Claude Code作为Anthropic面向编程场景优化的Claude模型其内置的queryLoop机制就是一个非常典型的、值得剖析的AI Agent核心循环实现。它不是为了炫技而是为了解决一个非常实际的问题如何让一个大语言模型LLM能够自主、连贯、可靠地完成一个复杂的、多步骤的编程任务比如理解一个陌生项目、定位Bug、编写新功能、甚至重构代码。通过分析queryLoop我们不仅能理解Claude Code的工作原理更能获得设计自己Agent的宝贵模式。这不再是简单地调用API而是学习如何为AI构建“思考”和“行动”的脚手架。2. 核心循环的三要素Thought, Action, Observation在深入queryLoop之前我们必须先标准化认知。当前主流的AI Agent框架如LangChain、AutoGPT及Claude Code的实现普遍遵循一个被称为“ReAct”Reasoning Acting的范式。这个范式将单次循环分解为三个清晰的阶段而queryLoop正是这一范式的精妙体现。2.1 Thought思考策略计算而非天马行空“Thought”环节常被误解为模型在漫无边际地“畅想”。实际上在一个设计良好的核心循环中“Thought”是一个高度结构化的策略计算过程。它的输入是明确的最终目标、当前状态包括之前的观察结果、可用工具列表、以及历史步骤。它的输出也应该是明确的对当前形势的分析、下一步行动的理由、以及具体的行动指令。例如当任务为“修复项目根目录下api.py文件中的JSON解析错误”时一个低质量的Thought可能是“我需要修复一个错误。” 而一个高质量的、queryLoop所鼓励的Thought应该是“用户报告了api.py中的JSON解析错误。我之前尚未查看过该文件。第一步应该是读取api.py的内容以具体了解错误发生的上下文、涉及的函数以及可能引发异常的代码行。我将使用‘read_file’工具。”为什么Thought如此重要它迫使模型将内部推理过程外部化、文本化。这带来了两个关键好处一是可解释性开发者可以追溯Agent的决策链二是稳定性将“思考”作为显式输出可以降低模型直接输出错误动作的概率相当于让模型“三思而后行”。2.2 Action行动与外部世界的唯一接口Action是Thought的具体执行。在编程Agent场景下Action几乎总是对应一个工具调用Tool Call。工具定义了Agent的能力边界。Claude Code的queryLoop通常会集成一套针对软件开发优化的工具集例如read_file(path): 读取指定路径文件内容。search_files(keyword, path): 在目录中搜索包含关键词的文件。run_command(command): 在安全沙箱中执行Shell命令如运行测试pytest、查找文件find。edit_file(path, old_code, new_code): 精确地替换文件中的代码块。ask_user(question): 在遇到模糊需求或需要确认时向用户提问。Action步骤的输出是一个严格格式化的调用比如read_file(‘src/utils/parser.py’)。这个格式会被循环的调度器捕获并映射到对应的工具函数执行。2.3 Observation观察环境的反馈与新一轮的输入Action执行后世界会给出反馈。这个反馈就是Observation。它可能是工具执行的成功结果如文件内容、命令输出、编辑确认也可能是失败信息如文件不存在、命令执行错误、权限不足。Observation的质量直接决定了后续循环的质量。一个设计良好的Observation应该完整包含工具返回的所有相关信息不能截断。结构化如果是错误应包含错误类型和堆栈信息如果是搜索结果应清晰列出文件列表。无歧义明确告知Action是成功还是失败。queryLoop会将Observation连同之前的Thought和Action作为新的上下文喂给模型开启下一个“Thought”环节。这就构成了一个“感知-思考-行动-再感知”的闭环。注意很多自建Agent的失败源于Observation处理不当。例如将一个长达1000行的错误日志直接塞给模型会导致模型注意力分散。更好的做法是让工具或一个预处理步骤先提取关键错误信息再将摘要和关键行作为Observation。3. 深入Claude Code的queryLoop一个动态的决策状态机基于上述三要素我们来构建Claude Code中queryLoop的运作模型。它不仅仅是一个简单的while循环更是一个拥有多种状态和决策路径的动态系统。3.1 循环的初始化设定目标与约束循环开始前需要完成关键的初始化工作这决定了Agent的起跑线。终极目标Ultimate Goal来自用户的初始请求如“为项目添加用户登录功能”。系统提示词System Prompt这是Agent的“人格”和“基本原则”。对于Claude Code提示词会强调“你是一个专业的软件工程师助手。你必须通过使用工具来完成任务。你的思考必须逐步进行。在修改文件前务必先查看相关代码。如果信息不足应向用户提问。”工具清单Tool Kit明确告知模型本次循环可用的所有工具及其详细描述、参数格式。工作区上下文Workspace Context初始的文件树结构、项目语言如Python、关键配置文件如requirements.txt,package.json的摘要。这为Agent提供了环境的初始地图。3.2 单次循环的微观流程一次典型的queryLoop迭代可以细分为以下步骤构建提示Prompt Construction将以下内容按顺序拼接成完整的提示输入给Claude模型系统提示词重申角色和规则。完整的对话历史包含之前所有轮次的Thought, Action, Observation。当前可用的工具描述。最新的用户指令或上一轮的Observation。一个强制的输出格式指令例如“你必须以‘Thought:’开始你的分析然后决定是输出‘Action:’调用工具还是‘Final Answer:’直接回答。”模型推理与解析Model Inference ParsingClaude模型接收提示后进行推理。系统会严格解析其输出寻找Thought:、Action:或Final Answer:等关键词。解析器必须足够健壮能处理模型输出的微小格式偏差。工具分发与执行Tool Dispatch Execution一旦解析出Action: tool_name(arguments)循环调度器就会验证工具是否存在、参数是否合法然后在受控环境如Docker容器沙箱中调用对应的工具函数。结果观察与历史更新Observation History Update工具执行的结果被格式化为Observation并立即与本次的Thought和Action一起追加到对话历史中。这个不断增长的历史就是Agent的“工作记忆”。3.3 循环的终止条件如何知道“任务完成”一个不会停止的Agent是危险的。queryLoop必须包含明确的终止逻辑常见的有模型主动终止模型输出Final Answer:并给出最终结论。这通常发生在模型认为已收集足够信息、完成任务时例如“已成功在auth.py中实现登录函数并添加了单元测试test_auth.py。所有测试通过。”成功条件达成预设的验证工具返回成功。例如在“运行测试并通过”的任务中当run_command(‘pytest’)的Observation显示所有测试通过时循环可自动终止。失败或超时工具连续多次失败、陷入重复动作如反复读取同一文件而无进展、或达到预设的最大循环次数如50步时循环应强制终止并给出错误报告。用户干预集成ask_user工具当模型遇到无法解决的歧义或需要确认高风险操作时循环会暂停等待用户输入。用户的回复作为特殊的Observation驱动循环继续。4. 从理论到实战queryLoop在复杂任务中的推演让我们通过一个虚构但非常真实的场景来可视化queryLoop是如何一步步推进的。任务“检查项目my_app中/api目录下的所有Python文件将过时的requests方法调用如.json()方法更新为新的安全API。”初始状态Agent获得工作区上下文知道/api目录下有5个.py文件。循环轮次Thought (推理)Action (行动)Observation (观察)1我需要先了解/api目录下具体有哪些文件以及它们的结构。我将使用list_files工具。list_files(‘/api’)[‘__init__.py’, ‘user.py’, ‘product.py’, ‘order.py’, ‘legacy_client.py’]2现在我有文件列表了。用户提到了“过时的requests方法”。我需要先查看一个文件了解当前代码中requests是如何被使用的。我选择先看user.py因为它可能包含典型的API调用。read_file(‘/api/user.py’)显示文件内容其中包含resp requests.get(url); data resp.json()这样的代码3我在user.py中确认了旧的.json()用法。根据任务我需要将其更新。但更新成什么我需要确认项目依赖或文档中指定的新安全API是什么。让我检查requirements.txt或相关的配置/文档。search_files(‘requests’, ‘/’)[‘requirements.txt’, ‘docs/api_migration.md’]4找到了相关文件。先看requirements.txt了解requests版本再看迁移文档。read_file(‘requirements.txt’)requests2.31.05版本是2.31.0。现在查看迁移文档获取新API格式。read_file(‘docs/api_migration.md’)“自requests 2.30起推荐使用resp.raise_for_status()配合resp.json()或使用新的resp.get_json(safeTrue)方法进行安全解析。”6我明白了。新安全API是resp.get_json(safeTrue)。现在回到user.py将resp.json()替换。我需要精确定位并修改。edit_file(‘/api/user.py’, ‘data resp.json()’, ‘data resp.get_json(safeTrue)’)Successfully edited ‘/api/user.py’.7user.py修改成功。现在需要对/api目录下的其他文件进行同样的检查和修改。我将编写一个脚本或使用搜索替换工具来批量处理但为了安全起见我先手动检查product.py。read_file(‘/api/product.py’)文件内容包含多处resp.json()调用8product.py中有多处需要修改。我将逐一进行替换。首先替换第45行...后续进行多次edit_file动作edit_file(...)Successfully edited...9在检查完所有文件并修改后所有/api目录下的Python文件已检查并更新。为了确保修改没有引入语法错误我应该运行一个快速的语法检查或导入检查。run_command(‘python -m py_compile /api/*.py’)无输出表示编译成功10语法检查通过。任务已完成。我可以给出最终答案了。Final Answer:“已完成对/api目录下所有Python文件的更新。将过时的resp.json()调用替换为新的安全APIresp.get_json(safeTrue)。涉及修改的文件包括user.py,product.py,order.py。已通过Python编译检查无语法错误。”从这个推演可以看出queryLoop驱动Agent像一位有条不紊的工程师先探索列出文件再调查读取内容、查阅文档然后制定方案理解新API最后谨慎执行逐个文件修改并验证运行检查。整个过程是可追溯、可解释的。5. 构建高效Agent的关键超越基础循环的优化策略理解了基础循环我们才能谈论优化。一个“能跑”的Agent和一个“好用”的Agent之间差的就是下面这些策略。这也是研究queryLoop的终极目的——指导我们自己的设计。5.1 短期记忆与长期记忆克服上下文长度限制LLM有上下文窗口限制如128K。一个复杂的任务可能经历几十轮循环很快会“撑满”上下文导致最早的关键信息如初始目标被“遗忘”。摘要压缩SummarizationqueryLoop不应机械地堆积所有历史。一个高级的实现会在每N轮循环后或当历史达到一定长度时触发一个“摘要”步骤。让模型自己将之前的冗长交互例如10轮文件查看和编辑总结成一段精炼的文本如“已分析/api目录结构并在user.py和product.py中将resp.json()替换为resp.get_json(safeTrue)。”然后用这个摘要替换掉那10轮原始历史从而大幅节省令牌数保留核心工作记忆。向量检索记忆Vector Retrieval Memory为整个对话历史和工作区文档建立向量索引。当模型需要回忆某个早期细节时如“我之前在哪个文件里看到过数据库配置”可以通过查询向量数据库将最相关的历史片段动态检索并插入当前上下文。这实现了类似人类的“联想记忆”。5.2 工具的设计哲学能力、安全与效率工具集是Agent的“双手”。设计时需权衡粒度工具应该多“细”一个万能的execute_code(code)工具很强大但极其危险。而像read_file,edit_file,run_test这样粒度细、功能单一的工具虽然步骤多但更安全、可控、易于解释。安全性任何执行代码或修改文件的工具都必须在严格的沙箱环境中运行。run_command应限制允许的命令列表白名单。edit_file应使用差异比对diff模式而不是直接写入最好能有预检查或确认环节。信息密度工具返回的Observation应进行处理。例如search_files返回的不是原始grep输出而是整理好的{file: line_number: content}列表。run_command在运行测试失败时应提取关键错误信息而不是返回全部日志。5.3 规划与反思让Agent更有“远见”基础ReAct是反应式的走一步看一步。高级Agent需要“规划”和“反思”能力。任务分解Task Decomposition在queryLoop开始前或遇到复杂任务时可以要求模型先输出一个多步骤的规划。例如“要添加登录功能我将1. 检查现有用户模型2. 创建认证路由3. 实现密码哈希4. 编写登录API5. 添加单元测试。” 这个规划可以作为后续循环的高层指南。反思Reflection在关键节点如一系列操作后、或遇到失败时插入一个“反思”步骤。让模型分析“我之前的操作是否有效当前状态距离目标还有多远我是否走错了方向” 这可以帮助Agent及时纠正错误策略避免在死胡同里浪费循环。6. 调试与评估当你的Agent行为“诡异”时怎么办即使理解了原理亲手实现的queryLoop也可能表现怪异。以下是常见的调试思路问题Agent陷入死循环重复同一操作。诊断观察历史。可能是Observation没有提供新的信息导致模型基于相同的上下文做出了相同的决策。解决1) 增强Observation的信息量比如在文件未找到时同时列出当前目录下的文件。2) 在系统提示词中强调“避免重复动作”。3) 实现硬性限制检测到连续N次相同动作则强制终止或转向。问题Agent忽略关键工具或总想使用不存在的工具。诊断工具描述不够清晰或者模型没有充分理解工具的能力边界。解决1) 重写工具描述使用更具体、无歧义的语言并附上示例。例如将“操作文件”改为“edit_file(path, old_text, new_text): 将文件中首次出现的old_text字符串精确替换为new_text。请确保old_text与文件中的内容完全匹配。” 2) 在每次提示中都以清晰格式重新列出可用工具。问题Agent的“Thought”质量低下逻辑跳跃。诊断系统提示词中对“Thought”的要求不够强或者模型本身推理能力不足。解决1) 在系统提示词中模板化Thought的输出要求例如“在Thought中你必须a) 总结当前状况b) 分析上一步Observation的含义c) 明确下一步要做什么及原因。” 2) 考虑使用更擅长推理的模型如Claude 3 Opus, GPT-4。如何评估Agent性能不能只看任务最终是否完成。应建立多维评估指标成功率在基准测试任务集上的完成比例。平均步数完成一个任务所需的平均循环次数。步数越少通常效率越高。人工评分评估最终产出的代码质量、解决方案的优雅程度。安全性是否执行了任何危险操作是否在修改前进行了查看拆解Claude Code的queryLoop最终是为了不再把它看作魔法。它是一套精心设计的机制将大语言模型的推理能力引导、规约到解决具体问题的有序工作流中。当你下次看到Agent在“思考”时你看到的不是一个黑盒而是一个正在按部就班执行queryLoop的清晰过程分析现状、选择工具、执行、观察结果、并准备下一步。理解这个过程是你从Agent的使用者迈向设计者的关键一步。
返回列表