公司动态

DeepAgent与Harness:从LangChain到LangGraph的AI Agent工程化指南

📅 2026/8/30 16:59:35
DeepAgent与Harness:从LangChain到LangGraph的AI Agent工程化指南
最近后台收到很多读者留言都在问同一个问题DeepAgent 到底是个新框架还是把 LangChain、LangGraph 又包装了一遍为什么有人叫它 DeepAgent有人叫它 Harness还有人直接在项目里搜 “deepseek harness”实际上这个问题的答案比很多人想象中更简单也更反直觉。DeepAgent 不是又一个大模型也不是又一个“写着玩”的 Agent 框架而是一套企业级 Agent 工程化的调度与控制体系。它在工程上真正解决的事情是让大模型的能力不再停留在“聊天框里的聪明回答”而是变成“生产环境里稳定可复用的智能工作流”。如果你最近正在接触 AI Agent 开发或者你已经用 LangChain、LangGraph 写了一些 Agent 原型但总觉得“跑通 demo 容易、上生产很难”这篇文章就是为你准备的。我会用 3 个小时左右的阅读和实践量从核心概念、运行机制、环境搭建、代码实现、问题排查到生产最佳实践把 DeepAgent、Harness、LangChain、LangGraph 这四者的关系一次讲清楚。文章里所有的代码都按可复制的标准提供看完可以直接在自己的项目里做最小验证。1. 这篇文章真正要解决的问题先说实话AI Agent 的开发正在经历一个和当年“后端框架”非常相似的阶段。早期单体应用时代大家写接口就是写接口没有“分层”概念。等到系统变复杂了才发现需要 MVC、需要服务层、需要依赖注入、需要统一配置管理。AI Agent 也一样。你今天用 LangChain 写一个 Agent明天用 LangGraph 画一个流程感觉都很快但一旦涉及工具权限、上下文管理、多轮记忆、失败重试、链路追踪你会发现代码越写越乱Agent 的行为越来越不可控。同一个功能在不同模型上的表现差异巨大。本地跑得好好的换到生产环境就开始超时、翻车、乱调工具。团队协作时每个人都有一套自己的 Agent 写法根本没有统一规范。DeepAgent 这种被反复讨论的概念正是冲着这些问题来的。用一句话概括它关心的是“Agent 如何被安全、稳定、可观测地运行”而不是“Agent 能不能回答一个问题”。所以这篇文章想帮你解决三个问题搞懂 DeepAgent 和 Harness 的本质不再被新名词绕晕。理清 LangChain、LangGraph 在 DeepAgent 体系里的真实定位。上手一个完整的最小实现知道怎么把 Agent 从“脚本”升级成“工程”。2. 基础概念与核心原理在开始写代码之前我们要先把四个高频词的概念边界划清楚。很多人学 AI Agent 觉得难不是因为代码复杂而是因为概念在脑子里糊成一团。2.1 DeepAgent不是单一软件而是一套工程规范DeepAgent 目前在社区里并没有一个“官方唯一定义”。从材料看它更像是一个以深度推理和工具调用为核心的 Agent 架构范式强调 Agent 在复杂任务中的规划能力、记忆能力、工具使用能力和自我纠错能力。说得更直白一点DeepAgent 是“把 Agent 做成企业级服务”的方法论集合。它包含但不限于统一的 Agent 运行容器Harness。可插拔的工具协议。可配置的规划与推理策略。上下文与记忆管理机制。全链路观测与评估体系。这也是为什么你在搜索时会看到 DeepAgent、deepseek harness、codex harness 这些词经常一起出现——因为它们本质上都在讨论同一个问题如何把大模型包装成一个可控、可靠、可维护的 Agent 服务。2.2 HarnessAgent 的“驾驶舱”和“安全带”Harness 这个词直译是“马具、安全带”在 AI Agent 领域它指的是包裹在大模型之上的一层运行控制环境。没有 Harness 时你直接调用模型接口就像开一台没有方向盘限位、没有仪表盘的车。模型返回什么你就接受什么模型出错你只能干瞪眼。有 Harness 之后开发者的工作被极大简化统一处理模型的输入输出格式。注入系统提示词和工具描述。控制模型最大执行步数。捕获异常并决定是重试还是终止。记录每一步的思考、调用和结果。所以Harness 本质上是“Agent 的运行时框架 安全护栏”。这也是为什么很多企业在上生产环境时第一时间要求把裸模型调用封装进 Harness。2.3 LangChain组件丰富的 Agent 开发工具箱LangChain 是最早火起来的 LLM 应用开发框架之一。它的定位很简单提供大模型应用开发的标准化组件。你可以用 LangChain 做这些事情统一对接不同厂商的大模型接口。快速实现 Prompt 模板的管理。内置 RAG检索增强生成相关组件。提供 Agent 的工具调用能力和记忆模块。用一句话理解LangChain 是“积木盒”里面装满了常用零件。你拿它拼出一个 Agent 很快但它本身不限制你拼成什么样。2.4 LangGraph把 Agent 从“链”升级为“图”LangGraph 是 LangChain 团队后续推出的编排框架它和 LangChain 的核心区别可以用一句话说清LangChain 适合“线性管道”LangGraph 适合“带状态、带分支、带循环的复杂 Agent 流程”。在 LangChain 的传统 Chain 模式中数据流是固定的A 模块处理完传给 BB 传给 C。但真实的 Agent 任务是动态的Agent 要先规划再执行工具根据工具结果判断要不要重新规划可能还要问用户确认。这种逻辑用链式模型写起来非常痛苦。LangGraph 提供的核心抽象是StateGraph状态图节点Node执行一个动作比如调用模型、执行工具。边Edge定义节点之间的流转条件。状态State在节点间共享的数据容器。这意味着你可以像画流程图一样构建 Agent而且每一步的状态都是可追踪、可回放的。放到 DeepAgent 架构里LangGraph 是非常理想的“流程编排引擎”。2.5 AI 大模型Agent 的“大脑底座”无论是 DeepAgent 还是 LangGraph底层都要挂在一个或多个大模型上。大模型负责核心的语义理解、推理和生成比如 GPT 系列、Claude、DeepSeek 等。在企业级 Agent 场景里模型选择通常不是“越强越好”而是要综合考虑推理能力能否理解复杂任务并进行多步规划。工具调用能力能否按照协议输出结构化调用参数。响应延迟与成本在业务场景下是否可接受。部署方式API 调用还是私有化本地部署。3. DeepAgent 的架构与核心机制理解了基本概念之后我们可以进入更核心的问题DeepAgent 的架构到底长什么样3.1 Agent 的核心循环感知-规划-行动-观察所有 Agent 框架不管叫什么名字内部本质上都在跑一个循环感知获取用户输入和当前环境信息。规划大模型根据输入决定下一步做什么。行动执行选定的工具或生成回复。观察获取执行结果决定继续规划还是结束。DeepAgent 和普通 Agent 脚本的区别在于它把上面的循环封装成了一个可配置、可观测、可干预的运行时。3.2 Harness 在 DeepAgent 中的角色在 DeepAgent 架构中Harness 贯穿整个循环在“感知”阶段Harness 负责把外部输入包装成标准消息格式同时注入系统级别的前置指令。在“规划”阶段Harness 负责把工具列表按照模型要求序列化并传给模型。在“行动”阶段Harness 负责解析模型的输出校验参数格式然后才真正执行工具调用。在“观察”阶段Harness 负责把工具返回结果截断、清洗、压缩再塞回上下文。这个设计带来的直接好处是业务代码不直接碰模型也不直接碰工具所有交互都经过 Harness 这一层。这就像在一个团队里所有外部请求先进网关再由网关路由给不同的服务。网关可以统一做鉴权、限流、日志记录不用每个服务自己做一遍。3.3 工具注册与服务发现企业级 Agent 一定会调用大量企业内部工具查询数据库、调用接口、读写工单、发送通知等。DeepAgent 的常见做法是建立一个工具注册表每个工具都有唯一的名称。每个工具都有清晰的描述和参数 Schema。工具注册后统一暴露给 HarnessHarness 再把这些描述注入模型提示词。这套机制的好处是新增一个工具不需要修改 Agent 的核心逻辑只需要实现一个注册函数然后录入描述。你新增一个“查天气”接口时就不用重新改写规划逻辑模型自然可以调用它。3.4 记忆与上下文管理大模型上下文窗口是有限的。一个长期运行的 Agent 如果每轮对话都把全部历史塞进去很快就“胀死”了。DeepAgent 对记忆的处理通常分成三层短期记忆当前任务内的对话历史和工具调用记录。长期记忆跨会话持久化存储通常放到外部数据库或向量库。工作记忆正在执行任务的临时状态由编排框架比如 LangGraph 的 State维护。Harness 则负责决定不同层级的记忆如何在每次模型调用时组装。比如最近的 10 轮对话放到上下文里更早的历史做摘要或存到向量库只有需要时才检索。4. 环境准备与前置条件先说明本文示例以 Python 生态为主因为 LangChain、LangGraph 的社区支持和示例最丰富。具体版本请以实际安装时官方发布为准下面演示的是通用思路。4.1 基础环境要求Python 3.10 及以上版本推荐 3.11 或 3.12。支持 pip 的虚拟环境管理工具。一个可访问的大模型 API 密钥可以是 OpenAI 兼容接口也可以是国内大模型服务商提供的接口。建议准备一个代理环境或内网模型服务地址保证能稳定调用模型接口。4.2 创建虚拟环境并安装依赖# 创建虚拟环境 python -m venv deepagent-demo # 激活虚拟环境Windows deepagent-demo\Scripts\activate # 激活虚拟环境macOS / Linux source deepagent-demo/bin/activate安装基础依赖pip install langchain langchain-openai langgraph openai python-dotenv安装完成后建议先检查一下包版本方便后续排查问题pip list | grep -E langchain|langgraph|openai4.3 配置模型访问创建一个.env文件放在项目根目录# 文件路径.env OPENAI_API_KEYsk-你的密钥 OPENAI_BASE_URLhttps://api.你的服务商.com/v1 LANGCHAIN_TRACING_V2false LANGCHAIN_API_KEY如果你的实际模型服务使用自定义 Base URL比如本地部署的模型网关、公司内部模型平台可以通过OPENAI_BASE_URL指向对应地址。需要提醒的是生产环境务必通过密钥管理服务注入环境变量不要硬编码在代码里。5. 核心流程拆解从零实现一个“极简 DeepAgent”这一章我们来做一次“解剖麻雀”。先用原生代码实现一个最简 Agent 循环然后再把它演进成 Harness 结构。这样做的目的是让你在还没有接触复杂框架之前先理解 Agent 最底层的运作机制。5.1 定义一个工具假设我们要让 Agent 具备一个能力根据城市名称查询天气。我们先用一个字典模拟工具返回结果# 文件路径tools.py def get_weather(city: str) - str: 模拟天气查询工具 weather_map { 上海: 多云25℃, 北京: 晴20℃, 广州: 雷阵雨28℃, } return weather_map.get(city, 暂无该城市天气数据) TOOL_SCHEMAS [ { type: function, function: { name: get_weather, description: 根据城市名称查询当前天气, parameters: { type: object, properties: { city: {type: string, description: 城市名称} }, required: [city], }, }, } ]这一步的关键是工具描述写得越清楚模型就越不容易调用错。5.2 实现一个最简 Agent 主循环我们直接用openai库来完成一次“模型决策 工具调用 结果反馈”的循环# 文件路径minimal_agent.py from openai import OpenAI from tools import get_weather, TOOL_SCHEMAS client OpenAI() def run_agent(user_query: str, max_steps: int 3): messages [ {role: system, content: 你是一个助手只能通过调用工具回答天气问题。}, {role: user, content: user_query}, ] for step in range(max_steps): response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolsTOOL_SCHEMAS, tool_choiceauto, temperature0.2, ) message response.choices[0].message # 1. 模型决定不调用工具直接返回最终答案 if not message.tool_calls: print(最终答案, message.content) return message.content # 2. 模型决定调用工具这里执行并回填结果 messages.append(message) for tool_call in message.tool_calls: if tool_call.function.name get_weather: args eval(tool_call.function.arguments) result get_weather(args[city]) messages.append({ role: tool, tool_call_id: tool_call.id, content: str(result), }) print(fStep {step 1}: 调用工具 get_weather({args[city]}) - {result}) raise RuntimeError(超过最大步数未得到最终结果) if __name__ __main__: run_agent(上海今天天气怎么样)这段代码虽然简单但包含了 Agent 循环中最核心的四个动作把系统提示词、用户输入、工具定义一起传给模型。判断模型输出是“最终答案”还是“工具调用”。如果是工具调用解析参数、执行函数、把结果追加回消息列表。带着工具结果再次调用模型直到模型给出最终答案。这就是后面所有框架替你做的事情。你只是把最底层的逻辑先亲手实现了一遍之后再看 LangChain 或 LangGraph就不会觉得它们“黑盒”了。5.3 把循环升级为 Harness 结构上面代码最大的问题是如果再加一个工具if tool_call.function.name get_weather这种硬编码分支会越来越长。Harness 的改进思路是把“工具注册”和“模型循环”拆开# 文件路径harness.py from typing import Callable, Dict from openai import OpenAI from tools import get_weather, TOOL_SCHEMAS TOOL_FUNCTIONS: Dict[str, Callable] { get_weather: get_weather, } class AgentHarness: def __init__(self, model: str gpt-4o-mini, max_steps: int 3): self.client OpenAI() self.model model self.max_steps max_steps history [] def register_tool(self, name: str, func: Callable): TOOL_FUNCTIONS[name] func def run(self, system_prompt: str, user_query: str, tool_schemas: list): messages [ {role: system, content: system_prompt}, {role: user, content: user_query}, ] for step in range(self.max_steps): response self.client.chat.completions.create( modelself.model, messagesmessages, toolstool_schemas, tool_choiceauto, temperature0.2, ) message response.choices[0].message if not message.tool_calls: return message.content messages.append(message) for tool_call in message.tool_calls: func TOOL_FUNCTIONS.get(tool_call.function.name) if not func: messages.append({ role: tool, tool_call_id: tool_call.id, content: f错误找不到工具 {tool_call.function.name}, }) continue args eval(tool_call.function.arguments) result func(**args) messages.append({ role: tool, tool_call_id: tool_call.id, content: str(result), }) raise RuntimeError(任务超时) harness AgentHarness() print(harness.run( system_prompt你是一个天气助手只能用工具回答。, user_query北京今天天气怎么样, tool_schemasTOOL_SCHEMAS, ))到这里你已经亲手完成了一个非常简版的 DeepAgent 运行时。后续所有复杂功能比如记忆、路由、重试、图编排都是在这样的 Harness 基础上不断丰富。6. 用 LangChain 和 LangGraph 落地 DeepAgent 工作流理解了底层机制后我们再来看工程上怎么用 LangChain 和 LangGraph 提升开发效率。6.1 LangChain 版本最快上手的企业级 Agent用 LangChain 实现上面的天气 Agent代码会简化很多# 文件路径langchain_agent.py from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate tool def get_weather(city: str) - str: 根据城市名称查询天气 weather_map { 上海: 多云25℃, 北京: 晴20℃, 广州: 雷阵雨28℃, } return weather_map.get(city, 暂无该城市天气数据) llm ChatOpenAI(modelgpt-4o-mini, temperature0.2) prompt ChatPromptTemplate.from_messages([ (system, 你是一个天气助手只能使用工具回答。), (placeholder, {chat_history}), (human, {input}), (placeholder, {agent_scratchpad}), ]) agent create_tool_calling_agent(llm, [get_weather], prompt) executor AgentExecutor(agentagent, tools[get_weather], verboseTrue) result executor.invoke({input: 上海今天天气怎么样}) print(result)LangChain 帮你处理了大量细节比如将tool装饰器定义的函数自动序列化为工具 Schema。自动维护agent_scratchpad也就是 Agent 的中间推理过程。内置AgentExecutor循环你不需要手写for step in range(...)。通过verboseTrue可以直观看到每一步的工具调用。6.2 LangGraph 版本把 Agent 画成状态图当你的任务不再是“一问一答”而是“先规划、再分批执行、根据结果调整”时LangGraph 会更合适。下面是一个极简的“规划-执行”双节点工作流# 文件路径langgraph_workflow.py from typing import TypedDict, List from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from langchain_core.tools import tool tool def get_weather(city: str) - str: 根据城市名称查询天气 weather_map {上海: 多云25℃, 北京: 晴20℃, 广州: 雷阵雨28℃} return weather_map.get(city, 暂无该城市天气数据) class AgentState(TypedDict): query: str steps: List[str] result: str def planner(state: AgentState) - dict: 规划阶段根据输入生成一个执行计划 llm ChatOpenAI(modelgpt-4o-mini, temperature0.2) prompt f请把任务拆解为不超过3个步骤{state[query]} plan_text llm.invoke(prompt).content return {steps: plan_text.split(\n)} def executor(state: AgentState) - dict: 执行阶段调用工具并生成最终结果 if 天气 in state[query] and 上海 in state[query]: result get_weather.invoke(上海) else: result 无法自动识别城市 return {result: result} workflow StateGraph(AgentState) workflow.add_node(planner, planner) workflow.add_node(executor, executor) workflow.set_entry_point(planner) workflow.add_edge(planner, executor) workflow.add_edge(executor, END) app workflow.compile() output app.invoke({query: 查询上海的天气, steps: [], result: }) print(最终结果, output[result])LangGraph 的核心价值体现在这个例子里每个节点都是独立函数节点之间的数据流转由 State 控制。以后你可能在 planner 和 executor 之间加一个“用户确认”节点或者加一个“异常处理”节点只需要修改边的定义不需要重写整条链路。6.3 LangChain 和 LangGraph 到底怎么选从 DeepAgent 工程化的角度看选择依据可以归纳为对比维度LangChainLangGraph核心抽象Chain / AgentExecutorStateGraph / 节点 / 边适合场景线性管道、快速原型、标准 RAG复杂多步、动态分支、循环 Agent状态管理相对隐式显式维护在 State 中调试体验通过 verbose 日志每个节点可单独测试状态可回放学习曲线较低略高一个务实的建议是能用 LangChain 快速搞定的需求不要为了“上 LangGraph”而上 LangGraph。复杂流程才值得引入状态图。企业里的 DeepAgent 往往两种都会用简单工具调用用 AgentExecutor复杂业务流程用 LangGraph 编排。7. 运行结果与效果验证7.1 运行 LangChain 示例python langchain_agent.py预期输出类似 Entering new AgentExecutor chain... Invoking: get_weather with {city: 上海} 上海多云25℃ Finished chain. {input: 上海今天天气怎么样, output: 上海今天天气多云气温25℃体感较为舒适。}判断标准日志中出现了工具调用记录。最终 output 里是自然语言的完整回答。没有出现“模型没调用工具却假装查询”的情况。7.2 运行 LangGraph 示例python langgraph_workflow.py预期输出最终结果 上海多云25℃同时会看到planner和executor依次执行。如果任务变复杂你可以为每个节点打印中间状态方便定位是哪一步出了问题。7.3 失败时先看哪里如果 Agent 表现不符合预期排查顺序应当是看模型输出日志模型有没有按预期生成工具调用看工具返回结果工具本身报错还是参数解析错了看最终回答模型是不是没有把工具结果组织成可读答案8. 常见问题与排查思路下面整理一些我见过的、也是社区里频率较高的问题问题现象可能原因排查方式解决方案Agent 不调用工具直接瞎编答案工具描述不清晰或模型不支持 tool calling打印实际发给模型的系统提示词检查工具 Schema优化工具 description换支持函数调用的模型工具参数解析出错模型返回的 JSON 格式与预期不符打印 tool_call.function.arguments 原始内容增加参数校验逻辑用强类型 Schema 约束反复调用同一个工具陷入死循环缺少最大步数限制或工具返回结果没有有效终止条件检查日志中工具调用次数在 Harness/LangGraph 中加入 max_steps超过上下文长度限制历史消息或工具结果过长查看报错的 token 数量增加消息压缩、历史摘要、截断工具返回同一个流程在换模型后表现差异大不同模型的工具调用和推理风格不同分模型跑同一测试集记录结果按业务场景锁定模型或做模型路由安装依赖时版本冲突langchain 和 langgraph 版本不兼容pip check查看依赖冲突锁定已知兼容版本组合生产环境工具鉴权失败工具调用未传递用户身份查看 Harness 是否透传认证上下文在 Harness 中统一注入身份与权限9. 最佳实践与工程建议9.1 工具设计最小权限原则企业级 Agent 最怕的不是“模型不够聪明”而是“模型拿到了不该用的工具”。工具设计有两条铁律每个工具只做一件具体的事不要提供一个“万能执行接口”。工具内部必须做用户身份校验和权限校验Harness 负责把用户上下文透传进去。不要因为嫌麻烦就给 Agent 暴露一个直接执行 SQL 的工具。真需要查数据库也要包一层只读查询、限制返回行数、过滤敏感字段。9.2 重试与超时有界重试而不是无限重试Agent 调用工具时外部服务可能超时。建议策略每次工具调用设置超时时间。超时后最多重试 1-2 次。重试仍失败把错误结果交给模型让模型决定是换一种方式还是向用户说明。无限重试在 Agent 场景里是最危险的它会把一个偶发错误放大成生产事故。9.3 可观测性每一步都留痕生产环境的 Agent 必须做到“每一步都能回放”。建议在 Harness 里记录模型请求的完整输入输出。工具名称、参数、返回结果、耗时。token 消耗量。最终结果与用户反馈。这些数据不仅是排查问题的依据也是后续评测模型、优化 prompt 的重要生产资料。9.4 评测先行不要凭感觉判断 Agent 好不好在把 Agent 接入业务之前建议准备 20-50 条覆盖典型场景的测试用例然后定义好评价指标指标含义任务完成率Agent 正确完成任务的占比工具调用准确率工具选择是否正确、参数是否合法平均步数Agent 完成任务需要多少轮调用平均延迟从用户输入到最终返回的耗时安全违规次数是否出现了未授权工具调用或敏感信息泄露没有评测Agent 的每一次改动都是在“赌”。9.5 版本管理与团队协作Agent 项目里Prompt 和工具描述和代码一样要纳入版本管理。建议Prompt 模板和代码分离不要硬编码在业务代码里。工具 Schema 变更必须有评审。模型版本升级前先跑一遍评测集再切换到生产。10. 总结与后续学习方向这篇文章从一个“DeepAgent 到底是什么”的问题切入拆开了 Agent 最底层的运行循环也用 LangChain 和 LangGraph 分别演示了工程化实现。从材料和实践来看最有价值的结论是DeepAgent 也好Harness 也好本质上都是为了让 AI Agent 从“可演示”走向“可交付”。如果你只是写脚本自己玩裸调模型完全够用。但如果你要在团队或企业环境里交付一个 Agent 服务Harness 的封装、LangGraph 的编排、评测体系的建设、权限与可观测性的落地一个都不能少。下一步建议大家按这个顺序继续深入用这篇文章第 5 章的极简 Harness 跑通一个你自己的工具。再用 LangGraph 把同一个工具改造成状态图版本体会两者的差异。找一个小业务场景比如“工单自动分类 回复助手”按照最佳实践章节的工具设计原则做成一个最小可评测的 Agent 原型。AI Agent 领域的热词还有很长一段时间会不断涌现但底层机制其实没有想象中那么玄。把主干概念吃透再去看任何新框架都不会再被绕晕。建议先收藏这篇文章动手把示例代码跑起来遇到问题随时回来对照排查思路。