从后端到 Agent,编程思维需要重新格式化
从传统后端转向 Agent 开发,最需要改的不是技术栈,而是思维方式——确定性逻辑与概率性输出是两种完全不同的世界。
最近面试了几家公司,聊下来发现一个有意思的现象。
对方问 "Agent 和传统后端的区别是什么",我答了一堆技术细节——MCP 协议、ReAct 循环、tool execution 这一套。面试官点头,但我觉得他没被触动。
后来跟一个做 Agent 框架的朋友喝酒,他说了句话让我愣住:
"写后端和写 Agent 是两个物种。你写后端的直觉,在 Agent 里全是反的。"
回去想了三天,觉得他说得对。而且奇怪的是,这种思维层面的差异,几乎所有 Agent 教程里都只字不提。
确定性,是最大的思维包袱
写后端最底层的假设是什么?给定输入,产出确定的输出。
def calculate_price(items):
total = sum(item.price for item in items)
return total * 1.13 # 加税
跑一万次,结果都一样。单元测试能写,断言能写,TDD 能玩。这是后端安身立命的底气。
Agent 完全不是这个逻辑。
def search_and_summarize(query):
# 模型决定要不要搜索
# 模型决定搜索什么关键词
# 模型决定怎么组织结果
return result # 每次可能都不一样
同样的 query,今天跑和明天跑,结果可能差一截。不是 bug,是模型换了个思路。
我做自己的项目时踩过这个坑。一开始习惯性写了一大堆断言来"验证" Agent 的行为,跑 CI 的时候疯狂挂掉。后来才意识到——你没法用确定性的工具去测一个非确定性的系统。
后端出身的第一个思维关要过的就是这个:从"断言输出"变成"约束范围"。不是去测 agent 会返回什么,而是测它返回的东西"在不在合理范围内"。
错误的形态变了
后端的错误是显式的。抛异常、返回 500、NPE、OOM。你写 try-catch,写 fallback,写熔断降级。错误来得很干脆,你处理得也干脆。
Agent 的错误是隐式的。
前阵子写了一个 Agent,让它查三个数据源然后综合给出结论。它跑了,没报错,返回了一段看起来很正常的文字。但我仔细一看——它只查了两个数据源,第三个它"忘了"。不是报错,不是超时,是模型自己觉得"两个够了"。
这种错误最可怕的地方在于:系统告诉你一切正常,但结果是错的。
后端的错误处理思路是"检测到异常→处理异常"。Agent 的思路得变成"检测到没有异常→还是可能有问题"。这就很反直觉了。你需要加 Validation Agent、加 Self-Consistency Check、加 Output Guardrails。这些概念在后端世界里几乎不存在。
测试,是最痛的认知跃迁
有后端经验的人上手 Agent 时,第一反应肯定是写测试。
我当初也是。
琢磨了半天,发现常规的单元测试几乎全部失效。你说 mock LLM 的返回?那测的是我 mock 的逻辑,不是 Agent 的逻辑。你说端到端跑一遍?一次跑一分钟,一次几毛钱,跑一千次 CI 谁扛得住。
后来圈子里学到的一套做法是 eval-driven development,但是跟 TDD 完全两码事。
TDD 是:写测试 → 写代码让测试通过 → 重构。
Eval 是:定义一组评测场景 → 跑 Agent → 人工看结果 → 改 prompt/代码 → 再跑。
每次跑 eval 都像是在做实验,不是在跑测试。你得接受一个事实——你的 Agent 没有"通过"一说,只有"在当前这组场景下表现还行"。
真实的 Agent 团队是怎么做的?据我所知,大致分三层:
- 烟雾测试:跑几个核心场景,确保能走通,Agent 没有卡在死循环里
- 场景集评测:50-200 个覆盖主要路径的 case,人工或 LLM-as-Judge 评分
- 线上监控:日志里捞真实用户的 query,定期回放看 Agent 的表现趋势
没有"测试覆盖率 90%"这种 Metrics。有的只是"这一周 Agent 的表现分是 8.5,上周是 8.2,好像退步了"。
这让我一个后端出身的人很不舒服。但习惯之后发现,这其实更接近真实世界的运作方式——你永远没法证明 Agent 是"对的",只能不断收集证据表明它"还没错"。
状态管理,从 SQL 到上下文窗口
后端的国家管理有一套成熟套路。数据放数据库,内存里缓存热点数据,分布式场景下用 Redis 存 session。状态是显式的、可查询的、可回溯的。
Agent 的状态呢?上下文窗口。
但上下文窗口不是数据库。它是"写进去之后可能自己忘了"的存储。
举个例子。Agent 在处理用户请求时,先查了一下用户信息,然后把结果放进了上下文。过了几轮对话,Agent 可能已经把那段信息挤出了窗口,或者虽然还在,但模型在生成的时候没注意到。
你做后端的时候永远不会担心"忘掉数据库里的一条记录"。但做 Agent 你要担心它"忘了自己刚才查到了什么"。
这迫使 Agent 架构跟后端产生了一个根本性差异:你需要显式地把关键状态"吐出来"写进外部存储,而不是依赖 Agent 自己记着。
我目前试的模式是:每个 Agent 步骤完成后,把关键决策和中间结果序列化到一个 State Store(目前用的 Redis),下个步骤开始时先把关键状态读回来注入上下文。相当于给 Agent 做了个"人工记忆刷新"。
听起来很蠢是吧?就像是你在帮一个金鱼记事情。但没办法,这就是当前 LLM 的 State Management 现状。
调试,从断点到思维链
调后端代码:打断点 → 看变量 → 找到 bug → 改之。
调 Agent:翻日志 → 看 LLM 返回的 JSON → 猜它为什么选择了这个工具而不是那个 → 改 prompt → 再跑一次 → 可能又变了。
心态经常从"我一定行"变成"大概就这样吧"。
说实话,这快一年下来,我唯一觉得好用的调试方法还是 Anthropic 提的那个"添加详细 logging"。把每次 LLM 调用的完整请求和响应都打出来,然后把关键的思维链步骤可视化。后面无论是自己做回溯分析,还是拿给 LLM 帮你看,都离不了这堆日志。
后端出身的习惯是"减少日志,性能优先"。做 Agent 你得反过来——日志就是你的调试器。
去年有个团队分享过一个数字:一个生产级 Agent 的单次请求,日志量是传统 API 的 50-100 倍。我觉得这个数不夸张。
所以,思维怎么"格式化"?
琢磨了一段时间,我觉得核心心态转变可以归纳成三条:
从确定性到概率性。 别写断言,写范围。别想"对不对",想"稳不稳"。你的 Agent 跑一百次,八十次达到预期,这个 Agent 就"还不错"。
从显式错误到隐式错误。 try-catch 不够了。你需要一层层的 Guardrails,像洋葱一样裹住你的 Agent。最外层拦截不安全输出,中间层检查逻辑一致性,最内层才是正常逻辑。
从测试到观测。 别死磕"一次跑对",搞一套好一点的监控和回放系统。Agent 的质量是观测出来的,不是测出来的。
我知道有人会觉得这些说法太悲观——"Agent 明明每天都在进步,你说得好像它不能用一样"。
恰恰相反。我觉得承认这些差异,反而能让 Agent 的技术栈更务实。你不必用后端的标准来要求 Agent,也不必因为 Agent 达不到后端的确定性就否定它。它本来就不是后端。
它是一套新的范式。你只是还没学会怎么跟它相处。
好,聊到这儿。
评论
发表评论