跳到主要内容

文档索引

在以下地址获取完整的文档索引:https://docs.langchain.org.cn/llms.txt

在进一步探索之前,请使用此文件发现所有可用页面。

一个 Deep Agent 可以创建子智能体来委派工作。你可以在 subagents 参数中指定自定义子智能体。子智能体对于上下文隔离(保持主智能体的上下文整洁)和提供专业化指令非常有用。 本页面涵盖了同步子智能体,即主管(supervisor)会阻塞直到子智能体运行结束。对于长时间运行的任务、并行工作流,或者需要中途转向和取消的情况,请参阅异步子智能体

为什么要使用子智能体?

子智能体解决了上下文膨胀问题。当智能体使用输出较大的工具(网页搜索、文件读取、数据库查询)时,上下文窗口会迅速被中间结果填满。子智能体隔离了这些详细的工作——主智能体只接收最终结果,而不是产生结果的几十个工具调用过程。 何时使用子智能体:
  • ✅ 会使主智能体上下文混乱的多步骤任务
  • ✅ 需要自定义指令或工具的专业领域
  • ✅ 需要不同模型能力的任务
  • ✅ 当你希望主智能体专注于高层协调时
何时不使用子智能体
  • ❌ 简单的单步任务
  • ❌ 当你需要维护中间上下文时
  • ❌ 当开销超过收益时

配置

subagents 应该是一个字典列表或 CompiledSubAgent 对象列表。共有两种类型:

默认子智能体

Deep Agents 会自动添加一个同步的 general-purpose 子智能体,除非你已经提供了一个同名的同步子智能体。
  • 要替换它,请传入你自己命名的 general-purpose 子智能体。
  • 要重命名或重新设定自动添加版本的提示词,请在活动的 harness profile 上设置 general_purpose_subagent=GeneralPurposeSubagentProfile(...)
  • 要禁用它,请参阅下面的在没有子智能体的情况下运行

在没有子智能体的情况下运行

要在没有 task 工具的情况下运行智能体,请执行以下两项操作:
  1. 在活动的 harness profile 上设置 general_purpose_subagent=GeneralPurposeSubagentProfile(enabled=False)
  2. create_deep_agent 时通过 subagents= 不传递任何同步子智能体。
Deep Agents 仅在存在至少一个同步子智能体时才会附加 SubAgentMiddleware(和 task 工具)。如果没有默认子智能体也没有调用者提供的子智能体,该智能体将在没有委派功能的情况下运行。 异步子智能体不受影响——它们通过自己的中间件和工具运行,详见异步子智能体
不要在这里尝试使用 excluded_middleware —— SubAgentMiddleware 是必需的基础结构,列出它会引发 ValueError。使用 general_purpose_subagent.enabled = False 开关是受支持的路径。

SubAgent(基于字典)

