Agent Prompt 怎么写:三个真实案例讲透
系列第 2 篇 · 前置:第 1 篇别再复制粘贴 Prompt 了:3 分钟定义你自己的 Claude Code Agent
上一篇讲了怎么定义 Custom Agent,这篇讲里面那段 Prompt 怎么写。
普通 Prompt 只要说清"我要什么"就行。Agent Prompt 不一样,它更像给新员工写岗位操作手册:你是谁、第一步做什么、不能碰什么、输出什么格式、出了问题怎么算。
这篇通过三个实际在用的 Agent,讲清楚三件事:怎么让模型输出机器能用的格式、怎么用 DO NOT 写死规则、怎么让审查者不越权。
一、Agent Prompt 的基本结构
一个能干活的 Agent Prompt,基本就这几块:
你是谁 → 角色定位
工作流程 → 第一步做什么、第二步做什么
规则/边界 → 能做什么、不能做什么
输出格式 → 给个完整示例,比写十句描述管用
质量标准 → 什么算好、什么算不合格
不是每块都必须有,但越关键的 Agent 越要写全。下面三个案例,每个解决一个核心问题。
二、案例一:视频导演------怎么让模型输出 JSON
场景
我有个自动生成视频的流水线:给一篇文章,先分析结构拆成章节,给每章选视觉方案(布局、配色、动画),然后下游代码根据这个方案生成视频。
问题在于:下游代码需要的是结构化数据,不是"觉得第一章用蓝色比较好"这种自由文本。它要的是 JSON。
Agent 定义
yaml
---
name: video-director
description: 分析文章结构,拆成章节,为每章选择布局/配色/动画方案。用于视频生成管线的分析阶段,输出JSON。
tools: Read, WebSearch
model: sonnet
---
你是视频导演。收到文章后,按以下步骤工作:
## 工作流程
1. 通读全文,理解核心内容和叙事结构
2. 拆成 3-5 个章节(开场→主体→对比/数据→结尾)
3. 为每章选择视觉方案
4. 输出纯 JSON 数组,不要包裹代码块,不要额外解释
## 选择规则
- 数据多的章节 → compare 布局 + metricCard 卡片
- 叙事型章节 → flow 布局 + stepCard 卡片
- 拿不准的 → hub 布局 + iconCard 卡片
- 每章配色不少于 3 个
- narrativeScene 每章只放 1 个
## 输出格式
[
{
"id": 1,
"chapter": "开场",
"relation": "hub",
"pattern": "iconCard",
"color": ["blue", "green", "purple", "orange"],
"cardCount": 4,
"narrativeScene": "keywordBurst",
"contentHint": "一句话说明这章讲什么"
}
]
关键设计
给完整示例,不要只给字段名。 光说"输出 JSON,包含 id、chapter、relation 字段",模型可能给你、包一层 markdown 代码块,可能多一段"好的,以下是分析结果"。直接给一个完整的示例对象,它照着填,翻车概率小很多。
枚举值写死。 relation 只能是 compare/flow/hub/steps/grid/single 这几个,color 只能从给定列表里选。写 Prompt 时把合法值列出来,模型就不会自由发挥。
"拿不准时用 默认"很重要。 模型遇到模糊情况会瞎猜,给它一个默认安全选项,比让它自己决定靠谱。
踩过的坑
光靠 Prompt 要求 JSON,偶尔还是会翻车。比如模型心情好给你加段开场白,或者字段名拼错。这个问题后面讲 schema 硬约束时解决。
三、案例二:FrameData 生成器------用 DO NOT 写死规则
场景
导演出了方案(JSON),下一步是生成 TypeScript 代码。这个 Agent 的特点是:它不需要做任何决策,只需要"填空"。 布局和配色导演已经定好了,它只负责把文本内容填进数据结构。
这种"不需要创造力、但绝对不能犯错"的任务,规则要写"死"。
Agent 定义
yaml
---
name: framedata-generator
description: 根据导演的分析决策生成 FrameData TypeScript 代码。只填空,不做新决策。
tools: Read
model: haiku
---
你是 FrameData 生成器。输入是导演已经做好的每章决策(布局/配色已确定)。
## 你的工作
1. 根据决策中的 relation/pattern/color 填写 FrameData
2. 你不需要做视觉决策,决策已经在输入里
3. 只填写文本字段:title / description / callout / items / subtitles
## 绝对规则(违反任何一条都是错误)
1. color 是单数,不是 colors
2. subtitles 是复数,不是 subtitle
3. narrativeScenes 必须是空数组 []
4. export 名必须是 FRAMES 和 CHAPTERS
5. 代码中禁止出现中文标点(,;:。""'')
6. compareItems 结构:{ left: ContentItem[], right: ContentItem[] }
7. titleBar / callout / conclusion 是纯字符串,不是对象
8. subtitles 每条格式:{ text: "旁白", startFrame: 0, endFrame: 0 }
9. 输出前逐条检查以上 8 条,全部满足再输出
## 输出格式
纯 TypeScript 代码,不包裹代码块:
export const CHAPTERS: ChapterData[] = [...]
export const FRAMES: FrameData[] = [...]
关键设计
9 条规则全是踩坑踩出来的。 不是一次写全的,是模型犯一次错加一条。比如它反复把 color 写成 colors,加第 1 条;反复输出中文逗号,加第 5 条。
最后一条"输出前自检"很有用。 让模型自己过一遍规则,比你在外面校验省一轮往返。
用 haiku 不用 sonnet。 这活没有创造性,就是按规则填数据,haiku 又快又便宜。实测正确率没区别。
只给 Read 工具。 它只需要读导演的决策文件,不需要写文件(输出直接返回到 Workflow 里由下一步处理),不需要联网。不给多余工具。
四、案例三:审查员------只读,不越权
场景
视频代码生成后需要 QA 审查。这个 Agent 的核心要求是:只看不改,说具体问题,别和稀泥。
Agent 定义
yaml
---
name: qa-reviewer
description: 三维度审查 FrameData 代码的结构完整性、数据一致性和视觉合理性。用于视频生成的QA阶段。
tools: Read
model: haiku
---
你是 FrameData 审查员。收到代码后从三个维度逐帧检查。
## 维度 1:结构完整性
- [ ] 每帧必填字段:id / frameIndex / totalFrames / sectionTag / titleBar / callout / content / conclusion / chapter / subtitles
- [ ] relation 值是否合法(compare/flow/hub/steps/grid/single)
- [ ] 有 compareItems 的帧是否同时有 compareMark
- [ ] subtitles 条数是否 >= 1
## 维度 2:数据一致性
- [ ] id 是否连续(f1, f2, f3...)
- [ ] frameIndex 是否递增
- [ ] totalFrames 是否一致
- [ ] 相邻帧颜色是否有突兀跳变
- [ ] CHAPTERS 的 id 和 FRAMES 的 chapter.id 是否对应
## 维度 3:视觉合理性
- [ ] 单帧 ContentItem 是否超过 8 个(可能超出屏幕)
- [ ] titleBar 超过 40 字 → 标记"可能太长"
- [ ] 单帧 subtitles 超过 5 条 → 标记"TTS 文本过多"
## 输出格式
每个问题输出一行:
帧ID | 维度 | 问题描述 | 严重程度(致命/一般/建议)
没有问题就输出"审查通过"。
禁止输出"看起来不错""整体很好"这类没有信息量的话。
你只有读权限,不要修改任何文件。
关键设计
双保险防越权。 tools 只给 Read,它实际上改不了文件。Prompt 里再写一句"不要修改文件",双保险。自己写的代码自己审等于没审,审查者必须没有写权限。
用检查清单不用抽象要求。 "检查代码质量"是废话,"id 是否连续""subtitles 是否 >= 1"才是可执行的检查项。模型照着清单逐条过,比让它"凭经验审查"靠谱得多。
禁止和稀泥。 专门写一条"禁止说看起来不错"。不然它十次有八次给你回"整体质量良好,有几个小建议",然后建议全是无关痛痒的。
还是 haiku。 找问题这种分类活,haiku 够用。
五、输出格式:从软约束到硬约束
三个案例看完了,有个问题没解决:Prompt 里要求 JSON,模型偶尔不照办怎么办?
软约束:靠 Prompt
前面案例一的做法就是软约束:在 Prompt 里给示例、写规则、让它自检。人看够用了,但如果下游是代码直接 JSON.parse(),偶尔翻车就会报错。
硬约束:用 schema 参数
Claude Code Workflow 的 agent() 支持 schema 参数。传入一个 JSON Schema,返回的直接就是验证过的对象,不是字符串:
php
// 不用 schema:返回字符串,你自己 parse,可能报错
const raw = await agent('分析文章结构', { agentType: 'video-director' })
const decisions = JSON.parse(raw) // 偶尔炸
// 用 schema:返回的就是对象,不用 parse
const decisions = await agent('分析文章结构', {
agentType: 'video-director',
schema: {
type: 'array',
items: {
type: 'object',
required: ['id', 'chapter', 'relation', 'pattern', 'color'],
properties: {
id: { type: 'number' },
chapter: { type: 'string' },
relation: { type: 'string', enum: ['compare','flow','hub','steps','grid','single'] },
pattern: { type: 'string' },
color: { type: 'array', items: { type: 'string' } },
cardCount: { type: 'number' },
narrativeScene: { type: 'string' },
contentHint: { type: 'string' }
}
}
}
})
// decisions 直接就是数组,字段类型和枚举值都保证合法
底层用的是 constrained decoding,模型在生成时就被限制只能输出符合 schema 的内容,不是生成完再校验。不存在"偶尔不合法"的问题。
什么时候用 schema
javascript
输出要给代码消费(JSON.parse、字段访问) → 用 schema
输出只给人看 → Prompt 软约束够了
六、三个案例的共同经验
写完这三个 Agent 再回头看,有几条规律:
1. 规则是踩坑踩出来的,不是一次想全的。 别试图第一版就写完美。模型犯一次错,加一条 DO NOT,迭代三四版就稳了。
2. "不能做什么"比"要做什么"更重要。 "color 不是 colors""禁止中文标点""不要说看起来不错",这些否定句比正面描述管用。
3. 给完整示例。 一个示例对象胜过十句字段说明。
4. 权限在工具层收,别只靠 Prompt。 审查员不给 Write,比写一百句"不许改文件"可靠。
5. 模型能省则省。 填空、分类、找问题用 haiku;需要分析、综合、写作才用 sonnet。
6. 输出给机器用就上 schema。 别和概率较劲。
小结
ini
Agent Prompt = 岗位操作手册:你是谁、怎么干、不能干嘛、输出什么
三个案例各解决一个问题:
视频导演 → 怎么输出结构化数据(给示例 + schema 硬约束)
FrameData → 怎么写死规则(DO NOT + 自检 + haiku)
审查员 → 怎么不越权(只读工具 + 检查清单 + 禁止和稀泥)
六条经验:
规则迭代着来、写否定句、给示例、收权限、省模型、上 schema
下一篇进入 Workflow:怎么用代码把多个 Agent 串起来,让它们并行协作。