2023 年,用 LangChain 构建一个 Agent 需要写大量「脚手架」代码:
- 路由逻辑:判断用户意图,决定调哪个 Chain
- 工具选择:根据任务类型选择合适的工具
- 输出解析:用 OutputParser 把模型的文本输出转成结构化数据
- 重试逻辑:模型返回格式错误时自动重试
- 提示模板:用 PromptTemplate 管理复杂的 Prompt 拼接
这些功能,LangChain 都提供了封装好的抽象。
2026 年,如果你用 Claude 3.7 或 GPT-4o 直接调用 API,大多数情况下不需要这些封装------模型自己就会做。
这就是框架层坍缩。
一、什么是框架层坍缩
「坍缩」不是说框架消亡了。是说框架过去承担的功能,正在被转移到两个方向:
一部分向下转移到模型层------模型变聪明了,以前需要代码来实现的逻辑,现在模型原生就能做。
一部分向上转移到 Harness 层------真正属于系统工程的部分,从框架里分离出来,成为独立的 Harness 关注点。
中间那层「框架胶水代码」正在萎缩。
二、已被模型吸收的功能(约 80%)
2.1 路由决策
2023 年的做法:写一个 Router Chain,根据用户意图的关键词或分类模型,决定把请求路由到哪个处理链。
2026 年的做法:直接告诉模型有哪些能力,让它自己决定用哪个:
# 2023 年:需要显式路由逻辑
from langchain.chains.router import MultiPromptChain
chains = {
"coding": coding_chain,
"writing": writing_chain,
"analysis": analysis_chain,
}
router = MultiPromptChain(router_chain=..., destination_chains=chains)
result = router.run(user_input)
# 2026 年:模型自己路由
response = client.messages.create(
model="claude-opus-4-7",
system="""你有以下能力:
- 代码编写和审查(写代码、debug、代码解释)
- 文档写作(技术文档、说明书、报告)
- 数据分析(统计、可视化建议、洞察)
根据用户请求,选择合适的能力完成任务。""",
messages=[{"role": "user", "content": user_input}]
)
# 模型自己判断该做什么,不需要路由逻辑
2.2 工具选择
以前需要手动实现工具选择逻辑,或者用框架的 Agent Executor 来管理工具调用顺序。
现在模型的 Function Calling / Tool Use 原生支持工具选择------给模型一组工具,它自己决定调哪个、什么时候调、调几次:
tools = [
{
"name": "read_file",
"description": "读取文件内容",
"input_schema": {"type": "object", "properties": {"path": {"type": "string"}}}
},
{
"name": "search_web",
"description": "搜索网络信息",
"input_schema": {"type": "object", "properties": {"query": {"type": "string"}}}
},
{
"name": "run_code",
"description": "执行 Python 代码",
"input_schema": {"type": "object", "properties": {"code": {"type": "string"}}}
}
]
# 模型自己决定用哪个工具、按什么顺序
response = client.messages.create(
model="claude-opus-4-7",
tools=tools,
messages=[{"role": "user", "content": "分析 data.csv 里的销售趋势"}]
)
# 模型会先 read_file("data.csv"),然后 run_code 做分析
# 不需要任何手动编排逻辑
2.3 输出解析
以前需要 OutputParser 把 "Answer: 42" 这样的文本提取出 42,或者把 Markdown 表格转成 Python 字典。
现在模型原生支持结构化输出:
import anthropic
from pydantic import BaseModel
class CodeReviewResult(BaseModel):
passed: bool
issues: list[str]
severity: str
suggestions: list[str]
# Claude 直接输出符合 schema 的 JSON,不需要解析
response = client.messages.create(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": f"审查以下代码:\n{code}"}],
tools=[{
"name": "submit_review",
"description": "提交代码审查结果",
"input_schema": CodeReviewResult.model_json_schema()
}],
tool_choice={"type": "tool", "name": "submit_review"} # 强制调用这个工具输出结构化结果
)
# 直接得到结构化结果,无需解析
result = CodeReviewResult(**response.content[0].input)
2.4 重试逻辑
以前当模型输出格式不对,需要手写 retry 循环,或者用框架的 RetryParser。
现在模型更可靠,格式错误率大幅下降;即使出错,可以直接在对话里纠正:
def get_structured_output(prompt: str, schema: type) -> dict:
messages = [{"role": "user", "content": prompt}]
for attempt in range(3): # 最多 3 次,通常第一次就对
response = client.messages.create(
model="claude-sonnet-4-6",
messages=messages,
tools=[{"name": "output", "input_schema": schema.model_json_schema()}],
tool_choice={"type": "tool", "name": "output"}
)
try:
return schema(**response.content[0].input)
except Exception as e:
# 把错误反馈给模型,让它自己修正
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": f"输出格式有误:{e},请重新输出"})
raise RuntimeError("多次尝试后仍无法获得正确格式")
三、仍在 Harness 层的部分(约 20%)
模型变聪明可以替代很多胶水代码,但有四类问题,再聪明的模型也解决不了------这些是 Harness 不可替代的部分。
3.1 持久化
模型没有持久记忆。对话结束,上下文消失。跨会话的状态------任务进度、用户偏好、项目背景------必须由 Harness 管理:
- 文件系统:CLAUDE.md、AGENTS.md、progress.txt------人类可读的持久化
- 数据库:结构化状态、用户数据、任务历史
- Git:代码变更的版本控制,也是 Agent 操作的审计日志
这不会被模型替代。模型可以读写文件,但决定「什么状态需要持久化、怎么组织、何时清理」是 Harness 设计问题。
3.2 确定性重放
模型是概率性的,同样的输入可能产生不同的输出。对于需要「从断点恢复」的长程任务,必须有确定性的检查点机制:
- 每完成一个关键步骤,把状态写入检查点
- 任务失败时,从最近的检查点重启,而不是从头来
- 人工审查时,能精确复现某次执行的完整路径
LangGraph 的 Checkpoint 机制是目前这类需求最成熟的解决方案。这不是模型能力问题,是工程基础设施问题。
3.3 可观测性
上一篇讲了 Agent 可观测性------Traces、Metrics、Logs。这些不是模型能力,是系统基础设施:
- 模型不能给自己追踪 Token 用量
- 模型不知道自己这次调用花了多少钱
- 模型不能在失败时自动报警
这些是 Harness 层的职责,无论模型多聪明都不会改变。
3.4 错误恢复
有一类错误是模型层面无法处理的------基础设施错误:
- API 限流(429 Too Many Requests)
- 网络超时
- OOM(内存溢出)
- 依赖服务宕机
处理这类错误需要 Harness 层的重试策略、断路器、降级方案。模型不知道外部世界发生了什么,它只能生成 token。
import anthropic
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=4, max=60),
retry=lambda exc: isinstance(exc, (anthropic.RateLimitError, anthropic.APITimeoutError))
)
def call_with_retry(messages: list) -> str:
"""Harness 层处理基础设施错误,模型层不感知"""
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
messages=messages
)
return response.content[0].text

