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

# 构建内容构建器代理

> 本指南展示了如何使用深度智能体构建内容创作智能体。该智能体能加载品牌语调和技能，将研究任务委托给子智能体，根据加载的技能起草博客或社交媒体内容，并通过Gemini生成配套图片。

## 概述

本指南展示了如何使用[深度智能体](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents.md)构建内容创作智能体。该智能体能加载品牌语调和技能，将研究任务委托给子智能体，根据加载的技能起草博客或社交媒体内容，并通过Gemini生成配套图片。

您构建的智能体将实现以下功能：

1. 从品牌指令和技能文件夹加载语调和工作流规则
2. 将网络研究委托给具有`web_search`能力的专用子智能体
3. 根据加载的技能起草博客或社交媒体内容
4. 使用Gemini生成封面或社交媒体图片并保存至项目目录

完整可运行的SDK项目示例请参考[content-builder-agent](https://github.com/langchain-ai/deepagents/tree/main/examples/content-builder-agent)。

### 核心概念

本教程涵盖以下内容：

* 品牌指令（通过[Managed Deep Agents](https://docs.langchain.com/langsmith/managed-deep-agents-instructions)的上下文，或SDK的[记忆](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/memory.md)文件）定义的持续生效的语调和研究规则
* [技能](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/skills.md)用于博客和社交媒体的运营手册
* [子智能体](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/subagents.md)用于写作前的研究
* SDK路径下的[文件系统后端](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/backends.md)实现文件读写
* 自定义[工具](https://langchain-docs-zh.mintlify.site/langchain/oss/langchain/tools.md)用于搜索和图像生成

## 先决条件

API密钥：

* Anthropic（Claude）或其他聊天模型供应商
* Google（Gemini）用于使用`gemini-2.5-flash-image`的图像生成
* [Tavily](https://www.tavily.com/)（免费版）用于网络搜索
* [LangSmith](https://smith.langchain.com)用于追踪（SDK路径下可选，托管深度智能体场景必需）

:::python
Python 3.11或更高版本。
:::

:::js
Node.js 18或更高版本。
:::

## 选择您的路径

从[托管深度智能体](https://docs.langchain.com/langsmith/managed-deep-agents-overview)开始运行无需维护基础设施的生产级智能体。或者，在保持与深度智能体框架兼容的前提下，使用深度智能体SDK自行托管智能体，或运行自定义[LangSmith部署](https://docs.langchain.com/langsmith/deployment)。

> [tab] Managed Deep Agents
>
> > [!NOTE]
> >
> > 托管深度智能体目前处于 **公开的 [beta](https://docs.langchain.com/langsmith/release-stages)** 版本，部署于 [LangSmith Cloud](https://docs.langchain.com/langsmith/cloud)。
>
> 托管深度智能体自动创建项目并托管运行时。品牌语调存放在`instructions.md`，技能文件位于`skills/`，在代码中声明工具和研究者子智能体。图像工具在`mda dev`期间将文件写入项目目录。
>
> ### 配置
>
> 要开始，你需要：
>
> :::python
>
> * Python 和 `uv`。
>   :::
>
> :::js
>
> * Node.js 和 npm。
>   :::
>
> * 向你的模型服务提供商申请的 API 密钥。
>
> **1. 创建项目**
>
> :::python
>
> ```bash theme={null}
> uvx --from managed-deepagents mda init content-builder
> cd content-builder
> ```
>
> :::
>
> :::js
>
> ```bash npm theme={null}
> npx managed-deepagents init content-builder
> cd content-builder
> ```
>
> ```bash pnpm theme={null}
> pnpm dlx managed-deepagents init content-builder
> cd content-builder
> ```
>
> ```bash bun theme={null}
> bunx managed-deepagents init content-builder
> cd content-builder
> ```
>
> :::
>
> **2. 添加 API 密钥**
>
> 将聊天、图像、搜索和LangSmith密钥添加至`.env`：
>
> ```text .env theme={null}
> ANTHROPIC_API_KEY=<ANTHROPIC_API_KEY>
> GOOGLE_API_KEY=<GOOGLE_API_KEY>
> TAVILY_API_KEY=<TAVILY_API_KEY>
> LANGSMITH_API_KEY=<LANGSMITH_API_KEY>
> ```
>
> `GOOGLE_API_KEY`密钥对于Gemini图像生成（即使使用Claude作为聊天模型）也是必需的。
>
> > [!WARNING]
> >
> > 不要将`.env`文件提交至版本控制。该文件包含敏感信息。
>
> **3. 安装依赖项**
>
> :::python
>
> ```bash theme={null}
> uv add tavily-python google-genai pillow
> ```
>
> :::
>
> :::js
>
> ```bash npm theme={null}
> npm install tavily @google/generative-ai zod
> ```
>
> ```bash pnpm theme={null}
> pnpm add tavily @google/generative-ai zod
> ```
>
> ```bash bun theme={null}
> bun add tavily @google/generative-ai zod
> ```
>
> :::
>
> ### 构建智能体
>
> **1. 添加工具**
>
> 创建搜索和图像工具。Markdown研究笔记使用智能体文件系统（`write_file`）。封面和社交媒体图片在本地`mda dev`期间通过宿主机写入项目目录。
>
> :::python
> 创建`tools/content.py`：
>
> ```python tools/content.py theme={null}
> import os
> from pathlib import Path
> from typing import Literal
>
> from langchain.tools import tool
>
> # Project root (parent of tools/)
> PROJECT_DIR = Path(__file__).resolve().parent.parent
>
>
> @tool
> def web_search(
>     query: str,
>     max_results: int = 5,
>     topic: Literal["general", "news"] = "general",
> ) -> dict:
>     """Search the web for current information.
>
>     Args:
>         query: The search query (be specific and detailed)
>         max_results: Number of results to return (default: 5)
>         topic: "general" for most queries, "news" for current events
>
>     Returns:
>         Search results with titles, URLs, and content excerpts.
>     """
>     try:
>         from tavily import TavilyClient
>
>         api_key = os.environ.get("TAVILY_API_KEY")
>         if not api_key:
>             return {"error": "TAVILY_API_KEY not set"}
>
>         client = TavilyClient(api_key=api_key)
>         return client.search(query, max_results=max_results, topic=topic)
>     except Exception as e:
>         return {"error": f"Search failed: {e}"}
>
>
> @tool
> def generate_cover(prompt: str, slug: str) -> str:
>     """Generate a cover image for a blog post.
>
>     Args:
>         prompt: Detailed description of the image to generate.
>         slug: Blog post slug. Image saves to blogs/<slug>/hero.png
>     """
>     try:
>         from google import genai
>
>         client = genai.Client()
>         response = client.models.generate_content(
>             model="gemini-2.5-flash-image",
>             contents=[prompt],
>         )
>
>         for part in response.parts:
>             if part.inline_data is not None:
>                 image = part.as_image()
>                 output_path = PROJECT_DIR / "blogs" / slug / "hero.png"
>                 output_path.parent.mkdir(parents=True, exist_ok=True)
>                 image.save(str(output_path))
>                 return f"Image saved to {output_path}"
>
>         return "No image generated"
>     except Exception as e:
>         return f"Error: {e}"
>
>
> @tool
> def generate_social_image(prompt: str, platform: str, slug: str) -> str:
>     """Generate an image for a social media post.
>
>     Args:
>         prompt: Detailed description of the image to generate.
>         platform: Either "linkedin" or "tweets"
>         slug: Post slug. Image saves to <platform>/<slug>/image.png
>     """
>     try:
>         from google import genai
>
>         client = genai.Client()
>         response = client.models.generate_content(
>             model="gemini-2.5-flash-image",
>             contents=[prompt],
>         )
>
>         for part in response.parts:
>             if part.inline_data is not None:
>                 image = part.as_image()
>                 output_path = PROJECT_DIR / platform / slug / "image.png"
>                 output_path.parent.mkdir(parents=True, exist_ok=True)
>                 image.save(str(output_path))
>                 return f"Image saved to {output_path}"
>
>         return "No image generated"
>     except Exception as e:
>         return f"Error: {e}"
> ```
>
> ※ 重要提示：在您之前的输出中占位符集不正确。缺少的 id：\['0']；意外的额外 id：\[]。请再次翻译全文，并保持每个占位符（六边形括号 + 数字）的原位置，且仅出现一次。
>
> :::
>
> :::js
> 创建`tools/content.ts`：
>
> ```ts tools/content.ts theme={null}
> import { tool } from "@langchain/core/tools";
> import * as z from "zod";
> import * as fs from "node:fs";
> import * as path from "node:path";
> import { fileURLToPath } from "node:url";
>
> const PROJECT_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
>
> export 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'),
>     }),
>   },
> );
>
> export 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(PROJECT_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"),
>     }),
>   },
> );
>
> export 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(PROJECT_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"),
>     }),
>   },
> );
> ```
>
> :::
>
> **2. 添加品牌指令**
>
> 将始终生效的品牌语调和研究要求存放在`instructions.md`。托管深度智能体将此文件作为主智能体系统的系统提示（这是SDK的`AGENTS.md` / `memory=`角色，而非持久化[记忆](https://docs.langchain.com/langsmith/managed-deep-agents-memory)）：
>
> ```markdown expandable wrap theme={null}
> # Content Writer Agent
>
> You are a content writer for a technology company. Your job is to create engaging, informative content that educates readers about AI, software development, and emerging technologies.
>
> ## Brand Voice
>
> - **Professional but approachable**: Write like a knowledgeable colleague, not a textbook
> - **Clear and direct**: Avoid jargon unless necessary; explain technical concepts simply
> - **Confident but not arrogant**: Share expertise without being condescending
> - **Engaging**: Use concrete examples, analogies, and stories to illustrate points
>
> ## Writing Standards
>
> 1. **Use active voice**: "The agent processes requests" not "Requests are processed by the agent"
> 2. **Lead with value**: Start with what matters to the reader, not background
> 3. **One idea per paragraph**: Keep paragraphs focused and scannable
> 4. **Concrete over abstract**: Use specific examples, numbers, and case studies
> 5. **End with action**: Every piece should leave the reader knowing what to do next
>
> ## Content Pillars
>
> Our content focuses on:
> - AI agents and automation
> - Developer tools and productivity
> - Software architecture and best practices
> - Emerging technologies and trends
>
> ## Formatting Guidelines
>
> - Use headers (H2, H3) to break up long content
> - Include code examples where relevant (with syntax highlighting)
> - Add bullet points for lists of 3+ items
> - Keep sentences under 25 words when possible
> - Include a clear call-to-action at the end
>
> ## Research Requirements
>
> Before writing on any topic:
> 1. Use the `researcher` subagent for in-depth topic research
> 2. Gather at least 3 credible sources
> 3. Identify the key points readers need to understand
> 4. Find concrete examples or case studies to illustrate concepts
> ```
>
> 部署时，托管深度智能体会将这些指令同步至[上下文中心](https://docs.langchain.com/langsmith/managed-deep-agents-context-hub)。
>
> **3. 添加技能**
>
> Create a `skills/` directory. Each skill is a folder with a `SKILL.md`. Managed Deep Agents 会自动发现技能；你不需要传递 `skills=` 参数。
>
> Create `skills/blog-post/SKILL.md`:
>
> ````md expandable wrap theme={null}
> ---
> name: blog-post
> description: Writes and structures long-form blog posts, creates tutorial outlines, and optimizes content for SEO with cover image generation. Use when the user asks to write a blog post, article, how-to guide, tutorial, technical writeup, thought leadership piece, or long-form content.
> ---
>
> # Blog Post Writing Skill
>
> ## Research First (Required)
>
> **Before writing any blog post, you MUST delegate research:**
>
> 1. Use the `task` tool with `subagent_type: "researcher"`
> 2. In the description, specify BOTH the topic AND where to save:
>
> ```
> task(
>     subagent_type="智能体",
>     description="研究 [主题]。将研究结果保存到 research/[slug].md"
> )
> ```
>
> Example:
> ```
> task(
>     subagent_type="智能体",
>     description="研究 2025 年 AI 智能体的现状。将研究结果保存到 research/ai-agents-2025.md"
> )
> ```
>
> 3. After research completes, read the findings file before writing
>
> ## Output Structure (Required)
>
> **Every blog post MUST have both a post AND a cover image:**
>
> ```
> blogs/
> └── <slug>/
>     ├── post.md        # 博客文章内容
>     └── hero.png       # REQUIRED: 生成的封面图片
> ```
>
> Example: A post about "AI Agents in 2025" → `blogs/ai-agents-2025/`
>
> **You MUST complete both steps:**
> 1. Write the post to `blogs/<slug>/post.md`
> 2. Generate a cover image using `generate_image` and save to `blogs/<slug>/hero.png`
>
> **A blog post is NOT complete without its cover image.**
>
> ## Blog Post Structure
>
> Every blog post should follow this structure:
>
> ### 1. Hook (Opening)
> - Start with a compelling question, statistic, or statement
> - Make the reader want to continue
> - Keep it to 2-3 sentences
>
> ### 2. Context (The Problem)
> - Explain why this topic matters
> - Describe the problem or opportunity
> - Connect to the reader's experience
>
> ### 3. Main Content (The Solution)
> - Break into 3-5 main sections with H2 headers
> - Each section covers one key point
> - Include code examples, diagrams, or screenshots where helpful
> - Use bullet points for lists
>
> ### 4. Practical Application
> - Show how to apply the concepts
> - Include step-by-step instructions if applicable
> - Provide code snippets or templates
>
> ### 5. Conclusion & CTA
> - Summarize key takeaways (3 bullets max)
> - End with a clear call-to-action
> - Link to related resources
>
> ## Cover Image Generation
>
> After writing the post, generate a cover image using the `generate_cover` tool:
>
> ```
> generate_cover(prompt="图片的详细描述...", slug="your-blog-slug")
> ```
>
> The tool saves the image to `blogs/<slug>/hero.png`.
>
> ### Writing Effective Image Prompts
>
> Structure your prompt with these elements:
>
> 1. **Subject**: What is the main focus? Be specific and concrete.
> 2. **Style**: Art direction (minimalist, isometric, flat design, 3D render, watercolor, etc.)
> 3. **Composition**: How elements are arranged (centered, rule of thirds, symmetrical)
> 4. **Color palette**: Specific colors or mood (warm earth tones, cool blues and purples, high contrast)
> 5. **Lighting/Atmosphere**: Soft diffused light, dramatic shadows, golden hour, neon glow
> 6. **Technical details**: Aspect ratio considerations, negative space for text overlay
>
> ### Example Prompts
>
> **For a technical blog post:**
> ```
> 等距 3D 插画，展示相互连接的发光立方体代表 AI 智能体，每个立方体都有微妙的电路图案。立方体通过发光的数据流连接。深海军蓝背景 (#0a192f) 配合亮蓝色 (#64ffda) 和柔和紫色 (#c792ea) 的点缀。简洁极简风格，顶部留出大量空白用于标题。专业科技美学。
> ```
>
> **For a tutorial/how-to:**
> ```
> 简洁平面插画，展示双手在键盘上打字，抽象代码符号向上漂浮，转化为灯泡和齿轮。背景为从柔和珊瑚到浅桃色的渐变色。友好、亲切的风格。居中构图，留出文本叠加空间。
> ```
>
> **For thought leadership:**
> ```
> 抽象可视化，展示人形剪影与几何神经网络图案融合。分割构图 - 左侧为有机水彩纹理，右侧过渡到干净矢量线条。柔和的橄榄绿和温暖陶土色系。沉思、前瞻的氛围。
> ```
>
> ## SEO Considerations
>
> - Include the main keyword in the title and first paragraph
> - Use the keyword naturally 3-5 times throughout
> - Keep the title under 60 characters
> - Write a meta description (150-160 characters)
>
> ## Quality Checklist
>
> Before finishing:
> - [ ] Post saved to `blogs/<slug>/post.md`
> - [ ] Hero image generated at `blogs/<slug>/hero.png`
> - [ ] Hook grabs attention in first 2 sentences
> - [ ] Each section has a clear purpose
> - [ ] Conclusion summarizes key points
> - [ ] CTA tells reader what to do next
> ````
>
> Create `skills/social-media/SKILL.md`:
>
> ````md expandable wrap theme={null}
> ---
> name: social-media
> description: Drafts engaging social media posts, writes hooks, suggests hashtags, creates thread structures, and generates companion images. Use when the user asks to write a LinkedIn post, tweet, Twitter/X thread, social media caption, social post, or repurpose content for social platforms.
> ---
>
> # Social Media Content Skill
>
> ## Research First (Required)
>
> **Before writing any social media content, you MUST delegate research:**
>
> 1. Use the `task` tool with `subagent_type: "researcher"`
> 2. In the description, specify BOTH the topic AND where to save:
>
> ```
> task(
>     subagent_type="研究者",
>     description="研究[TOPIC]。将发现保存到research/[slug].md"
> )
> ```
>
> Example:
> ```
> task(
>     subagent_type="研究者",
>     description="研究2025年可再生能源趋势。将发现保存到research/renewable-energy.md"
> )
> ```
>
> 3. After research completes, read the findings file before writing
>
> ## Output Structure (Required)
>
> **Every social media post MUST have both content AND an image:**
>
> **LinkedIn posts:**
> ```
> linkedin/
> └── <slug>/
>     ├── post.md        # 帖子内容
>     └── image.png      # REQUIRED: 生成的视觉元素
> ```
>
> **Twitter/X threads:**
> ```
> tweets/
> └── <slug>/
>     ├── thread.md      # 帖子内容
>     └── image.png      # REQUIRED: 生成的视觉元素
> ```
>
> Example: A LinkedIn post about "prompt engineering" → `linkedin/prompt-engineering/`
>
> **You MUST complete both steps:**
> 1. Write the content to the appropriate path
> 2. Generate an image using `generate_image` and save alongside the post
>
> **A social media post is NOT complete without its image.**
>
> ## Platform Guidelines
>
> ### LinkedIn
>
> **Format:**
> - 1,300 character limit (show more after ~210 chars)
> - First line is crucial - make it hook
> - Use line breaks for readability
> - 3-5 hashtags at the end
>
> **Tone:**
> - Professional but personal
> - Share insights and learnings
> - Ask questions to drive engagement
> - Use "I" and share experiences
>
> **Structure:**
> ```
> [钩子 - 1句引人入胜的话]
>
> [空行]
>
> [背景 - 为什么这很重要]
>
> [空行]
>
> [主要见解 - 2-3段简短段落]
>
> [空行]
>
> [号召行动或问题]
>
> #hashtag1 #hashtag2 #hashtag3
> ```
>
> ### Twitter/X
>
> **Format:**
> - 280 character limit per tweet
> - Threads for longer content (use 1/🧵 format)
> - No more than 2 hashtags per tweet
>
> **Thread Structure:**
> ```
> 1/🧵 [钩子 - 主要见解]
>
> 2/ [支持点1]
>
> 3/ [支持点2]
>
> 4/ [示例或证据]
>
> 5/ [结论+号召行动]
> ```
>
> ## Image Generation
>
> Every social media post needs an eye-catching image. Use the `generate_social_image` tool:
>
> ```
> generate_social_image(prompt="详细描述...", platform="linkedin", slug="your-post-slug")
> ```
>
> The tool saves the image to `<platform>/<slug>/image.png`.
>
> ### Social Image Best Practices
>
> Social images need to work at small sizes in crowded feeds:
> - **Bold, simple compositions** - one clear focal point
> - **High contrast** - stands out when scrolling
> - **No text in image** - too small to read, platforms add their own
> - **Square or 4:5 ratio** - works across platforms
>
> ### Writing Effective Prompts
>
> Include these elements:
>
> 1. **Single focal point**: One clear subject, not a busy scene
> 2. **Bold style**: Vibrant colors, strong shapes, high contrast
> 3. **Simple background**: Solid color, gradient, or subtle texture
> 4. **Mood/energy**: Match the post tone (inspiring, urgent, thoughtful)
>
> ### Example Prompts
>
> **For an insight/tip post:**
> ```
> 一个发光的灯泡悬浮在深紫色渐变背景上，灯泡由相互连接的金色几何线条构成，向外散发柔和的光线。极简、引人注目、高对比度。方形构图。
> ```
>
> **For announcements/news:**
> ```
> 由彩色几何形状组成的抽象火箭船向上发射，留下粒子轨迹。明亮珊瑚色和蓝绿色调，背景为干净白色。充满活力、庆祝氛围。大胆扁平插画风格。
> ```
>
> **For thought-provoking content:**
> ```
> 两个重叠的半透明圆圈，一个蓝色一个橙色，在中心形成发光的交集。代表合作或想法的交集。深煤灰背景，柔和空灵的光芒。极简和沉思。
> ```
>
> ## Content Types
>
> ### Announcement Posts
> - Lead with the news
> - Explain the impact
> - Include link or next step
>
> ### Insight Posts
> - Share one specific learning
> - Explain the context briefly
> - Make it actionable
>
> ### Question Posts
> - Ask a genuine question
> - Provide your take first
> - Keep it focused on one topic
>
> ## Quality Checklist
>
> Before finishing:
> - [ ] Post saved to `linkedin/<slug>/post.md` or `tweets/<slug>/thread.md`
> - [ ] Image generated alongside the post
> - [ ] First line hooks attention
> - [ ] Content fits platform limits
> - [ ] Tone matches platform norms
> - [ ] Has clear CTA or question
> - [ ] Hashtags are relevant (not generic)
> ````
>
> **4. 创建智能体**
>
> 用下面的完整文件替换脚手架生成的智能体入口。它会创建一个带有图像工具和内联研究者子智能体（使用 `web_search`）的智能体。技能和指令来自项目文件。
>
> :::python
> 替换 `agent.py`：
>
> ```python agent.py theme={null}
> from managed_deepagents import define_deep_agent
>
> from tools.content import generate_cover, generate_social_image, web_search
>
> researcher = {
>     "name": "researcher",
>     "description": (
>         "ALWAYS use this first to research any topic before writing content. "
>         "Searches the web for current information, statistics, and sources. "
>         "When delegating, tell it the topic AND the file path to save results "
>         "(e.g., 'Research renewable energy and save to research/renewable-energy.md')."
>     ),
>     "model": "anthropic:claude-haiku-4-5-20251001",
>     "system_prompt": """You are a research assistant. You have access to web_search and write_file tools.
>
> ## Your Tools
> - web_search(query, max_results=5, topic="general") - Search the web
> - write_file(file_path, content) - Save your findings
>
> ## Your Process
> 1. Use web_search to find information on the topic
> 2. Make 2-3 targeted searches with specific queries
> 3. Gather key statistics, quotes, and examples
> 4. Save findings to the file path specified in your task
>
> ## Important
> - The user will tell you WHERE to save the file - use that exact path
> - Always include source URLs in your findings
> - Keep findings concise but informative
> """,
>     "tools": [web_search],
> }
>
> agent = define_deep_agent(
>     name="content-builder",
>     model="anthropic:claude-sonnet-4-5-20250929",
>     tools=[generate_cover, generate_social_image],
>     subagents=[researcher],
> )
> ```
>
> :::
>
> :::js
> 替换 `agent.ts`：
>
> ```ts agent.ts theme={null}
> import { defineDeepAgent } from "managed-deepagents";
>
> import {
>   generateCover,
>   generateSocialImage,
>   webSearch,
> } from "./tools/content";
>
> const researcher = {
>   name: "researcher",
>   description:
>     "ALWAYS use this first to research any topic before writing content. " +
>     "Searches the web for current information, statistics, and sources. " +
>     "When delegating, tell it the topic AND the file path to save results " +
>     "(e.g., 'Research renewable energy and save to research/renewable-energy.md').",
>   model: "anthropic:claude-haiku-4-5-20251001",
>   systemPrompt: `You are a research assistant. You have access to web_search and write_file tools.
>
> ## Your Tools
> - web_search(query, max_results=5, topic="general") - Search the web
> - write_file(file_path, content) - Save your findings
>
> ## Your Process
> 1. Use web_search to find information on the topic
> 2. Make 2-3 targeted searches with specific queries
> 3. Gather key statistics, quotes, and examples
> 4. Save findings to the file path specified in your task
>
> ## Important
> - The user will tell you WHERE to save the file - use that exact path
> - Always include source URLs in your findings
> - Keep findings concise but informative
> `,
>   tools: [webSearch],
> };
>
> export const agent = defineDeepAgent({
>   name: "content-builder",
>   model: "anthropic:claude-sonnet-4-5-20250929",
>   tools: [generateCover, generateSocialImage],
>   subagents: [researcher],
> });
> ```
>
> ※ 重要提示：在您之前的输出中占位符集不正确。缺少的 id：\['0']；意外的额外 id：\[]。请再次翻译全文，并保持每个占位符（六边形括号 + 数字）的原位置，且仅出现一次。
>
> :::
>
> ### 运行智能体
>
> **1. 本地运行**
>
> :::python
>
> ```bash theme={null}
> uv sync
> uv run mda dev
> ```
>
> :::
>
> :::js
>
> ```bash npm theme={null}
> npm install
> npx mda dev
> ```
>
> ```bash pnpm theme={null}
> pnpm install
> pnpm exec mda dev
> ```
>
> ```bash bun theme={null}
> bun install
> bunx mda dev
> ```
>
> :::
>
> `mda dev` 会在 LangSmith Studio 中打开智能体。发送类似下面的提示词：
>
> ```txt wrap theme={null}
> Write a blog post about how AI agents are transforming software development
> ```
>
> 你应该会看到智能体加载技能、委托给 `researcher`、编写 Markdown 并调用图像工具。更多信息请参阅 [使用 LangSmith Studio 进行本地开发](https://docs.langchain.com/langsmith/managed-deep-agents-local-development)。
>
> **2. 部署（可选）**
>
> :::python
>
> ```bash theme={null}
> uv run mda deploy
> ```
>
> :::
>
> :::js
>
> ```bash npm theme={null}
> npx mda deploy
> ```
>
> ```bash pnpm theme={null}
> pnpm exec mda deploy
> ```
>
> ```bash bun theme={null}
> bunx mda deploy
> ```
>
> :::
>
> See [Deploy](https://docs.langchain.com/langsmith/managed-deep-agents-deploy).

> [tab] Deep Agents SDK
>
> 当你希望自行托管智能体或运行自定义 [LangSmith 部署](https://docs.langchain.com/langsmith/deployment) 时，请使用开源 SDK。该示例将行为保存在记忆文件、技能和子智能体定义中，并额外使用 [FilesystemBackend](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/backends.md)。
>
> ### 设置
>
> :::python
>
> **1. 创建项目目录**
>
> ```bash theme={null}
> mkdir content-builder-agent
> cd content-builder-agent
> ```
>
> **2. 安装依赖项**
>
> ```bash pip wrap theme={null}
> pip install deepagents google-genai pillow pyyaml rich tavily-python langchain
> ```
>
> ```bash uv wrap theme={null}
> uv init
> uv add deepagents google-genai pillow pyyaml rich tavily-python langchain
> uv sync
> ```
>
> 在你自己的项目中将 `deepagents` 固定到受支持的版本范围（例如 `>=0.3.5,<0.4.0`），以与上游示例保持一致。
>
> **3. 设置 API 密钥**
>
> ```bash theme={null}
> export ANTHROPIC_API_KEY="your_anthropic_api_key"
> export GOOGLE_API_KEY="your_google_api_key"
> export TAVILY_API_KEY="your_tavily_api_key"           # Optional
> export LANGSMITH_API_KEY="your_langsmith_api_key"     # Optional
> ```
>
> :::
>
> :::js
>
> **1. 创建项目目录**
>
> ```bash theme={null}
> mkdir content-builder-agent
> cd content-builder-agent
> ```
>
> **2. 安装依赖项**
>
> ```bash npm wrap theme={null}
> npm install deepagents @langchain/core @langchain/anthropic @google/generative-ai tavily zod tsx
> ```
>
> ```bash yarn wrap theme={null}
> yarn add deepagents @langchain/core @langchain/anthropic @google/generative-ai tavily zod tsx
> ```
>
> 添加 `tsx` 以运行 `content_writer.ts`。安装 `@langchain/anthropic`，以便 LangChain 加载 `createDeepAgent` 使用的默认 Claude 模型。
>
> **3. 设置 API 密钥**
>
> ```bash theme={null}
> export ANTHROPIC_API_KEY="your_anthropic_api_key"
> export GOOGLE_API_KEY="your_google_api_key"
> export TAVILY_API_KEY="your_tavily_api_key"           # Optional
> export LANGSMITH_API_KEY="your_langsmith_api_key"     # Optional
> ```
>
> :::
>
> ### 添加配置文件
>
> **1. 添加 AGENTS.md**
>
> 在项目根目录创建 `AGENTS.md`。当你在创建智能体时通过 [记忆](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/memory.md) 参数传入此文件，它会被加载到系统提示词中，使品牌语调和研究期望在每次运行中生效：
>
> ```markdown expandable wrap theme={null}
> # Content Writer Agent
>
> You are a content writer for a technology company. Your job is to create engaging, informative content that educates readers about AI, software development, and emerging technologies.
>
> ## Brand Voice
>
> - **Professional but approachable**: Write like a knowledgeable colleague, not a textbook
> - **Clear and direct**: Avoid jargon unless necessary; explain technical concepts simply
> - **Confident but not arrogant**: Share expertise without being condescending
> - **Engaging**: Use concrete examples, analogies, and stories to illustrate points
>
> ## Writing Standards
>
> 1. **Use active voice**: "The agent processes requests" not "Requests are processed by the agent"
> 2. **Lead with value**: Start with what matters to the reader, not background
> 3. **One idea per paragraph**: Keep paragraphs focused and scannable
> 4. **Concrete over abstract**: Use specific examples, numbers, and case studies
> 5. **End with action**: Every piece should leave the reader knowing what to do next
>
> ## Content Pillars
>
> Our content focuses on:
> - AI agents and automation
> - Developer tools and productivity
> - Software architecture and best practices
> - Emerging technologies and trends
>
> ## Formatting Guidelines
>
> - Use headers (H2, H3) to break up long content
> - Include code examples where relevant (with syntax highlighting)
> - Add bullet points for lists of 3+ items
> - Keep sentences under 25 words when possible
> - Include a clear call-to-action at the end
>
> ## Research Requirements
>
> Before writing on any topic:
> 1. Use the `researcher` subagent for in-depth topic research
> 2. Gather at least 3 credible sources
> 3. Identify the key points readers need to understand
> 4. Find concrete examples or case studies to illustrate concepts
> ```
>
> 要匹配你自己的语调、内容支柱和格式规则，请更新 `AGENTS.md`。
>
> :::python
>
> **2. 添加 subagents.yaml**
>
> 创建 `subagents.yaml`。它描述了一个 `researcher` 子智能体，带有由 Tavily 支持的 `web_search` 工具：
>
> ```yaml subagents.yaml expandable wrap theme={null}
> # Subagent definitions
> # These are loaded by content_writer.py and wired up with tools
>
> researcher:
>   description: >
>     ALWAYS use this first to research any topic before writing content.
>     Searches the web for current information, statistics, and sources.
>     When delegating, tell it the topic AND the file path to save results
>     (e.g., 'Research renewable energy and save to research/renewable-energy.md').
>   model: anthropic:claude-haiku-4-5-20251001
>   system_prompt: |
>     You are a research assistant. You have access to web_search and write_file tools.
>
>     ## Your Tools
>     - web_search(query, max_results=5, topic="general") - Search the web
>     - write_file(file_path, content) - Save your findings
>
>     ## Your Process
>     1. Use web_search to find information on the topic
>     2. Make 2-3 targeted searches with specific queries
>     3. Gather key statistics, quotes, and examples
>     4. Save findings to the file path specified in your task
>
>     ## Important
>     - The user will tell you WHERE to save the file - use that exact path
>     - Always include source URLs in your findings
>     - Keep findings concise but informative
>   tools:
>     - web_search
> ```
>
> 创建深度智能体时会传入该文件。
>
> :::
>
> **3. 添加技能**
>
> 创建一个 `skills/` 目录。每个技能都是一个文件夹，其中包含带有 YAML frontmatter（`name`、`description`）和指令的 `SKILL.md` 文件。
>
> Create `skills/blog-post/SKILL.md`:
>
> ````md expandable wrap theme={null}
> ---
> name: blog-post
> description: Writes and structures long-form blog posts, creates tutorial outlines, and optimizes content for SEO with cover image generation. Use when the user asks to write a blog post, article, how-to guide, tutorial, technical writeup, thought leadership piece, or long-form content.
> ---
>
> # Blog Post Writing Skill
>
> ## Research First (Required)
>
> **Before writing any blog post, you MUST delegate research:**
>
> 1. Use the `task` tool with `subagent_type: "researcher"`
> 2. In the description, specify BOTH the topic AND where to save:
>
> ```
> task(
>     subagent_type="智能体",
>     description="研究 [主题]。将研究结果保存到 research/[slug].md"
> )
> ```
>
> Example:
> ```
> task(
>     subagent_type="智能体",
>     description="研究 2025 年 AI 智能体的现状。将研究结果保存到 research/ai-agents-2025.md"
> )
> ```
>
> 3. After research completes, read the findings file before writing
>
> ## Output Structure (Required)
>
> **Every blog post MUST have both a post AND a cover image:**
>
> ```
> blogs/
> └── <slug>/
>     ├── post.md        # 博客文章内容
>     └── hero.png       # REQUIRED: 生成的封面图片
> ```
>
> Example: A post about "AI Agents in 2025" → `blogs/ai-agents-2025/`
>
> **You MUST complete both steps:**
> 1. Write the post to `blogs/<slug>/post.md`
> 2. Generate a cover image using `generate_image` and save to `blogs/<slug>/hero.png`
>
> **A blog post is NOT complete without its cover image.**
>
> ## Blog Post Structure
>
> Every blog post should follow this structure:
>
> ### 1. Hook (Opening)
> - Start with a compelling question, statistic, or statement
> - Make the reader want to continue
> - Keep it to 2-3 sentences
>
> ### 2. Context (The Problem)
> - Explain why this topic matters
> - Describe the problem or opportunity
> - Connect to the reader's experience
>
> ### 3. Main Content (The Solution)
> - Break into 3-5 main sections with H2 headers
> - Each section covers one key point
> - Include code examples, diagrams, or screenshots where helpful
> - Use bullet points for lists
>
> ### 4. Practical Application
> - Show how to apply the concepts
> - Include step-by-step instructions if applicable
> - Provide code snippets or templates
>
> ### 5. Conclusion & CTA
> - Summarize key takeaways (3 bullets max)
> - End with a clear call-to-action
> - Link to related resources
>
> ## Cover Image Generation
>
> After writing the post, generate a cover image using the `generate_cover` tool:
>
> ```
> generate_cover(prompt="图片的详细描述...", slug="your-blog-slug")
> ```
>
> The tool saves the image to `blogs/<slug>/hero.png`.
>
> ### Writing Effective Image Prompts
>
> Structure your prompt with these elements:
>
> 1. **Subject**: What is the main focus? Be specific and concrete.
> 2. **Style**: Art direction (minimalist, isometric, flat design, 3D render, watercolor, etc.)
> 3. **Composition**: How elements are arranged (centered, rule of thirds, symmetrical)
> 4. **Color palette**: Specific colors or mood (warm earth tones, cool blues and purples, high contrast)
> 5. **Lighting/Atmosphere**: Soft diffused light, dramatic shadows, golden hour, neon glow
> 6. **Technical details**: Aspect ratio considerations, negative space for text overlay
>
> ### Example Prompts
>
> **For a technical blog post:**
> ```
> 等距 3D 插画，展示相互连接的发光立方体代表 AI 智能体，每个立方体都有微妙的电路图案。立方体通过发光的数据流连接。深海军蓝背景 (#0a192f) 配合亮蓝色 (#64ffda) 和柔和紫色 (#c792ea) 的点缀。简洁极简风格，顶部留出大量空白用于标题。专业科技美学。
> ```
>
> **For a tutorial/how-to:**
> ```
> 简洁平面插画，展示双手在键盘上打字，抽象代码符号向上漂浮，转化为灯泡和齿轮。背景为从柔和珊瑚到浅桃色的渐变色。友好、亲切的风格。居中构图，留出文本叠加空间。
> ```
>
> **For thought leadership:**
> ```
> 抽象可视化，展示人形剪影与几何神经网络图案融合。分割构图 - 左侧为有机水彩纹理，右侧过渡到干净矢量线条。柔和的橄榄绿和温暖陶土色系。沉思、前瞻的氛围。
> ```
>
> ## SEO Considerations
>
> - Include the main keyword in the title and first paragraph
> - Use the keyword naturally 3-5 times throughout
> - Keep the title under 60 characters
> - Write a meta description (150-160 characters)
>
> ## Quality Checklist
>
> Before finishing:
> - [ ] Post saved to `blogs/<slug>/post.md`
> - [ ] Hero image generated at `blogs/<slug>/hero.png`
> - [ ] Hook grabs attention in first 2 sentences
> - [ ] Each section has a clear purpose
> - [ ] Conclusion summarizes key points
> - [ ] CTA tells reader what to do next
> ````
>
> Create `skills/social-media/SKILL.md`:
>
> ````md expandable wrap theme={null}
> ---
> name: social-media
> description: Drafts engaging social media posts, writes hooks, suggests hashtags, creates thread structures, and generates companion images. Use when the user asks to write a LinkedIn post, tweet, Twitter/X thread, social media caption, social post, or repurpose content for social platforms.
> ---
>
> # Social Media Content Skill
>
> ## Research First (Required)
>
> **Before writing any social media content, you MUST delegate research:**
>
> 1. Use the `task` tool with `subagent_type: "researcher"`
> 2. In the description, specify BOTH the topic AND where to save:
>
> ```
> task(
>     subagent_type="研究者",
>     description="研究[TOPIC]。将发现保存到research/[slug].md"
> )
> ```
>
> Example:
> ```
> task(
>     subagent_type="研究者",
>     description="研究2025年可再生能源趋势。将发现保存到research/renewable-energy.md"
> )
> ```
>
> 3. After research completes, read the findings file before writing
>
> ## Output Structure (Required)
>
> **Every social media post MUST have both content AND an image:**
>
> **LinkedIn posts:**
> ```
> linkedin/
> └── <slug>/
>     ├── post.md        # 帖子内容
>     └── image.png      # REQUIRED: 生成的视觉元素
> ```
>
> **Twitter/X threads:**
> ```
> tweets/
> └── <slug>/
>     ├── thread.md      # 帖子内容
>     └── image.png      # REQUIRED: 生成的视觉元素
> ```
>
> Example: A LinkedIn post about "prompt engineering" → `linkedin/prompt-engineering/`
>
> **You MUST complete both steps:**
> 1. Write the content to the appropriate path
> 2. Generate an image using `generate_image` and save alongside the post
>
> **A social media post is NOT complete without its image.**
>
> ## Platform Guidelines
>
> ### LinkedIn
>
> **Format:**
> - 1,300 character limit (show more after ~210 chars)
> - First line is crucial - make it hook
> - Use line breaks for readability
> - 3-5 hashtags at the end
>
> **Tone:**
> - Professional but personal
> - Share insights and learnings
> - Ask questions to drive engagement
> - Use "I" and share experiences
>
> **Structure:**
> ```
> [钩子 - 1句引人入胜的话]
>
> [空行]
>
> [背景 - 为什么这很重要]
>
> [空行]
>
> [主要见解 - 2-3段简短段落]
>
> [空行]
>
> [号召行动或问题]
>
> #hashtag1 #hashtag2 #hashtag3
> ```
>
> ### Twitter/X
>
> **Format:**
> - 280 character limit per tweet
> - Threads for longer content (use 1/🧵 format)
> - No more than 2 hashtags per tweet
>
> **Thread Structure:**
> ```
> 1/🧵 [钩子 - 主要见解]
>
> 2/ [支持点1]
>
> 3/ [支持点2]
>
> 4/ [示例或证据]
>
> 5/ [结论+号召行动]
> ```
>
> ## Image Generation
>
> Every social media post needs an eye-catching image. Use the `generate_social_image` tool:
>
> ```
> generate_social_image(prompt="详细描述...", platform="linkedin", slug="your-post-slug")
> ```
>
> The tool saves the image to `<platform>/<slug>/image.png`.
>
> ### Social Image Best Practices
>
> Social images need to work at small sizes in crowded feeds:
> - **Bold, simple compositions** - one clear focal point
> - **High contrast** - stands out when scrolling
> - **No text in image** - too small to read, platforms add their own
> - **Square or 4:5 ratio** - works across platforms
>
> ### Writing Effective Prompts
>
> Include these elements:
>
> 1. **Single focal point**: One clear subject, not a busy scene
> 2. **Bold style**: Vibrant colors, strong shapes, high contrast
> 3. **Simple background**: Solid color, gradient, or subtle texture
> 4. **Mood/energy**: Match the post tone (inspiring, urgent, thoughtful)
>
> ### Example Prompts
>
> **For an insight/tip post:**
> ```
> 一个发光的灯泡悬浮在深紫色渐变背景上，灯泡由相互连接的金色几何线条构成，向外散发柔和的光线。极简、引人注目、高对比度。方形构图。
> ```
>
> **For announcements/news:**
> ```
> 由彩色几何形状组成的抽象火箭船向上发射，留下粒子轨迹。明亮珊瑚色和蓝绿色调，背景为干净白色。充满活力、庆祝氛围。大胆扁平插画风格。
> ```
>
> **For thought-provoking content:**
> ```
> 两个重叠的半透明圆圈，一个蓝色一个橙色，在中心形成发光的交集。代表合作或想法的交集。深煤灰背景，柔和空灵的光芒。极简和沉思。
> ```
>
> ## Content Types
>
> ### Announcement Posts
> - Lead with the news
> - Explain the impact
> - Include link or next step
>
> ### Insight Posts
> - Share one specific learning
> - Explain the context briefly
> - Make it actionable
>
> ### Question Posts
> - Ask a genuine question
> - Provide your take first
> - Keep it focused on one topic
>
> ## Quality Checklist
>
> Before finishing:
> - [ ] Post saved to `linkedin/<slug>/post.md` or `tweets/<slug>/thread.md`
> - [ ] Image generated alongside the post
> - [ ] First line hooks attention
> - [ ] Content fits platform limits
> - [ ] Tone matches platform norms
> - [ ] Has clear CTA or question
> - [ ] Hashtags are relevant (not generic)
> ````
>
> 它们指示智能体先调用 `researcher` 子智能体，将 Markdown 写入 `blogs/`、`linkedin/` 或 `tweets/`，并调用 `generate_cover` 或 `generate_social_image` 生成图像。
>
> ### 构建脚本
>
> :::python
> 在项目根目录创建 `content_writer.py`。以下各部分应按顺序放在同一个文件中。
> :::
>
> :::js
> 在项目根目录创建 `content_writer.ts`。以下各部分应按顺序放在同一个文件中。
> :::
>
> **1. 添加工具**
>
> :::python
> 研究者子智能体使用 Tavily 搜索。博客和社交媒体工作流使用 Gemini 图像生成。稍后创建智能体时，`load_subagents` 会读取 `subagents.yaml` 并将工具名称解析为这些函数。
>
> ```python theme={null}
> import os
> from pathlib import Path
> from typing import Literal
>
> import yaml
> from langchain.tools import tool
>
> EXAMPLE_DIR = Path(__file__).parent
>
>
> @tool
> def web_search(
>     query: str,
>     max_results: int = 5,
>     topic: Literal["general", "news"] = "general",
> ) -> dict:
>     """Search the web for current information.
>
>     Args:
>         query: The search query (be specific and detailed)
>         max_results: Number of results to return (default: 5)
>         topic: "general" for most queries, "news" for current events
>
>     Returns:
>         Search results with titles, URLs, and content excerpts.
>     """
>     try:
>         from tavily import TavilyClient
>
>         api_key = os.environ.get("TAVILY_API_KEY")
>         if not api_key:
>             return {"error": "TAVILY_API_KEY not set"}
>
>         client = TavilyClient(api_key=api_key)
>         return client.search(query, max_results=max_results, topic=topic)
>     except Exception as e:
>         return {"error": f"Search failed: {e}"}
>
>
> @tool
> def generate_cover(prompt: str, slug: str) -> str:
>     """Generate a cover image for a blog post.
>
>     Args:
>         prompt: Detailed description of the image to generate.
>         slug: Blog post slug. Image saves to blogs/<slug>/hero.png
>     """
>     try:
>         from google import genai
>
>         client = genai.Client()
>         response = client.models.generate_content(
>             model="gemini-2.5-flash-image",
>             contents=[prompt],
>         )
>
>         for part in response.parts:
>             if part.inline_data is not None:
>                 image = part.as_image()
>                 output_path = EXAMPLE_DIR / "blogs" / slug / "hero.png"
>                 output_path.parent.mkdir(parents=True, exist_ok=True)
>                 image.save(str(output_path))
>                 return f"Image saved to {output_path}"
>
>         return "No image generated"
>     except Exception as e:
>         return f"Error: {e}"
>
>
> @tool
> def generate_social_image(prompt: str, platform: str, slug: str) -> str:
>     """Generate an image for a social media post.
>
>     Args:
>         prompt: Detailed description of the image to generate.
>         platform: Either "linkedin" or "tweets"
>         slug: Post slug. Image saves to <platform>/<slug>/image.png
>     """
>     try:
>         from google import genai
>
>         client = genai.Client()
>         response = client.models.generate_content(
>             model="gemini-2.5-flash-image",
>             contents=[prompt],
>         )
>
>         for part in response.parts:
>             if part.inline_data is not None:
>                 image = part.as_image()
>                 output_path = EXAMPLE_DIR / platform / slug / "image.png"
>                 output_path.parent.mkdir(parents=True, exist_ok=True)
>                 image.save(str(output_path))
>                 return f"Image saved to {output_path}"
>
>         return "No image generated"
>     except Exception as e:
>         return f"Error: {e}"
>
>
> def load_subagents(config_path: Path) -> list:
>     """Load subagent definitions from YAML and wire up tools.
>
>     Unlike `memory` and `skills`, deep agents do not load subagents from files by default.
>     This helper externalizes configuration so you can edit YAML without changing Python code.
>     """
>     available_tools = {
>         "web_search": web_search,
>     }
>
>     with open(config_path) as f:
>         config = yaml.safe_load(f)
>
>     subagents = []
>     for name, spec in config.items():
>         subagent = {
>             "name": name,
>             "description": spec["description"],
>             "system_prompt": spec["system_prompt"],
>         }
>         if "model" in spec:
>             subagent["model"] = spec["model"]
>         if "tools" in spec:
>             subagent["tools"] = [available_tools[t] for t in spec["tools"]]
>         subagents.append(subagent)
>
>     return subagents
> ```
>
> :::
>
> :::js
> 研究者使用 Tavily 搜索。博客和社交媒体工作流使用 Google Generative AI SDK 进行图像生成。
>
> ```ts theme={null}
> 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"),
>     }),
>   },
> );
> ```
>
> :::
>
> **2. 创建智能体**
>
> :::python
> 创建深度智能体时，通过@\[create\_deep\_agent]传递内存路径、技能目录、图像工具、子智能体定义（从YAML中传入），并配置以example目录为根的[FilesystemBackend](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/backends.md)，以确保路径如`./AGENTS.md`和`./skills/`能正确解析。
>
> ```python Google theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="google_genai:gemini-3.6-flash",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> ```python OpenAI theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="openai:gpt-5.5",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> ```python Anthropic theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="anthropic:claude-sonnet-5",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> ```python OpenRouter theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="openrouter:z-ai/glm-5.2",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> ```python Fireworks theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="fireworks:accounts/fireworks/models/glm-5p2",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> ```python Baseten theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="baseten:zai-org/GLM-5.2",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> ```python Ollama theme={null}
> from deepagents import create_deep_agent
> from deepagents.backends import FilesystemBackend
>
>
> def create_content_writer():
>     """Create a content writer agent configured by filesystem files."""
>     return create_deep_agent(
>         model="ollama:north-mini-code-1.0",
>         memory=["./AGENTS.md"],
>         skills=["./skills/"],
>         tools=[generate_cover, generate_social_image],
>         subagents=load_subagents(EXAMPLE_DIR / "subagents.yaml"),
>         backend=FilesystemBackend(root_dir=EXAMPLE_DIR),
>     )
> ```
>
> :::
>
> :::js
> 创建深度智能体时，通过@\[createDeepAgent]传递内存路径、技能目录、图像工具、内联子智能体定义，并配置以example目录为根的[FilesystemBackend](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/backends.md)，以确保路径如`./AGENTS.md`和`./skills/`能正确解析。
>
> ```ts Google theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "google:gemini-3.6-flash",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> ```ts OpenAI theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "openai:gpt-5.5",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> ```ts Anthropic theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "anthropic:claude-sonnet-5",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> ```ts OpenRouter theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "openrouter:z-ai/glm-5.2",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> ```ts Fireworks theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "fireworks:accounts/fireworks/models/glm-5p2",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> ```ts Baseten theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "baseten:zai-org/GLM-5.2",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> ```ts Ollama theme={null}
> import { createDeepAgent, FilesystemBackend } from "deepagents";
>
> function createContentWriter() {
>   const researcherSubagent = {
>     name: "researcher",
>     description:
>       "Research subagent with web search capability. Delegate research tasks here.",
>     systemPrompt:
>       "You are a research assistant. Use the web_search tool to find current, accurate information and return well-organized findings.",
>     tools: [webSearch],
>   };
>
>   return createDeepAgent({
>     model: "ollama:north-mini-code-1.0",
>     memory: ["./AGENTS.md"],
>     skills: ["./skills/"],
>     tools: [generateCover, generateSocialImage],
>     subagents: [researcherSubagent],
>     backend: new FilesystemBackend({ rootDir: EXAMPLE_DIR }),
>   });
> }
> ```
>
> :::
>
> **3. 添加入口点**
>
> :::python
> 通过用户消息调用智能体以验证其运行状态：
>
> ```python theme={null}
> import sys
>
> from langchain.messages import HumanMessage
>
> if __name__ == "__main__":
>     task = (
>         " ".join(sys.argv[1:])
>         if len(sys.argv) > 1
>         else "Write a blog post about how AI agents are transforming software development"
>     )
>
>     agent = create_content_writer()
>     result = agent.invoke(
>         {"messages": [HumanMessage(content=task)]},
>         config={"configurable": {"thread_id": "content-builder-demo"}},
>     )
>
>     for msg in result.get("messages", []):
>         if hasattr(msg, "content") and msg.content:
>             print(msg.content)
> ```
>
> :::
>
> :::js
>
> ```ts theme={null}
> 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);
> }
> ```
>
> :::
>
> ### 运行智能体
>
> > [!WARNING]
> >
> > 文件系统后端可在`root_dir`下读写和删除文件。仅限专用目录运行，发布前请审阅生成内容。
>
> :::python
> 从项目目录调用智能体时，既可省略参数，也可通过参数传递提示词：
>
> ```bash Default wrap theme={null}
> python content_writer.py
> ```
>
> ```bash With prompt wrap theme={null}
> python content_writer.py Write a blog post about prompt engineering
> ```
>
> :::
>
> :::js
> 从项目目录执行：
>
> ```bash theme={null}
> npx tsx content_writer.ts
> ```
>
> 通过额外参数传递提示词：
>
> ```bash theme={null}
> npx tsx content_writer.ts Write a blog post about prompt engineering
> ```
>
> :::
>
> 当`LANGSMITH_API_KEY`配置就绪后，可通过[LangSmith](https://docs.langchain.com/langsmith/observability)查看运行记录。
>
> ### 输出
>
> :::js
> 调用成功时，智能体会在项目根目录下写入生成物，例如：
> :::
>
> :::python
> 调用成功时，生成物会写入系统临时目录（macOS/Linux通常为`/tmp/`），而非项目文件旁。
> :::
>
> ```text theme={null}
> 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框架的流式输出界面。

## 下一步操作

* 编辑品牌规则：在`instructions.md`（托管深度智能体）或`AGENTS.md`（SDK）中修改
* 为新内容类型添加技能至`skills/<name>/SKILL.md`
* SDK路径下在`subagents.yaml`添加子智能体并在`load_subagents`注册工具；托管深度智能体则需编辑`agent.py`或`agent.ts`中的内联`researcher`
* 阅读文档：[Subagents](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/subagents.md)、[Skills](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/skills.md)和[Customization](https://langchain-docs-zh.mintlify.site/langchain/oss/deepagents/customization.md)
* 参考指南：[Managed Deep Agents](https://docs.langchain.com/langsmith/managed-deep-agents-overview)和[从深度智能体迁移](https://docs.langchain.com/langsmith/managed-deep-agents-migrate)

***

> 官方原文：[src/oss/deepagents/content-builder.mdx](https://github.com/langchain-ai/docs/blob/main/src/oss/deepagents/content-builder.mdx) · 非官方翻译，译文由 AI 生成，以英文原文为准。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.