对于大多数用例,将子智能体定义为符合 SubAgent 规范的字典,并包含以下字段:
字段类型描述
名称str必填。子智能体的唯一标识符。主智能体在调用 task() 工具时使用此名称。子智能体名称会成为 AIMessage 和流式传输的元数据,有助于区分不同的智能体。
descriptionstr必填。描述该子智能体的功能。请具体且以动词为导向。主智能体根据此描述决定何时进行委派。
system_promptstr必填。子智能体的指令。自定义子智能体必须定义自己的提示词。应包括工具使用指南和输出格式要求。
不从主智能体继承。
toolslist[Callable]可选。子智能体可以使用的工具。保持最小化,仅包含所需的工具。
默认继承自主智能体。一旦指定,将完全覆盖继承的工具。
modelstr | BaseChatModel可选。覆盖主智能体的模型。省略则使用主智能体的模型。
默认继承自主智能体。你可以传递模型标识符字符串(如 'openai:gpt-5.4',使用 'provider:model' 格式)或 LangChain 聊天模型对象(await initChatModel("gpt-5.4")new ChatOpenAI({ model: "gpt-5.4" }))。
middlewarelist[Middleware]可选。用于自定义行为、日志记录或速率限制的附加中间件。
不从主智能体继承。
interrupt_ondict[str, bool]可选。为特定工具配置人机交互。子智能体的值会覆盖主智能体。需要检查点。
默认继承自主智能体。子智能体的值会覆盖默认值。
skillslist[str]可选。技能源路径。指定后,子智能体将从这些目录加载技能(例如 ["/skills/research/", "/skills/web-search/"])。这允许子智能体拥有与主智能体不同的技能集。
不从主智能体继承。只有通用子智能体会继承主智能体的技能。当子智能体配置了技能时,它会运行自己的独立 SkillsMiddleware 实例。技能状态是完全隔离的——子智能体加载的技能对父级不可见,反之亦然。
responseFormatResponseFormat可选。子智能体的结构化输出架构。设置后,父级接收到的子智能体结果将是 JSON 而不是自由文本。接受 Zod schema、JSON schema 对象、toolStrategy(...)providerStrategy(...)。参见结构化输出
CLI 用户: 你也可以将子智能体定义为磁盘上的 AGENTS.md 文件,而不是在代码中定义。namedescriptionmodel 字段对应于 YAML 前置内容(frontmatter),而 markdown 正文则成为 system_prompt。文件格式请参阅自定义子智能体Deploy 用户:subagents/ 下将子智能体定义为目录,并带有各自的 deepagents.tomlAGENTS.md。捆绑器会自动发现它们。完整配置参考请参阅部署子智能体

CompiledSubAgent

对于复杂的工作流程,可以使用预构建的 LangGraph 图作为 CompiledSubAgent
字段类型描述
名称str必填。子智能体的唯一标识符。子智能体名称会成为 AIMessage 和流式传输的元数据,有助于区分不同的智能体。
descriptionstr必填。描述该子智能体的功能。
runnableRunnable必填。一个已编译的 LangGraph 图(必须先调用 .compile())。

使用 SubAgent

import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { createDeepAgent, type SubAgent } from "deepagents";
import { z } from "zod";

const internetSearch = tool(
  async ({
    query,
    maxResults = 5,
    topic = "general",
    includeRawContent = false,
  }: {
    query: string;
    maxResults?: number;
    topic?: "general" | "news" | "finance";
    includeRawContent?: boolean;
  }) => {
    const tavilySearch = new TavilySearch({
      maxResults,
      tavilyApiKey: process.env.TAVILY_API_KEY,
      includeRawContent,
      topic,
    });
    return await tavilySearch._call({ query });
  },
  {
    name: "internet_search",
    description: "Run a web search",
    schema: z.object({
      query: z.string().describe("The search query"),
      maxResults: z.number().optional().default(5),
      topic: z
        .enum(["general", "news", "finance"])
        .optional()
        .default("general"),
      includeRawContent: z.boolean().optional().default(false),
    }),
  },
);

const researchSubagent: SubAgent = {
  name: "research-agent",
  description: "Used to research more in depth questions",
  systemPrompt: "You are a great researcher",
  tools: [internetSearch],
  model: "openai:gpt-5.4",  // Optional override, defaults to main agent model
};
const subagents = [researchSubagent];

const agent = createDeepAgent({
  model: "claude-sonnet-4-6",
  subagents,
});

使用 CompiledSubAgent

对于更复杂的用例,你可以通过 CompiledSubAgent 提供自定义子智能体。你可以使用 LangChain 的 create_agent 创建自定义子智能体,或者使用 图 API 制作自定义 LangGraph 图。 如果你正在创建自定义 LangGraph 图,请确保该图具有名为 "messages" 的状态键
import { createDeepAgent, CompiledSubAgent } from "deepagents";
import { createAgent } from "langchain";

// Create a custom agent graph
const customGraph = createAgent({
  model: yourModel,
  tools: specializedTools,
  prompt: "You are a specialized agent for data analysis...",
});

