跳到主要内容

文档索引

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

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

技能是可重用的代理功能,提供专门的工作流程和领域知识。
技能需要 deepagents>=1.7.0
您可以使用 Agent Skills 为您的 Deep Agent 提供新功能和专业知识。有关旨在提高代理在 LangChain 生态系统任务中表现的现成技能,请查看 LangChain Skills 仓库。 Deep Agent 技能遵循 Agent Skills 规范

什么是技能

技能是一个文件夹目录,其中每个文件夹包含一个或多个文件,这些文件提供了代理可以使用的上下文
  • 包含有关该技能说明和元数据的 SKILL.md 文件
  • 附加脚本(可选)
  • 附加参考信息,如文档(可选)
  • 附加资产,如模板和其他资源(可选)
任何附加资产(脚本、文档、模板或其他资源)必须在 SKILL.md 文件中引用,并附带有关文件内容及其使用方法的信息,以便代理决定何时使用它们。

技能的工作原理

当您创建 Deep Agent 时,可以传入包含技能的目录列表。当代理启动时,它会读取每个 SKILL.md 文件的元数据(frontmatter)。 当代理收到提示词时,它会检查在满足该提示词的过程中是否可以使用任何技能。如果找到匹配的提示词,它会随后查看剩余的技能文件。这种仅在需要时才查阅技能信息的模式称为渐进式披露(progressive disclosure)

示例

您可能拥有一个包含“以特定方式使用文档网站”技能的技能文件夹,以及另一个用于搜索 arXiv 预印本研究论文库的技能
    skills/
    ├── langgraph-docs
    │   └── SKILL.md
    └── arxiv_search
        ├── SKILL.md
        └── arxiv_search.ts # code for searching arXiv
SKILL.md 文件总是遵循相同的模式,以元数据(frontmatter)开头,后面紧跟该技能的说明。 以下示例展示了一个技能,该技能提供了有关在收到提示时如何提供相关 LangGraph 文档的说明:
---
name: langgraph-docs
description: Use this skill for requests related to LangGraph in order to fetch relevant documentation to provide accurate, up-to-date guidance.
---

# langgraph-docs

## Overview

This skill explains how to access LangGraph Python documentation to help answer questions and guide implementation.

## Instructions

### 1. Fetch the Documentation Index

Use the fetch_url tool to read the following URL:
https://docs.langchain.org.cn/llms.txt

This provides a structured list of all available documentation with descriptions.

### 2. Select Relevant Documentation

Based on the question, identify 2-4 most relevant documentation URLs from the index. Prioritize:

- Specific how-to guides for implementation questions
- Core concept pages for understanding questions
- Tutorials for end-to-end examples
- Reference docs for API details

### 3. Fetch Selected Documentation

Use the fetch_url tool to read the selected documentation URLs.

### 4. Provide Accurate Guidance

After reading the documentation, complete the user's request.
更多技能示例,请参阅 Deep Agents 示例技能
重要提示有关编写技能文件时的约束和最佳实践,请参考完整的 Agent Skills 规范。值得注意的是:
  • 如果 description 字段超过 1024 个字符,将被截断。
  • 在 Deep Agents 中,SKILL.md 文件必须小于 10 MB。超过此限制的文件在加载技能时会被跳过。

完整示例

以下示例展示了一个使用所有可用元数据字段的 SKILL.md 文件
---
name: langgraph-docs
description: Use this skill for requests related to LangGraph in order to fetch relevant documentation to provide accurate, up-to-date guidance.
license: MIT
compatibility: Requires internet access for fetching documentation URLs
metadata:
  author: langchain
  version: "1.0"
allowed-tools: fetch_url
---

# langgraph-docs

## Overview

This skill explains how to access LangGraph Python documentation to help answer questions and guide implementation.

## Instructions

### 1. Fetch the documentation index

Use the fetch_url tool to read the following URL:
https://docs.langchain.org.cn/llms.txt

This provides a structured list of all available documentation with descriptions.

### 2. Select relevant documentation

Based on the question, identify 2-4 most relevant documentation URLs from the index. Prioritize:

- Specific how-to guides for implementation questions
- Core concept pages for understanding questions
- Tutorials for end-to-end examples
- Reference docs for API details

### 3. Fetch selected documentation

Use the fetch_url tool to read the selected documentation URLs.

### 4. Provide accurate guidance

After reading the documentation, complete the user's request.

用法

在创建 Deep Agent 时传入技能目录
import { createDeepAgent, type FileData } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";

const checkpointer = new MemorySaver();

function createFileData(content: string): FileData {
  const now = new Date().toISOString();
  return {
    content: content.split("\n"),
    created_at: now,
    modified_at: now,
  };
}

const skillsFiles: Record<string, FileData> = {};

