最近后台收到很多读者留言,都在问同一个问题: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 Harness:Agent 的“驾驶舱”和“安全带”
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 模块处理完传给 B,B 传给 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。
- 工具注册后统一暴露给 Harness,Harness 再把这些描述注入模型提示词。
这套机制的好处是:新增一个工具不需要修改 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|openai"4.3 配置模型访问
创建一个.env文件,放在项目根目录:
# 文件路径:.env OPENAI_API_KEY=sk-你的密钥 OPENAI_BASE_URL=https://api.你的服务商.com/v1 LANGCHAIN_TRACING_V2=false 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( model="gpt-4o-mini", messages=messages, tools=TOOL_SCHEMAS, tool_choice="auto", temperature=0.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(f"Step {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( model=self.model, messages=messages, tools=tool_schemas, tool_choice="auto", temperature=0.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_schemas=TOOL_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(model="gpt-4o-mini", temperature=0.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(agent=agent, tools=[get_weather], verbose=True) result = executor.invoke({"input": "上海今天天气怎么样?"}) print(result)LangChain 帮你处理了大量细节,比如:
- 将
@tool装饰器定义的函数自动序列化为工具 Schema。 - 自动维护
agent_scratchpad,也就是 Agent 的中间推理过程。 - 内置
AgentExecutor循环,你不需要手写for step in range(...)。 - 通过
verbose=True可以直观看到每一步的工具调用。
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(model="gpt-4o-mini", temperature=0.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 工程化的角度看,选择依据可以归纳为:
| 对比维度 | LangChain | LangGraph |
|---|---|---|
| 核心抽象 | Chain / AgentExecutor | StateGraph / 节点 / 边 |
| 适合场景 | 线性管道、快速原型、标准 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 领域的热词还有很长一段时间会不断涌现,但底层机制其实没有想象中那么玄。把主干概念吃透,再去看任何新框架,都不会再被绕晕。建议先收藏这篇文章,动手把示例代码跑起来,遇到问题随时回来对照排查思路。