// Use it as a custom subagent
const customSubagent: CompiledSubAgent = {
  name: "data-analyzer",
  description: "Specialized agent for complex data analysis tasks",
  runnable: customGraph,
};

const subagents = [customSubagent];

const agent = createDeepAgent({
  model: "google_genai:gemini-3.1-pro-preview",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
  subagents: subagents,
});

流式处理

流式传输追踪信息时,智能体名称在元数据中以 lc_agent_name 形式提供。在查看追踪信息时,你可以使用此元数据来区分数据来自哪个智能体。 以下示例创建了一个名为 main-agent 的 Deep Agent 和一个名为 research-agent 的子智能体:
import os
from typing import Literal
from tavily import TavilyClient
from deepagents import create_deep_agent

tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])

def internet_search(
    query: str,
    max_results: int = 5,
    topic: Literal["general", "news", "finance"] = "general",
    include_raw_content: bool = False,
):
    """Run a web search"""
    return tavily_client.search(
        query,
        max_results=max_results,
        include_raw_content=include_raw_content,
        topic=topic,
    )

research_subagent = {
    "name": "research-agent",
    "description": "Used to research more in depth questions",
    "system_prompt": "You are a great researcher",
    "tools": [internet_search],
    "model": "google_genai:gemini-3.1-pro-preview",  # Optional override, defaults to main agent model
}
subagents = [research_subagent]

agent = create_deep_agent(
    model="google_genai:gemini-3.1-pro-preview",
    subagents=subagents,
    name="main-agent"
)
当你提示 Deep Agent 时,由子智能体或 Deep Agent 执行的所有智能体运行在其元数据中都将包含智能体名称。在这种情况下,名为 "research-agent" 的子智能体在其任何关联的智能体运行元数据中都将具有 {'lc_agent_name': 'research-agent'} LangSmith 示例追踪显示元数据

结构化输出

子智能体支持结构化输出,因此父级智能体接收的是可预测、可解析的 JSON,而不是自由文本。
子智能体的结构化输出要求 deepagents>=1.8.4
在子智能体配置中传递 responseFormat。当子智能体运行结束时,其结构化响应将被序列化为 JSON,并作为 ToolMessage 内容返回给父级智能体。该架构接受 createAgent 支持的任何内容:Zod schema、JSON schema 对象、toolStrategy(...)providerStrategy(...)
import { z } from "zod";
import { createDeepAgent } from "deepagents";

const ResearchFindings = z.object({
  summary: z.string().describe("Summary of findings"),
  confidence: z.number().describe("Confidence score from 0 to 1"),
  sources: z.array(z.string()).describe("List of source URLs"),
});

const researchSubagent = {
  name: "researcher",
  description: "Researches topics and returns structured findings",
  systemPrompt: "Research the given topic thoroughly. Return your findings.",
  tools: [webSearch],
  responseFormat: ResearchFindings,
};

const agent = createDeepAgent({
  model: "claude-sonnet-4-6",
  subagents: [researchSubagent],
});

const result = await agent.invoke({
  messages: [{ role: "user", content: "Research recent advances in quantum computing" }],
});

// The parent's ToolMessage contains JSON-serialized structured data:
// '{"summary": "...", "confidence": 0.87, "sources": ["https://..."]}'
如果不使用 response_format,父级将直接接收子智能体的最后一条消息文本。使用它后,父级始终能获得符合架构的有效 JSON,这在父级需要以编程方式处理结果或将其传递给下游工具时非常有用。 有关架构类型和策略(工具调用 vs 提供商原生)的完整详细信息,请参阅结构化输出

通用子智能体

除了用户定义的任何子智能体外,每个 Deep Agent 始终可以访问一个 general-purpose(通用)子智能体。该子智能体:
  • 具有与主智能体相同的系统提示词
  • 可以访问所有相同的工具
  • 使用相同的模型(除非被覆盖)
  • 从主智能体继承技能(在配置了技能的情况下)

覆盖通用子智能体

在你的 subagents 列表中包含一个 name: "general-purpose" 的子智能体以替换默认值。使用它为通用子智能体配置不同的模型、工具或系统提示词:
import { createDeepAgent } from "deepagents";

// Main agent uses Gemini; general-purpose subagent uses GPT
const agent = await createDeepAgent({
  model: "google_genai:gemini-3.1-pro-preview",
  tools: [internetSearch],
  subagents: [
    {
      name: "general-purpose",
      description: "General-purpose agent for research and multi-step tasks",
      systemPrompt: "You are a general-purpose assistant.",
      tools: [internetSearch],
      model: "openai:gpt-5.4",  // Different model for delegated tasks
    },
  ],
});
当你提供一个名称为 general-purpose 的子智能体时,系统不会添加默认的通用子智能体,你的规范将完全取代它。 如果你想完全移除内置的通用子智能体而不是替换它,请将活动 harness profile 的通用子智能体 enabled 标志设置为 False

何时使用

通用子智能体非常适合在没有特殊行为需求的情况下进行上下文隔离。主智能体可以将复杂的多步骤任务委派给此子智能体,并获得简洁的结果,而不会被中间工具调用所造成的臃肿所困扰。

示例

主智能体不再进行 10 次网页搜索并用结果填满上下文,而是将其委派给通用子智能体:task(name="general-purpose", task="研究量子计算趋势")。子智能体在内部执行所有搜索,并仅返回摘要。

技能继承

在通过 create_deep_agent 配置技能时:
  • 通用子智能体:自动从主智能体继承技能
  • 自定义子智能体:默认情况下不继承技能——使用 skills 参数为它们赋予自己的技能
只有配置了技能的子智能体才会获得 SkillsMiddleware 实例——不带 skills 参数的自定义子智能体则不会。存在时,技能状态在两个方向上完全隔离:父级的技能对子级不可见,子级的技能也不会传播回父级。
import { createDeepAgent, SubAgent } from "deepagents";

// Research subagent with its own skills
const researchSubagent: SubAgent = {
  name: "researcher",
  description: "Research assistant with specialized skills",
  systemPrompt: "You are a researcher.",
  tools: [webSearch],
  skills: ["/skills/research/", "/skills/web-search/"],  // Subagent-specific skills
};

const agent = createDeepAgent({
  model: "google_genai:gemini-3.1-pro-preview",
  skills: ["/skills/main/"],  // Main agent and GP subagent get these
  subagents: [researchSubagent],  // Gets only /skills/research/ and /skills/web-search/
});

最佳实践

编写清晰的描述

主智能体使用描述来决定调用哪个子智能体。请具体化: 好: "分析财务数据并生成带有置信分数的投资见解" 差: "处理财务事务"

保持系统提示词详细

包含有关如何使用工具和格式化输出的具体指导
const researchSubagent = {
  name: "research-agent",
  description: "Conducts in-depth research using web search and synthesizes findings",
  systemPrompt: `You are a thorough researcher. Your job is to:

  1. Break down the research question into searchable queries
  2. Use internet_search to find relevant information
  3. Synthesize findings into a comprehensive but concise summary
  4. Cite sources when making claims

  Output format:
  - Summary (2-3 paragraphs)
  - Key findings (bullet points)
  - Sources (with URLs)

  Keep your response under 500 words to maintain clean context.`,
  tools: [internetSearch],
};

最小化工具集

只给子智能体提供它们需要的工具。这可以提高专注度和安全性
// ✅ Good: Focused tool set
const emailAgent = {
  name: "email-sender",
  tools: [sendEmail, validateEmail],  // Only email-related
};

// ❌ Bad: Too many tools
const emailAgentBad = {
  name: "email-sender",
  tools: [sendEmail, webSearch, databaseQuery, fileUpload],  // Unfocused
};

根据任务选择模型