四、Framework vs Harness 的本质区别
理解了什么被吸收、什么留下来,就能看清楚 Framework 和 Harness 的本质区别:
Framework 解决的是「开发者如何构建 Agent」的问题------抽象、封装、减少样板代码。当模型变强,开发者需要的抽象减少,框架的价值自然下降。
Harness 解决的是「Agent 如何在生产中安全运行」的问题------持久化、可观测性、故障隔离、成本控制。这些不随模型能力变化而消失,生产系统永远需要这些。
这两件事的目标受众不同:Framework 服务开发者,Harness 服务运行中的 Agent。
五、各框架的进化方向
既然框架层在坍缩,各框架是怎么应对的?
5.1 LangChain → LangGraph
LangChain 最初的定位是「AI 应用开发框架」,提供大量封装好的 Chain、Agent、Memory 抽象。随着模型能力增强,这些抽象的必要性下降。
LangChain 的应对:把重心转移到 LangGraph------专注于工作流编排(状态机、检查点、持久化),而不是封装模型调用。
这个转型方向对:LangGraph 提供的正是「仍在 Harness 层」的那部分功能,不会被模型替代。
5.2 CrewAI → 企业级 Harness
CrewAI 从角色编排框架演进,正在向企业级 Harness 平台发展------加入更多生产特性:任务追踪、成本监控、企业权限管理、合规报告。
这个方向也对:把框架定位从「帮你写 Agent」变成「帮你在生产中跑 Agent」。
5.3 AutoGen → MAF(微软统一框架)
Microsoft 把 AutoGen 和 Semantic Kernel 合并,构建 MAF(Microsoft Agent Framework)------不再只是对话式多 Agent,而是覆盖从 Agent 开发到企业级部署的完整栈。
六、轻量 Harness 方法:把规则写进提示
框架层坍缩还催生了一种新的 Harness 模式:Markdown-based Harness------把 Harness 规则直接写进系统提示或配置文件,而不是用代码实现。
6.1 AGENTS.md 模式(Codex 推广的约定):在项目根目录放一个 AGENTS.md 文件,Agent 在开始任务前自动读取:
# AGENTS.md
## 工作约束
- 修改代码前先运行测试,确认当前基线通过
- 每完成一个子任务,git commit 一次,commit message 格式:feat/fix/refactor: 简短描述
- 不要修改 .env 和 credentials/ 目录下的任何文件
- 如果不确定,停下来问,不要猜
## 代码规范
- Python 3.11+,使用 type hints
- 单行不超过 88 字符(black 格式化标准)
- 所有公共函数必须有 docstring
## 测试要求
- 修改任何功能代码后,新增或更新对应测试
- 运行命令:pytest tests/ -v --tb=short
- 覆盖率目标:核心模块 90%+
## 禁止操作
- 不执行 DROP TABLE, DELETE FROM(无 WHERE 条件)
- 不 push 到 main 分支,只能提 PR
- 不在代码里硬编码 API key 或密码
6.2 CLAUDE.md 模式(Claude Code 的约定):项目级别的持久化记忆和约束,Claude Code 在每个会话开始时自动读取。
这种方法的优势:
- 零框架依赖:只是一个文件,任何 Agent 都能读
- 人类可读可编辑:不需要改代码就能调整 Agent 行为
- 版本控制友好:和代码一起提交,有完整的修改历史
限制:只能表达「静态规则」,动态的流程控制(条件分支、循环、检查点)仍然需要代码。
七、什么时候用框架,什么时候不用
有了前面的分析,可以给出一个实用的决策框架:
7.1 不需要框架的场景:
- 单次 LLM 调用,即使很复杂
- 简单的工具调用序列,不需要复杂编排
- 原型验证阶段,快速实验想法
这些场景直接用 SDK 就好------anthropic.messages.create(),干净、可控、没有额外依赖。
7.2 需要 LangGraph 的场景:
- 工作流有复杂的条件分支(成功/失败走不同路径)
- 需要跨会话的检查点和状态恢复
- 有人工审批节点的长程任务
7.3 需要 CrewAI 的场景:
- 明确的角色分工(代码生成 + 测试 + 审查)
- 需要快速上手多 Agent 编排
- 已有 CrewAI 技术栈的团队
7.4 不需要任何框架,但需要 Harness 的场景:
- 生产部署:可观测性、成本监控、错误恢复------这些用基础设施工具(Langfuse、Helicone),不需要 Agent 框架
- 长程任务:自己实现检查点,不一定要上 LangGraph
八、反直觉的结论:更少的框架依赖,更好的 Harness
一个经常被忽视的事实:框架引入了依赖、学习成本、升级风险。
当 LangChain 从 0.x 升到 1.x,API 全面破坏性变更,依赖它的项目要花大量时间迁移。这不是批评 LangChain------任何快速演进的框架都会这样。
成熟的团队正在走向「最小框架依赖」的方向:
- 直接用 Anthropic/OpenAI SDK
- 只在真正需要时引入 LangGraph(状态机编排)
- Harness 层用基础设施工具(不是框架):Langfuse 做可观测性,Helicone 做成本追踪
这不是反框架,是认清楚框架的边界------在它真正有价值的地方用它,在其他地方用更简单的方案。
# 2026 年的「最小框架依赖」Agent 架构
import anthropic # 直接用 SDK
from langfuse.decorators import observe # 只引入可观测性工具
@observe() # Harness:追踪
def run_agent(task: str) -> str:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": task}]
while True:
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
tools=TOOLS, # 工具列表
messages=messages
)
if response.stop_reason == "end_turn":
return response.content[0].text
# 处理工具调用(模型自己决定用哪个工具)
tool_results = execute_tool_calls(response.content)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
# Harness:检查点(每次工具调用后保存状态)
save_checkpoint(messages)
这段代码没有 LangChain,没有 CrewAI,没有 AutoGen,但它有 Harness:可观测性追踪、工具执行隔离、检查点保存。
这就是框架层坍缩之后,「真正的 Harness」长什么样。

参考文献: