第 02 章

快速入门

几分钟内构建你的第一个 Deep Agent

从安装依赖到运行一个具备规划、搜索和子 Agent 能力的研究型智能体

我们要构建什么

一个能自主规划、搜索、总结的研究型 Agent

传统聊天机器人只能一问一答。但现实中的研究任务需要多步推理、工具调用、上下文管理。Deep Agent 就是为此而生。

传统 LLM 调用

  • 单次问答,没有规划能力
  • 无法自主决定"接下来做什么"
  • 长上下文管理靠手动拼接
  • 复杂任务需要人类逐步指挥

Deep Agent

  • 自动将任务拆解为子任务并规划执行顺序
  • 自主选择工具(搜索、文件读写等)
  • 内置虚拟文件系统管理大量上下文
  • 可生成子 Agent 委派复杂子任务
本章目标:从零开始创建一个 Deep Agent,给它一个搜索工具,让它自主研究并撰写报告。完成本章后,你就拥有了构建复杂 Agent 的基础。
图:传统 LLM 调用与 Deep Agent 数据流对比

前提条件

你必须有

  • 一个模型提供商的 API Key(Gemini、OpenAI、Anthropic 等均可)
  • 一个 Tavily API Key(用于搜索功能,免费注册)
  • Node.js 运行环境

模型要求

  • 模型必须支持 tool calling(工具调用)
  • 推荐:Gemini 3.1 Pro、GPT-5.5、Claude Sonnet 4.6
  • 也支持 Ollama 本地模型

可选但推荐

  • LangChain Docs MCP Server(让 AI 编程助手访问最新文档)
  • LangChain Skills(提升 Agent 在 LangChain 任务上的表现)
注意:Deep Agents 依赖模型的 tool calling 能力。如果你的模型不支持工具调用,Agent 将无法正常运行。请查阅支持的模型列表确认兼容性。

安装依赖

只需一行命令,安装核心包和搜索工具

Deep Agents 的核心包是 deepagents,配合 langchain 和 @langchain/tavily 即可快速启动。

$ npm install deepagents langchain @langchain/core @langchain/tavily

或使用其他包管理器:

$ yarn add deepagents langchain @langchain/core @langchain/tavily
$ pnpm add deepagents langchain @langchain/core @langchain/tavily

各包的作用

包名做什么
deepagentsDeep Agent 核心,包含规划引擎和子 Agent 管理
langchainLLM 调用和工具集成的基础层
@langchain/coreLangChain 核心抽象(消息、工具等)
@langchain/tavilyTavily 搜索 API 的 LangChain 封装

关于搜索提供商

本教程使用 Tavily 作为搜索提供商,但你可以替换为任何搜索 API:

  • DuckDuckGo Search
  • SerpAPI
  • Brave Search

只需修改工具实现即可,Agent 代码不需要变。

配置密钥

配置你的模型提供商和搜索服务的密钥

Deep Agents 通过环境变量读取 API Key。根据你的模型提供商设置对应的变量:

Google Gemini
export GOOGLE_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
OpenAI
export OPENAI_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
Anthropic
export ANTHROPIC_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
DeepSeek
# DeepSeek 通过 @langchain/community 的 ChatDeepSeek 接入
# 或直接使用 "deepseek:模型名" 字符串(如 deepseek:deepseek-chat)
export DEEPSEEK_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"

通过 @langchain/community 的 ChatDeepSeek 或以 deepseek:模型名 字符串接入。具体可用型号与参数以 DeepSeek 官方公告为准。

OpenRouter
export OPENROUTER_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
Fireworks
export FIREWORKS_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
Baseten
export BASETEN_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
Ollama
# 本地使用:Ollama 必须在你的机器上运行
# 云端使用:设置你的 Ollama API Key 以进行托管推理
export OLLAMA_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"
其他提供商
# 设置你的提供商的 API Key
export <PROVIDER>_API_KEY="your-api-key"
export TAVILY_API_KEY="your-tavily-api-key"

Deep Agents 支持所有 LangChain 聊天模型,请设置你的提供商对应的 API Key。

支持的提供商

提供商环境变量
GoogleGOOGLE_API_KEY
OpenAIOPENAI_API_KEY
AnthropicANTHROPIC_API_KEY
DeepSeekDEEPSEEK_API_KEY
OpenRouterOPENROUTER_API_KEY
FireworksFIREWORKS_API_KEY
OllamaOLLAMA_API_KEY

配置格式

创建 Agent 时以 provider:model 格式指定模型:

// Google Gemini
model: "google-genai:gemini-3.1-pro-preview"

