惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
Cyberwarzone
Cyberwarzone
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
T
Troy Hunt's Blog
Help Net Security
Help Net Security
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
M
MIT News - Artificial intelligence
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V2EX - 技术
V2EX - 技术
Y
Y Combinator Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
T
Threatpost
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
SegmentFault 最新的问题
I
InfoQ
H
Hacker News: Front Page
D
Docker
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Blog — PlanetScale
Blog — PlanetScale
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
Netflix TechBlog - Medium
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
博客园 - 【当耐特】
T
Tor Project blog
U
Unit 42
H
Heimdal Security Blog
Microsoft Azure Blog
Microsoft Azure Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Privacy & Cybersecurity Law Blog
PCI Perspectives
PCI Perspectives
美团技术团队
O
OpenAI News
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
GbyAI
GbyAI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
MyScale Blog
MyScale Blog

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
LangChain DeepAgents 学习笔记
哥本哈士奇(aspnetx) · 2026-05-19 · via 博客园_首页

LangChain DeepAgents 学习笔记

摘要

LangChain的DeepAgents已经发布有段时间了,最近的几个版本基本覆盖了大多数智能体都应该有的功能。本笔记基于 LangChain 的 DeepAgents 框架,演示如何构建了一个具有角色扮演能力的 AI 助手,并集成了自定义技能系统。以此方便后续的knowledge review以及vibe coding的reference。

环境配置

环境变量设置

from dotenv import load_dotenv
import os

# 加载 .env 文件中的环境变量
load_dotenv()

# 设置环境变量供 deepagents 使用(OpenAI 兼容格式)
os.environ["OPENAI_API_KEY"] = os.getenv("DEEPSEEK_API_KEY", "")
os.environ["OPENAI_API_BASE"] = os.getenv("DEEPSEEK_API_BASE", "https://api.deepseek.com/v1")

这里我们使用在线版本的deepseek。

尝试过使用本地的小模型,需要留意的是,deepseek的小参数量模型,不支持工具的调用。即使换到qwen的小模型,对工具的调用也总会出莫名其妙的问题。所以为方便学习和测试,建议走在线的模型。

工具函数定义

为了演示方便,这里创建两个方法作为DeepAgent的工具。

时间查询工具

from datetime import datetime

def get_time():
    """Get current time"""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

位置查询工具

def get_location():
    """Get location"""
    return "北京"

为方便演示,位置查询的output直接写死。

注:方法要有注释,标注这个方法是干什么的,方便智能体的了解,不然会报错。

核心组件

记忆检查点(Checkpointer)

from langgraph.checkpoint.memory import InMemorySaver

checkpointer1 = InMemorySaver()

由于大模型的对话都是无状态的,比如你第一次对话问:来一首唐诗,第二次对话追问:再来一首,那么大模型会不知道到底再来一首啥。LangChain封装了这么一套方法来维护对话的状态。

代码讲解

  • InMemorySaver 是 LangGraph 提供的内存检查点存储
  • 用于保存对话状态,实现多轮对话的记忆功能
  • 每次对话后自动保存状态,下次可以继续同一话题
  • 支持通过 thread_id 区分不同的对话线程

中间件(Middleware)

from langchain.agents.middleware import SummarizationMiddleware

middleware=[
    SummarizationMiddleware(
        model="deepseek:deepseek-chat",
        trigger=("tokens",1000),
        keep=("messages",3)
    )
]

LangChain通过中间件的方式,来处理模型对话历史过长的问题,处理的方法有很多,比如消息裁剪等。这里演示的是更常用的,将历史对话进行大模型语义汇总的方式,基本的方法就是将指定久远之外的消息汇总成一个简短的摘要。

代码讲解

  • SummarizationMiddleware:摘要中间件,用于优化长对话的上下文管理
  • 参数说明
    • model:用于生成摘要的模型
    • trigger=("tokens",1000):当上下文达到 1000 tokens 时触发摘要
    • keep=("messages",3):保留3 条消息
  • 作用:当对话过长时,自动将早期对话摘要为简短总结,节省 token 并保持关键信息

如果keep的messages设置为3,那么最近的两条message会被完整保留,第三条是根据以前的会话记录summaize下来的信息。

本地 Shell 后端

from deepagents.backends import LocalShellBackend

backend=LocalShellBackend(
    root_dir=".",
    virtual_mode=True
)

