Agent 智能体:从“一问一答“到“自主干活“的技术全解析

发布时间:2026/9/27 15:22:38

Agent 智能体:从“一问一答“到“自主干活“的技术全解析
文章目录一、Agent 到底智能在哪1.1 普通对话一问一答任务即终止1.2 Agent持续运转的循环结构二、Agent 工作方式ReAct 三步循环2.1 一个场景走通 ReAct三、Tool UseAgent 的手和脚3.1 常见工具类型3.2 工具数量 能力边界四、MessageAgent 的记忆载体4.1 原生 OpenAI vs LangChain 的返回差异五、AI 工程从零构建编程助手 Agent5.1 工程目录5.2 前置知识async 函数六、完整实现编程助手 Agent6.1 环境与依赖6.2 初始化 LLM6.3 定义工具文件读取6.4 绑定工具到模型6.5 初始化消息6.6 核心循环ReAct 的代码实现6.7 执行流程可视化七、全文总结八、核心知识点复盘九、避坑指南❌ 坑 1ToolMessage 忘了传 tool_call_id❌ 坑 2串行调用多个工具❌ 坑 3LLM 的无状态特性❌ 坑 4无限循环❌ 坑 5工具 description 写得太模糊一、Agent 到底智能在哪字面理解——AI 会自己干活。这么理解没问题但这句大白话遮住了一个更关键的问题Agent 和普通的 AI 对话差别到底在哪里答案是结构不同。1.1 普通对话一问一答任务即终止你: 帮我写一封邮件 AI: (输出邮件内容) ← 任务结束LLM 输出一次对话终止。它是一个问答机器——问什么答什么答完即止没有后续。1.2 Agent持续运转的循环结构你给 Agent 一个任务它会拆解任务决定下一步做什么调用工具去外部世界获取信息观察结果判断是继续还是结束循环往复直到任务完成或触发退出条件超出循环次数、Token 上限、连续相同结果、任务失败这不是一问一答而是一个自主运转的执行循环。二、Agent 工作方式ReAct 三步循环Agent 每一轮循环只有三个核心动作动作英文含义思考Reason分析当前状态决定下一步做什么行动Act调用工具执行具体操作观察Observe接收工具返回的结果判断是否继续一轮结束后观察 → 再回到思考 → 再行动 → 再观察循环往复。这个循环就叫ReActReasoning Act Observe。它不是 LangChain 那种大型开发框架而是Agent 领域通用的循环工作标准是一种思维范式。面试重点ReAct 是 Agent 执行流程的行业共识几乎所有主流 Agent 框架LangChain、AutoGPT、CrewAI底层都遵循这个循环模型。2.1 一个场景走通 ReAct任务“帮我分析三家竞品写一份报告”┌─────────────────────────────────────────────────┐ │ 第一轮 │ │ Reason: 需要搜索竞品信息 │ │ Act: 调用搜索工具查三家竞品最新动态 │ │ Observe: 信息量挺大但缺少财务数据 │ ├─────────────────────────────────────────────────┤ │ 第二轮 │ │ Reason: 需要财务数据可以去官网或股市API │ │ Act: 调用 API 抓取财报数据 │ │ Observe: 财务数据拿到了可以开始写报告 │ ├─────────────────────────────────────────────────┤ │ 第三轮...第 N 轮 │ │ Reason: 信息充足写报告 │ │ Act: 生成完整竞品分析报告 │ │ Observe: 报告完成交给用户 │ └─────────────────────────────────────────────────┘每一轮都在Reason → Act → Observe的循环中推进直到任务完成。三、Tool UseAgent 的手和脚核心认知工具是 Agent 的能力边界。没有工具Agent 只能在脑子里转转完还是只有文字。3.1 常见工具类型工具类型能力代表产品搜索工具上网查实时信息Perplexity代码执行器运行代码、看结果、自验证Claude工程化验收机制最完善文件 I/O读写本地文件Cursor、Copilot浏览器操控打开网页、点击、提交表单ManusAPI 调用连接外部服务各类 SaaS Agent行业观察“文无第一武无第二”——Claude 在代码执行和工程化验收方面建立了事实标准。Anthropic 的 Agent 自测试机制是目前最成熟的 AI 工程质量验证方案。3.2 工具数量 能力边界工具的覆盖范围直接决定 Agent 的能力上限。选型 Agent 产品时先看它集成了多少工具、工具质量如何——这是最核心的评估维度。四、MessageAgent 的记忆载体Agent 的整个对话历史和工具调用结果全部存储在messages 数组中。四种核心消息类型类型角色用途SystemMessage系统设定 AI 身份、能力边界、行为规范HumanMessage用户用户的输入AIMessageAILLM 的回复可能包含工具调用ToolMessage工具工具执行结果的回传必须带tool_call_id⚠️易错点ToolMessage必须携带对应的tool_call_id否则 LLM 无法将工具结果与调用请求关联会产生幻觉或忽略结果。4.1 原生 OpenAI vs LangChain 的返回差异原生 OpenAI 返回工具调用时数据结构在additional_kwargs.tools中。LangChain 在invoke后会原样保留这个结构同时贴心地准备了tool_calls属性——这就是 LangChain 的工程价值提升 LLM 开发的便捷性和可读性。五、AI 工程从零构建编程助手 Agent5.1 工程目录hello-langchain/ ├── package.json ├── node_modules/ ├── .env # API Key 配置 └── src/ └── index.mjs # Agent 主程序5.2 前置知识async 函数// async 函数本身就是 Promise 实例// return 等同于 Promise.resolve()// return 的结果就是 resolve 的参数asyncfunctiongetData(){returnhello;// 等价于 Promise.resolve(hello)}// getData() 返回一个 Promise六、完整实现编程助手 Agent下面是一个可运行的完整 Agent逐段拆解。6.1 环境与依赖importdotenvfromdotenv;import{ChatOpenAI}fromlangchain/openai;import{tool}fromlangchain/core/tools;import{HumanMessage,SystemMessage,ToolMessage,// AIMessage // invoke 返回的 response 本身就是 AIMessage}fromlangchain/core/messages;importfsfromnode:fs/promises;import{z}fromzod;// 加载 .env 中的环境变量dotenv.config();6.2 初始化 LLMconstmodelnewChatOpenAI({modelName:deepseek-v4-flash,// 可替换为任意兼容 OpenAI 协议的模型apiKey:process.env.DEEPSEEK_API_KEY,temperature:0,// Agent 场景建议 0保证输出稳定性configuration:{baseURL:https://api.deepseek.com/v1,// 自定义 API 地址},});经验之谈Agent 场景temperature设 0因为工具调用的参数需要精确创造性在这里是负资产。6.3 定义工具文件读取constreadFileTooltool(async({filePath}){// 功能函数真正干活的代码 constcontentawaitfs.readFile(filePath,utf-8);// 给用户实时反馈Agent 任务可能很耗时用户需要感知进度console.log([工具调用] read_file(${filePath}) 成功读取${content.length}字节);returncontent;},{// 工具元信息LLM 用它来决定何时调用、传什么参数 name:read_file,description:用此工具来读取文件内容。当用户要求读取文件、查看代码、 分析文件内容时调用此工具。输入文件路径可以是相对路径或绝对路径,schema:z.object({filePath:z.string().describe(要读取的文件路径),}),});// 工具注册表consttools[readFileTool];设计要点description是 LLM 决定何时调用的唯一依据写得越精确调用越准确。schema用 Zod 定义参数约束LLM 会严格按 Schema 生成参数。6.4 绑定工具到模型// LangChain 的核心抽象将 LLM 和工具注册到一起constmodelWithToolsmodel.bindTools(tools);bindTools做的事情告诉 LLM你有这些工具可用需要时在回复中带上tool_calls。6.5 初始化消息constmessages[newSystemMessage(你是一个代码助手可以使用工具读取文件并解释代码。 工作流程 1. 用户要求读取文件时立即调用 read_file 工具。 2. 等待工具返回文件内容。 3. 基于文件内容进行分析和解释。 可用工具 - read_file: 读取文件内容使用此工具来获取文件内容),newHumanMessage(请读取 src/tool.mjs 文件内容并解释代码),];6.6 核心循环ReAct 的代码实现前置回顾tool_calls里面有什么llm原生tool_calls:LangChain额外返回的tool_calls:// 第一轮让 LLM 思考letresponseawaitmodelWithTools.invoke(messages);console.log(JSON.stringify(response,null,2));messages.push(response);// 将 AI 回复加入历史// ReAct 循环有工具调用就执行没有就结束 while(response.tool_callsresponse.tool_calls.length0){console.log(\n[检测到${response.tool_calls.length}个工具调用]);// ---- Act并行执行所有工具调用 ----consttoolResultsawaitPromise.all(response.tool_calls.map(async(toolCall){// 查找对应的工具定义constmatchedTooltools.find(tt.nametoolCall.name);if(!matchedTool){return错误找不到工具${toolCall.name};}console.log([执行工具]${toolCall.name}(${JSON.stringify(toolCall.args)}));try{// LangChain 的 tool.invoke() 方法内部调用你写的功能函数constresultawaitmatchedTool.invoke(JSON.parse(toolCall.args));returnresult;}catch(err){return错误工具${toolCall.name}执行失败 ——${err.message};}}));// ---- Observe将工具结果打包为 ToolMessage 加入历史 ----response.tool_calls.forEach((toolCall,index){messages.push(newToolMessage({content:toolResults[index],tool_call_id:toolCall.id,// 必须LLM 靠这个 ID 关联请求和结果}));});// ---- 下一轮 Reason把所有消息喂给 LLM让它继续思考 ----responseawaitmodelWithTools.invoke(messages);messages.push(response);}// 循环结束LLM 不再要求调用工具说明任务完成console.log(\n 最终输出 );console.log(response.content);6.7 执行流程可视化messages [SystemMessage, HumanMessage] │ ▼ ┌──────────────────────────────┐ │ modelWithTools.invoke() │ ← Reason: LLM 思考决定是否调工具 │ 返回 response (AIMessage) │ └──────────┬───────────────────┘ │ 有 tool_calls ──No──▶ 输出 response.content任务完成 │ Yes │ ▼ ┌──────────────────────────────┐ │ Promise.all(tool.invoke()) │ ← Act: 并行执行所有工具 │ 返回 toolResults[] │ └──────────┬───────────────────┘ │ ▼ ┌──────────────────────────────┐ │ messages.push(ToolMessage) │ ← Observe: 结果带 tool_call_id 回传 └──────────┬───────────────────┘ │ ▼ 回到 Reason继续循环七、全文总结Agent 的核心差异在于结构——从一问一答升级为思考→行动→观察的自主循环。理解这个循环就理解了 AgentReAct是 Agent 的通用工作框架不是某个库的专利Tool Use是 Agent 的手和脚工具范围 能力边界Message 数组是 Agent 的记忆四种消息类型承载了整个对话流LangChain的价值在于工程抽象——bindTools、tool()、消息体系让开发者聚焦业务逻辑八、核心知识点复盘知识点一句话总结ReAct 循环Reason → Act → Observe → 循环直到任务完成或触发退出条件Tool UseAgent 操作外部世界的能力工具的覆盖范围决定 Agent 的能力上限SystemMessage定义 Agent 的身份、能力、行为规范ToolMessage工具执行结果必须带tool_call_id才能被 LLM 正确关联model.bindTools()LangChain 的核心抽象将工具注册到 LLMtool()定义工具的元信息name/description/schema 功能函数temperature: 0Agent 场景建议设为 0保证工具调用参数的精确性Promise.all多个工具调用应并行执行而非串行九、避坑指南❌ 坑 1ToolMessage 忘了传 tool_call_id// 错误写法messages.push(newToolMessage({content:result}));// LLM 无法关联可能导致幻觉// 正确写法messages.push(newToolMessage({content:result,tool_call_id:toolCall.id,// 必须}));❌ 坑 2串行调用多个工具当 LLM 返回多个tool_calls时它们通常是互相独立的应该用Promise.all并行执行而不是for循环串行等。❌ 坑 3LLM 的无状态特性LLM本身不记忆任何东西。每一轮调用你必须把完整的 messages 数组传给它。少传一条历史消息Agent 就失忆了。Agent 的记忆全靠你手动维护 messages 数组。❌ 坑 4无限循环Agent 可能陷入调工具→不满意→再调→还不满意的死循环。生产环境必须设置硬限制最大循环次数如 20 轮Token 总量上限连续相同结果检测防重复调用❌ 坑 5工具 description 写得太模糊LLM 靠description判断何时调用工具。写用来处理文件和写当用户要求读取文件内容、查看代码、分析文件时调用此工具效果天差地别。description 是工具调用的说明书越精准越好。

