news 2026/8/31 10:51:25

LangGraph与LangChain对比:从链式调用到图计算的工作流编排实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangGraph与LangChain对比:从链式调用到图计算的工作流编排实战

过去几个月,我陆续看了不少 LangGraph 实战项目,也动手写了好几个 Agent 工作流。一个很强烈的感受是:LangGraph 真正改变的不是“调用大模型的方式”,而是我们组织 AI 应用流程的思维模型——从线性的 Chain 链式调用,升级成有状态、有分支、有循环的图计算。

很多人在 LangChain 里写了大量 Try-Except、If-Else、循环和状态堆栈,最后发现代码越来越乱。这不能完全怪业务复杂,更多是因为工具本身选错了抽象方式。LangGraph 回答的正是这个问题:当流程开始分叉、需要根据中间结果动态决定下一步、甚至要支持循环和子流程时,我们应该用什么结构来承载这些逻辑?这篇文章我会从 LangGraph 和 LangChain 的差异讲起,再拆解 State、Node、Edge、Conditional Edge 这些核心概念,最后用一套更接近工程的路径帮你避开新手最容易踩的坑。

1. 先搞明白:LangGraph 和 LangChain 到底差在哪

1.1 大多数人的第一反应是“升级版”,其实不一样

我第一次看到 LangGraph 时,第一反应是这可能是 LangChain 的加强版,用更高级的方式写 Chain。实际用下来发现,它根本不是 LangChain 的简单升级,而是一次抽象层级的切换。

LangChain 的 Chain 模式,本质是把一步调模型、一步调工具、一步做解析,按顺序串成一条固定管道。管道一旦定义好,执行路径就是确定的:A 节点执行完,B 节点执行,B 节点做完,C 节点执行。如果你想在中间加一个判断,比如“如果用户输入包含某个关键词,先走工具调用,否则直接回复”,你通常得在 Chain 内部写一个自定义函数,或者用分支 Chain 手动拼接。这种分支逻辑一旦多起来,整条链会变得非常难看,因为每个 Chain 都只能表达线性关系。

LangGraph 换了一种抽象:它把整个流程描述成一张图。节点是函数,边是节点之间的连接关系。你可以用条件路由,也就是由函数来决定下一步去哪个节点;你可以加循环,让流程在某个节点之间反复迭代直到满足条件;你还可以把一个小流程作为子图嵌套进大图里。

表面上看,LangGraph 也能实现 LangChain 的效果,但底层模型不一样。LangChain 更像一条流水线,每个工位固定;LangGraph 更像一张地图,每一步走到哪里,由当前状态和路由规则决定。这个差别直接决定了你能不能在复杂 Agent 工作流里持续维护代码。

1.2 链式调用的天花板,正是图模型的起点

我用 LangChain 写过客服 Agent,一开始还算顺利:用户输入进来,调用 LLM,LLM 决定是否调用工具,然后解析结果,最后返回答案。这个流程用 Chain 写起来很简单。

但第一个麻烦来了:如果 LLM 决定要调用多个工具呢?比如“帮我查一下北京和上海的天气,然后对比一下”。理想流程是先并行或顺序调两次天气工具,再汇总结果。用 Chain 写,要么把多个工具塞进一个工具节点,要么写一个复杂的 AgentExecutor。如果中间某次工具调用失败,还需要重试,那 Chain 的线性结构就很难优雅表达。

第二个麻烦是状态共享。多轮对话里,下一次调用需要知道之前已经拿到了哪些信息。在 Chain 模式里,你通常要往外部的 context 字典里塞东西,每个节点自己去读取和写入。时间久了,你根本不知道哪个节点改过这个字段。

LangGraph 对这两个问题的处理方式就很直接:状态是显式的图状态,任何节点都能往 state 里写数据,但必须返回一个字典,让状态变更可以被追踪;路由是条件函数,下一步执行哪个节点完全由当前 state 决定;工具调用失败可以走回头路,回到某个节点重试或改写策略。这种结构带来的不是某个具体函数更高效,而是整个流程的可控性上了一个台阶。

所以对于固定流程、单次调用、简单工具链,直接用 LangChain Chain 就够了,没必要上 LangGraph。但如果你的流程里有分支、循环、状态共享、子流程和多智能体协作,LangGraph 的图模型会是更合适的基础设施。