这个是用来确保,智能体能够读取到skills,并且能够运行里面的脚本。

代码讲解

  • LocalShellBackend:本地 Shell 执行后端
  • 参数说明
    • root_dir=".":工作目录根路径,设置为当前目录
    • virtual_mode=True:启用虚拟模式,限制文件访问范围,提高安全性
  • 作用:允许 Agent 执行本地命令和脚本,扩展其能力范围

创建 Deep Agent

核心代码

from deepagents import create_deep_agent

agent = create_deep_agent(
    model="deepseek:deepseek-chat",
    system_prompt="你是于谦,捧话之王,说话坏简介明了直奔主题。",
    tools=[get_time, get_location],
    checkpointer=checkpointer1,
    middleware=[
        SummarizationMiddleware(
            model="deepseek:deepseek-chat",
            trigger=("tokens",1000),
            keep=("messages",3)
        )
    ],
    backend=LocalShellBackend(
        root_dir=".",
        virtual_mode=True
    ),
    skills=["./skills"],
)

跟传统的create_agent比,创建deepagent的方法对应的是create_deep_agent。大多数的传入参数基本都是一样的。

参数详解

参数 说明
model 使用的模型名称,这里使用 DeepSeek 的 deepseek-chat 模型
system_prompt 系统提示词,定义 Agent 的角色和行为风格
tools 工具函数列表,Agent 可以调用这些函数
checkpointer 记忆检查点,用于保存对话状态
middleware 中间件列表,用于处理上下文摘要等任务
backend 执行后端,用于运行本地命令
skills 技能目录列表,加载自定义技能扩展

对话循环

智能体记忆的配置

配合智能体的记忆功能使用的。

config = {"configurable":{"thread_id":"1"}}

这个config是需要放在后续的invoke里的。(其实这里没太想明白,为什么不放在构造deepagent的构造函数里。)

代码讲解

  • thread_id:对话线程标识符
  • 相同的 thread_id 可以延续之前的对话
  • 不同的 thread_id 会开启新的对话线程

主循环逻辑

index=1

while(True):
    print(f"### 第{index}轮对话 ###")
    query = input("请输入:")
    if query == "exit":
        print("退出")
        break
    results=agent.invoke(
        {"messages": [{"role": "user", "content": query}]},
        config=config
    )

    for message in results["messages"]:
        message.pretty_print()

    index+=1

技能系统(Skills)

这里我们演示一个HR的请假系统,相应的代码我们只定义了接口,为了演示方便不做具体的实现以及系统的对接,只返回固定的output。

技能目录结构

通常我们建议单独的一个skills目录保存所有skills,然后通过每个子目录来保存不同的skill。

skills/
└── HR/
    └── SKILL.md

HR 技能的介绍

文件路径skills/HR/SKILL.md

技能元数据

---
name: HR assistant
description: HR 助手
---

这两个配置是每个skill必须都要包含的,包括

  • name:技能的唯一标识符
  • description:技能的简短描述

功能说明

本技能是 HR 系统的 AI 助手,根据系统接口文档和用户的问题,直接调用相应的接口完成操作。当用户说"小赵"时触发。

根据这段声明,我们定义了触发机制为

  • 触发词:"小赵"
  • 当用户在对话中提到"小赵"时,Agent 会自动调用此技能

支持的功能

这部分包含skill里都有什么功能

### 1. 请假
- **功能**:创建新的请假申请
- **需要确认的信息**:
  - 姓名
  - 请假开始时间
  - 请假结束时间
  - 请假类型(病假,事假,年假,婚假,丧假,产假,其他)
- **操作流程**:
  1. 检查用户提供的信息是否完整
  2. 如果有任何信息不完整,依次向用户确认
  3. 所有信息确认后,让用户再次确认所有信息
  4. 调用 `create_leave_application` 函数创建请假申请

根据这段描述我们可以看到,这里我们要求skill

  1. 信息收集

    • 主动询问缺失的信息
    • 一次只问一个问题,避免用户困惑
  2. 信息确认

    • 汇总所有信息展示给用户
    • 等待用户最终确认
  3. 执行操作

    • 调用具体的函数实现业务逻辑

SILLL完整代码

---
name: HR assistant
description: HR 助手
---

# HR 助手

## 功能说明

本技能是HR系统的AI助手,根据系统接口文档和用户的问题,直接调用相应的接口完成操作。当用户说"小赵"时触发。

## 支持的功能

