Skip to content

agent

3 posts with the tag “agent”

DeerFlow 子Agent委派实现说明

DeerFlow的子Agent系统是基于LangGraph构建的任务委派机制,允许主Agent将复杂任务委托给专门的子Agent执行,实现上下文隔离、并行处理和专业化分工。


组件位置职责
执行引擎packages/harness/deerflow/subagents/executor.py子Agent同步/异步执行、线程池管理、任务状态跟踪、超时控制
注册中心packages/harness/deerflow/subagents/registry.py管理可用子Agent配置,支持config.yaml配置覆盖
工具入口packages/harness/deerflow/tools/builtins/task_tool.py对外暴露task工具,是父Agent调用子Agent的统一入口
内置子Agentpackages/harness/deerflow/subagents/builtins/提供两种开箱即用的子Agent类型:general-purpose(通用型)、bash(命令行专家)
限流中间件packages/harness/deerflow/agents/middlewares/subagent_limit_middleware.py强制限制最大并发子Agent数为3,避免资源耗尽

1. 触发阶段:父Agent调用task工具

Section titled “1. 触发阶段:父Agent调用task工具”

当父Agent需要委派任务时,调用task工具,传入参数:

  • description: 3-5字的任务简短描述(用于日志和前端展示)
  • prompt: 给子Agent的详细任务指令,需要具体明确
  • subagent_type: 子Agent类型(general-purposebash
  • 可选max_turns: 子Agent最大交互轮次,覆盖默认配置
  1. 从注册中心获取对应类型的子Agent默认配置
  2. 应用config.yaml中的自定义配置(如超时时间覆盖)
  3. 注入当前已启用的技能提示到子Agent的系统提示词
  4. 若指定了max_turns,覆盖默认配置值

子Agent自动继承父Agent的运行上下文,保持环境一致性:

  • 沙箱状态(sandbox_state):保持文件系统访问权限和路径映射一致
  • 线程数据(thread_data):共享线程级别的配置和状态
  • 线程ID(thread_id):关联到同一个会话线程
  • 模型配置(parent_model):可配置继承父Agent使用的LLM模型
  • 追踪ID(trace_id):统一分布式追踪ID,关联父子Agent的日志
  • 子Agent的工具集通过get_available_tools()获取,但强制关闭子Agent功能subagent_enabled=False),防止递归嵌套调用
  • 根据子Agent配置的工具白名单/黑名单进一步过滤可用工具
    • general-purpose:拥有除task外的所有工具权限
    • bash:仅拥有命令执行相关工具权限
  1. 创建SubagentExecutor执行器实例
  2. 任务提交到双层线程池异步执行:
    • _scheduler_pool(3 worker):负责任务调度、状态管理、超时控制
    • _execution_pool(3 worker):负责实际的子Agent逻辑执行
  3. 子Agent创建独立的LangChain Agent实例,使用对应类型的专用系统提示词,运行在隔离上下文
  4. 以stream模式执行,实时收集AI生成的所有中间消息,用于后续调试和审计
  5. 父Agent调用task工具后会通过5秒间隔轮询等待子Agent执行完成(对当前会话是同步阻塞的),但子Agent运行在独立线程池,不会阻塞其他会话的Agent执行

执行过程中通过SSE流实时推送事件到前端:

  • task_started:任务开始执行
  • task_running:执行中,包含子Agent的中间输出消息(1-based索引)
  • task_completed:任务成功完成,返回最终结果
  • task_failed:任务执行失败,返回错误信息
  • task_timed_out:任务执行超时

子Agent执行完成后,将最终结果返回给父Agent,父Agent可以基于这个结果继续后续处理,完成后自动清理后台任务记录,避免内存泄漏。


  • 子Agent运行在独立的线程和执行上下文,不会污染父Agent的状态
  • 工具集独立配置,权限按需分配
  • 子Agent默认没有task工具权限,无法嵌套调用其他子Agent,避免无限递归
  • 线程池层面的执行超时:可配置,默认15分钟
  • 轮询层面的超时保护:超时时间+60s缓冲,作为兜底机制防止任务卡死
  • 最大并发子Agent数为3,由SubagentLimitMiddleware中间件自动拦截超过限制的工具调用
  • 支持通过配置文件自定义子Agent超时时间
  • 注册中心设计支持扩展更多内置子Agent类型

类型适用场景工具权限
general-purpose复杂多步骤任务、探索性研究、需要多种工具配合的工作task外的所有工具
bashGit操作、构建流程、批量命令执行、大量命令输出的场景仅命令行相关工具

config.yaml中可以配置子Agent的超时时间:

subagents:
enabled: true
timeouts:
general-purpose: 900 # 15分钟
bash: 300 # 5分钟

Agent 是什么?

Agent (智能体) 的定义与业界共识

Section titled “Agent (智能体) 的定义与业界共识”

在人工智能(特别是目前的大模型应用)领域,关于 Agent(智能体) 业界最广泛接受、且对开发者最具有指导意义的定义,可以用一句话概括:

Agent 是一个能够感知环境、进行推理(Reasoning)、自主决策并采取行动(Action)以实现特定目标的智能系统。

如果把大模型(LLM)比作“大脑”,那么 Agent 就是一个拥有大脑、双手(工具)和任务清单的完整“数字员工”。


目前在 LLM 应用开发领域(如 LangChain, AutoGPT, Dify 社区),大家普遍引用 OpenAI 应用研究主管 Lilian Weng 的定义: Agent=LLM(大脑)+Planning(规划)+Memory(记忆)+Tools(工具使用) 这个公式之所以经典,是因为它指出了 Agent 区别于普通 ChatGPT 对话框的核心:它不再只是单纯的“生成文本”,而是具备了“解决问题”的能力。


2. Agent 与传统程序/普通 AI 的区别

Section titled “2. Agent 与传统程序/普通 AI 的区别”

为了区分你的程序是只是一个“工作流(Workflow)”还是一个真正的“智能体(Agent)”,可以看它是否具备以下 3 个核心特征

  • 普通 Chatbot: 用户问一句,它答一句。它是被动的。
  • 工作流 (Workflow): 按照你写死的代码 if A then B 执行。路径是固定的。
  • Agent: 你给它一个模糊的目标(例如:“帮我整理这周所有的数学错题”),它会自己决定先去哪里查数据、怎么分类、如果数据缺失该怎么办。
    • 判据: 遇到意料之外的错误,它能自我修正重试吗?如果能,它就是 Agent。

B. 感知-行动循环 (Perception-Action Loop)

Section titled “B. 感知-行动循环 (Perception-Action Loop)”

这是计算机科学中 Agent 的经典定义(源自 Russell & Norvig 的《人工智能:一种现代方法》)。Agent 不是线性的(Input -> Output),而是循环的

  1. 感知 (Perceive): 看看现在情况咋样?
  2. 思考 (Think): 决定下一步做什么。
  3. 行动 (Act): 调用工具(搜索、代码解释器)。
  4. 观察 (Observe): 看看行动的结果(比如报错了,或者拿到数据了)。
  5. 再思考 (Think Again): 基于观察结果,决定下一步…(循环直到目标达成)。

C. 工具使用能力 (Tool Use / Function Calling)

Section titled “C. 工具使用能力 (Tool Use / Function Calling)”
  • 大模型本身是封闭的“缸中之脑”。
  • Agent 的标志性能力是打破第四面墙,它能根据意图,自主选择调用外部 API(比如你的试题库 API)、操作数据库或浏览网页。

3. 举个通俗的例子:出数学卷子

Section titled “3. 举个通俗的例子:出数学卷子”

假设场景:你要给学生出一套数学卷子。

类型行为模式典型表现
LLM (ChatGPT)纯文本生成你问:“给我出5道初一数学题。”
它答:凭记忆生成文本。可能会算错,可能题目数据不严谨。
(它是百科全书)
Workflow自动化脚本代码逻辑:第一步去数据库随机取5题 -> 第二步拼成 Word -> 第三步发邮件。
(它是流水线机器,如果数据库挂了,它就报错停止)
Agent自主决策你指令:“帮我出一套涵盖‘一元一次方程’难点的卷子。”
它的内心戏
1. “先去检索‘易错点’。” (规划)
2. “查到了,现在去题库搜对应标签。” (工具)
3. “搜到10道,我自己做一遍,挑出最难的5道。” (反思 & 循环)
4. “调用 Python 排版并输出。” (行动)
(它是专业的教务助理)

在开发者的语境下:

Agent 的本质 = 循环执行的大模型逻辑 (Looping LLM)

它不再是一次性的文本生成,而是一个运行环境,在这个环境中,大模型作为控制器,不断地与外部世界交互,直到解决问题。

  • Workflow (工作流): 适合确定性高、流程固定的任务(如:输入题目 -> 翻译 -> 存库)。
  • Agent (智能体): 适合模糊性高、需要动态决策的任务(如:分析这道题,如果算不出来就去搜索,搜索不到就尝试自己推导)。
  • Lilian Weng (OpenAI) 的博文 “LLM Powered Autonomous Agents” (2023)
  • 《人工智能:一种现代方法》(Artificial Intelligence: A Modern Approach)