// OpenAI
model: "openai:gpt-5.5"

// Anthropic
model: "anthropic:claude-sonnet-4-6"

// DeepSeek(通过 @langchain/community 的 ChatDeepSeek,或直接用 "deepseek:模型名")
model: "deepseek:deepseek-chat"        // 稳妥示例:具体可用型号与参数以 DeepSeek 官方公告为准

// Ollama 本地
model: "ollama:llama3"
常见问题:如果报错 API key not found,请确认环境变量已正确设置。在 Windows 上使用 set 而非 export,或者使用 .env 文件配合 dotenv 包。

创建搜索工具

用 LangChain 的 tool 函数封装 Tavily 搜索能力

工具是 Agent 感知外部世界的手脚。我们用 tool() 函数把 Tavily 搜索封装成 Agent 可调用的工具。

比喻是为了帮你理解——实际上,工具不过是一段定义了 name、description 和 schema 的函数。Agent 通过 LLM 的 tool calling 能力来决定何时调用它,并非真的有"手脚"。

import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { z } from "zod";

// 定义搜索工具:tool() 接收执行函数和元数据两个参数
const internetSearch = tool(
  // 执行函数:每次 Agent 决定搜索时调用
  async ({
    query,                     // 搜索关键词
    maxResults = 5,            // 最多返回几条结果
    topic = "general",         // 搜索类别:general / news / finance
    includeRawContent = false, // 是否包含原始网页内容(更耗 token)
  }: {
    query: string;
    maxResults?: number;
    topic?: "general" | "news" | "finance";
    includeRawContent?: boolean;
  }) => {
    // 创建 Tavily 搜索实例,传入 API Key 和配置
    const tavilySearch = new TavilySearch({
      maxResults,
      tavilyApiKey: process.env.TAVILY_API_KEY,
      includeRawContent,
      topic,
    });
    // _call() 执行搜索并返回结果
    return await tavilySearch._call({ query });
  },
  // 元数据:帮助 LLM 理解工具的用途和参数
  {
    name: "internet_search",        // Agent 调用时的工具名称
    description: "Run a web search", // LLM 据此判断何时该调用此工具
    schema: z.object({
      query: z.string().describe("The search query"),
      maxResults: z.number().optional().default(5)
        .describe("Maximum number of results"),
      topic: z.enum(["general", "news", "finance"])
        .optional().default("general")
        .describe("Search topic category"),
      includeRawContent: z.boolean().optional().default(false)
        .describe("Whether to include raw content"),
    }),
  },
);

工具代码解读

理解 tool() 函数的两个核心部分

第一部分:执行函数

即 tool() 的第一个参数,一个 async 函数:

  • 接收参数:query(搜索词)、maxResults、topic、includeRawContent
  • 内部创建 TavilySearch 实例
  • 调用 _call({ query }) 执行搜索
  • 返回搜索结果给 Agent

第二部分:工具描述

即 tool() 的第二个参数,一个配置对象:

  • name:工具名称,Agent 通过它调用
  • description:工具描述,帮助 LLM 决定何时调用
  • schema:用 Zod 定义参数结构,LLM 据此生成合法调用
关键设计:schema 用 Zod 定义而非手写 JSON Schema,因为 Zod 同时提供类型检查和运行时验证。description 写得越清楚,LLM 就越能准确判断什么时候该调用这个工具。
常见错误:description 太模糊(如 "search stuff")会导致 LLM 在不该调用时调用,或者该调用时不调用。写清楚工具做什么、输入是什么、输出是什么。

创建智能体

用 createDeepAgent() 一行代码组装完整智能体

接下来,用 createDeepAgent() 把模型、工具和系统提示词组合在一起:

import { createDeepAgent } from "deepagents";

// 系统提示词:定义 Agent 的角色、工作方式和工具使用说明
// 这个提示词会叠加在 SDK 内置提示之上,不会替换它
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "google-genai:gemini-3.1-pro-preview",  // 以 "provider:model" 格式指定模型
  tools: [internetSearch],                         // Agent 会自主决定何时调用搜索
  systemPrompt: researchInstructions,              // 你的自定义提示叠加在 SDK 默认提示之上
});
其他模型提供商配置(点击展开)
OpenAI
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "openai:gpt-5.5",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});
Anthropic
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "anthropic:claude-sonnet-4-6",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});
DeepSeek
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "deepseek:deepseek-chat",       // 稳妥示例:具体可用型号以 DeepSeek 官方公告为准
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});

DeepSeek 通过 @langchain/community 的 ChatDeepSeek 接入,或直接使用 deepseek:模型名 字符串。需设置 DEEPSEEK_API_KEY 环境变量。

