> ## Documentation Index
> Fetch the complete documentation index at: https://cndoc-langchain.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 构建内容生成代理

> 构建一个具有品牌记忆、技能、子代理和图像生成功能的内容写作代理

## 概述

本指南演示如何使用 [Deep Agents](/oss/javascript/deepagents) 从零开始构建一个内容写作代理。

你构建的代理将：

1. 从 `AGENTS.md` 和技能文件夹加载语音和工作流规则
2. 将网络研究任务委托给具有 `web_search` 功能的专用子代理
3. 根据加载的技能起草博客或社交内容
4. 使用 Gemini 生成封面或社交图片，并将文件保存在项目目录下

本教程中的代码集成了图像生成工具和文件系统后端，以便代理可以在项目目录下读写文章、研究笔记和图片。有关完整的可运行项目，请参阅 [content-builder-agent](https://github.com/langchain-ai/deepagents/tree/main/examples/content-builder-agent) 示例。

### 核心概念

本教程涵盖：

* 用于 TODO 的[长期记忆](/oss/javascript/deepagents/long-term-memory)
* 用于 TODO 的[技能](/oss/javascript/deepagents/skills)
* 用于 TODO 的[子代理](/oss/javascript/deepagents/subagents)
* 用于文件读写的[文件系统后端](/oss/javascript/deepagents/backends)
* 用于搜索和图像生成的自定义[工具](/oss/javascript/langchain/tools)

## 前提条件

API 密钥：

* Anthropic (Claude) 或其他提供商的 API 密钥
* 用于使用 `gemini-2.5-flash-image` 进行图像生成的 Google (Gemini) 密钥
* 用于网络搜索的 [Tavily](https://www.tavily.com/)（免费套餐）
* 用于跟踪的 [LangSmith](https://smith.langchain.com/)（可选）

Node.js 18 或更高版本。

## 设置

<Steps>
  <Step title="创建项目目录">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    mkdir content-builder-agent
    cd content-builder-agent
    ```
  </Step>

  <Step title="安装依赖">
    <CodeGroup>
      ```bash npm wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      npm install deepagents @langchain/core @langchain/anthropic @google/generative-ai tavily zod tsx
      ```

      ```bash yarn wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      yarn add deepagents @langchain/core @langchain/anthropic @google/generative-ai tavily zod tsx
      ```
    </CodeGroup>

    添加 `tsx` 以运行 `content_writer.ts`。`--input-type=module` 标志仅适用于 `--eval`、`--print` 或标准输入，不适用于脚本文件路径。

    安装 `@langchain/anthropic`，以便 LangChain 可以加载 `createDeepAgent` 使用的默认 Claude 模型。
  </Step>

  <Step title="设置 API 密钥">
    ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    export ANTHROPIC_API_KEY="your_anthropic_api_key"
    export GOOGLE_API_KEY="your_google_api_key"
    export TAVILY_API_KEY="your_tavily_api_key"           # 可选
    export LANGSMITH_API_KEY="your_langsmith_api_key"     # 可选
    ```
  </Step>
</Steps>

## 添加配置文件

该示例将行为保留在三种文件中：记忆、技能和子代理定义。

<Steps>
  <Step title="添加 AGENTS.md">
    在项目根目录创建 `AGENTS.md`。
    当你稍后创建代理并指定此文件作为[记忆](/oss/javascript/deepagents/long-term-memory)参数的一部分时，它会被加载到系统提示中，以便品牌语音和研究期望适用于每次运行。

    ```markdown expandable wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    # 内容写作代理

    你是一家科技公司的内容作家。你的工作是创建引人入胜、信息丰富的内容，向读者介绍人工智能、软件开发和新兴技术。

    ## 品牌语音

    - **专业但平易近人**：像一位知识渊博的同事那样写作，而不是教科书
    - **清晰直接**：除非必要，避免使用行话；简单解释技术概念
    - **自信但不傲慢**：分享专业知识，但不居高临下
    - **引人入胜**：使用具体的例子、类比和故事来阐述观点

    ## 写作标准

    1. **使用主动语态**：“代理处理请求”而不是“请求由代理处理”
    2. **以价值为导向**：从对读者重要的内容开始，而不是背景信息
    3. **每段一个观点**：保持段落集中且易于浏览
    4. **具体胜于抽象**：使用具体的例子、数字和案例研究
    5. **以行动结尾**：每篇文章都应让读者知道下一步该做什么

    ## 内容支柱

    我们的内容专注于：
    - 人工智能代理和自动化
    - 开发者工具和生产力
    - 软件架构和最佳实践
    - 新兴技术和趋势

    ## 格式指南

    - 使用标题（H2、H3）来分隔长内容
    - 在相关处包含代码示例（带语法高亮）
    - 对于 3 项以上的列表使用项目符号
    - 尽可能将句子保持在 25 个单词以内
    - 在结尾包含明确的行动号召

    ## 研究要求

    在撰写任何主题之前：
    1. 使用 `researcher` 子代理进行深入的主题研究
    2. 收集至少 3 个可信来源
    3. 确定读者需要理解的关键点
    4. 找到具体的例子或案例研究来阐述概念
    ```

    要使此代理符合你自己的语气、支柱和格式规则，请更新 `AGENTS.md` 中的文本。
  </Step>

  <Step title="添加技能">
    创建一个 `skills/` 目录。每个技能是一个包含 `SKILL.md` 文件的文件夹，该文件包含 YAML frontmatter（`name`、`description`）和技能说明。

    创建 `skills/blog-post/SKILL.md` 并将以下文本复制到其中，其中包含有关创建长篇文章、优化 SEO 内容和生成封面图像的信息。

    ````md expandable wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    ---
    name: blog-post
    description: 撰写和构建长篇博客文章，创建教程大纲，并优化 SEO 内容以及生成封面图像。当用户要求撰写博客文章、文章、操作指南、教程、技术文章、思想领导力文章或长篇内容时使用。
    ---

    # 博客文章写作技能

    ## 先研究（必需）

    **在撰写任何博客文章之前，你必须委托研究：**

    1. 使用 `task` 工具，设置 `subagent_type: "researcher"`
    2. 在描述中，同时指定主题和保存位置：

    ```
    task(
        subagent_type="researcher",
        description="研究 [主题]。将发现保存到 research/[slug].md"
    )
    ```

    示例：
    ```
    task(
        subagent_type="researcher",
        description="研究 2025 年人工智能代理的现状。将发现保存到 research/ai-agents-2025.md"
    )
    ```

    3. 研究完成后，在写作前阅读发现文件

    ## 输出结构（必需）

    **每篇博客文章必须同时包含文章和封面图像：**

    ```
    blogs/
    └── <slug>/
        ├── post.md        # 博客文章内容
        └── hero.png       # 必需：生成的封面图像
    ```

    示例：一篇关于“2025 年人工智能代理”的文章 → `blogs/ai-agents-2025/`

    **你必须完成两个步骤：**
    1. 将文章写入 `blogs/<slug>/post.md`
    2. 使用 `generate_image` 生成封面图像并保存到 `blogs/<slug>/hero.png`

    **没有封面图像的博客文章是不完整的。**

    ## 博客文章结构

    每篇博客文章应遵循以下结构：

    ### 1. 钩子（开头）
    - 以引人入胜的问题、统计数据或陈述开始
    - 让读者想要继续阅读
    - 保持在 2-3 句话

    ### 2. 背景（问题）
    - 解释为什么这个主题重要
    - 描述问题或机会
    - 与读者的经验联系起来

    ### 3. 主要内容（解决方案）
    - 分为 3-5 个主要部分，使用 H2 标题
    - 每个部分涵盖一个关键点
    - 在有帮助的地方包含代码示例、图表或截图
    - 对列表使用项目符号

    ### 4. 实际应用
    - 展示如何应用这些概念
    - 如果适用，包含分步说明
    - 提供代码片段或模板

    ### 5. 结论和行动号召
    - 总结关键要点（最多 3 个要点）
    - 以明确的行动号召结尾
    - 链接到相关资源

    ## 封面图像生成

    撰写文章后，使用 `generate_cover` 工具生成封面图像：

    ```
    generate_cover(prompt="图像的详细描述...", slug="your-blog-slug")
    ```

    该工具将图像保存到 `blogs/<slug>/hero.png`。

    ### 撰写有效的图像提示

    使用以下元素构建你的提示：

    1. **主体**：主要焦点是什么？具体而明确。
    2. **风格**：艺术指导（极简主义、等距、扁平设计、3D 渲染、水彩等）
    3. **构图**：元素如何排列（居中、三分法、对称）
    4. **调色板**：特定颜色或情绪（温暖的大地色调、凉爽的蓝色和紫色、高对比度）
    5. **光照/氛围**：柔和的漫射光、戏剧性的阴影、黄金时段、霓虹灯辉光
    6. **技术细节**：宽高比考虑、用于文本叠加的负空间

    ### 示例提示

    **对于技术博客文章：**
    ```
    等距 3D 插图，展示相互连接的发光立方体，代表人工智能代理，每个立方体都有微妙的电路图案。立方体通过发光的数据流连接。深海军蓝背景（#0a192f），带有电蓝色（#64ffda）和柔和紫色（#c792ea）点缀。简洁的极简风格，顶部有大量负空间用于标题。专业的科技美学。
    ```

    **对于教程/操作指南：**
    ```
    干净的扁平插图，展示双手在键盘上打字，抽象的代码符号向上漂浮，变成灯泡和齿轮。温暖的渐变背景，从柔和的珊瑚色到浅桃色。友好、平易近人的风格。居中构图，留有文本叠加空间。
    ```

    **对于思想领导力：**
    ```
    人类轮廓与几何神经网络图案融合的抽象可视化。分割构图 - 左侧是有机的水彩纹理，过渡到右侧干净的矢量线条。柔和的鼠尾草绿和温暖的赤陶色调。沉思、前瞻的情绪。
    ```

    ## SEO 考虑

    - 在标题和第一段中包含主要关键词
    - 在全文中自然使用关键词 3-5 次
    - 将标题保持在 60 个字符以内
    - 撰写元描述（150-160 个字符）

    ## 质量检查清单

    完成前：
    - [ ] 文章已保存到 `blogs/<slug>/post.md`
    - [ ] 封面图像已生成在 `blogs/<slug>/hero.png`
    - [ ] 钩子在前 2 句话中抓住注意力
    - [ ] 每个部分都有明确的目的
    - [ ] 结论总结了关键点
    - [ ] 行动号召告诉读者下一步该做什么
    ````

    接下来，创建 `skills/social-media/SKILL.md` 并将以下文本复制到其中，其中包含有关起草社交媒体帖子和生成配套图像的信息：

    ````md expandable wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    ---
    name: social-media
    description: 起草引人入胜的社交媒体帖子，撰写钩子，建议标签，创建线程结构，并生成配套图像。当用户要求撰写 LinkedIn 帖子、推文、Twitter/X 线程、社交媒体说明、社交帖子或为社交平台重新利用内容时使用。
    ---

    # 社交媒体内容技能

    ## 先研究（必需）

    **在撰写任何社交媒体内容之前，你必须委托研究：**

    1. 使用 `task` 工具，设置 `subagent_type: "researcher"`
    2. 在描述中，同时指定主题和保存位置：

    ```
    task(
        subagent_type="researcher",
        description="研究 [主题]。将发现保存到 research/[slug].md"
    )
    ```

    示例：
    ```
    task(
        subagent_type="researcher",
        description="研究 2025 年可再生能源趋势。将发现保存到 research/renewable-energy.md"
    )
    ```

    3. 研究完成后，在写作前阅读发现文件

    ## 输出结构（必需）

    **每篇社交媒体帖子必须同时包含内容和图像：**

    **LinkedIn 帖子：**
    ```
    linkedin/
    └── <slug>/
        ├── post.md        # 帖子内容
        └── image.png      # 必需：生成的视觉图像
    ```

    **Twitter/X 线程：**
    ```
    tweets/
    └── <slug>/
        ├── thread.md      # 线程内容
        └── image.png      # 必需：生成的视觉图像
    ```

    示例：一篇关于“提示工程”的 LinkedIn 帖子 → `linkedin/prompt-engineering/`

    **你必须完成两个步骤：**
    1. 将内容写入适当的路径
    2. 使用 `generate_image` 生成图像并保存在帖子旁边

    **没有图像的社交媒体帖子是不完整的。**

    ## 平台指南

    ### LinkedIn

    **格式：**
    - 1,300 字符限制（约 210 个字符后显示更多）
    - 第一行至关重要 - 让它成为钩子
    - 使用换行提高可读性
    - 结尾使用 3-5 个标签

    **语气：**
    - 专业但个人化
    - 分享见解和学习心得
    - 提出问题以促进互动
    - 使用“我”并分享经验

    **结构：**
    ```
    [钩子 - 一句引人入胜的话]

    [空行]

    [背景 - 为什么这很重要]

    [空行]

    [主要见解 - 2-3 个短段落]

    [空行]

    [行动号召或问题]

    #hashtag1 #hashtag2 #hashtag3
    ```

    ### Twitter/X

    **格式：**
    - 每条推文 280 字符限制
    - 较长内容使用线程（使用 1/🧵 格式）
    - 每条推文不超过 2 个标签

    **线程结构：**
    ```
    1/🧵 [钩子 - 主要见解]

    2/ [支持点 1]

    3/ [支持点 2]

    4/ [示例或证据]

    5/ [结论 + 行动号召]
    ```

    ## 图像生成

    每篇社交媒体帖子都需要一张引人注目的图像。使用 `generate_social_image` 工具：

    ```
    generate_social_image(prompt="详细描述...", platform="linkedin", slug="your-post-slug")
    ```

    该工具将图像保存到 `<platform>/<slug>/image.png`。

    ### 社交图像最佳实践

    社交图像需要在拥挤的动态中以小尺寸工作：
    - **大胆、简单的构图** - 一个清晰的焦点
    - **高对比度** - 在滚动时脱颖而出
    - **图像中无文字** - 太小无法阅读，平台会添加自己的文字
    - **正方形或 4:5 比例** - 适用于所有平台

    ### 撰写有效的提示

    包含以下元素：

    1. **单一焦点**：一个清晰的主体，而不是繁忙的场景
    2. **大胆风格**：鲜艳的色彩、强烈的形状、高对比度
    3. **简单背景**：纯色、渐变或微妙的纹理
    4. **情绪/能量**：匹配帖子语气（鼓舞人心、紧迫、深思熟虑）

    ### 示例提示

    **对于见解/技巧帖子：**
    ```
    单个发光的灯泡漂浮在深紫色渐变背景上，灯泡由相互连接的金色几何线条制成，柔和的光线向外辐射。极简、引人注目、高对比度。正方形构图。
    ```

    **对于公告/新闻：**
    ```
    由彩色几何形状组成的抽象火箭向上发射，留下粒子轨迹。明亮的珊瑚色和蓝绿色配色方案，背景为干净的白色。充满活力、喜庆的情绪。大胆的扁平插图风格。
    ```

    **对于发人深省的内容：**
    ```
    两个重叠的半透明圆圈，一个蓝色一个橙色，在中心形成发光的交集。代表协作或思想的交汇。深炭灰色背景，柔和空灵的光芒。极简主义且引人深思。
    ```

    ## 内容类型

    ### 公告帖子
    - 以新闻开头
    - 解释影响
    - 包含链接或下一步

    ### 见解帖子
    - 分享一个具体的学习心得
    - 简要解释背景
    - 使其可操作

    ### 问题帖子
    - 提出一个真诚的问题
    - 先提供你的看法
    - 保持专注于一个主题

    ## 质量检查清单

    完成前：
    - [ ] 帖子已保存到 `linkedin/<slug>/post.md` 或 `tweets/<slug>/thread.md`
    - [ ] 图像已生成在帖子旁边
    - [ ] 第一行吸引注意力
    - [ ] 内容符合平台限制
    - [ ] 语气符合平台规范
    - [ ] 有明确的行动号召或问题
    - [ ] 标签相关（非通用）
    ````

    它们指示代理首先调用 `researcher` 子代理，在 `blogs/`、`linkedin/` 或 `tweets/` 下编写 markdown，并调用 `generate_cover` 或 `generate_social_image` 生成图像。

    当你稍后创建代理并指定技能文件夹时，这些技能文件夹中 `SKILLS.md` 文件的 frontmatter 会被加载到系统提示中，以便代理在任务匹配技能描述时可以使用该技能。
  </Step>
</Steps>

## 构建脚本

在项目根目录创建 `content_writer.ts`。以下部分按顺序属于一个文件。

<Steps>
  <Step title="添加工具">
    研究员使用 Tavily 搜索。博客和社交工作流使用 Google Generative AI SDK 进行图像生成。

    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { tool } from "@langchain/core/tools";
    import * as z from "zod";
    import * as fs from "node:fs";
    import * as path from "node:path";

    const EXAMPLE_DIR = path.dirname(new URL(import.meta.url).pathname);

    const webSearch = tool(
      async ({ query, maxResults = 5, topic = "general" }) => {
        const apiKey = process.env.TAVILY_API_KEY;
        if (!apiKey) return { error: "TAVILY_API_KEY not set" };
        try {
          const { TavilyClient } = await import("tavily");
          const client = new TavilyClient({ apiKey });
          return client.search(query, { maxResults, topic });
        } catch (e) {
          return { error: `Search failed: ${e}` };
        }
      },
      {
        name: "web_search",
        description: "Search the web for current information.",
        schema: z.object({
          query: z.string().describe("The search query (be specific and detailed)"),
          maxResults: z
            .number()
            .optional()
            .describe("Number of results to return (default: 5)"),
          topic: z
            .enum(["general", "news"])
            .optional()
            .describe('"general" for most queries, "news" for current events'),
        }),
      },
    );

    const generateCover = tool(
      async ({ prompt, slug }) => {
        try {
          const { GoogleGenerativeAI } = await import("@google/generative-ai");
          const genai = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY ?? "");
          const model = genai.getGenerativeModel({
            model: "gemini-2.5-flash-image",
          });
          const result = await model.generateContent(prompt);
          const part = result.response.candidates?.[0]?.content?.parts?.find(
            (p) => p.inlineData,
          );
          if (!part?.inlineData) return "No image generated";
          const outputPath = path.join(EXAMPLE_DIR, "blogs", slug, "hero.png");
          fs.mkdirSync(path.dirname(outputPath), { recursive: true });
          fs.writeFileSync(outputPath, Buffer.from(part.inlineData.data, "base64"));
          return `Image saved to ${outputPath}`;
        } catch (e) {
          return `Error: ${e}`;
        }
      },
      {
        name: "generate_cover",
        description: "Generate a cover image for a blog post.",
        schema: z.object({
          prompt: z
            .string()
            .describe("Detailed description of the image to generate."),
          slug: z
            .string()
            .describe("Blog post slug. Image saves to blogs/<slug>/hero.png"),
        }),
      },
    );

    const generateSocialImage = tool(
      async ({ prompt, platform, slug }) => {
        try {
          const { GoogleGenerativeAI } = await import("@google/generative-ai");
          const genai = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY ?? "");
          const model = genai.getGenerativeModel({
            model: "gemini-2.5-flash-image",
          });
          const result = await model.generateContent(prompt);
          const part = result.response.candidates?.[0]?.content?.parts?.find(
            (p) => p.inlineData,
          );
          if (!part?.inlineData) return "No image generated";
          const outputPath = path.join(EXAMPLE_DIR, platform, slug, "image.png");
          fs.mkdirSync(path.dirname(outputPath), { recursive: true });
          fs.writeFileSync(outputPath, Buffer.from(part.inlineData.data, "base64"));
          return `Image saved to ${outputPath}`;
        } catch (e) {
          return `Error: ${e}`;
        }
      },
      {
        name: "generate_social_image",
        description: "Generate an image for a social media post.",
        schema: z.object({
          prompt: z
            .string()
            .describe("Detailed description of the image to generate."),
          platform: z.string().describe('Either "linkedin" or "tweets"'),
          slug: z
            .string()
            .describe("Post slug. Image saves to <platform>/<slug>/image.png"),
        }),
      },
    );
    ```
  </Step>

  <Step title="创建代理">
    使用 [createDeepAgent](https://reference.langchain.com/javascript/deepagents/agent/createDeepAgent) 创建深度代理时，传入记忆路径、技能目录、图像工具、内联子代理定义和一个以示例目录为根的 [FilesystemBackend](/oss/javascript/deepagents/backends)，以便 `./AGENTS.md` 和 `./skills/` 等路径能正确解析。

    <CodeGroup>
      ```ts Google theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "google-genai:gemini-3.1-pro-preview",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```

      ```ts OpenAI theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "openai:gpt-5.4",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```

      ```ts Anthropic theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "anthropic:claude-sonnet-4-6",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```

      ```ts OpenRouter theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "openrouter:anthropic/claude-sonnet-4-6",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```

      ```ts Fireworks theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "fireworks:accounts/fireworks/models/qwen3p5-397b-a17b",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```

      ```ts Baseten theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "baseten:zai-org/GLM-5",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```

      ```ts Ollama theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
      import { createDeepAgent, FilesystemBackend } from "deepagents";

      function createContentWriter() {
        const researcherSubagent = {
          name: "researcher",
          description:
            "具有网络搜索能力的研究子代理。将研究任务委派至此。",
          systemPrompt:
            "你是一个研究助理。使用 web_search 工具查找当前、准确的信息，并返回组织良好的研究结果。",
          tools: [webSearch],
        };

        return createDeepAgent({
          model: "ollama:devstral-2",
          memory: ["./AGENTS.md"],
          skills: ["./skills/"],
          tools: [generateCover, generateSocialImage],
          subagents: [researcherSubagent],
          backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
        });
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="添加入口点">
    ```ts theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    const task =
      process.argv.slice(2).join(" ") ||
      "Write a blog post about how AI agents are transforming software development";

    const agent = createContentWriter();
    const result = await agent.invoke({
      messages: [{ role: "user", content: task }],
      config: { configurable: { threadId: "content-builder-demo" } },
    });

    const messages = result.messages ?? [];
    for (const msg of messages) {
      if (msg.content) console.log(msg.content);
    }
    ```

    AI代理正在改变软件开发的方式。
  </Step>
</Steps>

## 运行代理

<Warning>
  文件系统后端可以读取、写入和删除 `root_dir` 下的文件。仅在专用目录中运行，并在发布前审查生成的内容。
</Warning>

从项目目录：

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
npx tsx content_writer.ts
```

将提示作为额外参数传递：

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
npx tsx content_writer.ts Write a blog post about prompt engineering
```

设置了 `LANGSMITH_API_KEY` 后，你可以在 [LangSmith](/langsmith/home) 中检查运行情况。

## 输出

成功后，代理会在项目根目录（示例目录）下写入工件，例如：

```text theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
blogs/
└── prompt-engineering/
    ├── post.md
    └── hero.png
research/
└── prompt-engineering.md
```

路径遵循 `SKILL.md` 中的技能说明。

## 完整代码

在 GitHub 上浏览完整的 [content-builder-agent 示例](https://github.com/langchain-ai/deepagents/tree/main/examples/content-builder-agent)，包括基于 Rich 的流式 UI。

## 后续步骤

* 编辑 `AGENTS.md` 以更改品牌语音和研究要求
* 在 `skills/<name>/SKILL.md` 下添加新内容类型的技能
* 在 `subagents.yaml` 中添加子代理，并在 `load_subagents` 中注册工具
* 阅读[子代理](/oss/javascript/deepagents/subagents)、[技能](/oss/javascript/deepagents/skills)和[自定义](/oss/javascript/deepagents/customization)以进行更深入的配置

***

<div className="source-links">
  <Callout icon="terminal-2">
    [将这些文档](/use-these-docs)连接到 Claude、VSCode 等，通过 MCP 获取实时答案。
  </Callout>

  <Callout icon="edit">
    [在 GitHub 上编辑此页面](https://github.com/langchain-ai/docs/edit/main/src/oss/deepagents/content-builder.mdx) 或 [提交问题](https://github.com/langchain-ai/docs/issues/new/choose)。
  </Callout>
</div>
