lead_agent 模块是 DeerFlow 的主代理引擎,负责根据用户请求创建、配置并返回一个可执行的 LangGraph Agent,具体的代码位置:deer-flow\backend\packages\harness\deerflow\agents\lead_agent
01 主要文件
__init__.py:导出make_lead_agent
agent.py:Lead Agent 工厂 — 创建 LangGraph Agen
prompt.py:系统提示词模板 + 技能加载管理
agent.py中的make_lead_agent(config)是主流程的入口,整个调用链如下:
make_lead_agent(config)└─> _make_lead_agent(config, app_config)├─ 1. 解析运行时配置├─ 2. 解析模型名称├─ 3. 加载工具(过滤 + 延迟工具处理)├─ 4. 构建中间件链├─ 5. 生成系统提示词└─ 6. create_agent() 返回 LangGraph Agent
02 解析运行时配置
主要从 RunnableConfig.configurable 和 config.context 合并获取,主要获取下面的内容:
model_name/model:指定模型名称thinking_enabled:是否启用 extended thinkingreasoning_effort:reasoning 强度is_plan_mode:是否启用 TodoList 任务跟踪subagent_enabled:是否启用子代理委托max_concurrent_subagents:子代理并发上限(默认3)is_bootstrap: 是否为引导模式(创建新agent)agent_name:自定义 agent 名称
RunnableConfig 是 LangChain 的标准类型,来自 langchain_core.runnable,是 LangGraph 的统一配置容器,而 _get_runtime_config 把里面分散的配置项(configurable + context)合并成一个扁平的 dict,方便 agent 内部用 cfg.get("xxx") 读取。
举例说明:
当用户发起请求时,config大概如下所示:
config = {"configurable": {"model_name": "gpt-4o","thinking_enabled": True,"is_plan_mode": False,"subagent_enabled": True,"agent_name": "my-agent",},"context": {"user_id": "user-123","thread_id": "thread-456",},"metadata": {"session_id": "sess-789",},}
03 模型解析 - _resolve_model_name
请求模型 → agent_config模型 → 全局默认模型
如果请求的模型不在配置中,记录 warning 并 fallback 到默认模型
如果没有配置任何模型,抛出异常
04 技能 - skill
1)_available_skill_names(agent_config, is_bootstrap: bool)
agent_config = load_agent_config(agent_name) if not is_bootstrap else Noneavailable_skills = _available_skill_names(agent_config, is_bootstrap)
_available_skill_names可以简单成根据智能体名称获取对应的可支持的skills。
load_agent_config(agent_name)函数实现了从磁盘加载自定义Agent的配置文件,返回AgentConfig对象:
name = "my-agent"model = "gpt-4o"tool_groups = ["coding"]skills = ["code-assistant", "web-research"]
agent_config 后续用于:
1. 获取自定义模型 agent_model_name = agent_config.model if agent_config and agent_config.model else None
2. 获取工具组合 tool_groups = agent_config.tool_groups if agent_config else None
3. 获取可用技能列表(结合 _available_skill_names) available_skills = set(agent_config.skills) if agent_config and agent_config.skills is not None else None
2)_load_enabled_skills_for_tool_policy
说明:该函数实现了技能驱动的工具控制策略机制,简单来说就是 每个 Skill 对象有一个 allowed_tools,一旦有任何技能声明了 allowed_tools,遗留的"允许所有工具"行为就被禁用。
返回的数据类型:
Skill(name=name,description=description,license=license_text,skill_dir=skill_file.parent,skill_file=skill_file,relative_path=relative_path or Path(skill_file.parent.name),category=category,allowed_tools=allowed_tools,enabled=True, # Actual state comes from the extensions config file.)
上面allowed_tools是工具过滤的依据之一。
举例子说明:
假设 extensions_config.json 中启用了两个技能:技能 A (web-research/SKILL.md):---name: web-researchdescription: Web research skilllicense: MITallowed_tools:- tavily-search- jina-reader技能 B (code-assistant/SKILL.md):---name: code-assistantdescription: Code assistant skilllicense: MITallowed_tools:- bash- read_file- write_file结果:- 只有这 5 个工具可用:tavily-search, jina-reader, bash, read_file, write_file- 其他所有工具(如 present_files, ask_clarification 等)都会被过滤掉
这个机制让 DeerFlow 能够:
细粒度工具控制 - 不同技能绑定不同工具集
安全隔离 - 防止 Agent 越权使用未授权的工具
按需加载 - 只加载当前上下文需要的工具
3)注入系统提示词
skills_section = get_skills_prompt_section(available_skills, app_config=app_config)
get_skills_prompt_section 函数用于生成技能系统的提示词片段,告诉 LLM 有哪些技能可用以及如何使用它们。
生成的提示词结构如下:
<skill_system>You have access to skills that provide optimized workflows for specific tasks. Each skill contains best practices, frameworks, and references to additional resources.**Progressive Loading Pattern:**1. When a user query matches a skill's use case, immediately call `read_file` on the skill's main file using the path attribute provided in the skill tag below2. Read and understand the skill's workflow and instructions3. The skill file contains references to external resources under the same folder4. Load referenced resources only when needed during execution5. Follow the skill's instructions precisely**Skills are located at:** /mnt/skills## Skill Self-EvolutionAfter completing a task, consider creating or updating a skill when:- The task required 5+ tool calls to resolve- You overcame non-obvious errors or pitfalls- The user corrected your approach and the corrected version worked- You discovered a non-trivial, recurring workflowIf you used a skill and encountered issues not covered by it, patch it immediately.Prefer patch over edit. Before creating a new skill, confirm with the user first.Skip simple one-off tasks.<available_skills><skill><name>web-research</name><description>Web research skill [built-in]</description><location>/mnt/skills/public/web-research/SKILL.md</location></skill><skill><name>code-assistant</name><description>Code assistant skill [custom, editable]</description><location>/mnt/skills/custom/code-assistant/SKILL.md</location></skill></available_skills></skill_system>
05 工具 - tool
raw tools
函数get_available_tools(),获取所有原始工具:config工具、Built-in工具、MCP工具、ACP工具、subagent工具,工具类型详细说明:
Config 工具:config.yaml 中定义的工具
Built-in 工具:内置工具,在项目代码中实现,如present_file_tool, ask_clarification_tool
MCP 工具:已启用的 MCP 服务器工具,get_cached_mcp_tools()
ACP 工具 :ACP 外部代理工具,build_invoke_acp_agent_tool()
工具过滤
filter_tools_by_skill_allowed_tools(),按照技能策略进行过滤
处理延迟加载工具
_assemble_deferred()该函数实现了延迟工具加载机制,用于MCP工具的按需加载。
要解决的核心问题:
MCP 工具数量可能很多,如果全部在启动时绑定到模型,会导致:
模型上下文窗口浪费在庞大的工具 schema 上
工具选择困难(选择超载)
性能下降
解决方案:延迟加载
初始状态:
Agent 只知道"有这些 MCP 工具的名称"
不知道具体 schema(不占用上下文)
需要使用时:
Agent 调用 tool_search 工具查询
返回完整 schema,工具变为可调用
06 总结
lead_agent 是 DeerFlow 的核心编排引擎:
通过 make_lead_agent() 创建一个配置完善的 LangGraph Agent
系统提示词通过 apply_prompt_template() 动态组装(技能、子代理、记忆等)
中间件链负责截面横切关注点(记忆、摘要、循环检测、安全等)
支持 Thinking Mode、Plan Mode、Subagent Mode 三种运行模式
通过 Defer Tool 机制支持 MCP 工具的延迟加载
夜雨聆风