Agent 这个赛道现在有多火,不用我多说了。但我想先泼盆冷水,说个真实见闻:我见过不少团队,照着开源仓库搭了个带ReAct循环的Demo,就敢宣称已经“掌握了Agent开发”。结果一上真实业务,不是工具调用乱套,就是把上下文塞爆,最后花在调试和兜底上的时间,比写业务逻辑多十倍。
所以这篇东西,我不想给你复制一份“Prompt工程大全”或者某个框架的说明书。我会按我实际趟路子的顺序,把Agent从核心架构到底层原理,再到工程化遇到的坑和落地经验,一次性讲透。内容偏工程向,但对原理感兴趣的同学,前两章也能帮你建立一幅完整的地图。毕竟,Agent真正难的部分,从来不是让模型说出答案,而是让你的系统稳定地完成目标。
1. Agent不是ChatGPT套提示词:核心架构到底多了什么
想搞清楚Agent,先得把概念立住。很多人觉得Agent就是用Prompt包装一下大模型,这理解不能说全错,但一定低估了它。我习惯用一个更工程化的视角去拆,一个生产级的Agent系统,至少包含四块核心组件:模型、工具、记忆、控制循环。
1.1 四层拆解:模型、工具、记忆与控制循环
模型(Model):这是Agent的大脑,负责理解、推理和生成决策。但注意,CLAUDE这类模型本身不具备“干活”能力,它只会输出文本、输出结构化指令。真正让它“动手”的,是下面几个部件给它提供了“手”和“眼睛”。
工具(Tools):工具扩展了Agent的能力边界。搜索引擎帮助它获取实时信息,代码解释器让它能计算和写文件,各种API让它能操控业务系统。一个Agent能力上的差异,很大程度上取决于你给它接入了多少高质量工具,以及你对工具边界做了多严格的定义。
记忆(Memory):记忆很有意思。很多人的第一版Agent都栽在这里:模型聊着聊着就把前面的意图忘了,或者把无关信息当成前文关联。原因是他们没有区分短期记忆和长期记忆。短期记忆其实就是当前窗口内的上下文,长期记忆则是在留存于外部向量库、数据库里的历史信息和用户画像。能否管好这两层记忆,直接决定Agent在复杂任务里的稳定性。
控制循环(Control Loop):这是很多人忽略的“灵魂”。模型不是一次性输出答案就完了,它会根据当前状态,决定下一步是再调一个工具,还是直接生成最终回复。这个“思考—行动—观察—再思考”的循环,就是Agent区别于普通对话机器人的根本。控制循环设计得好,Agent会在失败后自己修正;设计得差,就会像个无头苍蝇一样反复犯错。
1.2 Agent、RAG与工作流的界限划分
我们经常把Agent、RAG、Workflow这三者放在一起说。这个概念不搞清楚,后面选型就会拧巴。
RAG的核心是检索增强生成,本质上是“先查资料,再写回答”。它适合知识密集型任务,比如企业知识库问答。它的链路相对固定:召回——重排——拼接——生成。整个链条里没有“自主决策”,每一步都是预设死的。
Workflow是在代码里把任务流程固定下来,比如先调用A接口,再调用B服务,最后给结果。它更适合业务流程确定的场景,比如风控审核、工单自动分类。
Agent则不同,它最大的特点是目标导向和路径不确定。你只给它一个目标,不告诉它具体怎么走,它会自己观察环境、选择工具、判断结果,甚至会根据中间反馈调整方案。
我见过很多团队把这三者混着用。实际上一个复杂的落地系统里,它们往往是配合关系:外层用Agent做任务规划,内层用Workflow保证关键流程的确定性,再用RAG做知识支撑。理解了边界,你才不会在需要确定性的工业场景里硬上纯Agent,然后在生产环境里被它的随机性折磨。
2. 选型决定成败:三件事在写第一行代码前就要确定
我在跟开发者交流时,发现大家最焦虑的不是“怎么写代码”,而是“用什么模型”“要不要上框架”“记忆怎么存”。这三个问题不前置解决,后面重构的成本会非常痛。这章我直接把我的选型逻辑和对比数据摊开来说。
2.1 模型选型:闭源API、开源部署与场景匹配的取舍
模型选型本质上是质量、成本、可控性三者之间的权衡,不要盲目追最强模型。
闭源API(如GPT-4o系列、Claude系列、国内通义、文心等):优点是调用简单、效果稳定、推理能力强,尤其在复杂工具调用和多步规划上表现优异。缺点是数据出境或合规问题(看企业要求)、按量计费的成本压力、以及某种程度上你对模型行为的约束力比较弱。
开源模型(如Qwen系列、DeepSeek系列、Llama系):优点是数据私有化、推理成本在长周期下更低、可以微调对齐自己的业务。缺点是部署运维需要团队有模型服务化能力,且小参数模型在复杂工具决策上确实会有明显差距。
我自己的经验是:做通用型、交互复杂度高的场景(比如客服、Copilot),优先选当前梯队最强的闭源API;做私有化交付、数据敏感、任务链路偏固定(比如文档抽取、合同审查)的场景,开源模型更有性价比。另一个实际建议是别把鸡蛋放一个篮子里,生产环境在网关层预留模型切换能力,A家API抖动或者涨价了,你能几分钟切到B家。
2.2 技术栈抉择:该不该用LangChain/LlamaIndex这类框架
这是被问烂了、但每次都要聊的问题。先说结论:如果你是在探索原型和学习阶段,用框架快速验证完全OK;但如果要上生产,千万不要无脑套框架的层层抽象。
LangChain这类框架的前半段价值是巨大的——它把Prompt模板、工具定义、记忆模块、各种外部集成都封装好了,新手拿来就可以搭流程跑通,这能极大降低学习门槛。但进入生产环境,抽象层带来的问题也很具体:排错困难(错误堆栈被封装得很深)、版本升级频繁破坏兼容性、以及很多内部封装已经超出了你自己的需求,白白增加复杂度和延迟。
我的建议是:用框架学理念,用代码写生产。你需要理解LangChain里“AgentExecutor”是怎么一步步调用工具的,理解“Tool”是怎么注册的,理解“Memory”是怎么管理的。然后把这一套逻辑,用几百行代码在你的代码库里复刻出来。这样你的系统是完全可控的,每一环都能观测、能测试、能一键回滚。
2.3 记忆选型:向量库是必选项,但对话记忆别只靠向量检索
记忆这块是重灾区。很多新手给Agent配了向量库,就以为万事大吉了,结果效果并不好,原因很简单——向量检索解决的是“语义相似度”问题,但对话历史管理还需要解决“信息密度”和“遗忘策略”问题。
记住这三条原则:
- 短期记忆用缓存和摘要,不要盲目全存。如果对话一长就往Prompt里塞,很快会超出上下文窗口,或者把关键信息稀释掉。建议约定一个阈值(比如超过12轮),触发一次摘要把前面的对话浓缩成几句话。
- 长期记忆要结构化。用户偏好、历史订单、业务实体的状态,这些别堆在一个向量库里查,建议落结构化数据库(PG、MySQL或者专门的记忆服务),按业务维度存取。
- 向量库里存的一定是“经过清洗的事实性知识”,而不是原始聊天记录的无脑切片。否则召回结果会非常不准确,且污染Agent的决策。
3. 手把手搭一个带工具调用和记忆的Agent,代码拆给你看
选型说完了,直接进入实操。这章我用Python和OpenAI风格的工具调用接口,手写一个极简但结构完整的Agent。我特意不依赖LangChain,就是为了让你看清每个齿轮是怎么转的。
3.1 核心循环实现:从Message到Tool Call的完整链路
一个Agent的主循环,本质上就是一个“while True”。我先定义一个最基础的函数调用Agent骨架。
代码核心思路如下:
from openai import OpenAI import json, os client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) def chat_once(messages, tools): resp = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, # 关键!通知模型有哪些工具可用 tool_choice="auto" ) return resp.choices[0].message def run_agent(user_input, system_prompt, tools, tool_executor, max_steps=8): messages = [{"role": "system", "content": system_prompt}] messages.append({"role": "user", "content": user_input}) for step in range(max_steps): # 1. 调用模型,得到回复 msg = chat_once(messages, tools) messages.append(msg) # 2. 如果模型没有要调用工具,说明任务结束了,直接返回答案 if not msg.tool_calls: return msg.content # 3. 如果有工具调用请求,就逐个执行 for tc in msg.tool_calls: result = tool_executor(tc.function.name, tc.function.arguments) # 4. 把工具执行结果作为新的消息回传给模型 messages.append({ "role": "tool", "tool_call_id": tc.id, "content": json.dumps(result, ensure_ascii=False) }) return "达到最大步数,任务结束。" if __name__ == "__main__": my_tools = [...] # 后面定义 print(run_agent("帮我查一下北京今天的天气,然后根据天气给我出行建议", "你是一个生活助手,回答要简洁。", my_tools, lambda name, arg: ...))这段代码的关键是“把工具调用结果返回给模型”这一步。模型先说要调用哪个工具、传什么参数,你执行完工具后,再把结果填充到对话历史的“tool”角色里,让模型接着推理。这就是一个完整的Agent步进循环。理解了这个循环,你就能在上面加各种复杂度了。
3.2 协议设计:为什么工具的Schema定义决定Agent能否调明白
很多人只关心工具函数怎么实现,却忽略了工具描述怎么写给模型看。实际上,模型理解工具的唯一渠道就是Tools Schema。写不好,模型就会反复传错参数。
我们看一个正反例子。假设要做一个订会议室工具:
{ "type": "function", "function": { "name": "book_meeting_room", "description": "预订指定时间段的会议室,仅当用户明确要求预定时才调用此工具。若会议室冲突,返回错误信息。", "parameters": { "type": "object", "properties": { "start_time": { "type": "string", "description": "开始时间,ISO格式,例如2025-06-01T14:00:00" }, "end_time": { "type": "string", "description": "结束时间,ISO格式,例如2025-06-01T15:00:00" }, "room_id": { "type": "string", "description": "会议室ID,来自会议室列表工具返回的room_id字段" } }, "required": ["start_time", "end_time", "room_id"] } } }你会发现,好的描述包含三个要素:触发条件(什么时候才该调)、参数格式示例(避免模型把时间格式传错)、字段来源(room_id怎么拿到)。这就是所谓的“协议设计意识”。你在真实项目里,工具描述大概率要迭代好几轮,每一轮都是看模型在哪些场景下调用错了,然后去优化描述。
3.3 上下文与记忆模块的落地:摘要记忆与向量召回的组合拳
我在生产里常用的记忆模块是这样的组合:短期用摘要记忆,长期用向量库+业务数据库。
摘要记忆的做法不复杂。当对话轮次超过N轮时,把之前的消息通过LLM压缩成一段纪要,塞回上下文开头。代码示意如下:
SUMMARY_SYSTEM_PROMPT = "你是对话摘要引擎,保留用户目标、已确认的信息、尚未完成的需求,输出200字以内的摘要。" def summarize_history(messages): # 触发条件:消息总数超过阈值 if len(messages) < 12: return messages # 前8条消息做摘要 to_summarize = messages[1:8] summary = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": SUMMARY_SYSTEM_PROMPT}, {"role": "user", "content": json.dumps(to_summarize, ensure_ascii=False)} ] ).choices[0].message.content return [{"role": "system", "content": f"[历史摘要] {summary}"}] + messages[8:]长期记忆则是把“事实性信息”抽取出来,写入向量库或者结构化存储仓库。比如用户聊到“家里有小孩,周末想去户外玩”,这个信息会被抽取成用户偏好记录,存起来。下次对话时,通过向量相似度把相关的偏好记录带进上下文。这就是“组合拳”的打法。
4. 工程化落地中翻车最多的五个环节
写完Demo只是万里长征第一步。下面这些坑,基本是我和身边同行做项目时公认的“生产事故高发区”,每一条都值得细看。
4.1 工具调用的“幻觉”与参数校验:模型说调了,其实没这回事
模型在工具调用上是有“幻觉能力”的。最典型的一种情况是:模型根本没有调用工具,但它直接“编造”了一个工具结果告诉你,比如“已查询到你本月消费共计523.5元”——其实它压根没查。原因是模型在训练时学会了模仿“调完工具后给结果”的语气,而不是真的调了工具。
解决这个问题的核心是为你的Agent建立“诚实约束”:
- 在系统提示词中明确说:“如果没有实际调用工具并获得返回结果,禁止声称你执行了查询或修改操作。”
- 工具执行层加严格校验:如果模型返回了工具调用ID,但执行引擎里找不到这个调用记录,直接终止并提醒。
- 涉及金额、状态、身份等关键信息时,强制要求Agent展示工具执行的原始返回,而不是转述。
4.2 上下文窗口的“垃圾填埋场”:Token超限与关键信息稀释
这个问题我见过太多次了。Agent每次循环都把上一轮的完整消息传回去,十几个步骤下来,初始的指令和目标已经被淹没在中间过程里。模型的注意力被中间日志、网页抓取内容、工具错误信息占满,最后给出一个完全偏离目标的回答。
应对方案:
- 目标Prompt的“锚定”:每隔N轮或每轮开头,重新注入一次用户原始目标和约束条件。
- 裁剪工具结果:工具返回的内容不要原封不动塞进上下文。过长的日志要截断、抽摘要,只保留关键事实。
- 滑动窗口:确认已经完成的步骤,将其压缩成一行摘要。
4.3 工具链的“雪崩”效应:一个工具超时引发全局不可用
真实业务里,工具的稳定性和云端API不可同日而语。你的查询接口可能会慢、会出错、会返回脏数据。如果Agent没有处理工具异常的意识,它就会带着一个错误结果继续往下走,最后把错误放大到决策层。
我的做法是给每个工具包三层防护:
- 超时控制:工具执行设硬超时,超过阈值强制返回“工具超时”状态。
- 重试策略:对幂等的查询类工具,做指数退避重试;对写操作,不做盲目重试,返回失败让模型另作打算。
- 错误结果语义化:工具返回的异常要先在引擎里加工成“干净的错误说明”再返回给模型,避免模型被一段堆栈跟踪带偏方向。
4.4 并发与成本:小心你的API账单一夜回到解放前
Agent的循环特性决定了它比普通对话消耗的Token多得多。你让Agent做个“网页内容总结并生成周报”的任务,中间可能要检索5次、总结10次,消耗几千Token。如果用户量上来了,又没有做流量管控,月底账单能吓死人。
控制成本的手段:
- 用便宜的小模型做中间步骤(摘要、抽取、格式转换用mini级模型),只把关键决策留给大模型。
- 设置单任务Token预算上限,超预算强制中断并转人工。
- 结果缓存:相同或高相似的中间查询结果(向量检索、信息抽取)做缓存,减少重复调用。
4.5 评估与回归:没有评测体系,你根本不知道改坏了什么
这个坑埋得最深,也最容易被忽视。Agent系统只要换个Prompt、加个工具,行为就可能剧烈变化——对A场景好了,对B场景可能就崩了。没有评测集,你完全没法判断一次升级到底是进步还是退步。
所以从项目第一天就要建评测集。评测集不需要多大,但要覆盖三类:核心需求场景(20-30条)、边界情况(10条)、风险情况(10条)。每次改动上线前,跑一遍回归,对比结果。没有评测体系的Agent项目,基本属于“裸奔开发”。
5. 从Demo到生产:评测、观测、人机回环与团队认知
最后一章,聊几个真正能帮你把Agent推进到生产环境的关键动作。这些认知层面的东西,往往比写多少行代码都有用。
5.1 建立最小评测集:20条核心用例比1000条噪声更有用
我刚才提到评测集,这里展开一下设计方法。很多人一开始就追求大而全,弄了上千条用例,结果每条用例的期望输出都是模糊的,评测就变成了一场主观评判。反而拖慢了迭代速度。
我的建议是做分级评测集:
- P0级(20条左右):核心高频业务,每条都有明确的通过标准(比如包含某关键词、通过了某审核规则)。
- P1级(30-50条):边界和异常输入,检查Agent的兜底能力和安全边界。
- P2级(可选):长对话、多轮复杂任务,做抽样人工评估。
每次上线前跑P0+P1,全过才能发布。P2周度抽测。
5.2 全链路可观测:Trace是Agent开发的“行车记录仪”
传统服务靠日志和监控就能排查问题,Agent不行。因为Agent是一个多步决策链,一道错误可能发生在第3步的工具调用,但直到第8步才显现。没有链路追踪,你连问题出在哪都找不到。
生产级Agent必须做Trace。最简单的方式是在每次循环里给Agent生成一个trace_id,记录每一步:模型输入输出、工具名、工具输入输出、耗时、Token消耗。等到推上线之后,遇到badcase,打开trace一看,就能快速定位是哪一步决策错了。市面上的LangSmith、Langfuse都能解决这个问题,自研也行,关键是每一步都要可回溯。
5.3 人机回环:让“转人工”成为一个优雅的设计而不是事故
我得说一个反直觉的结论:一个优秀的Agent不是永远不转人工,而是知道自己什么时候该转人工。硬要让Agent接住所有case,结果就是它在没有把握的任务上胡编乱造,最后用户找同事投诉,投入产出比极其糟糕。
好的设计是在Agent的规划循环里加入一个特殊工具叫“escalate”,当模型判断任务超出其可靠能力边界时,主动调用这个工具,把上下文完整转交给人。同时把转人工的标准在Prompt里说清楚,例如:涉及退款金额超限、用户情绪激烈、多轮对话无法达成目标。这个设计能让你的系统在可控风险范围内逐步扩大自动化覆盖面。
5.4 峰值成本与限流预案:被领导追问“为什么预算又超了”的解决方案
成本这件事,一定要在架构里就设计好,千万别上线后再补。我见过不止一个项目,上线前没有做成本预估,一周后被财务甩了份10万块的账单过来,全组傻眼。
这里给一个保守的成本预估公式(单位:美元/人民币自行换算):
单任务平均Token消耗 × 任务量/天 × 30天 × Token单价 = 月度预算
假设一个任务平均耗40000 Token(输入+输出),一天1000个任务,GPT-4o级别模型按输入$5/M、输出$15/M估算,这个数很容易就到一个月几万块。所以要做三层防线:单用户配额(比如每人每天最多20次Agent调用)、主动降级策略(高峰期自动切换到更便宜的模型)、预算告警(消耗到达80%自动通知负责人)。
5.5 组织与认知:Agent项目到底考验的是什么
最后说点不那么技术的。Agent项目的成功,技术只占一半,另一半是组织和预期管理。
第一,老板和业务方的预期要拉齐。一定要在项目启动时明确:Agent不是100%准确率的银弹,它是一条覆盖率逐渐提升的自动化曲线。大家总期望Agent能解决90%的问题,但实际上能做到70%自动解决、25%半自动(需要人审)、5%转人工,就已经是可观的业务价值了。
第二,Agent是持续运营的产品,不是一次性交付的项目。模型在迭代、工具在变化、用户输入习惯在漂移,评测集也随之上线更新。必须有一个常驻团队持续做badcase分析和Prompt迭代,这个工作不是“优化一下”就完事,它是无止境的。你越早意识到这一点,后面就越不会因为效果波动而手忙脚乱。
第三,从确定性开始,再逐步放权。早期落地时,先选一个流程相对固定、数据积累充分的场景(比如工单分类、知识库问答),把确定性链路跑通,积累经验和评测数据,再慢慢向复杂的决策型场景(比如自动下单、自动处理售后)扩展。很多人一上来就想搞一个全自动全能Agent,结果死在第一步。
我自己是踩过这些坑,吃过不少教训,才总结出这套打法的。你现在要是正打算启动Agent项目,我劝你前三章的内容多读两遍,尤其选型和架构设计,那是整个项目的地基,地基一旦打歪了,后面再怎么往上盖都是徒劳。