🛠️ 手搓 Agent vs 成熟框架
工程实践中,为什么有人宁愿「手搓」Agent,也不用 LangChain、LlamaIndex 这些成熟框架?一句话:框架不是问题,「不理解就依赖」才是。
一句话答案
成熟框架(LangChain / LlamaIndex 等)在POC 阶段确实能省大量样板代码:工具注册、ReAct 循环、对话历史、tracing、callback……几行就能跑通一个 Agent,速度快、心情好。
但一旦进入生产环境,三个痛点会逐渐暴露:
- 抽象层太多,出 bug 时 stack trace 四五十层,排查困难;
- 版本升级频繁带来 breaking change,线上稳定性受制于人;
- 通用设计产生隐性开销,高流量下变成真实可见的延迟和成本。
手搓(自己写核心逻辑)的最大价值是完全掌控:链路透明、好观测、好裁剪、不受框架升级影响。所以最务实的策略通常是:
框架的价值:为什么一开始大家都想用
从零搭一个 Agent,要做一大堆重复且大同小异的事情:
- 定义工具格式,让 LLM 正确理解每个工具是什么、需要哪些参数;
- 解析 LLM 返回的工具调用结果,提取参数;
- 维护对话历史,保证消息不丢、顺序不错;
- 处理工具调用失败的重试逻辑、异常处理;
- 接入向量数据库、文档解析等知识检索能力。
框架的价值就是把这些重复工作封装好,你直接用,不用每次都造轮子。LangChain 里一个 @tool 装饰器就能注册工具,AgentExecutor 把整个 ReAct loop 封装进去,还内置了 tracing、callback、记忆管理。早期上手快是真实优势。
注意:LangChain 的 AgentExecutor 在新版中已被废弃,官方推荐迁移到 LangGraph。这本身也印证了后面要说的「框架升级痛点」。
痛点从哪来?三个阶段逐渐浮现
框架的问题不是一开始就暴露的,而是随着项目推进逐步浮出来。可以用下面这条曲线理解:
痛点 ①:抽象层太多,排查困难
当 Agent 在特定场景输出错误工具参数,你开始排查。业务代码只有五十行,但报错 stack trace 有四五十层,一直追到框架内部。
🚗 手搓 Agent:老式汽车
出问题掀开引擎盖,自己就能看到哪根管子漏油。链路透明,根因定位快。
一眼定位🚙 框架 Agent:现代豪华车
掀开引擎盖是一堆看不懂的 ECU 和电子设备,只能去 4S 店连诊断仪。
层层追踪框架的抽象层让你排查问题时需要穿透那些「你没写、也不完全懂」的层,这是实实在在的认知负担。LangSmith 能追踪调用链,但它解决不了框架本身的抽象问题。
痛点 ②:版本升级带来 breaking change
线上跑了几个月,某次依赖升级,LangChain 改了接口,代码直接报错。你要么回滚,要么把代码改到兼容新版本,可能涉及十几处修改。
🧱 手搓:接口自己定
自己写的接口不会突然变。依赖只有底层 LLM SDK,相对稳定,生产环境长期运行更可控。
📦 框架:房东政策随时变
框架为了通用性经常重构,接口、参数、返回值格式都可能变。核心业务逻辑建立在第三方框架上,稳定性受制于人。
LangChain 后来采用了语义化版本控制,稳定性有所改善,但早期频繁的 breaking change 已经让很多团队对框架依赖保持警惕。
痛点 ③:通用设计带来的隐性性能开销
到了规模化阶段,你开始关心 Agent 的调用延迟。仔细 profile 之后,发现框架内部在每次调用时都做了你根本不需要的事:序列化中间结果、触发一堆 callback、记录详细日志……
这些逻辑是框架为了通用性设计进去的,对你的具体场景没有用,但每次调用都在跑。高流量下这些隐性开销累积起来,变成真实可见的延迟增加和费用浪费。
手搓的本质优势:完全掌控
说清框架的痛点之后,手搓的价值就显而易见了。它的核心优势就是三个字:完全掌控。
🔍 层面一:链路透明、可观测性好
每一行代码你都知道在干什么,可以在任意位置加日志、断点、监控。线上出了问题靠日志复现故障是最快的方式,链路越清晰,定位根因越快。
✂️ 层面二:精确裁剪、没有多余开销
只写你确实需要的逻辑,不带通用性包袱。工具调用、对话历史维护、错误重试,每一块都按具体场景实现,性能优化空间完全在自己手里。
🛡️ 层面三:稳定可控、不受升级影响
自己写的接口不会突然变,没有来自外部的 breaking change。依赖只有底层 LLM SDK,生产环境可以长期稳定运行。
什么时候用框架,什么时候手搓?
这不是非此即彼的选择,判断的关键是项目所处的阶段和对控制权的需求。
⚡ 用框架:速度快
目标只是跑通流程、验证 idea,几乎感受不到副作用。LangChain 几十行就能搭一个能用的 Agent,两周工作能缩短到两天。
- 目标:把流程跑通,不是优化;
- 团队刚接触 Agent,框架能少踩基础坑;
- 周边工具(文档解析、向量检索)可以直接用框架生态。
🐛 拆核心逻辑:排查 bug
当奇怪 bug 出现,stack trace 追到框架内部,你开始怀疑人生。这时应该把手伸进核心逻辑,把 ReAct 循环、工具解析、状态维护这几块拿回自己写。
- 业务代码五十行,报错栈四十层;
- 不知道问题出在自己代码还是框架版本;
- callback 触发时机不透明。
🚀 关键路径手搓:性能与成本
流量开始上来,调用延迟和费用变得敏感。把关键路径上的框架替换为手写代码,去掉不需要的序列化、callback、冗余日志。
- 高可观测性:链路要随时监控和回溯;
- 业务逻辑高度定制,和框架通用设计偏差大;
- 性能和成本成为核心 KPI。
🧰 框架留周边:文档解析 / tracing
核心业务逻辑已经稳定在自己手里,但没必要所有东西都自己写。文档解析、向量检索、调用链追踪这些「工具性」周边,借用成熟框架或 SDK 更划算。
📊 框架 vs 手搓:多维度对比
拖动维度,看看在不同考量下谁更占优。数值越高越适合该方案。
最务实的折中方案:核心手写,周边借用
实际项目里最常见、也最务实的选择是「核心手写,周边借用」。就像盖房子:承重墙自己设计,门窗水暖买现成。
🏗️ 核心逻辑:手搓(Agent 心脏)
这些直接影响业务正确性和稳定性,必须完全掌控。
🧰 工具性周边:借用框架 / SDK
通用、非关键路径,自己写收益低,用现成工具更划算。
🎯 面试总结:怎么答这道题
回顾开头的对话,只说「框架好用、效率高」是踩雷的。面试官真正想考的是你有没有想清楚框架和手搓各自的边界。
四个要点
- 框架的价值是真实的:POC 阶段省时省力,不要一开口就否定框架。
- 框架的痛点要说具体:抽象层太多导致排查困难、版本升级带来 breaking change、通用设计产生隐性性能开销。泛泛说「框架有缺点」没有说服力。
- 手搓的核心价值是「完全掌控」:可观测性好、稳定不受外部升级影响、性能可以精确裁剪,这些在生产环境是真实的成本节省。
- 最务实的答案是折中方案:核心逻辑手写,周边工具性功能借用框架。这是实际项目里最常见也最稳妥的选择,面试官通常很认可这个答法。
小结速记
| 维度 | 成熟框架 | 手搓 Agent |
|---|---|---|
| 定位 | 租房:拎包入住 | 自建房:完全掌控 |
| 适合阶段 | POC、快速验证 idea | 生产、规模化、高定制 |
| 核心优势 | 开发速度快、生态丰富 | 可观测、可裁剪、稳定可控 |
| 主要痛点 | 抽象层多、升级 break、隐性开销 | 前期投入大、重复造轮子 |
| 最佳实践 | 核心手写 + 周边借用 | |
同目录相关阅读:Agent 工具设计、ReAct 推理模式与实现、Agent 与工作流对比。