一个 agent 文件长什么样:frontmatter、角色声明、分节正文
如果你打开 agency-agents 这个仓库准备照着写自己的 agent,最省时间的做法不是先挑一个感兴趣的 agent 通读,而是先搞清楚这些文件的结构约定是什么、仓库用什么脚本卡这套约定。因为仓库里带 frontmatter 的 agent markdown 有 255 个,分布在 17 个 division,它们共用同一套模板。看懂一个,等于看懂两百多个;反过来,模板里有一条你没注意的规则,你写的每一个 agent 都会踩同一个坑。
下面这些内容全部来自阅读仓库源码:scripts/lint-agents.sh、scripts/check-agent-originality.sh、scripts/convert.sh、divisions.json,以及一份样例 agent 文件 engineering/engineering-ai-engineer.md。核对日 2026-08-09。我们没有安装过其中任何一个 agent,也没有运行过这些脚本,下面讲的全是源码写着什么,不是跑起来是什么样。
三层结构:frontmatter、角色声明、分节正文
拿样例 engineering/engineering-ai-engineer.md 来看,骨架长这样:
---
name: AI Engineer
description: Expert AI/ML engineer specializing in machine learning model development, deployment, and integration into production systems. ...
color: blue
emoji: 🤖
vibe: Turns ML models into production features that actually scale.
---
# AI Engineer Agent
You are an **AI Engineer**, an expert AI/ML engineer specializing in ...
## 🧠 Your Identity & Memory
- **Role**: AI/ML engineer and intelligent systems architect
- **Personality**: Data-driven, systematic, performance-focused, ethically-conscious
- **Memory**: You remember successful ML architectures, ...
- **Experience**: You've built and deployed ML systems at scale ...
## 🎯 Your Core Mission
### Intelligent System Development
- Build machine learning models for practical business applications
...
三层拆开说:
第一层 YAML frontmatter,是给工具链读的元数据。谁读它?convert.sh 读它来把这份 markdown 渲染成各家 AI 编码工具认识的格式——比如转 opencode 时 name、description、color 会原样搬进产物的 frontmatter,color 还要先解析成十六进制。所以这几个字段不是装饰,是下游转换真的要取的值。
第二层角色声明段,一个一级标题加一句 You are an **AI Engineer**, ...。
第三层分节正文,用 ## 级标题切成若干块,比如 Identity & Memory、Core Mission。
注意正文全程是第二人称,写的是 “You are”、“You remember”、“You’ve built”。这不是文档风格问题,这些正文就是要原样喂给模型的提示词,第二人称是它的目标形态。
顺带说一条容易误读的地方:样例里 Experience: You've built and deployed ML systems at scale 这类句子,是写给模型的人设设定,不是对任何真人履历的陈述。读 agent 文件时看到一堆「资深」「大规模落地经验」,那是提示词内容,不是能力证明,更不能当成这个 agent 好不好用的依据。
必填只有三个字段,其余是可选
lint-agents.sh 第 34 行把必填字段写死成一个数组:
REQUIRED_FRONTMATTER=("name" "description" "color")
name、description、color三项缺任意一项,lint 直接报 ERROR。- 样例里还出现了
emoji和vibe,这两个不在必填列表里,属于可选字段。vibe是一句话人设标语,被 app 一类的目录工具消费。
这个信息的实际用途是:如果你在批量生成或改写 agent 文件,脚本里只需要保证这三个字段一定写出来就不会卡 ERROR;emoji、vibe 缺了不影响校验,但会影响目录类工具的展示效果,属于「要不要花力气补」的取舍,不是「必须补」。
★ 最反直觉的一条:章节标题是路由,不是排版
这是我认为整套格式里最值得单独拎出来讲的设计。
lint-agents.sh 里有个 classify_header_target() 函数(第 40–53 行),把每个 ## 级标题分流到两个目标:
if [[ "$header_lower" =~ identity ]] ||
[[ "$header_lower" =~ learning.*memory ]] ||
[[ "$header_lower" =~ communication ]] ||
[[ "$header_lower" =~ style ]] ||
[[ "$header_lower" =~ critical.rule ]] ||
[[ "$header_lower" =~ rules.you.must.follow ]]; then
printf 'soul'
else
printf 'agents'
fi
命中 identity / learning+memory / communication / style / critical rule / rules you must follow 这几组关键词的标题,去 SOUL.md;其余全部去 AGENTS.md,默认桶就是 agents。
这两个文件名对应的是 convert.sh 转换 OpenClaw 格式时的工作区结构——那种格式下,一个 agent 会被渲染成一个目录,正文按上面这套关键词拆进 SOUL.md 和 AGENTS.md 两个文件(还有一个 IDENTITY.md)。lint 那边和 convert 那边用的是同一套分流逻辑。
判断依据在这里:你给章节起的标题,看起来只是文档排版,实际上决定了这段内容被写进哪个产物文件。写「## Your Communication Style」和写「## How You Talk」,前者进 SOUL.md,后者因为一个关键词都没命中,会被扔进 AGENTS.md。同样一段人设内容,落点完全不同。
所以写 agent markdown 之前,先把这六组关键词记住,起标题的时候有意识地去命中它——想让某段内容进 SOUL.md,标题里就得带 identity / communication / style / critical rule 这类词;不想进就避开。这条规则在仓库里没有醒目的文档提示,是藏在脚本函数里的,不看源码基本发现不了。
lint 还顺手做了一道保护:要求 SOUL.md 和 AGENTS.md 两边都至少有一个标题映射过去,否则各报一条 WARN,文案是 no section headers map to SOUL.md in convert.sh 和 ... to AGENTS.md in convert.sh。如果你写完一个 agent 跑 lint 看到这行警告,不用去猜是什么意思——就是你的所有 ## 标题全被分到了同一边。
lint 的检查清单:一道行尾预检加五道正式检查
脚本头部自述,它校验三件事:frontmatter 必须存在且含必填字段(ERROR)、推荐章节只警告(WARN)、文件必须有实质内容。用法是 ./scripts/lint-agents.sh [file ...],不给文件就扫描所有 agent 目录。下面这张表里,编号 0 的那条是跑在最前面的行尾预检,1 到 5 才是正式的五道。
| # | 检查 | 级别 | 细节 |
|---|---|---|---|
| 0 | 拒绝 CRLF 行尾 | ERROR | 仓库标准是 LF |
| 1 | frontmatter 分隔符存在 | ERROR | 取首尾两个 --- 之间的内容 |
| 2 | 必填字段齐全 | ERROR | name / description / color |
| 3 | 推荐章节存在 | WARN | RECOMMENDED_SECTIONS=("Identity" "Core Mission" "Critical Rules"),大小写不敏感匹配 |
| 4 | 正文有实质内容 | WARN | 正文词数 < 50 就警告 |
| 5 | 章节标题能映射到两个目标文件 | WARN | 就是上一节讲的那条 |
第 0 条对 Windows 用户格外重要。源码注释专门解释了为什么要单独设这道检查:行尾多一个 \r,会让后面的 frontmatter 检查报出令人困惑的「missing frontmatter ---」——你盯着文件开头明明就是 ---,怎么也想不通它为什么说没有。所以在 Windows 上写这类文件,编辑器和 Git 的行尾配置要先确认好,仓库里也放了 .gitattributes。
ERROR 和 WARN 的区别得记清楚:推荐章节缺失只是警告,不会让检查失败。第 3、4、5 三条都只是提示,第 0、1、2 三条才是硬门。
原创性检查:换皮 agent 是明确要防的东西
仓库还有一个 scripts/check-agent-originality.sh。脚本自述的动机很直白:新 agent 应该是真的新东西;把已有 agent 做一次查找替换换皮(比如把国家名或平台名一换),在评审里很难发现——它能合并、格式也规范——但会用重复内容把库撑肿。
它的算法是:把候选 agent 与整个已有花名册做对比,用实体中性化后的 8 词 shingle 重叠率打分。所谓实体中性化,就是先把一批专有名词抹平再比,源码里被中性化的词包括 vietnam/vietnamese、china/chinese、douyin/tiktok、korea/korean、japan/japanese 等(源码注释说会随着新市场出现继续扩充)。这样一来,换掉专有名词的抄袭藏不住。
阈值有两个,都是默认值,可以用环境变量覆盖:
| 变量 | 默认 | 含义 |
|---|---|---|
ORIGINALITY_FAIL | 40 | 达到或超过该百分比视为重复,退出码 1 |
ORIGINALITY_WARN | 20 | 达到或超过该百分比出警告,不失败 |
为什么阈值定在这个位置?源码注释给了校准结论:在现有 agent 库里,同一对之间最差的相似度约 1.5%,中位数 0%。也就是说双位数的相似度就已经是强异常了,默认的 40 / 20 留了很宽的误判安全边界。这两个数是该库内部的校准值,不是对任意 agent 库的普适结论——你自建一个题材更集中的库,正常相似度大概率不是这个量级,阈值该重新校。
用法上有两种模式:给文件参数就只查这些文件(CI 里用于检查变更文件),不给参数就全库两两互查(审计模式)。脚本依赖 python3,缺了直接退出码 2。
写自己的 agent 模板时,这套规则怎么用
把上面的东西压成一份动作清单:
- frontmatter 先保三个必填:
name、description、color。emoji、vibe按需要加。 - 章节标题按分流规则起名,别只考虑好不好看。想让内容落进 SOUL.md,标题里带 identity / learning & memory / communication / style / critical rules / rules you must follow 之一;其余默认全进 AGENTS.md。
- 两边都留至少一个标题,避免那两条 WARN。
- 行尾用 LF,Windows 侧尤其注意。
- 正文写成第二人称提示词,别写成第三人称的岗位说明书——它的最终形态是直接喂给模型的。
- 别做换皮:改几个专有名词复制一份,正是
check-agent-originality.sh专门在防的模式。
最后要说清楚边界。这套脚本管的是结构与重复度,不评估提示词写得好不好用:lint 全绿只说明格式合规、必填字段齐全、章节标题能正常分流,它不知道你这个 agent 提示词在真实任务里表现如何。这是两码事,别把「通过校验」当成质量背书。
另外,格式规则会影响到你意想不到的地方,章节标题决定落点只是其中一例。转换到 Cursor 格式时,产物 frontmatter 里的 alwaysApply 是被写死成 false 的,globs 写死成空串——也就是说转换出来的规则默认不会自动生效,需要在 Cursor 里按需引用。这类「模板层写死的值」和章节路由是同一类问题:不看转换脚本就不会知道,遇到「怎么好像没生效」也无从查起。
顺便给个时间锚点:这个仓库在 2026-08-09 的快照里 star 数是 140729。关注度高是事实,但这个数字不能推导出它适不适合你的项目、稳不稳定、提示词质量如何——那得你自己读文件判断。仓库标注为 MIT,具体条款以官方 LICENSE 原文为准。
延伸阅读
- 一份 JSON 管住五个脚本:单一真相源是怎么落地的
- agency-agents 的 agent 文件格式:name/description/color 是必填,emoji/vibe 不是
- 换个国家名就想混过去?8 词 shingle 重叠率不答应
本文依据 agency-agents 官方仓库(github.com/msitarzewski/agency-agents)的 README、
tools.json、divisions.json、scripts/ 下的安装与校验脚本整理,核对日 2026-08-09。
本文内容为仓库源码与文档口径,我们没有安装或运行过其中任何 agent。
目录、脚本与安装路径随上游更新而变动,请以仓库最新内容与 ./scripts/install.sh --help 的实际输出为准。
许可条款请以官方 LICENSE 原文为准,本文不构成法律意见。