const skillUrl =
  "https://raw.githubusercontent.com/langchain-ai/deepagentsjs/refs/heads/main/examples/skills/langgraph-docs/SKILL.md";
const response = await fetch(skillUrl);
const skillContent = await response.text();

skillsFiles["/skills/langgraph-docs/SKILL.md"] = createFileData(skillContent);

const agent = await createDeepAgent({
  checkpointer,
  // IMPORTANT: deepagents skill source paths are virtual (POSIX) paths relative to the backend root.
  skills: ["/skills/"],
});

const config = {
  configurable: {
    thread_id: `thread-${Date.now()}`,
  },
};

const result = await agent.invoke(
  {
    messages: [
      {
        role: "user",
        content: "what is langraph? Use the langgraph-docs skill if available.",
      },
    ],
    files: skillsFiles,
  },
  config,
);
skills
list[str]
技能来源路径列表。路径必须使用正斜杠指定,并且是相对于后端根目录的。
  • 如果省略,则不会加载任何技能。
  • 使用 StateBackend(默认)时,请通过 invoke(files={...}) 提供技能文件。
  • 使用 FilesystemBackend 时,技能将从相对于后端 root_dir 的磁盘路径中加载。
对于同名的技能,后面的来源会覆盖前面的来源(最后加载的生效)。
SDK 仅加载您在 skills 中传入的来源。它不会自动扫描 CLI 目录,例如 ~/.deepagents/...~/.agents/...有关 CLI 存储惯例,请参阅 应用数据
如果您想在 SDK 代码中实现 CLI 风格的分层,请明确按照优先级从低到高的顺序传入所有所需的来源
[
"<user-home>/.deepagents/{agent}/skills/",
"<user-home>/.agents/skills/",
"<project-root>/.deepagents/skills/",
"<project-root>/.agents/skills/",
]
然后在创建代理时,将该有序列表作为 skills 传入。

来源优先级

当多个技能来源包含同名技能时,在 skills 数组中靠后列出的来源中的技能具有优先权(最后生效)。这允许您对来自不同来源的技能进行分层。
// If both sources contain a skill named "web-search",
// the one from "/skills/project/" wins (loaded last).
const agent = await createDeepAgent({
  skills: ["/skills/user/", "/skills/project/"],
  ...
});

子代理的技能

当您使用 子代理 时,您可以配置每种类型可以访问哪些技能
  • 通用子代理:当您将 skills 传递给 create_deep_agent 时,它会自动继承主代理的技能。无需额外配置。
  • 自定义子代理:不会继承主代理的技能。请在每个子代理定义中添加一个 skills 参数,并指定该子代理的技能来源路径。
