最近在学习 Agent 和 harness 工程时,我连续遇到了几个很容易混在一起的词:loop engineering、graph engineering、LangChain 和 LangGraph。
它们听起来像是在描述同一件事,但其实处在不同层次。一个是运行方式,一个是组织任务的思路,另外两个则是具体的软件框架。把它们分开以后,我反而更容易理解现在的 Agent 系统到底在解决什么问题。
Loop 是 Agent 的基本呼吸
一个最基本的 Agent,通常就是一个循环:
调用模型
↓
模型决定是否使用工具
↓
执行工具并观察结果
↓
把结果交回模型
↓
继续,直到完成或停止
模型在这里并不是一次性给出答案,而是在行动和反馈之间反复调整。它需要决定下一步做什么、是否还缺信息、工具失败后要不要重试,以及什么时候可以结束。
我理解的 loop engineering,关注的正是这个循环本身:如何限制循环次数,如何处理失败,如何压缩越来越长的上下文,如何避免重复调用工具,以及如何控制成本和延迟。
这其实是一个很朴素的工程问题。一次循环里多消耗一点上下文,也许感觉不明显;但当任务需要几十轮模型调用时,所有重复的工具描述、日志和中间结果都会被反复支付。Agent 是否真正好用,很多时候取决于这些不起眼的循环细节。
Graph 是把路线画出来
Loop 解决的是“继续做什么”,Graph 则进一步把任务的结构表达出来。
分类
├── 查代码 ──┐
├── 查文档 ──┤→ 汇总 → 校验
└── 查历史 ──┘ ├── 通过 → 输出
└── 失败 → 修复
在这张图里,节点可以是普通代码、一次模型调用、一个工具,甚至另一个完整的 Agent;边表示状态应该怎样转移。哪些步骤固定,哪些步骤可以并行,哪里允许模型判断,哪里必须人工确认,都可以写进图里。
这样看,Graph Engineering 并不是把 Agent 拆得越细越好,而是把任务中本来就存在的结构显式表达出来。一个循环也可以看成最简单的有向图:模型节点连接工具节点,工具节点再回到模型节点,直到满足停止条件。
所以 Loop 和 Graph 并不是两个互相排斥的流派。Loop 是一种简单的图,Graph 则允许我们描述更复杂的分支、并行、重试和人工介入。最近 LangChain 社区重新讨论“Graph Engineering”,更像是给这类长期存在的工作流设计方法换了一个更醒目的名字。LangChain 的讨论
LangChain 和 LangGraph 不是二选一
如果把前面的概念放回软件栈里,关系会更清楚:
LangChain:面向 Agent 应用的高层框架
↓
LangGraph:负责状态和流程编排的底层运行时
↓
模型、工具、节点、边、持久化和恢复
LangChain 更适合快速组合模型、工具、提示词和 Middleware。用一个高层接口,就可以得到一个能够调用工具并持续循环的 Agent。
LangGraph 则把控制权交给开发者。开发者自己定义状态、节点和边,并决定任务如何暂停、恢复、重试、分支和汇合。它提供的是更底层的 Agent 编排能力,包括持久化执行、流式输出和人工介入。LangGraph 官方概览
有意思的是,当前 LangChain 的 create_agent 本身就建立在 LangGraph 之上。也就是说,使用 LangChain 的高层 Agent,并不代表没有 Graph;只是图已经被框架替我们搭好了。只有当默认的 Agent loop 不够用时,我们才需要显式地进入 LangGraph 层,自己修改节点和转移关系。LangChain Agent 文档
这和操作系统或数据库的抽象有一点相似:高层接口让大多数事情变简单,底层运行时则保留在复杂场景下接管系统的能力。真正重要的不是一定要使用哪一个框架,而是知道自己当前需要的是高层便利,还是底层控制。
图让失败更容易被看见
Graph 最直接的价值,是让一个复杂任务不再只有一条很长的黑盒轨迹。
当一个报告结果不对时,我们可以追问:是分类错了,搜索没找到证据,汇总遗漏了信息,还是校验节点没有拦住错误?当几个互不依赖的子任务同时执行时,也可以明确看到每个分支的输入和输出。任务被拆成有边界的节点以后,上下文也更容易隔离。
但这里有一个容易被忽略的陷阱:看得见失败,不等于失败变少了。
如果每个节点里面仍然只是一个没有约束的模型调用,那么我们只是把一个大问题拆成了几个小问题。节点之间的边界变清楚了,模型判断的不确定性却没有自动消失。甚至在每个节点后面都加一个“模型审查模型”的节点,也不等于获得了硬性的正确性保证。
我越来越认同一个简单的判断:凡是有明确答案的事情,就应该尽量交给确定性代码、Schema、测试和权限规则;只有真正需要理解和判断的部分,才交给模型。图的价值在于帮助我们把这两类工作放在合适的位置,而不是用更多节点掩盖没有规则的地方。
复杂度应该从哪里开始
我现在会用几个问题来判断是否值得引入 Graph:
任务是否有稳定的阶段和边界?
是否存在真正可以并行的子任务?
是否需要暂停、审批、恢复或审计?
是否因为上下文过大而开始出现质量下降?
如果答案大多是否定的,一个简单的 Agent loop 可能已经够用。为了显得架构完整而引入一张复杂的图,最后往往只是增加维护成本。
如果任务阶段相对稳定,且需要并行、人工门禁或失败恢复,那么显式的 Graph 会更有价值。对于开放式研究,事先并不知道应该怎样拆解问题,过早把路线写死反而会限制 Agent 的探索能力。这时更适合保留一个动态 loop,或者采用“固定骨架加局部动态规划”的混合方式。
这也让我重新理解 harness engineering。Harness 并不只是给模型配几个工具,而是在决定模型拥有多少上下文、多少行动权限、多少次尝试机会,以及哪些路径必须经过验证。Graph 只是其中一种组织控制流的方式。
真正的工程判断,不是把系统画得更复杂,而是决定哪些事情应该由模型临场判断,哪些事情必须由系统明确规定。Loop 让 Agent 能够持续行动,Graph 让行动路径变得清晰,确定性检查则决定这条路径是否值得信任。
模型越强,能承担的判断越多;工程越成熟,越知道哪些判断不应该交给模型。
参考资料: