01 · 框架分层与评测坐标系
前置:会调大模型 API。不需要用过任何框架。
你在群里问「LangChain 和 LangGraph 该用哪个」,有人说用 LangGraph,有人说 LangChain 就够了,还有人说都别用。
三个人都没说错 —— 因为 LangChain 本来就跑在 LangGraph 上面。这就像问「该用 Django 还是 WSGI」。
这类争论几乎全部来自同一件事:拿不在同一层的东西在比。 所以在拆具体框架之前,得先有一把尺子,量清楚每个框架站在哪一层、又该拿哪些问题去问它。这一篇就是那把尺子。
一、先把「Agent」这个词拆开
工程上,一个 Agent 只有两部分:
- Model:会思考、会决定调什么工具的那个大脑。你换不换框架,它都在那儿。
- Harness:模型周围的一切 —— 提示词、工具、循环、上下文裁剪、状态存储、失败重试、人工审批。
换句话说:框架卖的从来不是模型能力,卖的是 Harness。 所以「LangChain 和 GPT-5.5 哪个强」是个不成立的问题 ——「LangChain 那套 Harness,比我自己手写的 while 循环强在哪」才是要问的。
Harness 通常包含这些能力,你可以拿它当 checklist 去对每个框架:
图片来源:LangChain Docs
二、Agent Loop:所有框架的最小公约数
去掉包装,几乎所有框架的核心都是同一个循环:调模型 → 模型选工具 → 执行工具 → 把结果塞回上下文 → 再调模型 → 模型不再调工具就结束。

手写出来大概二十行:
def agent_loop(model, tools, messages, max_turns=20):
for _ in range(max_turns): # max_turns 是保险丝,防止无限循环烧钱
# ① 把「完整对话历史 + 可用工具清单」交给模型,让它决定下一步
response = model.invoke(messages, tools=tools)
messages.append(response) # 模型这次的输出也要记进历史
# ② 模型这次没要求调工具 → 说明它认为任务完成了,返回最终答案
if not response.tool_calls:
return response
# ③ 模型要求调工具 → 逐个执行,把结果塞回历史,下一轮它就能看到
for call in response.tool_calls:
result = tools[call.name](**call.args) # 真正执行的是你的代码,不是模型
messages.append(tool_message(result, call.id))
# call.id 很关键:模型靠它把「结果」和「是哪次调用」对上号
raise RuntimeError("超出最大轮数")
这二十行任何人一小时能写完 —— 所以框架的价值全在这二十行之外。
写完这二十行,你会觉得自己已经做出 Agent 了。接下来几周会依次发生下面这些事,每一件都不在这二十行里:
| 你会撞上的问题 | 手写方案的代价 |
|---|---|
messages 撑爆上下文窗口 | 得自己实现摘要 / 裁剪 / 卸载到磁盘 |
| 第 14 轮进程挂了 | 从头再跑一遍,钱和时间都白花 |
| 某个工具调用要人工确认 | 得把整个循环拆成可暂停的状态机 |
| 想看模型每一步在想什么 | 得自己埋点、自己做 trace UI |
| 要换个模型供应商 | 工具 schema、消息格式、流式协议全得重写 |
| 一个 Agent 忙不过来,要拆多个 | 得自己设计通信、路由、上下文隔离 |
这六行就是框架真正在卖的东西 —— 它们各自给出了一套现成答案。谁的答案更合你的场景,谁就是你该选的那个。
三、三层结构:Runtime / Framework / Harness
「Agent 框架」这个词现在同时指三种东西,混着比必然比不出结论。
3.1 Runtime(运行时):解决「跑」
这一层和 LLM 关系不大,和分布式系统关系很大 —— 它管的是任务怎么活着跑完:
- Durable execution 持久执行:进程崩了从上次检查点继续,而不是从头
- Streaming 流式:token 级、步骤级、状态级三种粒度
- Human-in-the-loop:在任意节点中断,等人改完状态再继续
- Persistence 持久化:线程内(一次会话)和跨线程(长期记忆)
代表:LangGraph。注意 Temporal、Inngest 这类通用持久执行引擎也在这一层 —— 它们不懂 LLM,但持久执行做得比谁都好,很多团队用 Temporal + 裸 SDK 而不用 LangGraph。