2. 核心概念拆解:State、Node、Edge、Conditional Edge

2.1 状态、节点、边:一切用代码理解

LangGraph 有四个基础概念,名字很直观,但细节上要注意。

  • State(状态):它是一个可共享的数据结构,通常用类型定义描述,比如 TypedDict。所有节点都接收当前 State 作为输入,返回更新后的字段。
  • Node(节点):一个普通函数,以 State 为入参,返回字典。返回的字典会更新 State 中对应的字段。
  • Edge(边):从一个节点到另一个节点的有向连接。可以有普通边,表示固定执行顺序;也可以有条件边,表示根据函数结果动态选择目标。
  • Conditional Edge(条件边):一条由路由函数决定去向的边。路由函数接收 State,返回一个字符串或节点名,LangGraph 根据返回值选择下一步节点。

先用最小代码把状态更新这个事跑通。下面是一个常见写法,具体 API 可能会随版本微调,但整体结构是稳定的。

from typing import TypedDict from langgraph.graph import StateGraph, START, END class GraphState(TypedDict): question: str answer: str steps: int def node_start(state: GraphState): # 节点函数返回一个字典,LangGraph 会把它合并到当前 State return {"steps": state["steps"] + 1, "question": state["question"].strip()} def node_generate(state: GraphState): # 实际项目中这里会调用 LLM,这里用拼接字符串做演示 answer = f"我对「{state['question']}」的模拟回答" return {"answer": answer, "steps": state["steps"] + 1} graph = StateGraph(GraphState) graph.add_node("start", node_start) graph.add_node("generate", node_generate) graph.add_edge(START, "start") graph.add_edge("start", "generate") graph.add_edge("generate", END) app = graph.compile() result = app.invoke({"question": "LangGraph 是什么?", "answer": "", "steps": 0}) print(result)

这个图只有一条直线:start 节点先执行,再执行 generate,最后结束。执行结果里,steps会变成 2,answer会被写入模拟回答。

这里最需要理解的是节点函数的返回方式:不是直接修改传入的 State 对象,而是返回一个字典,LangGraph 负责做合并。这意味着你可以在任意节点里只返回希望更新的字段,其他字段不动。这种设计让状态变更变得可追踪,但也会带来一个隐藏问题:如果你忘记返回某个字段,它在后续节点里可能会缺失或保持旧值。

2.2 改变 State 时的一个重要细节:默认覆盖和自定义合并策略

默认情况下,State 里的一个字段如果被节点返回,就会整体覆盖。比如question字段原来是字符串,节点返回新的字符串,就会被替换。这在很多场景下没有问题,但如果是消息列表,你可能想不断追加,而不是覆盖。

LangGraph 提供了一个更灵活的机制:用Annotated和 reducer 函数来定义字段的更新方式。最常见的例子是消息列表:

from typing import Annotated, TypedDict from langgraph.graph.message import add_messages class AgentState(TypedDict): # 表示 messages 字段的更新方式是调用 add_messages 来合并 messages: Annotated[list, add_messages] step: int

这样,每个节点返回的messages列表会被追加到上一轮的messages后面,而不是直接覆盖。这个机制应对多轮对话非常有用。

我在实际踩坑中经常看到的是:新手在节点里返回messages: new_message,结果下一轮对话列表变短,之前的上下文丢了。原因不是 LangGraph 删数据,而是默认覆盖策略把它覆盖了。所以只要涉及列表、数组、历史记录这类需要累积更新的字段,就要主动定义 reducer。

2.3 条件路由:让流程自己决定下一步

条件路由是 LangGraph 最有价值的能力之一。它的核心逻辑非常简单:写一个路由函数,函数根据当前 State 返回目标节点名,LangGraph 就会把执行权交给那个节点。

举一个意图判断的例子:用户输入进来,先判断意图,如果是“查天气”就走天气节点,如果是“闲聊”就走回复节点。