不同的模型擅长不同的任务
const subagents = [
  {
    name: "contract-reviewer",
    description: "Reviews legal documents and contracts",
    systemPrompt: "You are an expert legal reviewer...",
    tools: [readDocument, analyzeContract],
    model: "google_genai:gemini-3.1-pro-preview",  // Large context for long documents
  },
  {
    name: "financial-analyst",
    description: "Analyzes financial data and market trends",
    systemPrompt: "You are an expert financial analyst...",
    tools: [getStockPrice, analyzeFundamentals],
    model: "gpt-5.4",  // Better for numerical analysis
  },
];

返回简洁的结果

指示子智能体返回摘要,而非原始数据
const dataAnalyst = {
  systemPrompt: `Analyze the data and return:
  1. Key insights (3-5 bullet points)
  2. Overall confidence score
  3. Recommended next actions

  Do NOT include:
  - Raw data
  - Intermediate calculations
  - Detailed tool outputs

  Keep response under 300 words.`,
};

常见模式

多个专业化子智能体

为不同领域创建专门的子智能体
import { createDeepAgent } from "deepagents";

const subagents = [
  {
    name: "data-collector",
    description: "Gathers raw data from various sources",
    systemPrompt: "Collect comprehensive data on the topic",
    tools: [webSearch, apiCall, databaseQuery],
  },
  {
    name: "data-analyzer",
    description: "Analyzes collected data for insights",
    systemPrompt: "Analyze data and extract key insights",
    tools: [statisticalAnalysis],
  },
  {
    name: "report-writer",
    description: "Writes polished reports from analysis",
    systemPrompt: "Create professional reports from insights",
    tools: [formatDocument],
  },
];

const agent = createDeepAgent({
  model: "google_genai:gemini-3.1-pro-preview",
  systemPrompt: "You coordinate data analysis and reporting. Use subagents for specialized tasks.",
  subagents: subagents,
});
工作流程
  1. 主智能体制定高层计划
  2. 将数据收集委派给 data-collector
  3. 将结果传递给 data-analyzer
  4. 将见解发送给 report-writer
  5. 编译最终输出
每个子智能体都在专注其任务的整洁上下文中工作。

上下文管理

当你使用运行时上下文(runtime context)调用父级智能体时,该上下文会自动传播到所有子智能体。每个子智能体运行都会接收到你在父级 invoke / ainvoke 调用中传递的相同运行时上下文。 这意味着在任何子智能体内运行的工具都可以访问你提供给父级的相同上下文值:
import { createDeepAgent } from "deepagents";
import { tool } from "langchain";
import type { ToolRuntime } from "@langchain/core/tools";
import { z } from "zod";

const contextSchema = z.object({
  userId: z.string(),
  sessionId: z.string(),
});

const getUserData = tool(
  async (input, runtime: ToolRuntime<unknown, typeof contextSchema>) => {
    const userId = runtime.context?.userId;
    return `Data for user ${userId}: ${input.query}`;
  },
  {
    name: "get_user_data",
    description: "Fetch data for the current user",
    schema: z.object({ query: z.string() }),
  }
);

const researchSubagent = {
  name: "researcher",
  description: "Conducts research for the current user",
  systemPrompt: "You are a research assistant.",
  tools: [getUserData],
};

const agent = createDeepAgent({
  model: "google_genai:gemini-3.1-pro-preview",
  subagents: [researchSubagent],
  contextSchema,
});

// Context flows to the researcher subagent and its tools automatically
const result = await agent.invoke(
  { messages: [new HumanMessage("Look up my recent activity")] },
  { context: { userId: "user-123", sessionId: "abc" } },
);

每个子智能体的上下文

所有子智能体都会接收到相同的父级上下文。要传递特定于某个子智能体的配置,请在扁平的 context 映射中使用命名空间键(例如 researcher:max_depth),或者在你的上下文类型上将这些设置建模为单独的字段。
import { tool } from "langchain";
import type { ToolRuntime } from "@langchain/core/tools";
import { z } from "zod";

const contextSchema = z.object({
  userId: z.string(),
  researcherMaxDepth: z.number().optional(),
  factCheckerStrictMode: z.boolean().optional(),
});