### 1. 请假
- **功能**:创建新的请假申请
- **需要确认的信息**:
  - 姓名
  - 请假开始时间
  - 请假结束时间
  - 请假类型(病假,事假,年假,婚假,丧假,产假,其他)
- **操作流程**:
  1. 检查用户提供的信息是否完整
  2. 如果有任何信息不完整,依次向用户确认
  3. 所有信息确认后,让用户再次确认所有信息
  4. 调用 `create_leave_application` 函数创建请假申请


### 请假代码的具体实现
```python
def create_leave_application(name, start_time, end_time, leave_type):
    """
    创建新的请假申请
    
    参数:
    - name: 姓名
    - start_time: 请假开始时间(格式:YYYY-MM-DD HH:MM)
    - end_time: 请假结束时间(格式:YYYY-MM-DD HH:MM)
    - leave_type: 请假类型(病假,事假,年假,婚假,丧假,产假,其他)
    
    返回:
    - 申请结果字典
    """
    #实现方法略
    return {
        "success": True,
        "message": "请假申请已创建",
        "data": {
            "name": name,
            "start_time": start_time,
            "end_time": end_time,
            "leave_type": leave_type,
            "status": "pending"
        }
    }
```

技能使用示例

用户对话流程

以下是一段测试对话。

我比较喜欢的一个点是,通过skill,以及智能体的加持,对于参数的输入就灵活了很多,在体验上更人性化。比如接口对日期格式的要求是yyyy-MM-dd,跟智能体对话的时候你只要说明天或者后天,那么智能体会根据接口的定义自动转换成符合要求的日期格式。

用户:小赵,我想休一天的假
Agent:好的,我是 HR 助手小赵。请问您的姓名是?

用户:我是哈士奇
Agent:好的,哈士奇。请问您想请哪一天的假?

用户:后天
Agent:好的,后天(2026-05-21)。请问您想请什么类型的假?
       可选类型:病假、事假、年假、婚假、丧假、产假、其他

用户:年假
Agent:请确认以下请假信息:
       - 姓名:哈士奇
       - 请假类型:年假
       - 开始时间:2026-05-21 09:00
       - 结束时间:2026-05-21 18:00
       以上信息是否正确?

用户:正确
Agent:✅ 请假申请已成功创建!
       申请状态:pending(待审批)

关于上下文的汇总,由于需要比较多的智能体对话,所以测试结果不放在这里,感兴趣的朋友可以自己跑下代码,然后在输出部分看智能体是如何summarize历史对话记录的。

关键技术点总结

DeepAgents 架构优势

  1. 模块化设计

    • 工具(Tools):扩展 Agent 能力
    • 中间件(Middleware):处理上下文管理
    • 技能(Skills):实现特定领域功能
    • 后端(Backend):支持本地执行
  2. 记忆管理

    • 通过 Checkpointer 实现状态持久化
    • 支持多线程对话
    • 中间件自动摘要优化上下文
  3. 技能系统

    • 基于 Markdown 文件定义
    • 触发词机制自动激活
    • 支持复杂的多轮交互流程

最佳实践

  1. 系统提示词设计

    • 明确角色定位
    • 定义语言风格
    • 简洁具体
  2. 工具函数编写

    • 函数名清晰描述功能
    • 添加文档字符串
    • 返回值格式统一
  3. 技能开发

    • 明确触发条件
    • 设计完整的交互流程
    • 提供详细的参数说明

常见问题

  1. 中间件重复问题
    • 错误信息:AssertionError: Please remove duplicate middleware instances.
    • 原因:只要使用middleware那么就会报这个错,目前分析是版本的bug。以撰写此文的时间2026年5月18日为准,默认版本是0.6.1,经过我的测试,如果用0.5.1的版本的话就不会有这个问题。
    • 解决:pip卸载默认版本,安装0.5.1这个版本,具体方法可以参考我上一篇笔记。

另目前很多vibe coding生成langchain的deepagents代码都会有很多问题,主要是因为这个东西太新了,很多智能体即使有再牛的上下文系统也不知道该如何去生成正确的代码,所以需要自己去鉴别一下。

总结

目前LangChain的DeepAgents已经支持了跟智能体相关的大多数方法,通过学习DeepAgents,我们也可以顺便理解目前市面上主流的智能体其背后是如何工作的。此文做阶段性的学习总结,方便后续的review以及供vibe coding参考。

参考资料