from typing import Literal from langgraph.graph import StateGraph, START, END class IntentState(TypedDict): query: str intent: str result: str def analyze_intent(state: IntentState): # 这里简化成关键词判断,实际项目可以调用 LLM if "天气" in state["query"]: intent = "weather" else: intent = "chat" return {"intent": intent} def weather_node(state: IntentState): return {"result": "今天是晴天,适合出门"} def chat_node(state: IntentState): return {"result": "哈哈,这个话题很有意思"} def route_after_intent(state: IntentState) -> Literal["weather_node", "chat_node", "END"]: if state["intent"] == "weather": return "weather_node" elif state["intent"] == "chat": return "chat_node" return END graph = StateGraph(IntentState) graph.add_node("analyze_intent", analyze_intent) graph.add_node("weather_node", weather_node) graph.add_node("chat_node", chat_node) graph.add_edge(START, "analyze_intent") graph.add_conditional_edges("analyze_intent", route_after_intent) graph.add_edge("weather_node", END) graph.add_edge("chat_node", END) app = graph.compile() result = app.invoke({"query": "北京天气怎么样", "intent": "", "result": ""}) print(result["result"])

这里的关键是graph.add_conditional_edges("analyze_intent", route_after_intent),它表示从analyze_intent节点出去时,先执行route_after_intent路由函数,再根据返回值决定下一步。

条件路由本质上就是一张表:路由函数返回什么,图就走哪条边。这个设计看起来简单,但它解决了一个很核心的问题:LLM 应用里,你经常需要根据模型输出、工具结果、用户反馈来动态决定下一步。在 Chain 模式里这是很难写优雅的,在 LangGraph 里就是一个普通函数。

3. 进阶实战:分支控制、循环检测、子图和并行分支

3.1 条件路由再往前一步:不要让节点之间互相裸跳

条件路由用多了以后,很多人会忍不住把所有判断逻辑塞进一个路由函数里。比如先判断意图,再判断用户情绪,再判断当前轮次,然后根据四个维度组合出下一步。这会让路由函数变成一个巨型 if-else,维护性反而下降。

我的建议是:不要让一个路由函数承担太多职责,可以把判断拆成多个阶段节点。比如先判断意图,写入 state;再判断是否需要工具调用,写入 state;最后用一个路由函数读取这两个字段,决定下一步。这种方式看起来多走了一步,但每个节点职责单一,日志也容易定位。

LangGraph 的优势在这里体现得很明显:你可以像画流程图一样,把复杂的多条件判断拆成多个小节点,再用条件边串联。这样每个节点都能独立测试。

3.2 循环检测:不是无限循环,而是设计出口

LangGraph 支持循环,这是很多实际场景的刚需。比如一个 Agent 要反复调用工具,直到拿到信息够为止;或者一个“反思”流程,先生成答案,再检查,不满意就重新生成。循环如果控制不好,就是灾难。

LangGraph 本身提供了几个保护机制。最直接的一个是recursion_limit,它限制了图在一次执行中最多执行多少步。如果在invoke时不设置,默认值通常很低,但具体情况要看版本。更稳妥的做法是主动设置一个相对保守的上限。

result = app.invoke( input_state, config={"recursion_limit": 50} )

当执行步数超过限制时,LangGraph 会抛异常,提示你可能的循环问题。这样至少不会让程序一直跑下去。

但真正避免死循环,不是靠限制步数,而是要在路由函数里设计好退出条件。比如你写一个“反思优化”循环,就必须在某个节点里检查是否已经迭代了 N 次、结果是否满足分数阈值。这通常需要你维护一个iterations字段,每次循环加一,然后在路由函数里判断:

def route_after_reflect(state): if state["iterations"] >= 2 or state["score"] >= 90: return "final_node" return "revise_node"

使用循环时,我建议始终遵循一个小原则:每个循环都至少在两个地方设置出口。一个在路由函数里,根据状态判断是否继续;一个在外部执行参数里,用recursion_limit做兜底。这样即使路由函数写漏了,程序也不会失控。

3.3 子图(Subgraph):把复杂流程打包成可复用节点

当图的复杂度增加以后,你会发现整张图密密麻麻,看不清一个业务边界。LangGraph 提供子图能力,你可以把一个子流程定义成一个独立的图,然后把它作为一个节点挂到父图中。

举个例子,在一个客服 Agent 里,有一个“多轮对话”子流程,这个子流程内部有意图识别、槽位填充、条件路由,非常长。如果直接平铺在总图里,可读性很差。这时可以先把“多轮对话”做成一个子图:

dialogue_subgraph = StateGraph(DialogueState) # 添加子图内部节点和边 dialogue_subgraph.add_node(...) dialogue_subgraph.add_node(...) dialogue_subgraph.add_edge(...) subgraph_app = dialogue_subgraph.compile()

然后在父图里:

parent_graph.add_node("dialogue", subgraph_app)

子图编译后变成一个可调用对象,它接收父图的 State 输入,返回更新后的 State。子图内部的状态字段如果不冲突,可以直接沿用父图字段;如果需要独立,也可以定义单独的状态结构,然后在接口处做字段映射。

子图的核心价值不是缩短代码,而是让整个流程的结构变得可管理。你可以把“意图判断”“工具调用”“反思优化”“用户交互”分别封装成子图,在总图里只保留主干连接。这对团队协作很有帮助,不同人负责不同子图,互不干扰。

3.4 并行分支:不是所有流程都要并行,但用对地方很高效

LangGraph 里,从一个节点出发,如果同时加多条普通边,那么这些边指向的节点会在同一轮中并行执行。这种模式适合做“Map-Reduce”:多个节点针对同一份输入做独立计算,然后汇聚到一个汇总节点。

比较简单的做法是,先有一个拆分节点,然后从拆分节点分别连到几个处理节点,最后这些处理节点再汇入同一个汇总节点。比如“先让三个不同角色分别起草方案,再汇总成一个方案”。

如果分支数量是动态的,也就是你不确定到底要并几个任务,那么可以用 LangGraph 的SendAPI。它允许你根据当前 State 动态生成多个并行任务。不过这个概念相对进阶,新手可以先只掌握静态并行分支,也就是固定数量、固定节点的并行。

并行分支虽然能提高吞吐,但也会带来状态合并问题。多个并行节点同时修改同一个 state 字段,最终合并结果可能不符合预期。我在实践中会尽量让并行节点只更新各自独立的字段,最后在汇总节点统一定义合并逻辑。贸然让多个节点写同一个字段,会产生竞态和不稳定结果。

4. 从跑通到落地:调试、排查和工程化建议

4.1 新手最容易踩的五个坑

在我看了大量 LangGraph 相关提问后,发现真正容易卡住新人的,不是复杂的并行或子图,而是下面这几个基础问题。

  1. 节点返回空字典:节点函数如果返回{},LangGraph 会认为这个节点不更新任何状态。如果后续节点依赖某些字段,就会拿不到新值。更危险的是,如果你以为某个字段被更新了,但其实没有,排查起来很费劲。
  2. 条件路由返回的字符串不在映射表里add_conditional_edges如果不传第二个参数(映射字典),LangGraph 会默认按字符串节点名去查找。如果你路由函数返回的字符串对应的节点不存在,执行会直接报错。
  3. 图没有设置 END 出口:如果某些分支永远指向另一个节点,但某个路由分支写错了,导致它返回一个不存在的节点名,或者直接没有返回 END,就可能陷入死循环。虽然recursion_limit会兜底,但用户体感很差。
  4. 列表字段被意外覆盖:前面讲过,如果没有用 reducer 函数,返回列表会整体覆盖,历史记录容易丢。
  5. 版本差异导致 API 不同:LangGraph 的 API 一直处于迭代中。不同版本的StateGraphadd_conditional_edgesSTART/END写法可能有差异。网上很多教程用的还是旧版,照抄很难跑通。

4.2 一套可复现的排查链路

遇到 LangGraph 运行问题,我通常按下面的顺序排查,比一头扎进代码里要高效得多。

  1. 先看报错现象:是“KeyError”,还是“Node not found”,还是“Recursion limit reached”?不同现象指向不同层。
  2. 再看输入 State:确保调用invoke时传入的初始字典里包含了所有节点会读取的字段。最好提前打印初始 State。
  3. 检查每个节点的返回值:在每个节点函数入口和出口加一行print或日志,确认它拿到了什么,返回了什么。
  4. 检查路由函数:确认路由函数能访问正确的 state 字段,返回的节点名一定是图里存在的节点或END
  5. 检查图编译状态graph.compile()是否成功,添加边时是否引用了不存在的节点。
  6. 最后检查版本:如果代码本来跑得好好的,但是换了一个环境就出问题,优先查langgraphlangchain的版本依赖。

这个排查顺序并不是官方的,但它是工程上更稳妥的路径:先定位是哪一层出了问题,再决定修哪里,而不是直接怀疑语言模型或工具调用。

