智能体开发与传统软件开发的核心区别

张开发
2026/5/15 16:39:04 15 分钟阅读

分享文章

智能体开发与传统软件开发的核心区别
今年年初我们团队来了个新同事之前在阿里写了五年Java后端技术底子非常扎实。老板让我带他做Agent开发。第一周我给他分配了一个任务写一个工具函数根据订单号从数据库里查物流信息。他花了十分钟写完了。代码很漂亮有参数校验、有异常处理、有日志、有单元测试。他跑过来跟我说“写完了很简单的CRUD嘛。”我说“你把它注册成Agent的工具然后让Agent在对话里调用它。”他又花了半小时用LangGraph把这个工具挂上了。然后他试着跟Agent对话“帮我查一下订单12345的物流。”Agent说“好的正在为您查询。查询结果显示订单12345的物流状态为已发货预计明天送达。”他回头看了一眼数据库这个订单的状态明明是“已签收”。他又问了一遍Agent还是说“已发货预计明天送达”。他开始怀疑是自己的工具写错了进去查了半天工具返回的数据明明是“已签收”。那为什么Agent回答“已发货”我让他把Agent的思考日志打开。日志显示Agent在调用工具之前先在自己的记忆里检索了一下——它“记得”之前有个类似的对话那个订单是“已发货”。所以它没有用工具返回的结果而是用了自己的“幻觉”记忆。这位写了五年后端的新同事当场就懵了。他说“这不科学啊。我明明给它传了正确的数据它为什么不用”我笑了笑说“欢迎来到智能体开发的世界。在这里代码写得再对模型也可能不听话。”这件事让我意识到传统软件开发者和智能体开发者之间的认知鸿沟比我想象的要大得多。很多人以为Agent开发就是在传统架构外面套一层大模型API把业务逻辑从代码搬到Prompt里。但真正上手之后才发现这是两个完全不同的世界。今天这篇文章我就把这个“不同”彻底讲透。不堆概念直接用对比的方式从七个维度拆开来看。一、编程范式的根本转变确定性 vs 概率性传统软件开发的核心是“确定性”。你写一行代码if user_input 查询订单它就一定会执行对应的逻辑。你传参数get_weather(北京)它就一定会返回北京的天气数据。同一个输入跑一万遍输出一模一样。智能体开发的核心是“概率性”。你告诉Agent“用户问天气的时候调用天气工具”它不一定每次都照做。有时候它会自己“猜”一个答案有时候它会把“北京”理解成“背景”有时候它会忘了调用工具直接回答“我不知道”。这不是bug这是LLM的本质。大模型不是一个程序而是一个概率分布。它输出的每个token都是基于前面的内容计算出的“最可能的”下一个token。这个“最可能”意味着有时候它会选第二个、第三个可能的选项。这就给开发者带来了一个巨大的挑战你无法“确保”Agent的行为。你只能“提高概率”。我刚开始做Agent的时候总是试图用写代码的思维来写Prompt。我会写“如果用户说A你就做B如果用户说C你就做D。”结果发现模型根本不按这个if-else走。它会自己发明E、F、G。后来我才明白写Prompt不是在写代码而是在“训练”一个概率模型。你要通过示例、规则、约束让它“倾向于”做正确的事而不是“必须”做正确的事。这个区别听起来很抽象但它影响了一切。在传统开发里你发现一个bug只要定位到那行代码修好它bug就永远消失了。比如if user_id is None少判断了空值你加上判断问题就解决了。在Agent开发里你发现一个bug修了Prompt跑一遍测试发现好了。但你多跑几次可能又出现了。因为模型的决策路径变了。你修复的只是“概率”不是“确定性”。你需要持续监控持续优化永远不要指望“一劳永逸”。二、架构设计的差异三层架构 vs 五层传统后端架构分层很清晰。一般就是表现层、业务逻辑层、数据访问层再加个数据库。每层之间有明确的接口你改了下层的实现上层只要接口不变就不用动。Agent的架构要复杂得多。我画过一张图一个生产级Agent至少包含这些层感知层处理用户输入包括文本、图像、语音、文件等。推理规划层核心的大脑用LLM做意图识别、任务分解、路径规划。记忆层短期记忆上下文窗口、长期记忆向量数据库、工作记忆任务状态。工具层各种API、函数、数据库查询、外部服务。执行层实际调用工具、执行代码、发送请求。评估层反思、校验、自我纠错。安全层输入过滤、输出过滤、权限控制。这些层不是像传统分层那样从上到下依次调用。它们之间是网状交互的。记忆层可能在任何时候被检索评估层可能在执行后触发安全层在输入和输出两端都要介入。更复杂的是每一层的“逻辑”都不是写死的代码。推理层的逻辑写在Prompt里记忆层的检索策略写在向量查询里工具层的调用规则写在与模型共享的Schema里。这些东西——Prompt、向量、Schema——都不是传统意义上的“代码”。它们不能被编译不能被静态检查不能被断点调试。这就引出了下一个区别。三、编程语言的演变从代码到Prompt传统开发你用Java、Python、Go写的是语法严谨、逻辑明确的代码。编译器会帮你检查语法错误IDE会帮你自动补全单元测试会帮你验证逻辑。Agent开发你写的最多的“代码”是Prompt——自然语言。自然语言不是编程语言。它有歧义有模糊性没有编译器。你写“不要泄露用户隐私”模型可能理解为“不直接说出手机号但可以说出后四位”。你写“如果用户生气先道歉”模型可能在你还没惹用户生气的时候就先道歉。这导致了一个很尴尬的局面你没法“调试”Prompt。传统代码调试你设个断点跑起来看到变量值就知道哪儿出问题了。Prompt调试你只能——改一下跑一遍看输出不满意再改再跑。整个过程像在黑暗中摸索没有任何工具能告诉你“这行Prompt的第12个词导致了模型的误解”。更麻烦的是Prompt的效果跟模型强相关。同一个Prompt在GPT-4上跑得好好的换到Claude上可能就一塌糊涂。你换一个模型版本之前精心调优的Prompt可能又要重写。我记得有一次OpenAI发布了GPT-5我们兴高采烈地升级了。结果之前跑了三个月的Prompt在新模型上成功率暴跌了15%。因为新模型的推理方式变了之前写的那些“引导语”反而变成了干扰。我们又花了两周重新调Prompt。这就是Agent开发的常态。你的“代码”依赖于一个你无法控制的外部系统——LLM。LLM升级了你的“代码”可能就废了。四、测试与质量保障从单元测试到多维评估传统软件的测试体系非常成熟。单元测试、集成测试、端到端测试、回归测试、性能测试……每种测试都有明确的工具和方法。Agent的测试到现在都还是一个开放问题。怎么测试一个Agent的“回答是否正确”你不能用assert equals因为没有标准答案。你不能用覆盖率因为没有分支逻辑。我们目前的测试实践是“多层混合”的规则测试对于有明确答案的简单任务用正则或关键词匹配验证。比如“查订单”必须返回订单号。LLM-as-Judge用一个强大的模型比如GPT-5.5作为评判者给Agent的回答打分。这个方法有偏差但已经是最可行的了。对抗性测试专门写一些“刁钻”的输入看Agent会不会崩溃或泄露信息。A/B测试线上分流对比新旧版本的各项指标。但所有这些方法都无法替代传统测试的“确定性”。你永远不可能100%保证Agent在所有输入下都正确。你能做的只是让它在绝大多数情况下正确然后为剩下的情况设置兜底——人工介入。这个现实让很多从传统开发转过来的工程师很不适应。他们习惯了“bug-free”的追求到了Agent这里发现“bug-free”是不可能的只能“acceptable error rate”。五、调试的噩梦没有断点只有日志传统开发调试你可以设置断点单步执行看每个变量的值。你甚至可以热更新代码不用重启服务。Agent调试你能依赖的只有日志。而且不是任何日志是结构化的、带时间戳的、包含“思考过程”的日志。因为Agent的执行路径是不可预测的。你不知道它会调用哪些工具、调用几次、中间会走什么分支。唯一的办法是把每一步的“想法”记录下来。我们用的方案是LangSmith OpenTelemetry。每次LLM调用我们记录输入、输出、token消耗、耗时每次工具调用记录参数、返回值、状态每次状态变更记录新旧状态。这些数据汇集成一条trace可以回放Agent的整个执行过程。即便如此调试仍然非常痛苦。有时候你看到一个错误但trace里显示Agent每一步都“正确”——工具调用成功LLM返回合理。但你仔细看LLM的“思考”内容发现它在第三步的时候“误解”了某句话。这不是代码bug这是“理解偏差”。你没法用debugger找到它只能靠人工读日志。更糟糕的是Agent的非确定性意味着同一个错误可能不会稳定复现。你今天修复了一个问题跑测试通过了但上线后可能再次出现因为模型版本换了、温度参数有波动、或者记忆里多了一条之前没有的信息。六、运维与监控从监控系统到监控行为传统运维你监控CPU、内存、磁盘、网络、QPS、错误率。阈值设好告警配好出了问题看堆栈。Agent运维你要监控的东西完全不同。你要监控成功率——Agent有没有完成任务。这需要上面说的复杂评估不是简单的200状态码能判断的。你要监控延迟——不仅要P99还要P95、P50因为尾延迟的波动可能意味着模型排队的异常。你要监控成本——每个会话花了多少钱每个用户花了多少钱哪个意图最耗token。成本失控是Agent运维最常见的灾难。你要监控安全违规——有没有输出敏感信息有没有执行危险操作有没有被提示注入攻击你要监控模型漂移——同样的Prompt这周的成功率比上周低了可能模型悄无声息地更新了。我上个月就遇到过一个事我们客服Agent的成功率突然从94%掉到了88%。排查了两天发现OpenAI在三天前悄悄升级了GPT-4o-mini的版本新版本对中文地址的解析变差了。没有任何公告没有任何通知我们的监控就是靠每日成功率曲线发现了异常然后硬着头皮把Prompt里的地址解析示例从5个加到了20个才勉强拉回93%。这种“依赖外部系统且外部系统不可控”的特性是传统运维完全没有的。七、团队协作从产品-开发-测试到全员AI传统软件开发角色清晰产品提需求开发写代码测试验bug运维管上线。每个人有自己的专业领域边界相对清晰。Agent开发角色在融合。产品经理需要懂Prompt因为很多“需求”其实就是改一句System Prompt。开发需要懂产品因为Agent的行为不像代码那样精确你需要从用户体验的角度去判断“这样回答好不好”。测试需要懂数据因为测试结果不是简单的pass/fail而是一堆指标和分布。运维需要懂模型因为你需要判断“延迟上升是模型问题还是网络问题”。我们团队现在开周会坐在一起的人包括后端开发写工具和框架、算法工程师调Prompt和RAG、产品经理定义意图和成功标准、测试工程师建评估集和分析bad case、运维搭监控和告警。每个人都得懂一点Agent不然就没法沟通。更要命的是Agent上线后还会“自己变化”。你今天测试通过的版本跑了一周可能行为就变了——不是因为代码变了而是因为模型学到了新的模式或者记忆里积累了新的数据。这意味着“发布”不是一次性的动作而是持续的过程。八、开发心态的转变从控制到信任最后我想聊聊心态。这个可能是最根本的区别。传统开发者对系统有绝对的掌控欲。我写的代码我清楚每一步会怎么走。出错了我能修。Agent开发者必须学会放弃这种掌控欲。你没法控制模型怎么想你只能影响它。你没法确保每次调用都正确你只能提高概率。你没法预测所有边缘情况你只能建好监控和兜底。我刚开始做Agent的时候经常跟模型“较劲”。我觉得“我明明已经告诉你了为什么还错”后来我意识到模型不是不听话而是它的“理解”方式跟人类不一样。它不是在执行指令它是在“猜测”指令的意图。这种从“控制”到“信任”的转变是很多传统开发者转型失败的原因。他们试图用写代码的方式写Prompt试图用debugger调试模型试图用断言验证输出。当他们发现这些都行不通时就会觉得“Agent是个不靠谱的东西”。但Agent的能力上限远高于传统程序。它可以处理模糊的、开放的、需要推理的任务。它可以用自然语言跟你交互而不是按钮和表单。它可以调用任何工具而不是预先写好的死逻辑。代价就是你没法完全控制它。这就像养一个孩子。你没法像编程一样给他输入指令然后期待输出预期结果。你只能教育他、引导他、给他边界然后相信他大部分时候会做出正确的选择。偶尔他会犯错你纠正他他下次可能会好一些。但你永远不可能让他100%不犯错。我花了一年多才接受这个现实。现在我跟Agent的关系更像是“搭档”而不是“工具”。我会跟它说“这次做得不错”也会批评它“你刚才那个回答不太对”。我不会因为它的错误而愤怒因为我知道这不是它故意的——它只是概率上走到了错误的分支。九、写在最后你准备好转型了吗写到这里我问自己一个问题如果让我回到两年前重新选择一次我还会从传统后端转到Agent开发吗我的答案是会。不是因为Agent开发更轻松——它确实更累、更烦、更不确定。而是因为它让我重新思考了“编程”这件事的本质。传统编程是“告诉计算机怎么做”Agent编程是“告诉AI想要什么”。前者是命令后者是沟通。前者追求精确后者追求理解。前者关注逻辑后者关注意图。这是一个完全不同的思维模式。它让我学会了模糊容忍、概率思维、持续迭代、与不确定性共处。这些能力在过去十年的传统开发里我几乎没有练过。当然如果你是一个追求“确定性”、喜欢“控制”、享受“bug-free”的人Agent开发可能会让你抓狂。它不是适合所有人。但如果你愿意接受挑战愿意放弃一部分控制权去换取更大的能力上限那这条路值得走。最后我想对那位写了五年Java的新同事说别灰心你不是一个人。我们都在这条路上摸索着往前走。上次那个模型不听话的问题我们后来加了事实核查和输出过滤现在效果好多了。虽然偶尔还会犯傻但至少我们知道为什么会犯傻了。

更多文章