const result = await agent.invoke(
  { messages: [new HumanMessage("Research this and verify the claims")] },
  {
    context: {
      userId: "user-123",                        // shared by all agents
      "researcher:maxDepth": 3,                  // only for researcher
      "fact-checker:strictMode": true,           // only for fact-checker
    },
  },
);

const verifyClaim = tool(
  async (input, runtime: ToolRuntime<unknown, typeof contextSchema>) => {
    const strictMode = runtime.context?.factCheckerStrictMode ?? false;
    if (strictMode) {
      return strictVerification(input.claim);
    }
    return basicVerification(input.claim);
  },
  {
    name: "verify_claim",
    description: "Verify a factual claim",
    schema: z.object({ claim: z.string() }),
  }
);

识别哪个子智能体调用了工具

当父级和多个子智能体共享同一个工具时,你可以使用 lc_agent_name 元数据(与流式传输中使用的值相同)来确定是哪个智能体发起的调用。
import { tool } from "langchain";
import type { ToolRuntime } from "@langchain/core/tools";

const sharedLookup = tool(
  async (input, runtime: ToolRuntime) => {
    const agentName = runtime.config?.metadata?.lc_agent_name;
    if (agentName === "fact-checker") {
      return strictLookup(input.query);
    }
    return generalLookup(input.query);
  },
  {
    name: "shared_lookup",
    description: "Look up information from various sources",
    schema: z.object({ query: z.string() }),
  }
);
你可以结合使用这两种模式——从 runtime.context 读取智能体特定的设置,并在分支工具行为时从 runtime.config 元数据中读取 lc_agent_name
const flexibleSearch = tool(
  async (input, runtime: ToolRuntime<unknown, typeof contextSchema>) => {
    const agentName = runtime.config?.metadata?.lc_agent_name ?? "unknown";
    const ctx = runtime.context;
    const maxResults =
      agentName === "researcher" ? ctx?.researcherMaxDepth ?? 5 : 5;
    const includeRaw = false;

    return performSearch(input.query, { maxResults, includeRaw });
  },
  {
    name: "flexible_search",
    description: "Search with agent-specific settings",
    schema: z.object({ query: z.string() }),
  }
);

故障排除

子智能体未被调用

问题:主智能体尝试自己完成工作而不是委派。 解决方案
  1. 使描述更加具体
    // ✅ Good
    { name: "research-specialist", description: "Conducts in-depth research on specific topics using web search. Use when you need detailed information that requires multiple searches." }
    
    // ❌ Bad
    { name: "helper", description: "helps with stuff" }
    
  2. 指示主智能体进行委派
    const agent = createDeepAgent({
      systemPrompt: `...your instructions...
    
      IMPORTANT: For complex tasks, delegate to your subagents using the task() tool.
      This keeps your context clean and improves results.`,
      subagents: [...]
    });
    

上下文仍然臃肿

问题:尽管使用了子智能体,上下文仍然被填满。 解决方案
  1. 指示子智能体返回简洁的结果
    systemPrompt: `...
    
    IMPORTANT: Return only the essential summary.
    Do NOT include raw data, intermediate search results, or detailed tool outputs.
    Your response should be under 500 words.`
    
  2. 为大数据使用文件系统
    systemPrompt: `When you gather large amounts of data:
    1. Save raw data to /data/raw_results.txt
    2. Process and analyze the data
    3. Return only the analysis summary
    
    This keeps context clean.`
    

选择了错误的子智能体

问题:主智能体为任务调用了不合适的子智能体。 解决方案:在描述中清晰地区分子智能体:
const subagents = [
  {
    name: "quick-researcher",
    description: "For simple, quick research questions that need 1-2 searches. Use when you need basic facts or definitions.",
  },
  {
    name: "deep-researcher",
    description: "For complex, in-depth research requiring multiple searches, synthesis, and analysis. Use for comprehensive reports.",
  }
];
:::
© . This site is unofficial and not affiliated with LangChain, Inc.