
“你养龙虾了吗?”——这大概是 2026 年春天最流行的社交寒暄了。一个月前,我也跟风在阿里云买了台轻量服务器,把那只可爱的 OpenClaw 小龙虾接回了家。它能听懂指令、操控电脑,24 小时在线。可兴奋过后,我很快陷入了困惑:我到底该怎么“教”它干活?
这其实也是很多“养虾人”共同的瓶颈:OpenClaw 给你的只是一个空转的引擎,它潜力无穷,但它不知道你的目标是什么。有人用它自动盯盘选股,有人让它一键发公众号,还有人用它处理民生政务。真正用起来的人,都掌握了一项核心技能:给 AI 写一份靠谱的“说明书”。
今天,我们就一起来亲手写一份“说明书”。我们要做一个名为 Resume Forge 的 Skill,它能一键把你的 Markdown 简历转成精致的 PDF。全程不写复杂的 Agent 逻辑,只靠一个 SKILL.md 文件和 OpenClaw 的 Skills 机制。
为什么选“简历生成”这个场景?
原因很直接:
- 零外部依赖:不需要 API Key、数据库或网络。克隆下来就能跑。
- 输出直观:丢进去一份 Markdown,出来一份漂亮的 PDF,效果立等可取。
- 天然覆盖 Skill 所有特性:元数据、渐进式披露的三级加载、脚本、参考资料、资产、验证循环、陷阱清单、模板——这些会用到的知识全部用上。
我们的目标是:构建一个能在 Claude Code、VS Code with Copilot、Cursor 或任何支持 agentskills.io 规范的 Agent 中安装运行的完整 Skill。
最终目录结构
resume-forge/
├── SKILL.md ← 核心:Skill的“大脑”
├── scripts/ ← Level 3: 可执行代码
│ ├── parse_resume.py ← Markdown → 结构化JSON
│ ├── validate_resume.py ← 检查缺失内容、质量问题
│ └── generate_pdf.py ← JSON + 模板 → PDF
├── references/ ← Level 3: 按需加载
│ ├── ats-optimization.md ← ATS关键词策略和格式规则
│ └── industry-styles.md ← 不同行业的风格建议(科技、金融等)
└── assets/ ← Level 3: 静态资源
├── template_modern.html ← 现代风格模板
├── template_classic.html ← 经典风格模板
├── template_compact.html ← 紧凑风格模板
├── report_template.md ← 质量报告模板
└── sample_input.md ← 示例简历(供测试)
每个文件都对应着核心概念。我们一步步来搭建。
Step 1: 定义前置元数据(Frontmatter)
这是 Agent 在 Level 1 就能看到的“身份证”,启动时嵌入系统提示词,只消耗约 100 个 token。描述得是否精准,直接决定了 LLM 会不会把相关请求路由到你的 Skill。
---
name: resume-forge
description: >-
Convert a Markdown resume into a professionally formatted PDF with multiple
style options and ATS optimization. Use this skill when the user asks to
create a resume, format a resume, convert a resume to PDF, build a CV,
generate a professional resume, make a resume ATS-friendly, or restyle an
existing resume. Triggers include: 'resume', 'CV', 'curriculum vitae',
'resume PDF', 'format my resume', 'ATS-friendly resume', 'professional resume',
or any mention of creating career documents from markdown or plain text.
Do NOT use for: cover letters, job searching, interview preparation,
LinkedIn profile optimization, or portfolio websites.
license: Apache-2.0
compatibility: Requires Python 3.10+ and weasyprint. No network access needed.
metadata:
author: abvijaykumar
version: "1.0.0"
last-updated: "2026-03-17"
category: document-generation
tags: "resume, pdf, career, formatting"
allowed-tools: Bash(python3:*) Bash(pip:*) Read Write
---
逐项解读:
name:规范要求 1-64 个字符,只能用小写字母、数字和连字符,且必须和目录名一致。resume-forge 这个名字清晰明了。
description:这是最关键的字段。因为没有算法路由,LLM 全靠它来决定是否激活 Skill。所以这份描述必须做好三件事:
- 说明做什么:“Convert a Markdown resume into a professionally formatted PDF”
- 列出触发词:resume, CV, resume PDF, ATS-friendly resume……
- 划出负面边界:“Do NOT use for cover letters, job searching...”。负面边界能有效防止“帮我准备面试”这类无关请求被误触发。
license:既是法律声明,也是信任信号。Apache-2.0 意味着开源、允许商用,让人用着放心。
compatibility:告知 Agent 环境需求。如果机器没有 Python 3.10 或 WeasyPrint,Agent 能提前知晓。“No network access needed”是个额外的安全加分项。
metadata:规范对内容没有定义,是自由键值对。我在这里用它来做版本管理、作者、分类。这也是在没有内置 version 字段时一种推荐的版本追踪方式(配合 Git)。
allowed-tools:声明 Skill 需要的工具权限。这里只涉及 Python 脚本、pip 安装包、文件的读写。试想,如果一个简历 Skill 突然要执行 curl 或访问网络,那就是危险信号。
至此,前置元数据用到了规范里的所有字段,且每个都有实际意义。
Step 2: 编写 SKILL.md 正文
正文是 Level 2,当 LLM 判断 Skill 相关时才会加载。它包含了 Agent 需要遵守的完整指令。规范建议控制在 500 行、5000 个 token 以内。我们这篇正文约 186 行,~1350 token,很安全。
下面提炼几个关键的模式。
模式1:清单式工作流
## Workflow
Progress:
- [ ] Step 1: Obtain the Markdown resume
- [ ] Step 2: Parse into structured JSON (`scripts/parse_resume.py`)
- [ ] Step 3: Validate structure and content (`scripts/validate_resume.py`)
- [ ] Step 4: Fix any validation issues (loop until clean)
- [ ] Step 5: Select style and generate PDF (`scripts/generate_pdf.py`)
- [ ] Step 6: Final review and delivery
这个清单给 Agent 提供了清晰的进度感:它清楚自己身在何处、下一步要做什么、哪些已经完成。每一步都指向具体的脚本,Agent 不用自己去摸索“怎么做”。
模式2:验证循环
### Step 4: Fix and Re-validate
If validation reports issues:
1. Read the specific error messages — they explain what's wrong and how to fix it
2. Edit `resume.md` to address the issues
3. Re-run Step 2 (parse) and Step 3 (validate)
4. **Only proceed to Step 5 when validation passes with zero errors**
这就是经典的“执行-验证-修复-重复”模式。Agent 只有通过验证,才能进入下一步。验证器的错误消息被设计成自解释的,方便 Agent 进行自我纠正。
模式3:计划-验证-执行
整体流程是:解析简历(计划)→ 验证结构(验证)→ 生成 PDF(执行)。中间的 parsed.json 就是“计划”——一个结构化的呈现,可以在生成 PDF 前先按规则校验,防止“垃圾进,垃圾出”。
模式4:条件文件加载(渐进式披露 Level 3)
For ATS-specific optimization, read
[references/ats-optimization.md](references/ats-optimization.md)
before generating — it contains keyword placement strategies and formatting
rules that affect how ATS parsers score the resume.
For industry-specific styling guidance, read
[references/industry-styles.md](references/industry-styles.md)
only if the user specifies a target industry.
这就是渐进式披露在行动。参考文件不在启动或激活时一股脑加载,只在具体任务需要时才读取。一个只想“把我的简历转成 PDF”的用户,永远不会为 ATS 指南付出 token 成本。但若要求“为科技岗位做一份 ATS 友好的简历优化”,这两个文件才会被按需加载。
模式5:“Gotchas”陷阱清单
## Gotchas
- **WeasyPrint font rendering**: WeasyPrint uses system fonts. If a template
specifies a font not installed on the system, it silently falls back to
a default serif font.
- **Page overflow**: Long resumes may push content onto a second page with
awkward breaks mid-section.
- **Special characters in names**: Accented characters (é, ñ, ü) work fine
in the PDF but may break some ATS parsers.
- **Markdown parsing edge cases**: The parser expects `##` for sections and
`###` for sub-entries. Using `**bold text**` as a section header will cause
the parser to miss that section entirely.
陷阱清单是 Skill 里价值最高的内容之一。这些都是 Agent 不被告知就会踩的坑。每个陷阱都说明了症状、原因和隐含的解决方法。Agent 无需通过试错去发现,直接获得了“前人的智慧”。
Step 3: 编写脚本(scripts/)
脚本是干活的主力。它们通过 bash 运行,只有输出会进入 Agent 的上下文,脚本代码本身不加载,节省 token。
scripts/parse_resume.py —— 解析器
将 Markdown 转成结构化的 JSON。有几个设计上的亮点:
内联依赖(PEP 723)
# /// script
# dependencies = [
# "markdown-it-py>=3.0",
# ]
# ///
用 uv run scripts/parse_resume.py 就能自动安装依赖,不需要 requirements.txt,也不需要虚拟环境。Agent 一个命令就能跑起来。
结构化 JSON 输出
{
"status": "success",
"name": "Alex Chen",
"sections_found": ["Summary", "Experience", "Education", "Skills", "Certifications"],
"total_entries": 6
}
结构化输出远比自然语言好解析。Agent 可以程序化地检查 sections_found,而不是费力去理解一段文本。
友好的错误信息
Error: File not found: resume.md
Check the path and try again.
错误信息直接告诉 Agent 该怎么做。同时提供 --help 让 Agent 能探索接口:
python3 scripts/parse_resume.py --input resume.md --output parsed.json
python3 scripts/parse_resume.py --input resume.md # 输出到stdout
scripts/validate_resume.py —— 质量门禁
验证器让“计划-验证-执行”模式落了地。下面是一个损坏简历的验证输出示例:
{
"status": "fail",
"errors": [
{
"field": "name",
"message": "Missing name. Add an H1 heading (# Your Name) at the top of the Markdown."
},
{
"field": "contact.email",
"message": "Missing email address. Add it below your name: **Email:** you@example.com"
},
{
"field": "sections",
"message": "Missing required section: Skills. Add ## Skills to your Markdown."
},
{
"field": "sections.Experience",
"message": "Section \"Experience\" is empty. Add content or remove the heading."
}
],
"warnings": [
{
"field": "contact.phone",
"message": "No phone number found. Recommended for most job applications."
},
{
"field": "sections",
"message": "Consider adding a Summary section to strengthen your resume."
}
],
"summary": {
"error_count": 5,
"warning_count": 5
}
}
注意几个细节:
- 错误 vs 警告:错误会阻止流程(退出码 3),警告不会(退出码 0)。正文里明确规定“只有零错误才能继续”。
- 每条错误都包含修复建议:不只是说“缺少姓名”,而是具体到“添加 H1 标题 (# 你的姓名)”。Agent 能直接执行,无需再次询问用户。
- 退出码有意义:0=通过,1=文件错误,3=验证失败。不同的失败类型用不同码,便于脚本编排。
--strict 开关可以对每个项目符号检查动词(例如要求用“Led”“Developed”等行为动词开头),严格程度可调节。
scripts/generate_pdf.py —— 渲染器
接收 JSON 和样式名,加载对应的 HTML 模板,用 Jinja2 渲染,再用 WeasyPrint 转 PDF。
$ python3 scripts/generate_pdf.py --input parsed.json --style modern --output resume.pdf
{
"status": "success",
"output": "resume.pdf",
"style": "modern",
"pages": 1,
"overflow_warning": false
}
设计要点:
- 三种样式:modern, classic, compact,分别对应
assets/ 下的三个 HTML 模板。
- 页面溢出检测:脚本会检查 PDF 是否超过推荐页数,发出警告但不中断流程。长简历是有效的,但 Agent 需要知道。
- ATS 可提取性:PDF 由语义 HTML 生成,不是图片或 Canvas 绘图。像
pdfplumber 这样的工具能提取每一个单词,这对 ATS 兼容性至关重要。
Step 4: 定义参考资料(references/)
参考资料属于 Level 3,存放在文件系统,零 token 占用,只在需要时加载,为特定场景提供深度知识。
references/ats-optimization.md
仅在用户明确要求“ATS 友好”时加载。内容包括:
- 主流 ATS(Workday、Greenhouse、Lever、iCIMS)的工作原理
- 格式规则(禁用表格、多栏,使用标准标题)
- 关键词策略(镜像职位描述,包含缩写和全称)
- 章节排序建议
- 可靠 vs 易出错的日期格式
没有这个文件,Agent 只能给出泛泛的建议。有了它,Agent 就有了具体可操作的规则。
references/industry-styles.md
只在用户说“我想申请金融岗位”这类指令时加载。它会针对不同行业给出风格建议:
- 科技:现代风格,技能优先,包含 GitHub 链接
- 金融:经典风格,教育优先,严格一页
- 学术界:经典风格,无页数限制,必须包含出版物列表
- 设计:现代风格,突出作品集链接
- 医疗:经典风格,执照和证书优先
- 政府:经典风格,如有安全许可需注明
Agent 只读相关部分,绝不会浪费 token 在无关行业上。
Step 5: 定义资产(assets/)
资产是 Skill 使用的原材料。
HTML+CSS 模板
每个模板都是一个自包含的 HTML 文件,内嵌 CSS。生成器用 Jinja2 注入数据,WeasyPrint 转 PDF。以下是从现代模板截取的 CSS 片段:
.section-title {
font-size: 11pt;
font-weight: 700;
color: #1a1a2e;
text-transform: uppercase;
letter-spacing: 1.2pt;
border-bottom: 1.5pt solid #2563eb;
padding-bottom: 3pt;
margin: 14pt 0 8pt 0;
}
以及 Jinja2 模板标记:
{% for section in resume.sections %}
<div class="section">
<div class="section-title">{{ section.title }}</div>
{% for entry in section.entries %}
<div class="entry">
<div class="entry-header">
<span class="entry-title">{{ entry.title }}</span>
{% if entry.organization %}
<span class="entry-org"> — {{ entry.organization }}</span>
{% endif %}
{% if entry.dates %}
<span class="entry-dates">{{ entry.dates }}</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
三个模板,三种风格,全部从同一份 JSON 数据生成。
一个完整的示例简历,方便用户立刻上手测试:
# Alex Chen
**Email:** alex.chen@email.com | **Phone:** 555-0142 | **Location:** San Francisco, CA
https://github.com/alexchen | https://linkedin.com/in/alexchen
## Summary
Full-stack engineer with 6 years of experience...
## Experience
### Senior Software Engineer — Acme Cloud Inc (2022–Present)
- Led migration of monolithic Node.js application to microservices...
端到端运行演示
我们现在就用示例文件来跑通整个流程。
解析
$ python3 scripts/parse_resume.py --input assets/sample_input.md --output parsed.json
输出:
{"status": "success", "name": "Alex Chen", "sections_found": ["Summary", "Experience", "Education", "Skills", "Certifications"], "total_entries": 6}
5 个章节,6 个条目被成功提取。解析器找到了姓名、联系方式,并结构化每个经历项(标题、组织、日期、项目符号)。
验证
$ python3 scripts/validate_resume.py parsed.json
输出:
{
"status": "pass",
"errors": [],
"warnings": [
{ "field": "sections", "message": "Consider adding a Projects section to strengthen your resume." }
],
"summary": { "error_count": 0, "warning_count": 1, "sections_found": ["Summary", "Experience", "Education", "Skills", "Certifications"], "total_entries": 6, "total_bullets": 11 }
}
零错误,只有一条温和的建议(添加“项目”章节),但绝不会阻止流程。退出码 0,可以继续。
生成
$ python3 scripts/generate_pdf.py --input parsed.json --style modern --output resume.pdf
输出:
{"status": "success", "output": "resume.pdf", "style": "modern", "pages": 1, "overflow_warning": false}
一份干净、专业的一页现代风格 PDF 诞生。你也可以生成另外两种风格:
$ python3 scripts/generate_pdf.py --input parsed.json --style classic --output resume_classic.pdf
$ python3 scripts/generate_pdf.py --input parsed.json --style compact --output resume_compact.pdf
全部生成有效、单页、ATS 可提取的 PDF。
验证 ATS 可提取性
import pdfplumber
with pdfplumber.open('resume.pdf') as pdf:
for page in pdf.pages:
print(page.extract_text())
每个单词都能被正确提取,没有乱码,没有缺失的章节。ATS 系统能无障碍读取。就像一份精心打磨的技术文档,结构清晰,数据完整。
渐进式披露计分卡
我们把构建的 Skill 映射到三个 Level:
| Level |
内容 |
Token成本 |
何时加载 |
| Level 1 |
前置元数据 (name, description) |
~100 |
启动时 |
| Level 2 |
SKILL.md 正文 |
~1,350 |
Skill激活时 |
| Level 3 |
scripts/, references/, assets/ |
可变,按需 |
仅当需要时 |
如果用户安装了 50 个 Skill,启动时总开销也只有 $50 \times \sim100 = \sim5000$ token。只有当用户说“格式化我的简历”时,~1350 token 的正文才会加载。ATS 指南、行业风格、模板都只在任务需要时才出现。
试想,如果把所有内容(ATS 规则、行业指南、三个模板、陷阱清单)都一股脑塞进一个 SKILL.md,它会有 3000 多行,轻松撑爆任何合理的 token 预算。渐进式披露让这一切变得可控。
功能检查清单
下面这张表对照了 SKILL.md 规范的每个特性,并标注我们在 Resume Forge 中是否用到:
| 特性 |
是否使用 |
说明 |
name |
✅ |
resume-forge |
description |
✅ |
包含触发词和负面边界 |
license |
✅ |
Apache-2.0 |
compatibility |
✅ |
Python 3.10+, weasyprint |
metadata |
✅ |
版本、作者、标签等 |
allowed-tools |
✅ |
声明权限 |
| 清单式工作流 |
✅ |
Step 1-6 |
| 验证循环 |
✅ |
Step 4 循环 |
| 计划-验证-执行 |
✅ |
解析→验证→生成 |
| 条件文件加载 |
✅ |
ATS和行业指南按需 |
| Gotchas章节 |
✅ |
列出常见陷阱 |
| 脚本 |
✅ |
三个Python脚本 |
| 参考资料 |
✅ |
ats-optimization.md, industry-styles.md |
| 资产 |
✅ |
三个HTML模板,示例文件 |
| 帮助文档(--help) |
✅ |
每个脚本支持 |
| 错误码 |
✅ |
解析器、验证器用退出码区分状态 |
这就是一个覆盖了规范所有特性的完整 Skill。
安装 Skill
Claude Code
# 项目级(推荐)
cp -r resume-forge/ .claude/skills/resume-forge/
# 或全局(所有项目可用)
cp -r resume-forge/ ~/.claude/skills/resume-forge/
得益于实时文件监听,Claude Code 会立刻发现新 Skill。
VS Code with GitHub Copilot
cp -r resume-forge/ .github/skills/resume-forge/
Claude.ai
打包成 zip,通过“设置 → 功能”上传:
cd resume-forge && zip -r ../resume-forge.zip . && cd ..
调试技巧
- Skill 没触发:直接问 Agent:“你用了哪个 Skill?”或“你用 resume-forge Skill 了吗?”。如果没触发,八成是 description 里缺了用户实际使用的短语,把它加上就好。
- 解析器漏了章节:回头检查你的 Markdown 标题层级。解析器期望
## 作为章节标题,### 作为条目。用 **加粗文本** 当标题是无效的。
- PDF 显示不对:检查系统字体。WeasyPrint 使用操作系统字体,如果模板指定的字体没安装,它会静默回退到默认的衬线字体(serif)。
- 验证太严/太松:用
--strict 开启全面检查,默认模式更偏向实用。你也可以修改 validate_resume.py 里的 ACTION_VERBS 集合来适配你的领域。
一些 Hack
在开始写 Skill 之前,不妨先用这些工具来加速开发。
Hack #1:用 Skill Creator 来构建 Skill
Anthropic 官方 Skills 仓库里有一个元 Skill 叫 skill-creator。顾名思义,它是一个专门用来创建其他 Skill 的 Skill。
安装它:
cp -r skill-creator/ .claude/skills/skill-creator/
现在你对 Claude Code 说:“我想建一个 Skill,把 Markdown 简历转成 PDF。”skill-creator 就会激活,带你走完整流程:它会采访你关于用例、写草稿 SKILL.md、生成测试提示词、并行运行带/不带 Skill 的测试、启动基于浏览器的评测视图让你对比输出、再根据你的反馈迭代。循环是:草稿 → 测试 → 评审 → 改进 → 重复。
它还包含一个描述优化器,会测试 20 多个触发查询,测量触发准确率,然后重写描述来最大化命中率、最小化误报。
最有意思的功能是:它会生成“基线运行”(无 Skill)和“启用 Skill 的运行”,让你直观地看到 Skill 真正增加了什么价值。还会记录每次运行的耗时和 token 消耗,让你清楚 Skill 的真实成本。
用这个工具,构建 Resume Forge 的时间能砍半。
Hack #2:发布前验证 —— 用 skills-ref
官方 agentskills/agentskills 仓库里有一个参考库 skills-ref,可以验证你的 Skill 是否符合规范。
安装:
pip install -e path/to/agentskills/skills-ref
然后验证:
skills-ref validate path/to/resume-forge
它会检查前置元数据字段、目录命名规范、结构。帮你捕获那些只会在运行时才暴露的错误:name 字段不匹配、缺少 description、目录名和 Skill 名不一致等。
它还提供 to-prompt 命令,生成 Agent 用来发现 Skill 的 <available_skills> XML 块,让你能预览 Agent 在 Level 1 看到的元数据——那个决定你的 Skill 是否会被激活的关键信息。
Hack #3:从模板开始,别从零开始
Anthropic Skills 仓库包含一个 template/ 目录,里面是极简的 SKILL.md 骨架。一个 name、一个 description 占位符、一个正文占位符。这很关键——与其对着空文件回忆前置元数据的语法,不如直接克隆模板来填空。
cp -r template/ .claude/skills/my-new-skill/
编辑 name 字段以匹配目录名,写下你的描述,就可以开始了。这消除了记住 YAML 格式的摩擦,并保证你不会漏掉任何必填字段。
浏览示例 Skill
在动手构建自己的之前,可以先看看官方仓库 github.com/anthropics/skills/tree/main/skills 里的示例。
里面有生成 PDF、构建 DOCX、创建 PowerPoint 演示文稿、设计 Canvas 布局、构建 MCP 服务器等现成 Skill。即使没有一个完全匹配你的用例,它们也是学习如何组织脚本、参考资料和实现渐进式披露的绝佳参考。特别是 docx 和 pdf 这两个 Skill,如果你和我们一样在做文档生成,很值得深入研读。
核心回顾
- 原理:
SKILL.md 通过前置元数据(Level 1)、正文(Level 2)和按需加载的资源(Level 3)实现渐进式披露,让 Skill 既强大又轻量。LLM 根据描述进行路由,无需手写路由逻辑。
- 实践:构建一个高质量 Skill,关键在于写好
description(触发词+负面边界),用清单式工作流、验证循环、计划-验证-执行模式组织正文,并合理划分脚本、参考资料和资产。
- 避坑:调试 Skill 时,先检查描述是否包含用户实际使用的词汇;遇到触发不准就加负面边界;正文中一定要有“Gotchas”部分,把隐式知识显式化。
写在最后
这个 Skill 我们从零开始构建,每一行代码、每一个文件都对应着规范中的某个设计。它的意义远不止“能运行”,更在于它演示了如何把人类专家的经验——比如简历该怎么写、ATS 该怎么优化、不同行业的偏好是什么——封装进一个文件夹里,让 AI 去自动执行。
最让人感慨的是,构建这样一个功能完整的 Skill,我们几乎没有写复杂的 Agent 逻辑,只是写了一份“说明书”和一些确定性的 Python 脚本。AI 负责判断什么时候该用、怎么按步骤执行,而我们则把领域知识沉淀下来,一次编写,到处运行。
现在,你手头是不是也有那种“每次都要手动指导 AI 做”的重复性任务?如果把它封装成一个 SKILL.md,又会怎样呢?
在你的日常工作中,哪个任务最适合封装成 Skill?是部署流程、代码审查清单,还是某种文档生成?你会怎么设计它的渐进式披露层级?

云栈社区也一直在探索如何更好地沉淀和分享这类工程智慧,如果你有好的想法,不妨多来交流。