OpenRouter
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "openrouter:anthropic/claude-sonnet-4-6",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});
Fireworks
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "fireworks:accounts/fireworks/models/qwen3p5-397b-a17b",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});
Baseten
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "baseten:zai-org/GLM-5",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});
Ollama
import { createDeepAgent } from "deepagents";

// 系统提示词:引导 Agent 成为专业研究人员
const researchInstructions = `You are an expert researcher.
Your job is to conduct thorough research
and then write a polished report.

You have access to an internet search tool
as your primary means of gathering information.

## \`internet_search\`

Use this to run an internet search for a given query.
You can specify the max number of results to return,
the topic, and whether raw content should be included.
`;

const agent = createDeepAgent({
  model: "ollama:llama3",
  tools: [internetSearch],
  systemPrompt: researchInstructions,
});
三个必填参数:model(以 provider:model 格式指定)、tools(工具数组)、systemPrompt(系统提示词,引导 Agent 的行为和角色)。就这三样,一个完整的智能体就建好了。

代码逐行解读

理解 createDeepAgent 的每个参数

model 参数

以 "provider:model" 格式传入,例如:

  • "google-genai:gemini-3.1-pro-preview"
  • "openai:gpt-5.5"
  • "anthropic:claude-sonnet-4-6"
  • "deepseek:deepseek-chat"
  • "ollama:llama3"

也可以传入已初始化的模型实例,以自定义参数。

tools 参数

一个包含所有工具的数组。Agent 会根据用户任务自主选择调用哪些工具、调用几次。

本例中只有 internetSearch,但你可以添加更多工具。

systemPrompt 参数

系统提示词决定 Agent 的角色和行为。写好提示词的技巧:

  • 明确角色定位("expert researcher")
  • 描述可用工具及使用方式
  • 规定输出格式和质量标准
提示:系统提示词中列出了 internet_search 工具的使用说明,这帮助 LLM 理解每个参数的用途,从而做出更好的调用决策。

运行 Agent

用 invoke() 启动 Agent,传入用户消息即可

创建好 Agent 后,用 invoke() 方法运行它。传入一个包含用户消息的对象:

const result = await agent.invoke({
  messages: [{ role: "user", content: "What is langgraph?" }],
});

// 打印 Agent 的响应
console.log(result.messages[result.messages.length - 1].content);

输入格式

invoke() 接收一个对象,包含 messages 数组。每条消息有 role 和 content。

你可以传入单条消息,也可以传入完整对话历史。

输出格式

返回结果中的 messages 数组包含了完整的对话历史,包括 Agent 的所有中间步骤。

result.messages 的最后一条就是 Agent 的最终回复。

背后发生了什么:Agent 收到消息后,会自动规划研究步骤、调用搜索工具、整理信息、撰写报告。整个过程你只需要一行 invoke()。

工作原理

Deep Agent 自动执行五个阶段

当你调用 invoke() 后,Deep Agent 会自动执行以下步骤:

1. 规划方案

用 write_todos 工具拆解任务

2. 执行研究

调用 internet_search 收集信息

3. 管理上下文

用文件系统工具存取大量数据

4. 生成子 Agent

委派复杂子任务给专门 Agent

5. 综合报告

整合研究发现为连贯响应

阶段内置工具做什么
规划 write_todos 将研究任务分解为可执行的子任务列表
上下文管理 write_file / read_file 用虚拟文件系统处理大量搜索结果,避免上下文溢出
委派 子 Agent 机制 为复杂子任务创建专门的子 Agent 并行处理
图:Deep Agent 五阶段执行流程

流式输出

实时获取 Agent 执行的每一步更新

invoke() 会等待整个任务完成后才返回。如果你需要实时监控 Agent 的执行过程,可以使用流式输出。

invoke() — 批量模式

  • 等待全部完成后一次性返回
  • 适合后台任务、批处理
  • 用户看不到中间过程

stream() — 流式模式

  • 实时推送每一步的更新
  • 适合前端展示、进度追踪
  • 可观察工具调用和子 Agent 工作
// 流式获取 Agent 执行过程 —— 每完成一步就推送一个事件
const stream = await agent.stream({
  messages: [{ role: "user", content: "What is langgraph?" }],
});

for await (const event of stream) {
  // 每个 event 包含一步更新的信息
  // 事件类型包括:工具调用(tool_calls)、工具结果(tool_results)、LLM 响应等
  console.log(event);
}
流式输出的价值:Deep Agent 基于 LangGraph 的流式功能,能让你渐进式观察输出,审查和调试 Agent 及子 Agent 的工作——包括工具调用、工具结果和 LLM 响应。
图:invoke() 批量模式与 stream() 流式模式对比

