之前做内容运营时,最烦的一件事不是写正文,而是发完一个平台还要再改一版标题、换一套标签、重写一段简介。同一个主题,在 YouTube、B站、小红书上的表达方式完全不同,硬生生把写作变成了重复劳动。后来我用 ChatGPT 的 Skill 能力做了一个“多平台内容发布包生成器”,输入主题和素材,5 分钟内就能拿到三个平台各自可发布的标题、描述、标签、话题和发布清单。
这篇文章就把这个 Skill 的完整实现过程拆开讲清楚。你会理解 Skill 到底是什么、为什么它比普通 Prompt 更省心,也会拿到一份可以直接复制到自己项目里运行的代码仓库。适合有内容运营需求、经常跨平台发内容,或者想学习 Agent Skill 开发思路的读者。
1. 背景与核心概念
1.1 什么是 ChatGPT Skill
Skill 可以理解成 AI 助手的一个“专业技能包”。它不只是一个提示词,而是把一段固定能力描述、一组模板文件、若干执行脚本打包在一起,让 AI 在收到相关任务时,自动按照你预设的流程和工具去执行。
在 ChatGPT 这类 AI 工具里,普通对话是无状态的,你每次发任务都要重复说明“请按我的格式输出”,而 Skill 把这些规则固化下来。只要用户触发了 Skill 的关键词或意图,AI 就会自动加载对应的配置文件、模板和脚本,按既定流程完成工作。
这样的设计带来的直接好处是:
- 输出结果更稳定,不会每次凭 AI 心情自由发挥。
- 可复用一个定义好的流程,不需要反复描述需求。
- 可以把外部脚本、模板仓库、预置数据都集成进来。
- 适合处理标准化程度较高、需要多步骤协作的任务。
1.2 Skill 与普通 Prompt 的区别
很多同学最开始会把 Skill 理解为“一段写得很好的 Prompt”。这个理解只对了一半。
普通 Prompt 是一段自然语言指令,AI 只能靠语言理解去生成,结果好坏取决于上下文表达。Skill 则是一套完整的“指令 + 资源 + 逻辑”的组合,它除了让 AI 知道“做什么”,还提供了脚本、模板、文件路径等真实执行的素材。
举个例子:
普通 Prompt 的写法是:请帮我写一个适合在 YouTube 发布的标题,并给出 5 个标签。
Skill 的写法是:读取模板文件templates/youtube.txt,运行scripts/generate_bundle.py,传入主题和内容参数,输出一份 Markdown 格式的发布包文件。
两者对比,Skill 更适合做那些重复性强、格式固定、需要多文件协作的任务。
1.3 这个 Skill 解决什么问题
回到开头提到的场景。很多创作者同时在多个平台运营账号,但每个平台的内容调性完全不同:
- YouTube 更适合完整的标题 + 长描述 + 章节 + SEO 关键词。
- B站用户习惯“三连”和弹幕文化,标题要有信息量,简介要清晰,最好再配动态文案。
- 小红书是种草场景,标题要有情绪点,正文要口语化,标签要足够细。
人工为每个平台写一套发布物料,一个主题至少需要 15 到 30 分钟。而用 Skill 把模板和脚本固化后,AI 负责理解素材、套模板,脚本负责渲染输出,整个过程从输入到拿到文件只需要几分钟。
这个听起来像是“自动写文案工具”,但实际核心是:用 Skill 把“一次性的 AI 输出”升级成“可复用的内容生产线”。
2. 需求分析与整体设计
2.1 功能拆分
在动手写代码前,先把这个 Skill 要做什么拆清楚:
- 接收用户输入的主题和素材。
- 根据主题内容,由 AI 判断各平台的标题风格。
- 调用模板,渲染出三份不同平台的发布包。
- 将结果保存为独立 Markdown 文件,并生成一份发布清单。
整个流程不追求完全自动化代替人写,而是把最耗时的“排版 + 搭框架 + 写基础文案”部分交给 Skill 完成,创作者拿到结果后再人工润色。
2.2 各平台文案差异
做内容发布包,最核心的是理解平台差异。我在模板里预设了三种风格:
| 平台 | 标题特点 | 正文/简介 | 标签/话题 |
|---|---|---|---|
| YouTube | 关键词前置,包含明确信息量,突出教程价值 | 较长描述,带章节、时间点、关键资源 | 英文标签或中英混合,适合搜索 |
| B站 | 信息量明确,有一定好奇心驱动力 | 简洁简介,带节目风格或共创说明 | 多个中文标签,覆盖核心内容 |
| 小红书 | 情绪点 + 场景感,口语化,适度夸张 | 短段落,带表情和互动引导 | 细粒度话题标签,覆盖人群关键词 |
模板里会把这些差异固化下来,AI 在调用时不需要重新设计文案规范,只需要根据具体内容填充。
2.3 目录结构设计
这个 Skill 的项目结构如下:
social-bundle-creator/ ├── SKILL.md ├── scripts/ │ └── generate_bundle.py ├── templates/ │ ├── youtube.txt │ ├── bilibili.txt │ └── xiaohongshu.txt └── output/SKILL.md:技能描述文件,告诉 AI 这个 Skill 是什么、怎么用。scripts/generate_bundle.py:核心生成脚本,负责读取模板并输出发布包。templates/:三个平台的文案模板。output/:脚本运行后生成的发布包目录。
这样的结构不算复杂,但已经足够覆盖“固定模板 + 参数输入 + 文件输出”的完整链路。
3. 环境准备与版本说明
3.1 运行环境
因为这个 Skill 的核心逻辑是 Python 脚本,所以对环境要求很低:
- 操作系统:Windows / macOS / Linux 均可。
- Python:3.9 或以上版本。
- 依赖:本文示例只使用 Python 标准库,不需要安装任何第三方包。
- 文本编辑器:VS Code、Sublime 或任意可编辑 Markdown 文件的工具。
- AI 客户端:需要支持 Skill 功能的 ChatGPT 客户端或兼容 Agent Skill 的本地工具。
版本需要注意:不同客户端的 Skill 加载方式可能有差异,本文重点演示的是技能本身的设计思路和脚本实现。你在实际使用时,根据自己使用的客户端调整 Skill 目录的放置位置即可。
3.2 验证 Python 环境
打开终端,执行以下命令确认 Python 版本:
python --version如果你的系统里同时存在多个 Python 版本,也可以用python3:
python3 --version建议使用 Python 3.9 以上版本,这样代码里使用的pathlib、string.Template等标准库模块行为更稳定。
4. 编写 SKILL.md:定义技能的入口
4.1 SKILL.md 的作用
SKILL.md是整个 Skill 的“说明书”。AI 在加载 Skill 时,首先读取的就是这个文件。它定义了技能的名称、描述、触发条件和执行流程。
需要注意,不同平台对SKILL.md的字段定义不完全一致。本文使用的是比较通用的结构,你可以根据自己的客户端调整字段名。
4.2 完整示例
在social-bundle-creator/SKILL.md中写入以下内容:
--- name: social-bundle-creator description: 根据用户提供的主题和原始素材,自动生成 YouTube、哔哩哔哩、小红书三个平台的内容发布包,包括标题、描述、标签、话题和发布清单。 version: 1.0.0 author: your-name trigger: - 生成多平台发布包 - 生成小红书发布文案 - 帮我做内容发布素材 --- # 多平台内容发布包生成器 ## 技能说明 这个 Skill 用于把一段原始内容素材,快速加工成三个平台的发布包: 1. YouTube:侧重 SEO 标题、长描述、标签、章节。 2. 哔哩哔哩:侧重标题信息量、简介、动态文案、标签。 3. 小红书:侧重笔记正文、话题标签、互动引导。 ## 使用流程 1. 确认用户提供的主题 topic 和原始内容 content。 2. 询问或确认作者署名 author,如果用户没有提供,默认使用 default-author。 3. 调用仓库中的 Python 脚本,生成三个平台的 Markdown 文件。 4. 把生成结果展示给用户,提示可手动修改标题、标签和正文。 ## 调用示例 假设用户说:帮我把这篇 Python 自动化办公的教程,做成全平台发布包。 你可以执行: python scripts/generate_bundle.py --topic "Python 自动化办公" --content "这是一篇介绍用 pandas 处理 Excel 表格的教程..." --author "张三" ## 注意事项 - 如果用户输入的内容较长,可以放在单独的文件中,再传给脚本。 - 生成结果是初稿,需要保留用户手工调整的空间。 - 不要伪造作者信息,作者署名必须来自用户。在这个文件里,最重要的部分是“使用流程”。AI 看到的不只是一句“请生成文案”,而是一套可以执行的步骤。它会先确认参数,再调用脚本,最后展示结果。这种确定性正是 Skill 相比普通 Prompt 的优势。
4.3 字段说明
name:技能名称,用于内部标识。description:技能描述,AI 根据描述判断何时触发这个 Skill。trigger:触发词列表,帮助 AI 更快匹配用户意图。version:版本号,后续维护时方便回溯。author:作者信息,避免使用他人技能时混淆。
这里要提醒一下:trigger字段只是辅助匹配,不是强制规则。最终是否触发 Skill,取决于 AI 对用户输入语义的判断。你在实际使用中,尽量把 trigger 写成用户可能出现的原话,匹配率会更高。
5. 编写生成脚本:核心逻辑
5.1 脚本设计思路
脚本是整个 Skill 的执行核心。它接收主题、内容、作者、标签等参数,然后读取模板文件,用参数替换模板中的占位符,最终生成三个平台的发布包文件。
设计上我做了三个重点决定:
- 只用 Python 标准库,降低安装和部署成本。
- 模板与代码分离,改文案不用动代码。
- 每个平台输出独立文件,同时生成一个汇总清单,方便发布时对照。
5.2 完整代码
在social-bundle-creator/scripts/generate_bundle.py中写入:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 多平台内容发布包生成器 用法示例: python generate_bundle.py \ --topic "Python 自动化办公" \ --content "这是一段介绍用 pandas 处理 Excel 表格的教程内容" \ --author "张三" \ --tags "Python,pandas,Excel,自动化办公" \ --keywords "Python, pandas, Excel, 自动化办公" """ import argparse import json import os from datetime import date from pathlib import Path from string import Template def load_template(template_path: str) -> Template: """读取模板文件,返回 Template 对象。""" text = Path(template_path).read_text(encoding="utf-8") return Template(text) def render_template(template: Template, context: dict) -> str: """使用 context 中的字段渲染模板。""" return template.safe_substitute(context) def build_context(args) -> dict: """构建模板渲染上下文。""" today = date.today().isoformat() tags = args.tags if args.tags else "#Python #pandas #Excel #自动化办公" keywords = args.keywords if args.keywords else "Python, pandas, Excel, 自动化办公" return { "topic": args.topic, "content": args.content, "author": args.author, "date": today, "tags": tags, "keywords": keywords, } def main(): parser = argparse.ArgumentParser(description="生成多平台内容发布包") parser.add_argument("--topic", required=True, help="内容主题") parser.add_argument("--content", required=True, help="正文内容或素材") parser.add_argument("--author", default="匿名", help="作者署名") parser.add_argument("--tags", default="", help="标签,逗号分隔") parser.add_argument("--keywords", default="", help="SEO 关键词") parser.add_argument("--output-dir", default="output", help="输出目录") args = parser.parse_args() # 计算项目根目录 base_dir = Path(__file__).resolve().parent.parent template_dir = base_dir / "templates" output_dir = Path(args.output_dir) # 确保输出目录存在 output_dir.mkdir(parents=True, exist_ok=True) context = build_context(args) platforms = { "youtube": "YouTube", "bilibili": "哔哩哔哩", "xiaohongshu": "小红书", } for key, name in platforms.items(): template_path = template_dir / f"{key}.txt" if not template_path.exists(): print(f"[WARN] 找不到模板:{template_path}") continue template = load_template(template_path) rendered = render_template(template, context) out_file = output_dir / f"{key}_pub.md" out_file.write_text(rendered, encoding="utf-8") print(f"[OK] 已生成 {name} 发布包:{out_file}") # 生成发布清单 summary = { "topic": args.topic, "author": args.author, "date": context["date"], "platforms": [value for key, value in platforms.items() if (template_dir / f"{key}.txt").exists()], "output_dir": str(output_dir), } manifest = output_dir / "manifest.json" manifest.write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding="utf-8") print(f"[OK] 已生成发布清单:{manifest}") if __name__ == "__main__": main()5.3 代码关键点说明
第一,safe_substitute是string.Template的一个方法。它和substitute的区别是,即使模板里出现了未定义的占位符,safe_substitute也不会抛异常,而是保留原样。这在模板迭代期间非常友好,不会因为一个字段名写错导致整个脚本崩溃。
第二,base_dir的计算方式是Path(__file__).resolve().parent.parent。因为脚本位于scripts目录下,向上两级就是项目根目录social-bundle-creator,这样无论从终端哪个位置运行脚本,都能正确找到templates目录。
第三,脚本用output_dir参数控制输出位置。默认是当前运行目录下的output文件夹。如果需要把结果输出到别的地方,可以显式指定。
6. 编写各平台文案模板
6.1 YouTube 模板
在templates/youtube.txt中写入:
YouTube 发布包 ==================================== 标题: {topic} | 完整教程与实操案例 描述: 本期视频围绕「{topic}」展开,从基础概念入手,逐步演示完整操作流程。 视频中会涉及关键步骤拆解、常见问题规避和实战落地建议。 📌 时间轴 0:00 开场与背景介绍 2:30 核心概念与整体流程 6:00 实际操作演示 10:30 常见问题与避坑指南 13:00 总结与资源推荐 关键词: {keywords} 标签: {tags} 作者:{author} 日期:{date}这里需要说明,脚本用的是string.Template,占位符是${topic}这种形式,但为了模板方便阅读,我写成了{topic}。有两种处理方式:一种是改脚本,用.format()渲染;另一种是把模板占位符改成${topic}。为了让脚本和模板匹配,实际使用时应将模板中的{topic}改为${topic},其他同理。
为了避免复制后忘记,可以直接使用下面这份匹配脚本语法的 YouTube 模板:
YouTube 发布包 ==================================== 标题: ${topic} | 完整教程与实操案例 描述: 本期视频围绕「${topic}」展开,从基础概念入手,逐步演示完整操作流程。 视频中会涉及关键步骤拆解、常见问题规避和实战落地建议。 📌 时间轴 0:00 开场与背景介绍 2:30 核心概念与整体流程 6:00 实际操作演示 10:30 常见问题与避坑指南 13:00 总结与资源推荐 关键词: ${keywords} 标签: ${tags} 作者:${author} 日期:${date}6.2 B站模板
在templates/bilibili.txt中写入:
哔哩哔哩发布包 ==================================== 标题: 【教程】${topic},学会后再也不用加班 简介: 本期视频是一份面向零基础同学的上手教程,围绕「${topic}」展开。 内容包括完整流程演示、核心要点拆解、实战中的常见坑点。 喜欢的话记得一键三连,更新会更快。 动态文案: 刚做完一期《${topic}》的视频,从零开始完整演示操作流程。 视频里放了我整理的关键步骤和时间轴,欢迎来看。 关注我,后续会有更多实战内容。 标签: ${tags} 作者:${author} 日期:${date}B站的内容风格和 YouTube 不同,简介更短,动态文案偏轻松口语化。标签不需要太多,但必须覆盖核心主题。
6.3 小红书模板
在templates/xiaohongshu.txt中写入:
小红书发布包 ==================================== 标题: 绝了!${topic}这样做,效率直接翻倍✨ 正文: 真的建议所有新手都试试这个方法! 今天把「${topic}」从入门到实操完整梳理了一遍: ✅ 适用场景和准备工作 ✅ 完整步骤拆解 ✅ 常见坑点避雷 亲测好用,收藏起来慢慢看。 互动引导: 你是怎么处理的?评论区聊聊👇 话题标签: ${tags} 作者:${author} 日期:${date}小红书模板更注重情绪点、表情符号和互动引导。这类文案不是硬邦邦的教程,而是“分享感”很强的笔记风格。
7. 安装 Skill 并实际运行
7.1 放置 Skill 目录
如果你使用的是支持 Skill 功能的客户端,一般会有专门的 “Skills” 目录,用于存放用户自定义技能。把整个social-bundle-creator文件夹复制到该目录即可。
不同客户端的路径位置不同,有的在用户配置目录下,有的在插件商店的本地目录里。你可以在客户端的设置页找到类似 “Skills 目录” 或 “扩展目录” 的选项。如果找不到对应选项,优先查看官方文档。
7.2 通过命令行运行脚本
在项目根目录执行以下命令:
python scripts/generate_bundle.py \ --topic "Python 自动化办公" \ --content "这是一篇介绍用 pandas 处理 Excel 表格的入门教程,内容包括数据读取、清洗、透视表生成,适合职场新人学习。" \ --author "张三" \ --tags "Python,pandas,Excel,自动化办公" \ --keywords "Python, pandas, Excel, 自动化办公"预期输出:
[OK] 已生成 YouTube 发布包:output/youtube_pub.md [OK] 已生成 哔哩哔哩 发布包:output/bilibili_pub.md [OK] 已生成 小红书 发布包:output/xiaohongshu_pub.md [OK] 已生成发布清单:output/manifest.json7.3 查看生成结果
命令执行后,output目录下会多出四个文件:
youtube_pub.mdbilibili_pub.mdxiaohongshu_pub.mdmanifest.json
打开youtube_pub.md,你会看到一份完整的发布包,标题、描述、时间轴、标签都已经替换成刚才传入的主题内容。整个过程不需要手动编辑模板,也不需要复制粘贴。
7.4 在对话中调用 Skill
如果客户端已经成功加载 Skill,你甚至不需要手动执行脚本,而是直接在对话中输入:
帮我把这篇 Python 自动化办公的教程,做成全平台发布包AI 会读取SKILL.md,理解你的意思,然后自动执行脚本并返回结果。这是整个 Skill 最方便的地方:把“写代码”变成了“说一句话”。
8. 常见问题与排查思路
8.1 常见问题汇总
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 客户端提示找不到 Skill | 目录放置位置不对,或 SKILL.md 格式错误 | 检查 Skills 目录路径,确认 YAML frontmatter 没有被破坏 |
| 提示无法定位 codex cli binary | 客户端安装不完整,缺少本地 CLI 组件 | 检查安装目录完整性和版本,重新安装客户端 |
| 提示 can't load config.toml | 客户端配置文件格式或字段不合法 | 备份原配置文件后重置或修改有问题的字段 |
| 提示 spawn EINVAL | 本地调用子进程失败,参数无效或权限不足 | 检查命令路径、权限设置和系统环境变量 |
| 生成的文案风格不对 | 模板与脚本占位符不匹配 | 确认模板使用${xxx}形式,脚本使用safe_substitute |
| 中文输出乱码 | 编码环境问题 | 在 Python 脚本中明确使用encoding="utf-8",终端调整为 UTF-8 |
8.2 针对启动报错的排查思路
如果你遇到的是客户端本身的启动报错,比如chatgpt failed to start. unable to locate the codex cli binary,可以先按下面顺序排查:
- 确认客户端是否完整安装,安装包是否被安全软件拦截。
- 检查客户端内置的 CLI 组件路径是否存在。
- 查看客户端是否有可用的更新版本,优先升级到最新版。
- 如果问题依然存在,备份聊天记录和配置后彻底卸载并重装。
对于can't load config.toml这类问题,不要直接删除配置文件,建议先备份,再用文本编辑器检查配置文件中的语法问题。
这些报错基本都是客户端进程层面的问题,和 Skill 内容本身无关。你编写的 SKILL.md 和脚本可以单独用命令行验证,不会受到这些启动问题的影响。
9. 最佳实践与工程建议
9.1 模板与脚本分离
模板负责文案结构,脚本负责数据渲染。这样做的好处是,当你想调整某平台的文案风格时,只需要修改对应的txt文件,不需要动 Python 代码。
如果你发现自己频繁改代码,说明模板抽象得还不够。把平台之间的公共部分提取出来,差异部分保留在各自模板中,维护成本会明显降低。
9.2 善用版本管理
Skill 本质上也是一份代码仓库,建议使用 Git 管理。每次调整模板和脚本后提交一次,后续如果发行了新版本可以及时回退。
特别是团队合作时,不同成员维护不同平台的模板,版本管理可以避免“你改我也改,最后不知道谁覆盖了谁”的冲突。
9.3 文案要符合平台规则
自动生成的内容只是初稿,不能直接无脑发布。例如各平台都不鼓励诱导点赞、关注、分享等行为,不建议在模板里写“关注我领资料”“转发抽奖”这类违规风险较高的文案。
你可以在模板中保留互动引导的占位符,但具体表达需要人工把关,符合平台社区规范。
9.4 保留人工润色空间
Skill 的价值是帮你省去“从零开始”的时间,而不是完全替代你的创作判断。标题的情绪点、正文的语气、话题标签的精准度,这些仍然需要人来决定。
建议在实际使用中,把 Skill 生成的内容当作 80 分初稿,在此基础上进行微调,而不是直接原样发布。这样既保证速度,也保留个人风格。
9.5 提前设计好输入参数
脚本支持的参数越多,灵活度越高,但使用成本也随之增加。你可以为不同的内容场景设计几个预设模板,比如“教程类”“测评类”“日常类”,再把它们做成独立参数或独立模板文件。
比如增加一个--style参数,值为tutorial、review、daily,脚本根据不同的风格选择不同的模板目录。这种扩展方式不需要改动现有脚本的骨架。
9.6 注意隐私和数据边界
调用外部 AI 接口时,不要在输入内容中直接放入用户手机号、地址、内部系统截图等敏感信息。如果内容素材太长,建议先本地处理或提炼摘要,再传入 Skill。
涉及具体业务数据时,最好在本地先把内容脱敏,再交给 AI 生成发布文案。
10. 下一步可以扩展什么
到这里,你已经拥有一个可运行的“多平台内容发布包生成器”。如果继续深入,可以考虑这些方向。
第一,增加更多平台模板。例如知乎回答风格、微博短文案、微信公众号排期稿,只需要新增模板文件,并修改脚本里的platforms字典。
第二,接入标题评分逻辑。让脚本在输出标题后,自动检查标题长度、关键词密度、是否包含数字等指标,帮助创作者快速判断标题质量。
第三,把生成结果与草稿箱同步。如果平台提供 API,可以在脚本中增加自动发布或导出草稿的功能,进一步减少人工操作。
这个 Skill 的本质,是把“重复的排版劳动”交给脚本,把“创作判断”留给人。核心不是代码有多复杂,而是你如何设计模板和流程,让它真正贴合自己的工作习惯。
如果这篇文章对你有帮助,建议直接照着项目结构建一个自己的 Skill,把平时常用的几个平台的文案模板放进去。动手跑通一次,远比看十遍教程更有价值。