相关新闻

Spring Boot 3.x 整合 SSM 实战:5步构建RESTful API并对比传统SSH项目结构

Spring Boot 3.x 整合 SSM 实战:5步构建RESTful API并对比传统SSH项目结构

2026/8/23 0:48:31

Spring Boot 3.x 整合 SSM 实战:从传统架构到现代技术栈的演进之路技术栈演进背景与实战价值十年前走进任何一家Java企业,你大概率会看到Struts2HibernateSpring(SSH)组合占据开发主流。而今天,Spring BootSpring MVCM…

STM32与ADS8665构建高精度数据采集系统

STM32与ADS8665构建高精度数据采集系统

2026/8/24 1:15:29

1. 项目概述:高精度信号转换系统设计 在工业自动化、医疗设备和精密测量领域,16位ADC(模数转换器)搭配高性能MCU的组合已成为高精度信号采集的黄金标准。ADS8665作为TI推出的16位1MSPS SAR型ADC,配合STM32F756ZG这款带…

MCS-51单片机中断编程实战:5个中断源优先级配置与3个寄存器详解

MCS-51单片机中断编程实战:5个中断源优先级配置与3个寄存器详解

2026/8/30 12:08:29

MCS-51单片机中断编程实战:5个中断源优先级配置与3个寄存器详解 1. 中断系统架构与核心寄存器 MCS-51单片机的中断系统是其实时响应能力的核心引擎,包含5个中断源和3个关键控制寄存器。理解这个架构是进行中断编程的基础。 5个中断源及其特性 &#x…

CANN/GE ACL数据集缓冲区添加函数

CANN/GE ACL数据集缓冲区添加函数

2026/9/26 19:14:12

aclmdlAddDatasetBuffer 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Te…

用ffmpeg高效批量调整图片尺寸的实战指南

用ffmpeg高效批量调整图片尺寸的实战指南

2026/9/27 1:30:29

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

2026/9/27 1:30:37

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and mu…

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

2026/9/27 1:30:35

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system sup…

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

2026/9/27 1:30:34

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

2026/9/26 16:36:51

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting mi…

远程协作的工作台整理

远程协作的工作台整理

2026/9/26 14:29:04

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/26 13:57:22

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/26 23:35:16

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…