资讯动态

硬编码与Agent怎么选?从本质差异到技术选型完整指南

发布时间:2026/10/20 13:52:44 来源:尧图企业网站定制
得先承认这个标题里的问题问得特别好而且问到了很多团队正在纠结的点上。我最近在技术社区里频繁看到类似这样的争论有人汇报说要做 Agent被技术负责人当场问住——“你告诉我你说的这些事用 if-else 加几个接口调用能不能实现”也有人面试时被追问“既然我能用规则匹配把用户意图列清楚为什么还要花钱花时间上大模型”如果你也处于这种状态——感觉到硬编码方案哪里不对劲但又说不出 Agent 到底“多出来”了什么价值那这篇内容应该能帮上忙。我不会站在“Agent 万能论”那边去吹也不会全盘否定硬编码。我会从工程落地的角度把两者的本质差异、适用边界、真实成本和踩坑经验拆开讲清楚最后给你一张可以直接拿去用的技术选型对照表。读完之后你再面对“为什么要做 Agent”这个问题至少能给出一个有理有据、经得起追问的答案。1. 先把问题问清楚硬编码到底能干哪些活1.1 硬编码从来没有错过在讨论 Agent 的必要性之前我们得先给硬编码一个公道。很长一段时间里硬编码规则是业务系统最可靠的基石而且直到今天它依然是绝大多数系统的核心骨架。订单超时自动关闭、库存扣减、审批流的节点判断、接口参数的格式校验……这些场景有一个共同的特点逻辑边界完全确定输入输出可以被严格枚举。举一个很典型的例子订单支付超时关闭硬编码的实现可能就是def check_order_expired(order): expire_seconds 30 * 60 # 30分钟 if now() - order.created_at expire_seconds and order.status PENDING: close_order(order)这段代码的优点是明摆着的确定性执行、零额外成本、可单测、出问题能迅速定位。它的逻辑就摆在那里任何工程师一看就懂任何一个输入都有唯一确定的输出。在这种“规则明确、路径固定”的问题上你引入 Agent 不仅没有必要而且是在给自己挖坑——大模型输出带随机性响应有延迟调用还要花钱纯属给自己找麻烦。我见过太多团队犯这个错误。业务方提了一个模糊需求开发同学第一反应就是“我们用大模型来解决”结果模型上线之后输出飘忽不定用户问同样的问题两次拿到不同的答案投诉率比原来还高。最后老老实实改回硬编码。所以结论先放在这里硬编码在确定性问题上是牢不可破的它从来不是“错的”Agent 也不是来取代它的。1.2 那 Agent 到底多出来了什么如果硬编码在确定性问题上永远是优选那 Agent 存在的合理性只能来自另一个方向当问题变得“不确定”的时候。你需要先理解一个关键差异硬编码解决的是“规则确定、路径固定”的问题而 Agent 解决的是“目标确定、路径未知”的问题。这个区别用大白话说就是——硬编码像一张地铁线路图你告诉它起点和终点它一定给你一条固定的、预先铺好的路线绝不会跑偏。但它无法应对“前方修路”“临时封站”这些意外情况因为它只知道轨道上那些事。Agent 更像一个出行导航系统。你给它一个目的地它不知道路上会遇到什么但它可以根据实时路况自己决定走哪条路走不通还能重新规划。它的“智能”不在于它知道所有答案而在于它在面对未知路径时能动态做出决策。这个区别落在工程上就是“谁来承担决策责任”的问题。硬编码系统里决策逻辑是程序员预先写死的——用户这句话对应什么动作早在代码编写时就被定死了系统只是机械地执行。而到一个 Agent 系统里决策是在运行时由模型根据当前输入和上下文临时做出的——用户这句话可能对应什么意图该调用哪个工具任务应该拆成几步是模型在每一轮推理中实时判断的。这也就是“为什么一定要做 Agent”这个问题真正的答案如果一款软件需要在运行期应对不可预期的输入、动态规划完成路径那么要么程序员在代码里穷举所有可能性这在开放问题面前不可能要么把决策权下放给一个能推理的模型。Agent 不是让代码变得更强而是把“决定的环节”从人脑搬进了系统运行期。2. 硬编码在真实场景中是怎样一步步失控的2.1 从客服机器人的三个版本说起要理解硬编码的边界在哪最好的方式就是看一个具体的演进过程。我来用一个我实际参与过的客服机器人项目举例这个例子非常典型。第一个版本是最朴素的硬编码。运营团队定义了一批“关键词-回复”规则用户消息里包含“退款”就回复退款流程包含“发货”就回复物流信息。实现方式也最简单KEYWORD_RULES { 退款: 亲退款流程是……, 发货: 您的订单已发货……, 发票: 发票开具说明……, } def reply(user_message): for keyword, answer in KEYWORD_RULES.items(): if keyword in user_message: return answer return DEFAULT_REPLY这个版本的优点是简单直接上线的第一天还挺好用。但运营同学很快就发现了问题用户是不会按预定关键词说话的。“钱怎么还没退”里面没有“退款”“东西发出来没有”里面没有“发货”。第一个版本基本只能挡掉大约三成的问题剩下七成全部转人工。第二个版本团队开始补充规则。为了覆盖“钱怎么还没退”我们给“退款”这个意图补了一连串同义词和正则表达式比如“没退”“退钱”“到账”“什么时候还”……这个版本的效果确实好了很多能覆盖六成左右的问题但代码也开始变难看了一个关键词对应的正则就有七八条运营每次改一次规则都得拉上开发提心吊胆地回归一遍。真正压垮第二个版本的是一个极其正常的用户问题“我上一单的退款怎么还没到我明明已经把货寄回去了。你们到底什么时候处理”这句话里的关键词同时命中了“退款”“寄回”“处理”“到账”多条规则我们的程序同时返回了四个不同流程的回复直接把用户整懵了。规则的组合冲突开始指数级增长完全没法维护了。第三个版本我们终于想明白了问题出在哪用户用自然语言表达意图的方式几乎是无限的但规则系统只能覆盖有限个模式。你每补一个规则其实就是在承认一件事——还有更多你没枚举到的表达方式正在漏进来。这种“补丁式的穷举”是不可能走通的你需要的是理解语义的能力而不是更多的关键词。2.2 规则系统的“穷举陷阱”我前面说的案例背后其实是一条很硬的规律叫做组合爆炸。在真实的自然语言场景里一个意图可以被无数种句式表达而这些表达之间还会相互组合、相互干扰。假设你的业务里有 N 个意图、每个意图有 M 种典型表达方式那你的规则系统至少需要维护 N×M 条规则。但这还是理想情况因为现实中的用户根本不会按“典型方式”说话加上语气词、口语、错别字、省略语真实覆盖成本会远远超过这个乘积。更致命的是规则之间还会产生冲突。一个句子可能同时触发两个意图的规则优先级怎么定是关键词命中次数多胜出还是规则列表靠前的胜出每一次调整都可能连带影响其他规则。一旦规则数量超过几十条系统的行为就开始变得不可预测你就无法回答最简单的问题“这个用户到底会收到什么回复”这就是我常说的“穷举陷阱”硬编码本身没有错错的是用硬编码去处理“开放问题”。什么是开放问题就是输入空间无法预先枚举的问题。自然语言是开放问题识别一张图里有没有违规内容是开放问题判断一篇合同里甲乙双方责任是否对等也是开放问题。这些问题不是“规则没写好”而是“规则这种形式本身就不适用”。但注意我说的是“不适用”不是“不能用”。如果业务场景极其单一比如用户只会从三个按钮里选一个触发回复那硬编码绝对绰绰有余。判断标准很简单——数一数所有可能的输入方式如果边界清晰可枚举就用硬编码如果连你自己都说不清用户会怎么问你再努力写规则也追不上问题的扩散速度。3. Agent 的本质价值把“决策”和“执行”分离3.1 决策-执行分离很多人理解错了业内常说 Agent 的核心是“规划Planning 工具调用Tool Use 记忆Memory”这些描述都对但我觉得都不够本质。Agent 相比传统程序最底层的变化是把“决策逻辑”从“执行逻辑”中拆了出来让前者由模型承担后者由代码承担。传统程序的写法是什么样的一个函数它的输入决定了输出if-else 本身就是决策逻辑执行过程是同步走的。Agent 模式完全不一样它的运行结构是一个循环接收用户目标可能是自然语言也可能是一个半结构化的任务描述模型理解目标结合当前环境信息决定下一步做什么选择一个工具并传入参数这段代码是确定性执行的把工具的返回结果拼回上下文模型再次判断继续执行、调整方案、还是任务已完成这个循环就是所谓的Agent 运行主循环Agent Loop。硬编码也有决策但决策和执行是揉在一起的路径是固定的Agent 把决策这一层独立出来之后系统就获得了在运行期“改主意”的能力——这次调用工具失败了模型感知到错误信息可以换一个工具重试这在传统代码里需要程序员提前把所有故障分支都想好而在 Agent 里这是模型推理的自然结果。理解这一点之后你就明白了为什么 Agent 系统这么强调“工具”这个组件。因为模型本身不负责真正干活它只负责“决定做什么”而真正的“执行动作”比如查数据库、调外部 API、访问文件由工具完成。工具做得越规范、边界越清晰Agent 能执行的动作就越可靠。3.2 三个硬编码做不到的核心能力把决策和执行分离之后Agent 系统就获得了一些硬编码结构上就不具备的能力。我认为最值钱的三个是能力一接受非结构化输入。硬编码系统通常要求输入是结构化的字段定义得明明白白才能进入后续逻辑。Agent 系统可以直接吞下未经过滤的自然语言、PDF 文档、图片扫描件。比如用户丢过来一段语音转写文字说“帮我把这几件事按紧急程度排一下”Agent 可以理解语义、做信息抽取再调用待办工具把它结构化。这不是“替换规则”而是“凭空增加了解析能力”。能力二动态任务规划。对于一个复合目标比如“把这封客户反馈邮件总结成工单并判断应该转给技术还是售后然后起草一封回复草稿”硬编码需要你预先画好流程图每一步都是固定套路。Agent 则会把任务拆解成多个步骤每一步自己决定调用哪个工具先用邮件解析工具再调文本摘要工具再根据摘要内容做分类判断再调用写作工具生成草稿。这个拆解过程不是程序员预先写好的而是模型根据目标现场生成的。能力三从错误中恢复。这是被很多人低估的一点。传统程序如果走到了一个没有被预定义的分支通常行为就是抛出异常、崩溃、或者返回一个兜底内容。Agent 不一样它可以理解工具返回的错误信息然后调整策略。比如调用天气 API 失败它可以判断“是不是城市名格式不对”然后重新格式化参数再调一次。这在硬编码里对应的是什么是你要为每一个可能的失败场景都写好 try-catch 和补偿逻辑。这对开放的失败场景来说几乎是不可能穷举的。3.3 Agent 不等于 Chatbot这个误区必须纠正每次聊到这里总有人会问那我不就是接一个大模型 API 做个聊天框吗注意这还真不是一回事。聊天界面 大模型 API 只是一个“自然语言对话层”它没有工具、没有行动能力、没有状态管理本质上就是一个更聪明的问答库。你问它“帮我关掉订单”它如果只能回复一段文字说“好的你可以点击这里来关掉订单”那它就不是 Agent——因为它没有真的去执行“关掉订单”这个动作。Agent 的关键标志只有一个它必须能通过工具对现实系统产生影响。用户说“帮我关掉订单”Agent 调用订单系统的关闭接口订单真实状态被改变然后把执行结果反馈给用户。这中间必须存在“意图理解 → 工具选择 → 参数抽取 → 真实执行 → 结果反馈”的完整闭环。如果这个链路里缺少了真实执行环节你做的就不是 Agent充其量是个“带会话功能的搜索框”。所以判断一个项目要不要做成 Agent有一个很直接的试金石用户的目标最终需要落到多少种真实世界的操作上如果需要操作的对象广泛且不可预知比如“处理我所有待办”“帮我安排一周行程”那必须 Agent如果操作对象就两三个固定接口比如“查余额”“付款”那一个意图分类器加硬编码调用就足够了。4. 什么时候硬编码真的够用什么时候必须上 Agent4.1 先看这张技术选型决策矩阵聊完原理该上点能落地的工具了。我在做技术评审的时候遇到“要不要上 Agent”的争论从来不辩论只看四个维度。这四个维度列一张表答案基本就自己浮现出来了。判断维度偏好硬编码确定性方案偏好 Agent大模型方案输入可枚举性输入是枚举值、固定格式、有限集合输入是自然语言、非结构化文档、开放文本决策逻辑稳定性业务规则明确变化频率低规则模糊、需要理解语义或动态判断结果可预期性要求 100% 确定性不接受偶然偏差允许一定的灵活性和概率性输出路径灵活性步骤固定流程图稳定不变目标明确但实现路径需要动态规划故障恢复要求所有异常分支能预先枚举失败场景不可穷举需要自适应调整怎么看这张表如果前四项你全都落在左边那硬编码是绝对优选甚至不应该有任何犹豫。如果你的场景有一项甚至多项明显落在右边而且这种“不确定”是需求里天然存在的硬编码就会越来越吃力这时候再考虑 Agent才是理性的决策。我举个具体的例子。客户工单分类这件事如果你们的客户来源就三种邮件、电话、网页表单那规则分类绰绰有余——写几个关键词正则就够了。但如果客户来自天南海北表达方式千奇百怪分类体系还经常调整你再让运营去维护一套关键词库基本是在用人力对抗无限膨胀的语义空间。这时候 Agent 才能真正体现出价值——模型理解的是“语义”而不是“关键词”分类体系的调整只需要更新描述不用重写规则。4.2 警惕“被 Agent 化”的陷阱我见过不少项目不是“需要 Agent”而是“为了 Agent 而 Agent”。最典型的表现是业务流程里明明每一步都是固定的偏要在中间塞一个大模型结果就是成本上升、延迟翻倍、输出还要靠后面接一堆保底逻辑来兜。最后系统的整体可靠性不升反降。为什么会这样很多团队是被市场热度和 KPI 裹挟的。老板说“别人都在做 Agent我们也得有”于是一个本该用定时任务解决的问题被包装成了“智能调度中台”。但技术选型不该服务于叙事只能服务于业务问题的本质。如果业务处理对象抽象层次很低比如就是“触发了某个条件 → 执行某个动作”这类模式无论套多漂亮的壳内核都还是状态机。你不需要一个模型来帮你思考状态 A 下收到消息 X 该干嘛状态 B 下收到消息 Y 又该干嘛。这些分支你是能预先画干净的画不干净是因为业务没梳理清楚不是因为你缺一个 Agent。我建议所有准备立项做 Agent 的团队先在需求文档里回答三个问题第一用户的输入空间到底是不是开放的有没有办法枚举第二任务的实现路径到底是固定的还是需要根据上下文动态调整第三系统的失败模式能否预先穷举如果这三个问题的答案都是“可以预先定义”那这个项目本质上就不是 Agent 项目硬编码或者状态机才是更优解。这个结论能帮大量团队省下不必要的模型调用费。4.3 混合架构才是真正的常态说完了纯硬编码和纯 Agent必须强调一下真实生产环境里的最优解几乎永远是混合架构——确定性流程用代码管语义决策交给模型管中间用工具接口衔接。这是我认为本篇文章最重要的实践经验。很多团队上 Agent 容易走极端要么整条链路全塞给大模型结果不可控要么因为模型不稳定就全盘否定。但成熟的做法是把业务流程里“能确定的都先写死”只把“真正需要理解的缝隙”留给 Agent。举个例子。一个报销单审批 Agent最稳妥的做法是单据上传和字段校验用传统代码做格式不对直接打回不必经过模型。系统提示词让模型只做一件事读取报销单里的费用类型和发票金额按规则归类并把结果输出成固定 JSON。审批策略比如金额超过多少要升级到主管审批用硬编码的规则表实现模型不参与判断。只有“理解单据内容”这个环节用大模型因为它真的需要读 PDF 和图片。这种拆法模型只负责它擅长的非结构信息识别决策规则依然在代码里稳定可控好测试好审计。你完全不用为了一个 Agent 把整条业务逻辑都押在概率上。5. 如果真要上 Agent有哪些不踩坑的实操建议5.1 最小可用 Agent 的标准搭建步骤如果你已经判断清楚项目确实有 Agent 化的必要我分享一套这个领域里比较成熟的最小落地路径。这套步骤我拆过不少项目基本可以无脑复刻第一步定义工具接口。这是最重要的一步没有之一。需要先梳理清楚Agent 能对这个世界施加哪些动作每个动作的入参、出参、错误码是什么比如订单 Agent 至少要有“查订单状态”“取消订单”“修改收货地址”三个工具。每个工具都需要写清晰的描述说明“这个工具是干什么的什么时候该调用它”。模型不是神它看到哪件工具描述越清楚越可能做出正确选择。第二步写系统提示词。核心是给模型框定行动边界可以调哪些工具、在什么情况下用什么工具、输出必须遵循什么格式。这里最容易犯的错是提示词写得太开放模型什么都能干结果什么都干不好。目标不是让模型“变得更聪明”而是让它在你的业务范围内“变得规矩”。第三步实现主循环。核心结构可以用一个简化的伪代码来表达def run_agent(user_goal): memory [{role: system, content: SYSTEM_PROMPT}, {role: user, content: user_goal}] for step in range(MAX_STEPS): # 必须限制最大步数 response llm_chat(memory) # 模型决策 action parse_action(response) # 解析出工具调用意图 if action.type finish: return action.answer result call_tool(action) # 执行工具结果是确定性代码 memory.append({role: assistant, content: response}) memory.append({role: tool, content: result}) # 模型在下一轮根据工具结果继续推理第四步加入记忆和上下文。目的是让 Agent 在多轮交互中不丢状态比如用户中途补充了一句“刚才那个订单不要了”Agent 要能理解“刚才”指代的是哪个订单。这一步的复杂程度取决于业务有些场景只需要一个 session 级别的缓存有些则需要落到向量数据库做长期记忆。第五步搭评估集。这可能是整个落地过程中最容易被省略、但最不该省略的一步。准备 30 到 50 个真实业务问题作为测试集每个问题标注出期望的工具调用序列和最终结果然后跑回归测试。没有评估集的 Agent 项目等于在蒙眼开车改一版提示词也不知道是变好了还是变坏了。5.2 成本和延迟怎么控制Agent 模式有一个硬伤就是比单次模型调用贵、比硬编码慢。原因是用户的一个请求内部可能经过了多次模型推理。这是架构性质决定的但业内也有一些成熟的缓解手段第一能用小模型就别用大模型。不是所有环节都需要最强的推理能力。“意图粗分类”这类简单任务用一个参数较小的模型就够了只有真正复杂的规划步骤才用更大规模的模型。我见过不少团队把全部环节都交给大模型成本翻了几倍效果也没有肉眼可见的提升。有条件的话可以考虑一个轻量模型做意图路由一个强模型做复杂规划两者配合。第二给每次调用加缓存。把“用户问题 上下文摘要”的 hash 作为键把模型输出缓存起来。同一个问题第二次进来直接命中缓存既省钱又省时间。对于客服、问答这类高频场景缓存命中率往往高得惊人我实测过不少项目缓存能将成本削减一半以上。第三限制最大迭代步数。这一步是保命用的。Agent 一旦钻牛角尖可能会反复调用同一个工具循环停不下来。通常在系统里设置一个合理上限比如 5 到 8 步达到上限就强行终止返回当前已收集的信息再记录一次错误日志供排查。这能保证最差情况下用户也只是等了几秒而不是无限循环烧 token。5.3 用什么标准判断 Agent 做得好不好Agent 项目最闹心的是你怎么知道它变好了硬编码项目可以跑单测断言输入输出相等就行。Agent 输出是概率性的同一句话跑两遍结果可能不一样没有一模一样的断言可以做。我的经验是分级评估。第一级是最硬性的指标工具调用成功率。系统调用了错误的工具或者工具参数格式不合法这一类属于硬错误必须朝向 100% 收敛。第二级是任务完成率就是最终结果是否达成用户目标这个可以人工标注也可以借助一个更强的模型做评测。第三级才是体验层面比如回复是否自然、语气是否友好这类可以放宽要求不必追求完美。都跑通了之后再推进实时可观测性。生产环境里的 Agent日志一定比常规系统复杂——它涉及多轮模型调用、多次工具执行。建议每次运行都记录一条 trace包含输入、每一轮的模型输出、工具执行结果、最终输出。这样线上出问题时你才能快速回放出“它在哪一步开始跑偏”。没有 trace 数据的 Agent 运维基本就是大海捞针。6. 常见问题与排查技巧实录6.1 Agent 陷入死循环怎么办这是 Agent 项目上线后遇到的第一大问题概率极高。症状是用户一个简单请求系统却反复调用同一个工具输出日志一拉铺满了相似的调用记录Token 消耗数字十分感人。直接的解决手段有两个。一是前面提到的最大迭代步数这是硬性兜底。二是改变工具返回错误的方式。如果 Agent 调用的工具返回的错误信息是“调用失败请重试”模型很可能会继续调用同一个工具直到达到上限。更好的做法是返回结构化错误同时明确说清楚为什么失败比如“ERROR_CITY_NOT_FOUND: 城市Beijingn不存在请检查拼写”。模型看到这种带原因的错误提示更倾向于调整输入或者换工具而不是盲目重试。6.2 模型乱调用工具幻觉问题怎么治模型在拿不准的时候会脑补出一些根本不存在的工具名或者参数。比如业务里明明只有三个工具它偏偏调用了一个“send_email_to_boss”。这类问题治本的方法是工具白名单机制在代码层校验模型输出的工具名不在白名单里直接拦截并返回一条错误信息让模型自我纠正而不是真的尝试去执行一个不存在的操作。除此之外工具描述也要写得足够仔细。我建议每个工具描述里都写清楚工具的触发场景、适合的输入格式、典型示例、不能干什么。模型选择工具依赖的就是这些描述。描述含糊的后果就是模型靠猜猜就容易错。6.3 输出不稳定这次对下次错算不算 bug算但属于 Agent 的固有特性。应对措施有三个层面。第一把推理温度调低比如设到 0.2 以下模型的随机性会显著下降。第二对模型输出做严格的格式约束要求它必须输出 JSON 并携带指定字段不达标就让它重新生成代码层做 schema 校验。第三也是我最推荐的关键路径上不要依赖模型做最终决定而是让模型输出“候选”由确定性代码做“终判”。6.4 Agent 效果变差了但没改过代码这是错觉吗不是错觉。这种诡异情况通常有两个来源。一个是上游模型版本发生了升级或降级同一个提示词在模型更新后行为可能飘移导致效果波动排查方式就是关注模型本身的版本发布动态并在评估集上定期回归。另一个是工具行为变了比如外部接口返回的数据结构与之前不一致把模型判断带偏。解决办法是在工具层做好输入输出数据格式的兼容与隔离不要让自己模块的行为被外部接口的变动直接冲击。我把上面这些问题整理成一个速查表方便直接对照症状可能原因优先排查项反复调用同一工具跳过对应流程环节错误反馈不够明确未提示具体失败原因调用不存在的工具白名单缺失 / 工具描述含糊在代码层做白名单校验完善工具描述模型返回格式乱提示词约束不足 / 温度过高强制 JSON Schema调低温度效果随版本波动模型升级 / 工具数据变动在固定测试集上回归做好工具层隔离某类问题持续出偏差测试集未覆盖该场景补充对应的评估用例迭代提示词总结一下实操心态Agent 项目不像传统开发不存在“写完就稳了”的舒适状态。它在生产环境里更像一个需要持续调参和观察的“活系统”。我记得第一次把一个 Agent 项目推上线的时候心里特别没底因为习惯了“代码写完有确定性结果”的节奏对这种概率性输出天然排斥。后来真正跑起来才明白它有价值不是因为它聪明而是因为它解决了我无法预写规则的那部分问题。如果你仍然在纠结“为什么要做 Agent”我的建议是先别急着谈理想、谈架构把你业务里能确定的部分都列出来那些部分老老实实用代码实现只把“无法预写的缝隙”留给 Agent你自然就能判断这个技术对你到底有没有用。最后再分享一个我一直在用的判断标准出问题的时候如果补规则能解决就说明它本来就不需要 Agent如果补规则已经走不通了那才轮到 Agent 登场。这个标准帮我避免了很多次无意义的方案争论也帮你守住边界不盲目跟风。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