4.3 真正要长期使用,还需要补哪些工程化能力?

如果你只是做一次 Demo 或学习验证,把图编译完能跑通就够了。但如果你要把 LangGraph 放进一个实际产品,我建议至少补上这几块拼图。

  • 可观测性:每个节点执行前和执行后都记录日志,至少包括输入摘要、输出摘要、耗时、是否进入异常分支。这样线上排查时,你才能知道 Agent 卡在哪一步。
  • 重试与超时:节点里如果有外部 API 调用,要考虑超时、重试、降级。LangGraph 本身主要负责流程编排,不会替你处理网络中断或模型限流。
  • 状态持久化:多轮对话场景里,你可以把 State 保存到 Redis 或数据库,这样用户下次进来还能继续上下文。LangGraph 有 checkpointer 机制,但实践时还是要结合自己的存储方案。
  • 结构化输出:不要把 LLM 的输出直接塞进 State,最好先让模型输出结构化 JSON,或者至少经过一个解析校验节点,再更新状态。这样能减少很多奇怪的运行时错误。
  • 测试与回归:Graph 是由多个函数组成的,每个节点可以单独单元测试;整张图可以准备几条典型输入做集成测试。如果以后改了某个节点,至少能保证原有流程不炸。

4.4 什么时候不该用 LangGraph

这个话题很少被认真聊。LangGraph 很强大,但它不是万能的。如果你的业务流程很简单,比如“用户输入 -> 调一次模型 -> 返回结果”,那用 LangGraph 引入 State、Node、Edge、路由函数,反而会增加心智负担和代码量。这种场景直接用 LangChain Chain 甚至直接调用模型 SDK 都更轻量。

如果你的流程虽然复杂,但基本是固定的多步骤流水线,且不会有太多分支和循环,那 LangChain Chain 或者函数式脚本也能胜任。LangGraph 真正的优势是流程本身带有动态决策、循环、资源共享和子流程嵌套。换句话说,你的流程越像一张“图”,越适合 LangGraph;越像一条“直线”,越不值得为它引入一套图执行引擎。

给一个实用的判断标准:先画流程图。如果你画的流程图里,到处都是菱形判断框、循环回环、分支合并,那就大胆用 LangGraph。如果你画出来的图基本上是一连串矩形框,没有回头路,那你更需要的是一个普通的管道。

5. 一套可以复用的学习路径

5.1 先跑通最小图,再迭代替换

学习 LangGraph 时,我见过最典型的错误是,一上来就想做一个包含 20 个节点的多智能体系统,最后被各种 API 细节和状态问题淹没。

建议的顺序是:

  1. 先写一个只有两个节点、一条边的图,跑通compileinvoke
  2. 加一个条件路由,让流程能根据输入选择不同分支。
  3. 加一个循环,设计一个最多跑三圈的迭代流程,并设置recursion_limit
  4. 加一个子图,把其中两个节点打包成一个子图,挂到父图里。
  5. 再加并行分支,处理一个“同时算几个结果再汇总”的场景。

每一步都独立验证,再叠加下一个功能。不要一开始就探索全部能力。这个路径的意义不只是学 API,而是让大脑逐步适应“图状态机”的思考方式。

5.2 状态设计是所有设计的核心

LangGraph 里,节点的函数逻辑一般都比较简单,难点在于 State 设计。State 就是工作流里的共享内存。你要提前想清楚:哪些字段会被多个节点读取?哪些字段只需要在一个子图内部使用?哪些字段需要累积追加?哪些字段要覆盖?

我的经验是把 State 里的字段分成三类:

  • 输入字段:用户问题、外部参数,通常在流程启动时注入。
  • 中间字段:意图、工具结果、候选答案,只在一个阶段内使用,尽量不跨子图。
  • 输出字段:最终回答、统计信息、状态码,流程结束后需要对外暴露。

在定义 State 类型时,就按这三类分好。中间字段尽量少,因为字段越多,状态合并出错的可能性越大。子图之间只暴露必须传递的字段,其他内部字段留在子图里。

5.3 用“最小可用图”思维替代“完整功能图”思维

很多刚接触 LangGraph 的人会倾向于把功能全部画进一张图,觉得这样才是“完整”。但工程上,更好的是先做一个最小可用图,只包含能跑通主流程的节点和边,然后根据实际业务逐步加分支、循环、异常处理。