Prompt技巧:Few-shot

在编写智能体(Agent)或大模型(LLM)的提示词(Prompt)时,Few-shot(少样本提示/少样本学习) 是一个非常核心且高效的概念。

简单来说,Few-shot 就是在给 AI 下达任务指令时,不只给“规则”,还给它看几个“正确答案的例子”。

我们可以把它理解为一种 “类比教学”


1. 直观理解:从 Zero-shot 到 Few-shot

Section titled “1. 直观理解:从 Zero-shot 到 Few-shot”

为了理解 Few-shot,我们需要先看看它的“兄弟”们:

  • Zero-shot(零样本):

    你直接命令 AI 做事,不给任何例子。

    指令: 请将下面这句话翻译成英文:“今天天气真不错。”

    AI: The weather is really nice today.

  • One-shot(单样本):

    你给 AI 一个 例子,让它照猫画虎。

    指令: 请模仿下面的风格将句子翻译成英文。

    示例: “你好吗?” -> “How do you do?” (正式风格)

    任务: “今天天气真不错。”

    AI: The weather is quite pleasant today. (试图模仿正式感)

  • Few-shot(少样本):

    你给 AI 两个或更多(通常 3-5 个) 例子。

    这能帮 AI 锁定非常具体的模式、格式或逻辑。


大语言模型本质上是“文字接龙”的高手,它们非常擅长模式识别(Pattern Matching)。通过提供几个例子,你可以达到以下目的:

  1. 固定格式(关键): 假如你需要 AI 输出 JSON 或特定的代码格式,给例子比写一堆“请不要输出额外文字”的文字说明要有效得多。

  2. 规范风格: 比如你需要“鲁迅风格”或“小红书风格”,给几个样板段落,AI 就能瞬间领悟语调。

  3. 复杂逻辑引导: 对于数学题或推理题,给几个带有“解题步骤”的例子(这叫 Chain-of-Thought Few-shot),能显著提高 AI 的准确率。

  4. 处理边缘情况: 你可以在例子中包含一个“当找不到答案时输出什么”的样本,防止 AI 胡编乱造。


假设你想做一个 “从用户评论中提取情绪和关键词” 的智能体。

❌ 这种是 Zero-shot (效果可能不稳定)

Section titled “❌ 这种是 Zero-shot (效果可能不稳定)”

Prompt: 请分析下面的评论,告诉我用户的情绪是正面还是负面,并提取提到的产品特性。

评论: “这手机屏幕是很清楚,但是电池太不耐用了,用了半天就没电。”

AI 可能回答: “这是一个中性偏负面的评论。提到的特性有屏幕清晰度(正面)和电池续航(负面)。” (问题:回答格式随意,不方便程序后续处理)

✅ 这种是 Few-shot (效果稳定精准)

Section titled “✅ 这种是 Few-shot (效果稳定精准)”

Prompt: 任务:分析用户评论。 输出格式:情绪 (Positive/Negative/Mixed) | 关键词列表

示例 1: 输入:“味道好极了,而且送货很快!” 输出:Positive | [“味道”, “送货速度”]

示例 2: 输入:“衣服质量太差了,线头很多,而且客服不理人。” 输出:Negative | [“质量”, “做工”, “客服服务”]

示例 3: 输入:“虽然价格便宜,但是物流慢得要死。” 输出:Mixed | [“价格”, “物流速度”]

当前任务: 输入:“这手机屏幕是很清楚,但是电池太不耐用了,用了半天就没电。” 输出:

AI 会回答: Mixed | ["屏幕清晰度", "电池续航"] (结果:完全遵循了你设定的“情绪 | [列表]”这种特殊格式)


  1. 样本数量: 通常 3 到 5 个 例子性价比最高。太少(1个)可能导致 AI 过度拟合那个例子的特定内容;太多(几十个)会占用 Token,且收益递减。

  2. 多样性: 例子要覆盖不同的情况。比如上面的例子中,我分别列举了“正面”、“负面”和“混合”三种情况。

  3. 标签明确: 使用 输入:输出: 或者 User:Assistant: 这样清晰的分隔符,让 AI 知道哪里是例子,哪里是正文。

  4. 质量至上: 你的例子必须是完美的。如果例子里有错别字或逻辑错误,AI 会完美地学会这个错误。

Few-shot 就是 “先演示,后提问”

它是提示词工程(Prompt Engineering)中最简单、但提效最明显的手段。当你发现 AI 听不懂你的复杂指令,或者输出格式总是不对时,别再加长篇大论的解释了,直接给它加两个例子试试。