去年夏天团队内部上线了一个问答机器人第一周大家热情高涨第二周就几乎没人再点开它。原因听起来有点讽刺它太会聊天了聊得再漂亮也不会真的把要做的事办掉。同事问它上季度的需求文档更新了哪些内容它回复一大段得体的话可没人知道这段话靠不靠谱更没人指望它去文档库里把新旧版本差异真正拉出来。这个场景几乎每天都在各种团队里重演。大语言模型的强项是理解和生成文本而做事意味着理解之后还要决策、决策之后还要执行、执行之后还要检验。中间缺的不只是一个API而是一整套把模型能力延伸到真实系统的机制。这套机制就是现在被频繁提到的AI Agent。这篇文章不打算讲概念层面的花活。我会从会聊天和能做事的本质差异讲起拆解Agent内部真正干活的那几套机制再用一个我做过的合同处理Agent作为实例把工具设计、编排逻辑、实测翻车记录都摊开。最后聊一聊哪些场景适合Agent、哪些场景是在硬凑以及一套务实的落地路线。不管你是在评估技术方案还是准备亲手搭第一个Agent这篇都应该能给你一些可以抄作业的东西。1. 从对话窗口到执行入口Agent把理解变成了行动1.1 聊天机器人为什么不会做事市面上大多数聊天机器人本质是一个文本续写器。你输入一句话模型根据训练阶段学到的统计规律把最可能接下去的内容生成出来。它能写诗、能总结、能翻译是因为这些任务恰好属于语言空间里的变换。但做事要跨越的不只是语言空间还有现实空间。想一想用户说帮我把本周销售数据整理成周报这件事。聊天机器人能做的是给你一段周报模板或者一段零零散散的建议。它拿不到本周真实订单不会去数据库执行查询更不会把图表嵌进文档。你可以把它想成一个非常博学的顾问坐在那里口若悬河但手和脚都被绑住了。顾问的建议再有价值真要落地执行还是得靠别人跑腿。我并不是说聊天式交互没有价值。恰恰相反理解能力是Agent的地基。但只有当模型不再满足于说出答案而是能拿到证据、执行动作、交付结果时它的价值才从信息提供升级为事务处理。这一步的跨越靠的是把模型放进一个有工具、有反馈、有循环的系统里而这个系统就是Agent。1.2 一个最小可工作的Agent循环很多人第一次接触Agent时容易把它想象成一个更聪明的模型。其实Agent不是模型本身而是模型加外围机制组成的一个闭环。最简形式可以概括为四个英文单词Think、Act、Observe、Repeat。模型先接收任务想一下该怎么做然后决定调用哪个工具、传什么参数工具执行后把结果返回给模型模型看到结果判断任务是否完成没完成就继续下一步。这个循环必须显式地写出来不能指望模型一步到位。def agent_loop(task: str, tools: dict, max_steps: int 6) - str: messages [ {role: system, content: 你是一个可以使用工具的智能助手每轮先思考再行动。}, {role: user, content: task}, ] for step in range(max_steps): response llm.chat(messages, toolsTOOL_SCHEMA) # 模型认为可以直接给出最终答案 if response.is_final_answer(): return response.content # 模型决定调用某个工具 call response.tool_call observation tools[call.name](**call.arguments) # 把工具结果放回上下文让模型继续推理 messages.append({role: tool, name: call.name, content: str(observation)}) messages.append({role: assistant, content: 工具结果已返回请继续判断任务是否完成。}) return 达到最大步骤上限请调整任务或检查工具是否可用这段伪代码虽然短但它点出了Agent区别于聊天机器人的核心逻辑模型不直接产出一个答案而是产出一连串的动作决策。每个动作带来的新信息都会重新进入模型的上下文影响接下来的判断。这就是从输出文本到输出行动的转变。1.3 革命而不是升级三个关键转变把上面这个循环放到实际业务里你会发现它带来的不是聊天体验变好了而是整个软件交互范式变了。我总结了三个关键转变。第一从一次生成到多轮闭环。传统聊天是一次问答用户问完就结束。Agent是带着状态跑的任务没完成就是没完成闭环直到交付结果或触发终止条件。它更像一个执行流程不像一段对话。第二从语言空间到动作空间。模型不再只输出自然语言它可以输出结构化的工具调用指令比如{name: query_database, args: {sql: ...}}。真正做查询的是后端工具模型负责决策工具负责执行。两者解耦后模型能力边界被大幅扩展。第三从静态回答到环境交互。聊天机器人回答问题时不依赖外部世界的实时状态Agent每一步都在接触真实数据——数据库里多了一条记录、文件被修改了、接口返回了新的状态码。它感知的是此刻的环境而非训练数据里固化的世界。理解了这三个转变再看市面上各种Agent演示你就能分辨哪些是套壳聊天、哪些是真正在执行。2. 拆开引擎看活塞Agent能干活依赖的四套机制2.1 工具调用给模型装上手Agent能做事最直接的原因是它可以调用工具。但工具调用不是简单地给模型拼一个函数列表它依赖一套结构化的接口协议。模型需要知道有哪些工具、每个工具是干什么的、参数应该怎么填。我在项目中最常用的做法是把工具描述写成JSON Schema形式包含name、description、parameters三部分。其中description写得越具体模型触发工具的准确率越高。比如{ name: retrieve_contract_chunk, description: 在合同向量库中检索与查询最相关的段落。适用于用户询问付款条款、违约责任、保密协议等具体条款内容时。, parameters: { type: object, properties: { query: {type: string, description: 用户关心的核心问题}, top_k: {type: integer, description: 返回段落数量默认3} }, required: [query] } }这段描述看起来简单实际影响非常大。有一次我把description写成检索合同段落模型经常在用户提出这份合同要不要续签这类判断性问题时不调用检索工具直接凭上下文乱答。改成当用户询问合同中的具体条款内容时之后触发率明显提升。工具描述的本质是教模型什么时候该用这只手。还有一个工程细节工具的返回结果不能太长。向量检索返回了十段文本每段几百字一口气塞回上下文会把关键信息淹没。我会在工具层先做截断和重排只保留与查询最相关的三到五段再返回给模型。记住Agent的推理质量很大程度取决于喂给它的观察结果干净不干净。2.2 任务规划把大目标拆成小步骤有了工具模型还得知道按什么顺序用、用到什么程度停。这就是规划机制。在复杂任务里我倾向于让模型先输出一个执行计划把任务拆成若干子步骤再逐步执行。以合同的结构化抽取为例完整任务拆成四步解析文档获取全文文本。将文本切片并向量化建立索引。按字段清单逐项抽取关键信息。校验字段完整性缺失的重新抽取或标记人工确认。这种先计划、后执行的方式比让模型一步到位直接输出结果要稳得多。背后逻辑是每一步都缩小了搜索空间模型在每个子步骤上只做一件相对简单的事出错概率自然下降。规划并不总是需要复杂的调度算法。我见过很多团队上来就套任务分解框架结果简单任务也被拆得七零八落反而拉长了响应时间。我的建议是任务步骤少于两步时让模型直接决策只有任务天然具备多阶段特征时才引入显式规划流程。规划是为了降低复杂度不是为了展示技术。2.3 记忆体系记住对话、任务和长期偏好Agent的第二只手是记忆。聊天机器人也有多轮上下文但那只是短期记忆Agent真正有用的记忆体系至少分三层。短期记忆就是当前任务的上下文窗口包含用户原始指令、每轮工具调用和返回结果。它决定了当前任务的连贯性。中期记忆是任务状态比如文档已解析已抽取字段3/5用于在中断后恢复执行。长期记忆则依赖外部存储我把结构化的用户偏好、历史决策记录、常见问题解答存放在数据库里需要时通过检索拉回上下文。举一个实际例子。合同处理Agent在第一次被问到我们通常接受的付款账期是多久时如果库里已经存了团队的历史偏好记录它可以直接检索到最多接受30天账期老客户可到45天这条规则再结合当前合同的条款给出判断建议。没有长期记忆的Agent每次遇到类似问题都像失忆一样重新推理不稳定且低效。设计记忆体系时我会提醒自己记忆的意义是让Agent避免重复劳动同时保持决策一致性。如果你发现Agent在同一个问题上两次回答不一致大概率是记忆层没接好。2.4 自我反思错了不要紧要紧的是会改Agent和静态机器人还有一点不同它能看见自己动作的结果并据此修正策略。这个能力在行业里常被称为反思或自我修正。工具调用不是每次都成功的。接口可能超时SQL可能有语法错误解析器可能遇到不支持的格式。如果模型只会按原计划继续走一个错误可能滚成更大的错误。正确的做法是把错误信息原样返回给模型让它重新决策。我设定的标准流程是工具层捕获异常返回结构化的错误信息例如{error: file_not_found, detail: 指定路径不存在}模型看到后可以换路径、换工具、或者向用户请求补充信息。同时给整个循环设定最大步骤数防止它在一个错误里反复打转。反思机制最容易被忽略的部分是记录失败模式。我会在日志里把每次工具调用失败的原因归类比如参数格式错误、权限不足、文件损坏。跑一段时间后从统计里能看出哪些工具描述需要优化、哪些场景需要加预处理。这比事后人肉复盘高效得多。3. 落地实录从零构建一个合同管理Agent3.1 场景选择为什么先做文档型Agent讲完原理我拿一个实际做过的小项目来拆解。这个项目的目标是做一个合同管理Agent用户上传合同文件后能自动抽取关键条款还能用自然语言提问这份合同的付款期限是多久违约金比例是多少。为什么选这个场景因为它是典型的多步骤、要真实数据、结果可验证的任务。合同是静态文档不需要跨系统权限工具集可以控制在四五个以内风险边界清晰。对新团队来说这是练手Agent的最佳复杂度——不会简单到没有意义也不会复杂到失控。选这个场景还有一个私心它能把Agent的核心机制全部用上。工具调用负责解析和检索任务规划负责字段抽取流程记忆体系存储历史合同的处理结果反思机制处理解析失败和字段缺失。一个项目练完整套经验可以迁移到报表生成、工单处理等场景。3.2 工具集与数据流设计我设计的工具集如下工具名职责关键输出parse_document解析PDF/Word转为纯文本全文文本、页数、解析状态chunk_and_index分段并写入向量库切片数量、索引状态retrieve按问题检索相关段落相关段落列表已截断extract_fields从文本中抽取指定字段字段名与值的映射verify_result校验必填字段是否齐全缺失字段列表数据流是这样的用户上传合同文件Agent调用parse_document解析出文本文本交给chunk_and_index切成短段并向量化用户提问题时retrieve从向量库里找出相关内容需要抽取结构化字段时extract_fields逐项抽取最后verify_result检查有没有漏抽有漏就决定是重新抽取还是标记人工复核。这个数据流的设计原则是每个工具只做一件边界清晰的事Agent负责编排。一旦某个环节出问题你能精准定位是解析的锅、检索的锅还是模型决策的锅。3.3 编排逻辑与关键代码思路核心编排逻辑用伪代码呈现如下SYSTEM_PROMPT ( 你是一个合同管理助手。用户可能上传合同文件也可能直接提问。 遇到问题时应先检索相关合同内容再基于检索结果回答。 抽取字段时必须调用extract_fields不要凭记忆填写。 ) TOOL_SCHEMA [ { name: parse_document, description: 解析本地PDF或Word合同文件返回纯文本, parameters: { type: object, properties: {path: {type: string}}, required: [path], }, }, { name: retrieve, description: 在合同向量库中检索与查询最相关的段落, parameters: { type: object, properties: { query: {type: string}, top_k: {type: integer, default: 3}, }, required: [query], }, }, ]代码本身不复杂但有几个地方我在第一次实现时踩了坑。第一个坑是为了省事我把extract_fields设计成一次传入所有字段结果模型经常漏掉后面的字段。原因是待抽取字段一多上下文里的注意力被前面的字段稀释了。后来改成一次只抽一个字段循环调用准确率立刻上来。牺牲了一些调用次数换来更稳定的结果这笔账是划算的。第二个坑是工具返回的结果我没有加结构约束直接把数据库查询结果的原始字典塞回上下文。字典里有很多与用户问题无关的字段把模型的注意力带偏了。后来每个工具返回前都做一次裁剪只保留对后续决策有意义的字段。3.4 实测表现与两个翻车修复记录实测阶段我用三十份脱敏合同做了测试其中涵盖扫描件、电子签章件和扫描加手写批注的混合件。字段抽取的完整率从第一版的百分之七十几经过两轮修复后稳定在百分之九十五以上普通提问的响应时间在三到五秒之间复合检索加抽取的流程在十秒左右。第一个翻车记录是扫描件问题。第一版parse_document直接调用PDF文本抽取接口遇到扫描版合同时返回的是乱码。用户问违约金比例Agent检索到乱码段落给出的答案牛头不对马嘴。修复方案是在解析失败时自动切换到OCR流程并把文件为扫描件这个状态写进上下文后续抽取和检索都会自动按图像识别结果处理。第二个翻车记录是字段校验逻辑。早期verify_result只看字段是否存在于返回结果里后来发现有些字段模型填了一个空字符串校验直接通过了。改成校验非空且符合基础格式之后比如金额字段必须匹配数字模式、日期字段必须匹配日期模式漏抽率和误抽率同时下降。这个教训让我明白Agent的校验机制要和工具层的真实约束对齐不能只做存在性检查。4. 项目上线前必须想清楚的四件事4.1 上下文窗口不是无限的记忆Agent每次调用工具后都会把结果塞回上下文几轮下来上下文可能被工具返回撑爆。我在一次测试中发现任务是从十份合同里找出付款条件最宽松的一份每检索一份合同检索结果加模型中间推理就占用了两千多token五轮之后上下文接近临界值模型开始遗忘最初的任务约束。解决思路有三种可以组合使用。一是中间摘要每两到三轮让模型把已获得的关键信息压缩成一段短文替换掉原始的工具结果。二是结果截断工具层控制返回数据的长度只保留与当前子问题直接相关的部分。三是把长期记忆抽离到外部存储需要时再检索而不是全部堆在上下文里。上下文管理的核心原则是让模型始终看到全局目标同时只暴露当前步骤需要的细节。全局目标放在系统提示词里固定不动细节按需加载这样即使执行到第十步模型的决策质量也不会明显下降。4.2 工具返回的数据比模型输出更会坑人大多数人把Agent的稳定性归因于模型聪明不聪明但我在项目里发现更多事故发生在工具返回的数据质量上。数据库字段里的值可能是2024年3月21日也可能是3/21/2024还有可能是按合同约定执行。这些格式不一致的数据进入模型上下文后模型会做出各种奇奇怪怪的推断。我的对策是在工具层加一个标准的清洗与校验流程。日期统一格式金额统一保留两位小数无暂无按约定这类模糊值统一标记为unknown并在返回给模型之前完成类型校验。如果数据源本身存在无法自动处理的脏值工具可以返回一个明确的状态比如{field: payment_due, value: null, reason: unrecognized_format}模型看到后就知道不能瞎猜必须触发人工复核分支。这种做法相当于在模型和现实世界之间加了一道防火墙。模型可以不够聪明但工具返回的数据必须稳定可预期。大部分被吹得天花乱坠的Agent Demo一到真实数据环境就露馅根子就在这一层没做好。4.3 每一轮调用都在烧钱成本与性能平衡Agent的成本结构比普通聊天机器人要贵得多。一次复杂任务可能涉及五到八次模型调用每次调用都要携带累积的上下文token消耗呈递增趋势。我算过一笔账一个日常合同问答任务大约消耗两万到三万token换算成成本是聊天的几倍到十几倍。控制成本有几个实测有效的手段。第一给每个Agent设置最大调用次数限制死循环。第二对相同或高度相似的工具调用结果做缓存比如相同的合同片段、相同的检索结果不需要每次都重新生成token。第三在入口处用一个轻量分类模型判断任务类型简单问题直接用小模型回答复杂问题才路由到完整Agent链路。第四长文档不要每次全量塞给模型先检索后抽取只在必要时把具体段落送入上下文。成本控制不是把参数调小那么简单而是要在架构层面把每次都要靠大模型硬想变成能查的查、能缓存的缓存、能路由的路由。这样做了以后我的实际支出下降约百分之四十回答质量几乎没有变化。4.4 安全边界Agent能调工具会不会闯祸Agent变得越能干风险边界就越需要画清楚。一个会调数据库接口的Agent理论上可以把表删了一个能发邮件的Agent理论上可以给全公司群发错误内容。我在项目中坚持几条原则。最小权限原则是底线。Agent的工具权限应该只覆盖当前任务需要的最小范围比如合同管理Agent只读文档目录不碰生产环境数据库需要写操作的场景写入工具必须做参数白名单校验。敏感操作二次确认删除、覆盖、发送、审批这类不可逆操作默认要经过人工确认节点不直接自动执行。全程审计也不可少每一次工具调用的时间、输入、输出都记录日志出问题时能回溯。有一次测试里Agent在检索未能满足需求时居然编造了一个不存在的工具名想让系统调用它。这个细节提醒我护栏不是提防模型变坏而是提防它犯傻。系统的鲁棒性必须建立在工具层和安全层的确定性约束之上而不是建立在对模型自律的信任上。5. Agent不是万能的选场景比调模型更重要5.1 高ROI场景的三个特征做了几个Agent项目后我归纳出适合Agent落地的场景都具备三个特征多步骤、要真实数据、结果可验证。多步骤意味着Agent的规划与工具调用能力有用武之地任务越单点Agent相对传统脚本的优势越小。要真实数据意味着模型不能只靠训练记忆作答必须通过工具获取实时信息这正好是Agent的长处。结果可验证意味着你能为Agent的成功定义一个客观标准比如关键字段抽取完整率工单自动分派准确率没有客观标准的任务很难调优。符合这三个特征的典型场景包括客服工单自动分诊与回复辅助、报表数据拉取与解读、合同文档的条款抽取与问答、代码仓库的变更分析。这些场景的共同点是边界清晰、数据可得、效果可度量拿来做第一个Agent项目最合适。5.2 我踩过的伪需求与不适合Agent的领域我也踩过用Agent硬凑需求的坑。有段时间团队想做自动写周报Agent老板希望成员每天提交工作记录后系统自动生成周报。结果上线后发现周报里引用的数据除非严格结构化否则Agent汇总时会脑补出很多不存在的进展负责人不放心每天还得人工核对一遍ROI直接为负。这就是典型的结果不可验证问题——周报写得好不好没有客观标准人的信任成本降不下来。不适合Agent的领域也分几类。纯创意类内容产出比如广告文案、品牌故事需要极强的审美与主观判断人类参与价值很高Agent只能做素材铺垫。医疗诊断、司法建议、金融投资这类高风险决策哪怕Agent只是辅助责任归属问题也绕不开建议以信息检索人工决策的方式切入别贸然做全自动。还有一类是对接系统极其封闭的场景Agent要跑的业务逻辑全部藏在一个没有API的老旧系统里工具层做不出来Agent再强也等于断手断脚。选场景时我会问自己一个问题如果这个任务换成一段普通代码自动化能不能做到八成效果如果能那未必需要Agent如果代码只能按固定路径跑遇到变化就失灵而规则常常变化——这才是Agent真正该进场的地方。5.3 务实的落地路线先单点、再编排、后闭环最后聊一套我在多个项目里反复验证过的落地路线。第一步是单点突破只接一个工具、解决一个明确痛点。比如先做一个合同解析工具让用户上传文件就能拿到结构化摘要哪怕没有完整的Agent循环先跑起来积累数据。第二步是多工具编排把解析、检索、抽取、校验串起来形成最简Agent闭环。这时候你会真正感受到工具返回值如何影响模型决策这个核心命题。第三步是嵌入业务流程接入企业内部的审批、消息通知、权限体系让Agent从被用户调用变成出现在业务流程的关键节点上。这套路线的优点是把风险摊薄了。每个阶段都有可验证的交付物不会出现憋了三个月最后发现方向错了的情况。我见过不少团队一上来就搞超级Agent想同时打通十几个系统结果半年过去还在和权限、数据格式搏斗。与其这样不如先让一个Agent在一个小场景里稳定跑起来把工程细节打磨成熟后再横向复制。从会聊天到能做事我越来越觉得不是模型参数发生了什么突变而是我们把模型放进了一个包含工具、反馈、控制机制的真实系统里。模型依然是那个会续写文本的模型但它的决策开始作用于现实世界并且能观察到作用的结果。这一步看起来只是工程架构的变化实际带来的交互范式和价值空间比很多人想象的都要大。如果你也想做建议从一个小但真实的业务场景开始认真为它铺好一条通往真实世界的路。
阅读完成 · 觉得有帮助?