Agent ReAct and Loop

同步至个人站点:Agent ReAct and Loop

Agent ReAct and Loop

我一直在使用 ChatGPT 或通义千问这样的 AI 工具,它们很强大,但多数情况下都是"一问一答"。我提一个问题,它给一个答案。

但我注意到,像 Manus 或 Claude Code CLI 这样的"Agent"(智能体)产品,它们似乎可以自动执行任务。你给它一个目标,它会自己去调用工具、分析结果、继续下一步,直到任务完成。

这到底是怎么做到的?它如何摆脱"一问一答"的限制,实现自动循环?这就是我这周探索的问题。

关键概念:ReAct

我读了一些资料,发现了一个关键概念:ReAct

这是 2022 年一篇论文(ReAct: Synergizing Reasoning and Acting in Language Models)提出的思想。它模仿了人类的工作方式:

  1. Reason(思考):分析当前情况,决定下一步该做什么。
  2. Act(行动):执行一个动作(比如调用工具、搜索信息)。

完成"行动"后,会得到一个新的"观察"(Observation),比如工具的返回结果。然后,Agent 带着这个新结果,回到第 1 步,再次"思考",形成一个循环。

一个线索:Claude 的日志

这个"思考-行动"的循环听起来很合理。为了验证它,我做了一个小实验。

我查看了 Claude 编码助手(我在 Mac 上的路径是 ./claude/projects/*.jsonl)的会话日志文件。这些 .jsonl 文件记录了我和 Agent 的完整对话。

我发现,里面的消息(Message)并不仅仅是"我问"和"它答",而是主要有四种类型:

  • user:用户的消息。
  • assistant:模型(Agent)的消息。
  • tool_call:模型决定调用一个工具。
  • tool_result:工具执行后返回的结果。

这揭示了一个秘密:assistant 的回复并不总是最终答案。它可能是一个 tool_call(工具调用)请求,用来告诉外部程序:"请帮我执行这个函数"。

执行完毕后,系统会把 tool_result(工具结果)再发给 assistant

流程:一个循环

看到这里,我基本想通了。Agent 的自动执行,本质上就是这样一个流程:

[用户输入] -> [LLM 思考] -> [决定:调用工具 A] -> [系统执行 A] -> [A 的结果] -> [LLM 思考] -> [决定:调用工具 B] -> [系统执行 B] -> ... -> [最终答案]

这个流程的核心,就是一个循环(Loop)

只要 LLM 返回的不是最终答案,而是一个 tool_call,系统就去执行它,然后把结果塞回去,让 LLM 继续"思考"。

Demo 快速验证

我的逻辑很清晰:一个主函数,它负责调用 LLM。调用后,检查返回结果。

  • 如果结果是普通文本(最终答案),就返回它。
  • 如果结果是 tool_call,就去执行工具,然后把工具结果和之前的对话历史"拼"在一起,递归调用自己。

下面是一个简化的伪代码:

javascript 复制代码
class SimpleAgent {
  async chat(message) {
    const assistantResponse = await this.callLLM(message)
    if (assistantResponse.hasToolCall) {
      const toolResult = await this.callTool(assistantResponse.toolCall) // 递归调用,将tool result作为新消息
      return this.chat(toolResult)
    }
    return assistantResponse.content
  }
}

为了快速验证我的想法,我让 Claude Code 基于 Plasmo 快速开发了一个侧边栏形式的 Browser Agent,效果如下:

这不是产品,只是 Demo。仅用于验证我自己所理解的 Loop。

我的感想

在做完这些事情以后,我豁然开朗。

Agent 的"自动执行",其核心就是这个 "LLM 思考 -> 工具执行 -> 结果反馈 -> LLM 再思考" 的循环。

当然,我这个实现非常简陋。一个工业级的 Agent 框架(比如 LangChain)要复杂得多,它们需要处理:

  1. LLM 兼容 :如何适配不同厂商(OpenAI, Anthropic, Google)的接口和 tool_call 格式。
  2. 工具管理:如何动态注册、描述和安全地执行工具。
  3. 记忆(Memory):如何在循环中管理越来越长的对话历史,防止 Token 溢出。
  4. 路由(Router):当有上百个工具时,如何决定调用哪一个。

但通过亲自动手,我总算摸清了 ReAct 架构的基本原理。这对于我后续的学习,算是打下了一个很好的基础吧。

(完)

相关推荐
Lazy_zheng几秒前
从 0 到 1 创建 Claude Code Skill:使用 skill-creator实现发票信息提取
agent·ai编程·claude
倾颜12 分钟前
多智能体(Agent)不靠运气 ,一个受控协作系统的设计复盘
agent·next.js
鱼饼Y12 分钟前
AI时代,使用大模型学习LangChain (3)——LCEL
人工智能·langchain
明明如月学长13 分钟前
6 个 WorkBuddy 高阶功能,搞定复杂的办公任务
aigc·agent
枫叶V19 分钟前
Prompt Injection 防不住怎么办?从 Source-Sink 模型设计 Agent 安全边界
后端·agent
用户6676750937921 分钟前
LangChain 向量检索为什么要用 as_retriever?从 LCEL 到 RunnableParallel 一次讲清
langchain
5pat54OfCg27 分钟前
OpenCode 源码拆解(二):Token 怎么省?——上下文管理的 5 个设计模式
agent
晨曦中的暮雨33 分钟前
Learn Claude Code:CodeAgent 与后端程序大搭配——定时任务、Git Worktree 和MCP 服务
git·ai·llm·agent
xier_ran33 分钟前
【infra之路】从 KV Cache 到逐层语义:理解 Decoder-Only LLM 的推理过程
llm·infra
k4m7v2pz1 小时前
16GB Mac 本地跑大模型:ollama 局域网 OpenAI 兼容 API 实战(一:需求与配置)
llm·openai·api·mac·ollama·本地·atomcode