调试与追踪

用 LangSmith 可视化查看 Agent 的完整执行过程

当 Agent 行为不符合预期时,LangSmith 能帮你追踪每一个规划步骤、工具调用和子 Agent 委派。

LangSmith 能追踪什么

  • Agent 的任务规划和分解过程
  • 每次工具调用的输入和输出
  • 子 Agent 的创建和委派情况
  • LLM 的每次请求和响应
  • Token 消耗和执行耗时

如何设置

  • 注册 LangSmith 账号
  • 设置环境变量:LANGSMITH_API_KEY
  • 设置 LANGSMITH_TRACING=true
  • 运行 Agent,自动记录追踪
提示:LangSmith 是可选的。开发阶段强烈推荐使用它来调试,但生产环境中不是必须的。

完整代码汇总

从零到运行的所有代码,一个文件搞定

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

// 1. 创建搜索工具 —— 封装 Tavily API 为 LangChain 工具格式
const internetSearch = tool(
  async ({ query, maxResults = 5, topic = "general" }) => {
    const tavilySearch = new TavilySearch({
      maxResults,
      tavilyApiKey: process.env.TAVILY_API_KEY,  // 从环境变量读取密钥
      topic,
    });
    return await tavilySearch._call({ query });    // 执行搜索并返回结果
  },
  {
    name: "internet_search",
    description: "Run a web search",
    schema: z.object({
      query: z.string().describe("The search query"),
    }),
  },
);

// 2. 创建 Deep Agent —— 传入模型、工具和系统提示词
const agent = createDeepAgent({
  model: "google-genai:gemini-3.1-pro-preview",
  tools: [internetSearch],
  systemPrompt: "You are an expert researcher. "
    + "Conduct thorough research and write reports.",
});

// 3. 运行 —— invoke() 等待完整结果后返回
const result = await agent.invoke({
  messages: [{ role: "user", content: "What is langgraph?" }],
});
// result.messages 数组包含完整对话历史,最后一条是 Agent 最终回复
console.log(result.messages[result.messages.length - 1].content);
运行前确保:已设置 GOOGLE_API_KEY(或你选择的提供商 Key)和 TAVILY_API_KEY 环境变量。使用 ESM 模式("type": "module" in package.json)或 .mjs 后缀。
使用 DeepSeek 的完整代码
import { tool } from "langchain";
import { TavilySearch } from "@langchain/tavily";
import { z } from "zod";
import { createDeepAgent } from "deepagents";

// 1. 创建搜索工具 —— 封装 Tavily API 为 LangChain 工具格式
const internetSearch = tool(
  async ({ query, maxResults = 5, topic = "general" }) => {
    const tavilySearch = new TavilySearch({
      maxResults,
      tavilyApiKey: process.env.TAVILY_API_KEY,  // 从环境变量读取密钥
      topic,
    });
    return await tavilySearch._call({ query });    // 执行搜索并返回结果
  },
  {
    name: "internet_search",
    description: "Run a web search",
    schema: z.object({
      query: z.string().describe("The search query"),
    }),
  },
);

// 2. 创建 Deep Agent —— 使用 DeepSeek 模型
const agent = createDeepAgent({
  model: "deepseek:deepseek-chat",       // 稳妥示例:具体可用型号以 DeepSeek 官方公告为准
  tools: [internetSearch],
  systemPrompt: "You are an expert researcher. "
    + "Conduct thorough research and write reports.",
});

// 3. 运行 —— invoke() 等待完整结果后返回
const result = await agent.invoke({
  messages: [{ role: "user", content: "What is langgraph?" }],
});
console.log(result.messages[result.messages.length - 1].content);

DeepSeek 通过 @langchain/community 的 ChatDeepSeek 接入,或直接使用 deepseek:模型名 字符串。需设置 DEEPSEEK_API_KEY 和 TAVILY_API_KEY 环境变量。具体可用型号与参数以 DeepSeek 官方公告为准。

下一步学什么

你已经构建了第一个 Deep Agent,接下来可以深入这些方向

自定义你的 Agent

了解自定义选项,包括自定义系统提示词、工具和子 Agent。让 Agent 更贴合你的业务需求。

必读

添加长期记忆

启用持久化记忆,让 Agent 跨对话记住用户偏好和历史信息。

进阶

部署到生产环境

使用 Managed Deep Agents 在 LangSmith 中创建、运行和管理 Deep Agent 的生产部署。

生产

更多资源