技能状态是完全隔离的:主代理的技能对子代理不可见,子代理的技能对主代理也不可见。
const researchSubagent = {
  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 = await createDeepAgent({
  model: "google_genai:gemini-3.1-pro-preview",
  skills: ["/skills/main/"],  // Main agent and GP subagent get these
  subagents: [researchSubagent],  // Researcher gets only its own skills
});
有关子代理配置和技能继承的更多信息,请参阅 子代理

代理所看到的内容

当配置了技能后,“技能系统”部分会被注入到代理的系统提示词中。代理利用此信息遵循三个步骤的过程
  1. 匹配(Match)— 当用户提示到达时,代理会检查是否有技能的描述与任务相匹配。
  2. 读取(Read)— 如果某项技能适用,代理会使用其技能列表中显示的路径读取完整的 SKILL.md 文件。
  3. 执行(Execute)— 代理遵循技能说明,并根据需要访问任何配套文件(脚本、模板、参考文档)。
SKILL.md 的元数据中编写清晰、具体的描述。代理仅根据描述来决定是否使用某项技能——详细的描述能带来更好的技能匹配效果。

在沙箱中执行技能脚本

技能可以在 SKILL.md 文件旁边包含脚本,例如执行搜索或数据转换的 Python 文件。代理可以从任何后端读取这些脚本,但要执行它们,代理需要访问 shell —— 而这只有 沙箱后端 才能提供。 当您使用 CompositeBackend 将技能路由到 StoreBackend 进行持久化,同时以沙箱作为默认后端时,技能文件位于存储中,而不是代码运行的沙箱中。为了使沙箱能够使用这些脚本,您必须使用 自定义中间件 在代理启动前将技能脚本上传到沙箱中:
import { readFile, readdir } from "node:fs/promises";
import { join, posix, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";

import { createMiddleware } from "langchain";
import {
  CompositeBackend,
  createDeepAgent,
  type FileData,
  StoreBackend,
} from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";

import { DaytonaSandbox } from "@langchain/daytona";

/** Identical skill bundles for every user: one shared store namespace. */
const SKILLS_SHARED_NAMESPACE = ["skills", "builtin"] as const;

function createFileData(content: string): FileData {
  const now = new Date().toISOString();
  return {
    content: content.split("\n"),
    created_at: now,
    modified_at: now,
  };
}

function normalizeSkillsStoreKey(key: string): string {
  const k = String(key);
  if (k.includes("..") || /[*?]/.test(k)) {
    throw new Error(`Invalid key: ${key}`);
  }
  return k.startsWith("/") ? k : `/${k}`;
}

async function walkFiles(dir: string): Promise<string[]> {
  const entries = await readdir(dir, { withFileTypes: true });
  const files: string[] = [];
  for (const entry of entries) {
    const fullPath = join(dir, entry.name);
    if (entry.isDirectory()) {
      files.push(...(await walkFiles(fullPath)));
    } else if (entry.isFile()) {
      files.push(fullPath);
    }
  }
  return files.sort((a, b) => a.localeCompare(b));
}

/** Load canonical skill files from disk into the shared store namespace (run once at deploy).
 *  You can retrieve skills from any source (local filesystem, remote URL, etc.).
 */
async function seedSkillStore(store: InMemoryStore) {
  const moduleDir = resolve(fileURLToPath(new URL(".", import.meta.url)));
  const skillsDir = resolve(moduleDir, "skills");
  const filePaths = await walkFiles(skillsDir);
  for (const filePath of filePaths) {
    const rel = relative(skillsDir, filePath);
    // StoreBackend keys are paths *relative to the routed backend root*.
    // CompositeBackend strips the route prefix (`/skills/`) before delegating,
    // so store keys should look like "/<skillname>/SKILL.md".
    const key = `/${posix.normalize(rel.split("\\").join("/"))}`;
    const content = await readFile(filePath, "utf8");
    await store.put([...SKILLS_SHARED_NAMESPACE], key, createFileData(content));
  }
}

/** Copy shared skill files from the store into the sandbox before each agent run. */
function createSkillSandboxSyncMiddleware(backend: CompositeBackend) {
  return createMiddleware({
    name: "SkillSandboxSyncMiddleware",
    beforeAgent: async (state, runtime) => {
      const store = (runtime as any).store;
      if (!store) {
        throw new Error(
          "Store is required for syncing skills into the sandbox. " +
            "Pass `store` to createDeepAgent and ensure your runtime provides it.",
        );
      }

      const encoder = new TextEncoder();
      const files: Array<[string, Uint8Array]> = [];

      for (const item of await store.search([...SKILLS_SHARED_NAMESPACE])) {
        const normalized = normalizeSkillsStoreKey(String(item.key));
        const data = item.value as FileData;
        // CompositeBackend routes paths and batches uploads to the right backend.
        files.push([
          `/skills${normalized}`,
          encoder.encode(data.content.join("\n")),
        ]);
      }

      if (files.length > 0) await backend.uploadFiles(files);

      return state;
    },
  });
}

async function main() {
  const store = new InMemoryStore();
  await seedSkillStore(store);

  const sandbox = await DaytonaSandbox.create({
    language: "python",
    timeout: 300,
  });

  const backend = new CompositeBackend(sandbox, {
    "/skills/": new StoreBackend({
      store,
      namespace: () => [...SKILLS_SHARED_NAMESPACE],
    } as any),
  });

  try {
    const agent = await createDeepAgent({
      model: "google-genai:gemini-3.1-pro-preview",
      backend,
      skills: ["/skills/"],
      store,
      middleware: [createSkillSandboxSyncMiddleware(backend)],
    });

  } finally {
    await sandbox.close();
  }
}

main().catch((err) => {
  console.error(err);
  process.exitCode = 1;
});
中间件的 beforeAgent 钩子在每次代理调用之前运行,从共享命名空间读取技能文件并将其上传到沙箱文件系统中。一旦同步,代理就可以像沙箱中的任何其他文件一样使用 execute 工具来执行脚本。 有关同步 记忆 的更完整双向同步示例,请参阅 通过自定义中间件同步技能和记忆

技能与记忆的区别

技能和 记忆 (AGENTS.md 文件) 的用途不同
技能内存
目的通过渐进式披露发现的按需功能启动时始终加载的持久化上下文
加载方式仅在代理确定相关性时读取始终注入系统提示词中
格式命名目录中的 SKILL.mdAGENTS.md 文件
分层用户 → 项目(最后生效)用户 → 项目(合并)
使用场景说明是任务特定的,且可能很大上下文始终相关(项目惯例、偏好)

何时使用技能与工具

以下是使用工具和技能的一些通用准则
  • 当上下文较多时,使用技能以减少系统提示词中的 Token 数量。
  • 使用技能将功能捆绑成更大的操作,并提供超出单一工具描述的额外上下文。
  • 如果代理无法访问文件系统,请使用工具。

© . This site is unofficial and not affiliated with LangChain, Inc.