1. 先搞明白:Agent和LLM到底差在哪
这几年做AI落地最常被问到的一个问题,就是"你搞的AI Agent,和ChatGPT、和DeepSeek到底有什么区别?"。我习惯把答案浓缩成一句话:大模型是一个会说话的大脑,Agent是一个会办事的人。ChatGPT网页版和DeepSeek这类产品背后是LLM,它们能答题、能续写,但不会自己去查你的数据库,不会主动调你公司的内部接口,更不会在一项任务失败后换个工具重试。Agent则不一样,它会规划、会拆解任务、会调用工具,还会根据执行结果调整策略。
这个系列叫"AI Agent 工程化实战",第00篇我们不写代码,先把最要命的概念讲清楚:工程化到底在工程什么。你会发现,把模型API接上、写几行循环让AI自己调用工具,这件事半天就能跑通;但真正把一个Agent变成能上生产、能扛并发、能被业务方信任的系统,难度完全不在一个量级。所以我给这篇文章定了个很朴素的立场——先别急着追新框架,把底层的"工程零件"一个个装好,比什么花活都值钱。
1.1 模型是"大脑",不是"身体"
我见过不少团队上来就买一堆GPU、选一个超大参数的模型,然后让Agent做各种复杂操作。结果模型确实聪明,但该查库存的时候不会查,该下单的时候不会下,最后项目卡死在"模型好像什么都会,但什么都做不完"的尴尬里。
原因很简单:模型只有推理能力,没有执行能力。你让DeepSeek写一段Python代码,它能写得很好;但如果你让它"去把服务器上跑着的服务重启一下",它没有手去执行命令,也没有权限去触碰你的运维系统。这就像公司来了个顶级顾问,分析问题头头是道,但你不能指望他自己去把PPT做了、邮件发了、合同签了。
Agent的逻辑恰恰是把"大脑"和"手脚"分开。大脑负责理解意图、拆解任务、决定下一步调什么工具;手脚是那些真实的API、数据库连接、命令行工具、业务系统。工程化的第一课,就是明确这条边界:模型负责决策,工具负责执行,中间那层胶水代码由你写。谁也别越界,否则系统一定乱。
1.2 DeepSeek这类模型在Agent里扮演什么角色
回到热搜词里那个高频问题:DeepSeek属于哪个?答案很明确:DeepSeek是一个LLM(大语言模型),不是一个Agent。你打开DeepSeek的聊天网页,它看起来像Agent,是因为官方在它外面套了一层产品壳:有对话历史、有联网搜索按钮、有上传文件入口。但这些能力不是模型天生自带的,而是外面那层工程系统接上去的。
在实战里,我们经常把DeepSeek当成Agent系统的"底座大脑"。原因有几个:第一,它支持Function Calling,可以让模型输出结构化的工具调用指令;第二,上下文长度足够大,能装下多轮对话和工具返回结果;第三,API价格便宜,适合做To B场景里高频调用。但要留个心眼:不同模型的Function Calling格式不太一样,换模型往往意味着工具适配层也要跟着改。所以工程上我通常会在模型和Agent核心逻辑之间加一层适配器,把各家模型的输出统一成本地结构,这样以后换模型就像换插座,不用把整面墙砸了。
1.3 为什么说"搭个Agent不难,难的是把它变成产品"
我随便搜一下GitHub,能看到大量教你用Python几十行代码搭Agent的教程。照着做确实不难:定义一个工具函数列表,把用户问题、系统提示词、历史记录一起扔给模型,模型返回一个JSON说"我要调用get_weather这个函数,参数是北京",你执行函数,再把结果喂回去,循环几次就出结果了。
难在哪?难在真实环境里那堆没人提的破事:用户同时涌进来1000个请求,你要不要限流?工具调外部API超时了,Agent怎么处理?模型连续调用同一个工具三次还不收敛,要不要掐断?某个租户的敏感数据会不会被模型"看到"并泄露给另一个租户?改了一版提示词,回头发现原本能正常执行的场景开始抽风了,怎么拦住?这些问题每一个都会在Demo阶段假装不存在,但上线第一天就会变成事故。
这就是我写这个系列的初衷。我想把"能跑通的代码"和"能上线的系统"之间那块巨大的空白地带,一点点填实。你不需要是算法专家,也不需要是十年架构师,但你需要具备工程思维:把不确定性用规则和工具约束住,让Agent像一台经过调校的机器那样可预测地工作。
2. 工程化到底在工程什么:拆解Agent的六大核心件
既然要给Agent做工程化,第一步得先有个全景图。我习惯把Agent生产系统拆成六个模块:模型网关、上下文工程、工具调用、记忆系统、规划与工作流、可观测性与安全护栏。这六个模块不是纸上谈兵,而是每一个都对应着你在生产环境里迟早要踩的坑。下面逐个说清楚它们各自要解决的问题,以及为什么没有它们不行。
2.1 模型网关:管好API、Key与多模型切换
很多新手写Agent,第一版代码是这样的:直接在业务逻辑里调用openai.chat.completions.create(...),把API Key硬编码在配置文件里。Demo阶段没问题,但一旦多人协作、多个环境、多个模型供应商,就开始乱了。我见过一个团队,开发、测试、生产共用同一个Key,结果账单爆炸后都不知道是哪个环境跑出来的调用。
模型网关要做的事:统一所有模型的接入入口,上层业务不直接感知模型厂商;集中管理API Key和调用权限,每个租户/每个业务线有独立的预算和配额;自动处理重试、超时、限流,遇到某个模型服务商抖动就切换到备用模型;顺便把每一笔调用的token数、成本、时延记录下来,方便月底对账。
这个网关可以是一个独立服务,也可以是一层库,甚至是一张配置表。重要的是"集中"两个字。哪怕你用最简单的FastAPI包一层代理,也比业务代码里散落一堆模型调用要强一百倍。工程化的本质不是用多 fancy 的架构,而是让混乱的东西有唯一入口、有规则、能审计。
2.2 上下文工程:比Prompt Engineering更重要的窗口管理
现在模型动辄支持128K、256K甚至1M的上下文窗口,听起来很大,但你真正跑一个Agent就会发现:它会跟用户聊100轮,会调用20次工具,每次工具返回一大坨JSON,再把历史中间结果全部塞进去,几轮下来窗口就满了。而且更大的问题在于,中间那些过时的工具返回结果,会对后面的决策产生严重干扰。
我见过一个典型事故:一个客服Agent在回答用户退货问题时,上下文里还留着上一轮查询订单状态的工具返回值,模型把"订单已签收"当成"可以退款"的判断依据,直接给出了错误答复。这种问题靠加长上下文窗口解决不了,反而窗口越长,模型越容易被无关信息带偏。
所以上下文工程的核心是"少给一点,给得准一点"。你要对送入模型的每一段内容做生命周期管理:对话历史按策略裁剪或摘要,工具调用结果只保留关键字段,用户画像和业务数据通过检索按需加载,而不是一股脑全塞进去。这个过程和"爆仓"的管理很像——仓库再大,乱堆乱放也会找不到东西;定期清理、贴上标签、按需取用,才能在有限空间里保持高效。
2.3 工具调用:Agent的"手"怎么接才稳
工具是整个Agent系统里最容易"看起来能跑,实际一用就崩"的部分。工具定义本质上是给模型一份关于"你可以做什么"的结构化说明书,模型根据说明书决定调哪个函数、传什么参数。问题在于:模型的判断是概率性的,它可能传一个你Schema里没有的枚举值,可能漏掉必填参数,可能把一个字符串传成了数组。
工程上要给工具调用做四层防护。第一层,入参校验:模型输出的参数必须经过JSON Schema校验,非法输入拦在工具执行之前,把清晰的错误信息返回给模型,让它重新生成调用。第二层,超时控制:每个工具调用都要有超时上限,后端服务卡了5秒,Agent不能跟着傻等10分钟。第三层,幂等设计:同一个工具函数被执行两次不能产生重复扣费、重复下单等副作用。第四层,审计与权限:谁在什么场景下调用了哪个工具,必须留痕;高危操作比如删除数据、发邮件、转账,要设置二次确认甚至人工审批。
还有一点我特别想强调:工具数量不是越多越好。有些团队给Agent挂了50个工具,结果模型每次选择困难症发作,频繁调错。更好的做法是先挂5个最常用的,用到一定阶段再用命名空间或动态加载机制扩——让Agent的"手"越用越灵活,而不是一开始就长成八爪鱼。
2.4 记忆系统:短期、长期与向量检索
记忆这个词在Agent圈被说烂了,但很多人理解的记忆只是"把聊天记录存起来,下次再塞给模型"。这远远不够。我倾向于把记忆分成三层:短期记忆(当前会话里的上下文,跟着对话窗口走)、长期记忆(用户偏好、历史事实、业务规则,需要持久化存储)、工作记忆(当前任务执行过程中产生的临时状态,比如已经做完哪一步、下一步计划是什么)。
实现上,短期记忆通常直接用模型上下文窗口,配合裁剪压缩;长期记忆更复杂,常见方案是存在数据库里,需要时用向量检索(Embedding相似度)捞出来。但要注意,向量检索不是万能药,它适合找"语义相近的片段",不适合查"用户上周三买的订单号"。所以真正的工程系统往往是混合存储:结构化数据放MySQL/PostgreSQL,非结构化知识放向量库,记忆按业务规则决定何时写入、何时读取。
更重要的一点是遗忘机制。长期记忆不是只增不减,用户的偏好可能变化,过期的业务规则会误导Agent。我通常会给每条记忆打上时间戳和置信度,定期做TTL清理,高频访问的记忆提权,长期不用的记忆降权。说白了,一个连忘记都不会的系统,称不上有记忆。
2.5 规划与工作流:从单轮到多步的决策控制
早期的Agent都是"自动规划"派:给模型一个目标,让它一步步自己思考、自己决定动作。这种方法在开放域问题里表现惊艳,但在商业场景里是灾难——你根本不知道它下一步会说什么、会调什么工具,整个执行过程像一个失控的即兴演员。
工程化实践告诉我,生产级Agent一定需要混合控制:把业务流程里确定的步骤用代码写死(比如先查订单,再判断是否在售后期内,最后调用退款接口),把不确定的地方交给模型(比如理解用户的自然语言、决定用什么关键词搜索)。这就是我常说的"流程骨架 + 模型填充"。
具体到技术选型,你可以用LangGraph这类框架画状态图,也可以用传统工作流引擎配合LLM节点。核心原则是:越靠近资金、权限、核心链路的地方,越要写死;越靠近语言理解、内容生成的地方,越要放开。全自动等于全失控,全流程编排又失去了Agent的灵活性。工程化就是在两端之间找到那个可配置的旋钮。
2.6 可观测性、评估与安全护栏
这一块常常被忽略,但它是"敢不敢把Agent交出去"的决定性因素。传统后端出问题,你可以看日志、看慢查询、看错误堆栈;Agent出问题,你往往只知道"结果不对",但不知道模型内部到底怎么想的。所以要做过程透明的Agent:把每一轮的思考过程、工具调用输入输出、token消耗、耗时、成本全部记录下来,形成一条完整的"决策链路",问题发生时可以回溯、可以复现。
评估方面,不能只看跑通没跑通。一个Agent修改提示词后变聪明了,但可能同时导致另一个场景变傻,这就是"回归"。所以一定要建立一个固定集:比如50个核心业务问题,每次改完跑一遍,用规则或LLM-as-judge打分,输出准确率、成本、时延三张曲线。没有这套东西,你每次改动都是在赌命。
安全护栏则是底线。Agent能调用的工具必须是白名单机制;对模型可见的业务数据要做脱敏;任何涉及用户隐私或资金的操作,必须经过权限校验和人工审批环节。别指望"提示词里写一句不要泄露用户手机号"就能守住红线,要用工程机制把红线焊死。
3. 从0到1搭一个最小工程化Agent(实操向)
聊完理论,我们来点能落地的东西。我假设你想自己动手,从零搭一个Agent玩一玩或者做验证。这一节给你一条清晰的路径:先选型,再实现最小循环,再加工程化改造,最后给一个能跑的示例。每一步都有我的取舍理由,你直接抄作业即可。
3.1 选型:什么时候直接调API,什么时候上框架
打开技术社区,你能看到正反两派:一派说别用框架,裸写最可控;一派说框架是标配,自己写纯属重复造轮子。我的建议很现实,分三种情况:
- 场景一:验证想法,只调一两个工具,代码不超过300行。直接裸写,用
openai或volcengine这类SDK,自己维护一个while循环就够了。理由:框架的抽象需要时间理解,映射到你的小场景反而费力。 - 场景二:要做带状态、多步骤、多Agent协调的业务系统。用LangGraph或类似编排框架。理由:它帮你处理状态持久化、图执行、分支跳转,你只需要关注业务逻辑。
- 场景三:企业内部要快速搭建面向业务人员的Agent应用。直接用Dify、Coze这类低代码平台,或者Java团队用Spring AI结合自家平台。理由:内置了知识库、工作流、监控和权限,节省的人力成本远超平台学习的成本。
我个人的倾向是:第一版先裸写,跑通了再决定要不要上框架。因为框架会掩盖底层细节,而工程化恰恰需要你理解每个细节,知道哪一环可能出问题。裸写能让你把每一步都踩一遍,之后再上框架,你会更清楚它的每个配置在解决什么问题。
3.2 核心链路:ReAct循环的十行伪代码
Agent最经典的执行模式就是ReAct(Reasoning + Acting,推理与行动)。原理不复杂,就是一个循环:模型根据当前信息推理(想),输出一个行动(做),执行工具后得到观察(看),然后再推理,直到得到最终答案或达到最大步数。
用伪代码表示,核心链路就十行:
def run_agent(question, tools, max_steps=5): messages = [system_prompt(), user(question)] for step in range(max_steps): response = llm.chat(messages, tools=tools) if response.has_final_answer(): return response.final_answer() tool_call = response.tool_call() # 执行工具,拿到结果 observation = execute_tool(tool_call) # 把这次的决策和观察结果追加到对话历史里 messages.append(assistant_with_tool_call(response)) messages.append(tool_result(observation)) return "未能在最大步数内找到答案"别小看这个循环,工程化的所有课题几乎都围绕它展开:上下文窗口管理就是控制messages列表不要无限膨胀;工具调用的可靠性就是确保execute_tool这一层各种异常不会直接搞挂循环;可观测性就是把每一步的response和observation记录下来;安全护栏就是给execute_tool加上权限校验。
3.3 工程化改造:加上会话、日志、超时与熔断
从上一步的伪代码到能上线的代码,需要做的改造不是加功能,而是加"防御"。我整理了一份最小改造清单:
- 会话隔离:每次请求带一个
session_id,不同会话的消息不能互相串场。在messages里附加会话ID,便于追踪。 - 结构化日志:每一步循环写一条日志,包含
session_id、step、prompt_tokens、completion_tokens、tool_used、observation_preview、latency_ms。这些日志是后面排障和优化的唯一依据。 - 超时与熔断:给单次模型调用设置超时(比如30秒),给单次工具调用设置超时(按工具类型,1~10秒不等);如果一个工具连续失败N次,触发熔断,不再调用该工具并返回错误提示。
- 预算上限:记录整个会话累计的token消耗,超过阈值(比如10万token)就强制停止,提示用户开启新会话。
- 人工回退:循环里如果连续两次出现"同一个动作+同一个错误",不要无限重试,直接交给人工处理或返回兜底话术。
做完这五项,你的Agent就不太容易在半夜三更搞出让人头大的线上事故了。
3.4 一个可跑的示例:用Python实现一个会查天气的Agent
做示例我习惯用天气查询,因为它的工具语义清晰。下面是一段可以直接跑的简化代码,假设你已经配置好deepseek的API Key:
import json from openai import OpenAI client = OpenAI(api_key="YOUR_DEEPSEEK_KEY", base_url="https://api.deepseek.com/v1") def get_weather(city: str): # 真实场景这里会调天气服务API,这里为了演示返回固定值 return f"{city}今天多云,气温24~31℃,适合出门但建议带伞" tools = [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的实时天气,参数为城市名,例如'上海'", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名,中文,例如:北京"} }, "required": ["city"] } } } ] def run_agent(user_input): messages = [ {"role": "system", "content": "你是一个天气助手。需要查询天气时调用get_weather工具,不要编造信息。"}, {"role": "user", "content": user_input} ] for step in range(5): resp = client.chat.completions.create( model="deepseek-chat", messages=messages, tools=tools, tool_choice="auto" ) msg = resp.choices[0].message if msg.tool_calls: messages.append(msg) for tc in msg.tool_calls: args = json.loads(tc.function.arguments) result = get_weather(args["city"]) messages.append({ "role": "tool", "tool_call_id": tc.id, "content": result }) else: return msg.content return "抱歉,我在天气预报上卡住了,请稍后再试。" print(run_agent("上海今天适合跑步吗?"))这段代码已经把Agent最核心的"模型决策+工具执行+结果回填"跑通了。但你注意,它的工程化程度还是比较初级的:没有日志、没有超时、没有会话隔离。如果你想把它变成生产代码,对照上一节的改造清单逐项加上就行。我自己做项目的时候就是这么一套套路:先跑通,再加固,最后再考虑要不要换框架。
4. 常见坑与排查实录:工程化落地时的真实教训
操作层面的坑,讲一天一夜都讲不完。我挑四个最有代表性的,每个都是真实踩过、也见过别人踩的。这些经验常规文档不会告诉你,但它们才是决定项目生死的关键。
4.1 Agent"答非所问":先查上下文污染
有一次我做一个客服Agent,测试时发现一个诡异现象:用户问"我什么时候能收到货",Agent回答"亲,你的收货地址是上海市浦东新区XX路XX号"。明明用户没留地址,哪来的?一查日志发现,上一轮工具调用把订单信息里的地址字段写进了上下文,模型在下一轮回答时就把地址当成用户当前问题的一部分带了出来。这就是典型的上下文污染。
解法很简单:对送入模型的每一条消息做字段裁剪,不在当前决策所需范围内的信息一律不写进去。工具返回结果尤其要小心,它往往包含大量冗余字段。工程上可以给每个工具定义"返回给模型的最小结构",只保留干结论,不完整体转储。排查的时候也要学会看prompt实际长什么样——不要只看模型回复,把每次发送给模型的完整消息体打印出来,很多"玄学"问题一眼就破。
4.2 无限循环与token燃烧:怎么用预算和最大步数兜底
我的一个朋友做数据分析Agent,测试时输入"对比上个月和这个月的销售额",结果Agent先查了销售额,又查了订单数,又查了客户数,又回去查销售额……来回折腾了十几轮,token烧了几万,最后也没给出结论。这种问题的根源在于模型在不确定"什么指标足够回答这个问题"时,会不断尝试新工具来寻找安全感。
工程上一定要设置"刹车":一是最大步数,我通常设6~8轮;二是累计token预算,超过就强制终止;三是死循环检测,如果检测到连续N轮调用同一工具且入参基本一致,就中断并告诉模型"你已经在同一个动作上重复多次,请重新审视思路或直接基于已有信息作答"。预算消耗看起来只是成本问题,但用户更在意的是"一个回答等了两分钟还没出来"的体验问题。
4.3 工具调用时好时坏:给模型准确的结构定义
模型决定调不调工具、怎么调工具,本质是一个生成任务,所以它天然有概率性。可能同样的输入,这次顺利调出了天气工具,下次就把参数写成了"city": "Shanghai, 12:00"这种带多余信息的值。如果后端解析直接报错,Agent就卡住了。
我的经验是三条。第一,工具定义的description要写得像"给一个很聪明但完全不了解你系统的新员工看",把约束、示例、边界都写清楚;第二,参数校验一定要独立于工具实现,先校验,再执行;第三,校验失败时不要把"参数格式错误"这种干巴巴的报错丢给模型,要给它可理解的错误信息,比如"city字段只接受中文城市名,你传的值是City=Shanghai,请改为'上海'"。模型看到具体错误,大概率能自我纠正;看到抽象的异常堆栈,只会原地懵圈。
4.4 没有评估集的Agent,不要上生产
我最想强调的坑是这个。很多团队花大力气把Agent调得很好,然后某天改了一句话术,用户反馈突然变差了,但代码逻辑没动,根本不知道问题出在哪。LLM系统就是这样:你改了输入端某个字,输出可能完全变样。没有回归测试,你就是在摸黑前行。
所以我在每个Agent项目里都会强制要求建立一个"golden set",也就是金标测试集,包含三类问题:核心业务问题、边界case、涉及安全合规的问题。每次变更后跑一遍,人工抽查加上LLM评委打分,最终得出三个数字:准确率、平均延迟、平均成本。只要这三个数字不劣化,改动才允许合并。听起来麻烦,但对生产系统来说,这是唯一的保命手段。
5. 从项目到产品:工程化是一场组织能力升级
做完技术上的拆解,我想把视角拉高一点。Agent工程化不只是写代码,它背后是一套组织协作流程、一种对不确定性的管理能力。这一节聊三个话题:行业时间窗口、团队角色分工,以及从单Agent走向多Agent时应该有的清醒认知。
5.1 为什么说2026年是工业智能体的分水岭
最近看到一种共识:2026年是从概念演示走向工程化落地的分水岭。我比较认同这个判断。原因不是模型会在2026年突然涌现什么神级能力,而是基础设施层面到了那个节点会大致成熟:模型推理成本逐步降到企业可接受的范围,工具调用相关的协议和生态趋于标准化,企业内部已有的系统(ERP、MES、CRM)开始愿意开放API给Agent调用,再加上前两年积累的试点项目经验,足够沉淀出一批可复用的工程模式。
但这并不意味着等2026年再动手。恰恰相反,现在正好是积累工程能力的时间窗口。因为到2026年,市面上真正稀缺的不是"能用模型写一段话"的人,而是能把Agent嵌进业务流程、能控制故障半径、能算清楚ROI的人。这类能力只能靠实际踩坑攒出来,临时上车是来不及的。
5.2 团队里谁来做"Agent工程师"
我观察到一种争论:Agent工程师到底偏算法、偏后端、还是偏产品?我的答案是不用纠结单一标签,这个角色更像"最懂模型行为边界的后端工程师"。他不需要重新训练模型,但要清楚模型什么能做、什么做不了,知道怎么设计提示词和工具来发挥模型的长处,也知道怎么用后端手段兜住模型的不确定性。
放到团队协作里,我建议最少要有三方参与:业务方定义流程和验收标准,Agent工程师负责模型行为与工具链的衔接,平台/运维负责网关、监控、部署。很多项目失败,就是因为这三方互相不沟通:业务方以为AI什么都行,工程师埋头调prompt,运维根本不知道Agent在依赖哪些外部服务。工程化本质是让这三股力量拧到一根绳上。
5.3 下一步:从单体Agent到多Agent协作
最后泼一盆冷水。市面上鼓吹多Agent系统、Agent群体的内容很多,但在我接触的真实项目里,一上来就搞多Agent的,大概率会死于混乱。多Agent之间的通信协议、任务分配、资源共享、冲突仲裁,每一项都是工程难题;你让A Agent写方案,B Agent评审,C Agent执行,最后往往变成三个模型在互相甩锅。
我的建议是:先用单Agent跑通流程,必要时通过确定性工作流编排多个角色,而不是让多个Agent自由对话。等到你确实遇到了单Agent无法承载的复杂度——比如需要长时间异步执行、需要不同专业领域各自独立的上下文、需要不同权限级别——再考虑引入多Agent,并且务必先定义好消息格式、状态存储、容错机制。先窄后宽,先严格控制再逐渐放开,这是工程化的通用法则。
在写作这部分内容时,我回忆了不少自己做项目的经历。Agent工程化最吸引我的地方,是它逼着你同时用"算法直觉"和"工程洁癖"去思考问题:一边要让模型保持灵活,一边又要让系统足够稳定。矛盾,但正是这种矛盾里藏着真正的价值。希望这个系列的第00篇能帮你看清全局,后面我们再一项项啃细节。