这种思维和写代码是一样的:你不是先写一个庞大系统再调试,而是先写一个最小核心流程,再迭代扩展。LangGraph 的图结构让这种增量迭代特别方便:你可以先只做“意图判断 -> 天气查询 -> 返回结果”,跑通以后,再加“咨询量太大时转人工”“多次查询失败时换重写”,每次只加一个小分支,单独验证。长此以往,整个流程会变得稳定又可扩展。

站在更长的时间轴上看 LangGraph

如果把 LangGraph 放进 AI 应用开发的演进坐标系里,它真正改变的不是某个 API 的用法,而是让我们可以用工程化的方式管理 Agent 的“不确定性”。LLM 的输出天然不可控,但状态、路由、循环、子图这些结构是可控的。LangGraph 的价值就是在这两种东西之间建立一层稳定的桥。

所以与其说 LangGraph 是一个工具库,不如说它是一套“AI 工作流工程化”的思维工具。你越早理解 State 和 Conditional Edge 背后的设计意图,就越不会在复杂 Agent 项目里陷入“长了又拆、拆了又长”的泥潭。

我建议你从今天开始,不要只收藏教程,而是把最小的两节点流程跑一遍。只有当你亲手看到 State 被一个节点更新、又被另一个节点读取,再被条件路由决定走向时,LangGraph 和普通 Chain 的区别才会真正变成你自己的判断。这一步跑通之后,后面的子图、并行、持久化,都只是同一套逻辑的自然延伸。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 10:50:32

Vercel 开源 vgpu:WebGPU 浏览器端并行计算的新范式

Vercel 这次开源了一个很有意思的项目: vgpu 。它不是传统意义上的“虚拟 GPU”驱动,而是一个用 TypeScript 编写的 WebGPU 库,定位是面向 AI Agent 的着色器计算框架。简单说,它让大模型/Agent 可以直接在浏览器里操作 GPU 做并…

作者头像 李华
网站建设 2026/8/31 10:49:37

Flume Taildir Source 深度解析:文件轮转跟踪、断点续采与目录监控机制

Flume Taildir Source 深度解析:文件轮转跟踪、断点续采与目录监控机制Apache Flume 是一个分布式、可靠、可扩展的服务,用于高效地收集、聚合和移动大量日志数据。在 Flume 的众多 Source 组件中,Taildir Source 因其独特的优势而备受关注。…

作者头像 李华
网站建设 2026/8/31 10:49:21

再比如“美蛋多功能工具箱v1优化版

点击获取资源:再比如"美蛋多功能工具箱v1优化版https://pan.baidu.com/s/1YwwW4jCQz2_7AlwCrhGqpg?pwdhjpx 【名称与分类】美蛋多功能工具箱v1是一款经过优化的实用工具,在原有功能基础上进行了改进与完善。 【功能概述】软件运行稳定,…

作者头像 李华
网站建设 2026/8/31 10:48:55

exo:多台设备组AI集群,RDMA让大模型跑得更快

exo:多台设备组AI集群,RDMA让大模型跑得更快 【免费下载链接】exo Run frontier AI locally. 项目地址: https://gitcode.com/GitHub_Trending/exo8/exo exo 是一个开源的本地 AI 集群工具:把它装上 MacBook、Mac Studio 甚至 Linux 服…

作者头像 李华
网站建设 2026/8/31 10:46:52

Quicker+豆包+2api+deepseekharness:构建本地多模态自动化工作流

这次我们来看一条常见的本地多模态自动化链路:Quicker、豆包、2api、deepseekharness 四件套串起来,解决“选中文本、截个图、丢一段材料,就能让大模型理解并返回结构化结果”的桌面工作流问题。Quicker 是 Windows 上比较成熟的快捷动作工具…

作者头像 李华
网站建设 2026/8/31 10:46:09

DeepSeek Harness解析:Agent开发中模型与工具之间的执行外壳

“DeepSeek Harness 打破 GitHub 记录”这个标题,看起来确实很有冲击力。但一个做工程的人,看到这种说法时往往不会先去看星标数,而是会先问一句:Harness 到底是什么?它到底改变了什么?如果你只是用过网页版…

作者头像 李华