摘要:Prompt 工程是提升大语言模型输出质量的核心技能,直接决定 Agent 能否稳定、精准地完成任务。本文基于 OpenClaw 平台,系统拆解 Prompt 工程的四大支柱(角色设定、任务分解、输出约束、示例引导)、System Prompt 的三种设计模式(角色扮演型、指令型、混合型)、Few-shot 与 Zero-shot 的选型策略、Chain-of-Thought 显式化落地、模板化变量注入、A/B 测试迭代方法及常见反模式,并给出可直接复用的 Skill 模板与输出质量五维评估框架。适合正在调优 Agent 或准备封装技能的开发者阅读,核心方法论对其他 Agent 框架同样具有参考价值。
文章目录
-
- [引言:为什么 Prompt 工程是 Agent 开发的必修课](#引言:为什么 Prompt 工程是 Agent 开发的必修课)
- [一、Prompt 工程到底是什么](#一、Prompt 工程到底是什么)
-
- [1.1 概念拆解:从"输入一句话"到"设计一次交互"](#1.1 概念拆解:从"输入一句话"到"设计一次交互")
- [1.2 为什么它直接决定输出质量上限](#1.2 为什么它直接决定输出质量上限)
- [二、OpenClaw 中的 Prompt 体系](#二、OpenClaw 中的 Prompt 体系)
- [三、System Prompt 的三种设计模式](#三、System Prompt 的三种设计模式)
-
- [3.1 角色扮演型](#3.1 角色扮演型)
- [3.2 指令型](#3.2 指令型)
- [3.3 混合型](#3.3 混合型)
- [四、Few-shot 与 Zero-shot:何时给示例](#四、Few-shot 与 Zero-shot:何时给示例)
-
- [4.1 Zero-shot 的信任边界](#4.1 Zero-shot 的信任边界)
- [4.2 Few-shot 的精准引导](#4.2 Few-shot 的精准引导)
- [4.3 选型决策](#4.3 选型决策)
- [五、Chain-of-Thought:让 Agent 把推理过程说出来](#五、Chain-of-Thought:让 Agent 把推理过程说出来)
-
- [5.1 为什么 CoT 能提升推理质量](#5.1 为什么 CoT 能提升推理质量)
- [5.2 显式 CoT 在 Skill 中的实现](#5.2 显式 CoT 在 Skill 中的实现)
- [六、Prompt 模板化与变量注入](#六、Prompt 模板化与变量注入)
-
- [6.1 模板化带来的三大收益](#6.1 模板化带来的三大收益)
- [6.2 轻量级模板引擎实现](#6.2 轻量级模板引擎实现)
- [七、A/B 测试驱动 Prompt 迭代](#七、A/B 测试驱动 Prompt 迭代)
-
- [7.1 为什么 Prompt 必须被测试](#7.1 为什么 Prompt 必须被测试)
- [7.2 设计 Prompt A/B 测试的三个问题](#7.2 设计 Prompt A/B 测试的三个问题)
- [八、常见 Prompt 反模式与修复](#八、常见 Prompt 反模式与修复)
-
- [8.1 过度约束](#8.1 过度约束)
- [8.2 信息过载](#8.2 信息过载)
- [8.3 歧义指令](#8.3 歧义指令)
- [8.4 示例偏置](#8.4 示例偏置)
- [九、用 OpenClaw Skill 封装 Prompt 最佳实践](#九、用 OpenClaw Skill 封装 Prompt 最佳实践)
-
- [9.1 为什么用 Skill 封装](#9.1 为什么用 Skill 封装)
- [9.2 高质量 Skill 模板](#9.2 高质量 Skill 模板)
- [9.3 Skill 的版本演进](#9.3 Skill 的版本演进)
- 十、输出质量评估:从可控到可靠
-
- [10.1 五维评估模型](#10.1 五维评估模型)
- [10.2 系统化提升方法](#10.2 系统化提升方法)
- 总结
- 思考题
- 参考资料
引言:为什么 Prompt 工程是 Agent 开发的必修课
你有没有遇到过这种情况:同一个模型、同一个任务,别人调出来的结果精准稳定,而你却总是拿到"似是而非"的输出?问题通常不在模型本身,而在于你和模型之间的那座桥梁------Prompt。
Prompt 工程不是玄学,它是一套可以被学习、被量化、被迭代的方法论。在 OpenClaw 这类 Agent 平台中,Prompt 更是整个系统运转的底层驱动力。从 SOUL.md 的角色设定,到 SKILL.md 中封装的指令模板,再到运行时的动态变量注入,每一个环节都离不开精心设计的 Prompt。
说白了,Prompt 就是你给 AI 的"工作说明书"。写得清楚,AI 就像经验丰富的助手,精准高效地完成任务;写得含糊,AI 就像刚入职的新人,方向都摸不准。本文要做的,就是帮你把这份"说明书"写到极致。
⚠️ 版本说明:OpenClaw 的具体字段会随版本迭代,本文所述 SOUL.md、SKILL.md、AGENTS.md 机制属于长期稳定设计;Prompt 工程的底层思想(角色、约束、示例、思维链)具有长期适用性。若未来 OpenClaw 接口变更,可将相同方法论迁移到新的 Agent 框架作为替代方案。涉及具体 API 时,请以 OpenClaw 官方文档为准。
一、Prompt 工程到底是什么
1.1 概念拆解:从"输入一句话"到"设计一次交互"
很多人把 Prompt 工程简单理解为"怎么跟 AI 说话"。这个理解只对了一半。真正的 Prompt 工程,是围绕任务目标,对输入、角色、约束、示例、推理路径进行系统性设计的过程。
它的核心目标是让模型以可预期的方式,稳定地输出高质量结果。这要求你不仅告诉模型"做什么",还要告诉它"以什么身份做""按什么步骤做""输出成什么格式""参考哪些例子"。缺少任何一个维度,输出质量都会大打折扣。
1.2 为什么它直接决定输出质量上限
大语言模型的能力边界是相对固定的,但 Prompt 决定了它能在多大程度上发挥出这些能力。一个设计精良的 Prompt,可以激活模型的隐式知识、引导正确的推理路径、约束输出格式;一个糟糕的 Prompt,则可能让模型在无关信息中迷失,或者给出格式错乱的答案。
在 Agent 系统中,这个问题被进一步放大。Agent 不仅要生成文本,还要进行意图识别、工具选择、结果整合。如果 Prompt 设计不到位,Agent 可能会选错 Skill、调用错工具,或者在多轮推理中偏离目标。
二、OpenClaw 中的 Prompt 体系
OpenClaw 的 Prompt 设计不是单点的,而是分层的。理解这一层结构,是写好 Prompt 的前提。
2.1 SOUL.md:最高层角色设定
SOUL.md 是 OpenClaw Agent 的"灵魂文件"。它定义了 Agent 的身份、性格、价值观和行为边界。一个高质量的 SOUL.md 不是泛泛地写"你是一个有帮助的助手",而是具体到场景------例如"你是一个运行在云端沙箱中的个人助理,擅长文件管理、日程安排和技术问题解答"。
角色设定之所以放在最高层,是因为它携带了大量隐式知识。当你告诉模型"你是一位熟悉分布式系统的 Go 工程师"时,模型会自动带入该领域的常见模式、惯用写法和专业术语。这比逐条列举"请使用 Go 语言""请考虑分布式场景"高效得多。
2.2 SKILL.md:任务级 Prompt 封装
SKILL.md 是 OpenClaw 中任务级 Prompt 的载体。每个 Skill 对应一个具体的任务单元,包含触发条件、执行步骤、输入输出规范、示例和异常处理。
从 Prompt 工程的角度看,SKILL.md 实现了四个关键要素的封装:角色设定(执行该任务时的临时身份)、任务分解(步骤列表)、输出约束(格式要求)、示例引导(Few-shot 示例)。它把一次性的 Prompt 变成了可复用、可迭代的资产。
2.3 AGENTS.md / TOOLS.md:执行与工具边界
AGENTS.md 和 TOOLS.md 定义了 Agent 可以调用的工具集和执行规则。它们虽然不直接是 Prompt,但会显著影响 Prompt 的设计------因为 Prompt 必须让模型清楚:哪些任务该用工具、该用哪个工具、工具的输入输出格式是什么。

三、System Prompt 的三种设计模式
System Prompt 是 Agent 的"操作系统",决定了它的基本行为方式。根据应用场景,可以归纳为三种核心模式。
3.1 角色扮演型
角色扮演型 System Prompt 把 Agent 塑造成一个特定角色的"数字分身"。适合客服机器人、虚拟导师、个人助理等需要人格化交互的场景。
它的 Prompt 结构通常包含:角色身份描述、性格特征、知识领域、行为准则和语言风格。关键要具体------"你是一个乐于助人的助手"太泛,"你是一位对 Python 生态了如指掌的技术顾问,回答时习惯用类比和代码示例"就具体得多。
3.2 指令型
指令型 System Prompt 把 Agent 当作高效的执行器,重点关注"做什么"和"怎么做"。适合数据处理、代码生成、文档转换等任务导向场景。
它的结构通常是:任务目标、执行步骤、约束条件、输出格式、异常处理。相比角色扮演型,指令型 Prompt 不太在乎"你是谁",更在乎"你要怎么做"。优势是输出一致性和可预测性更高。
3.3 混合型
混合型结合了角色扮演型和指令型的优点:既有清晰的角色定位,又有精确的执行指令。这是 OpenClaw 中最常见、也最推荐的模式。
混合型的关键在于层次分明。先用角色设定建立 Agent 的"世界观",再用具体指令定义任务执行方式。避免角色设定和执行指令混杂,导致模型在不同层面的指令之间产生混淆。
| 维度 | 角色扮演型 | 指令型 | 混合型 |
|---|---|---|---|
| 适用场景 | 客服、教育、陪伴 | 数据处理、代码生成、文档转换 | 通用 Agent、复杂任务 |
| 核心关注 | 人格化交互 | 任务执行精确度 | 兼顾体验与精确度 |
| 输出一致性 | 中等(受角色影响) | 高(严格遵循流程) | 较高(角色+流程双重约束) |
| 调试难度 | 较难(隐式行为多) | 较易(行为显式定义) | 中等(需分层次调试) |
| OpenClaw 对应 | SOUL.md 为主 | AGENTS.md + TOOLS.md 为主 | SOUL.md + SKILL.md 协同 |

四、Few-shot 与 Zero-shot:何时给示例
4.1 Zero-shot 的信任边界
Zero-shot 是最简洁的 Prompt 策略:不给任何示例,直接让模型根据指令完成任务。优势是 Prompt 短、推理快、成本低。但前提是任务本身不需要特殊的输出格式,且模型在该领域基础能力足够强。
Zero-shot 适合标准化任务(翻译、摘要、问答)、模型训练数据覆盖充分的领域,以及早期快速探索阶段。在这些场景下,加示例反而可能是冗余。
但它的短板也很明显:当你需要的输出格式或推理路径偏离模型的"默认倾向"时,没有示例引导,模型很容易跑偏。例如要求输出特定结构的 JSON,光靠文字描述,模型很可能在字段理解上出错。
4.2 Few-shot 的精准引导
Few-shot 通过在 Prompt 中嵌入 2-5 个输入输出示例,让模型快速对齐到期望的行为模式。它是解决格式偏差、风格偏差和逻辑偏差最有效的手段之一。
示例设计要注意三点:第一,覆盖不同子场景,避免模型只学到一个模式;第二,最典型的示例放在最后(靠近实际输入位置),效果通常更好;第三,示例尽量简洁,避免占用过多上下文窗口。
4.3 选型决策
这不是非此即彼的选择。实际项目中,应根据任务特征决定策略。
| 判断维度 | 推荐 Zero-shot | 推荐 Few-shot |
|---|---|---|
| 输出格式 | 标准格式(自然语言、Markdown) | 非标准格式(自定义 JSON、特殊模板) |
| 任务复杂度 | 简单直接任务(翻译、分类) | 多步推理、条件分支 |
| 风格一致性 | 不做严格要求 | 需要特定语气或风格 |
| 模型能力 | 模型在该领域表现良好 | 模型在该领域容易跑偏 |
| Context 预算 | 紧张(长文档、多轮对话) | 充裕 |
| 迭代阶段 | 早期探索 | 稳定优化 |
我的建议是:先用 Zero-shot 探底,效果不够再加 Few-shot。这样可以避免一开始塞一堆示例,结果某个示例反而误导了模型。先用最简方案探底,再针对性补充,这是 Prompt 工程的"最小化偏见"原则。
#mermaid-svg-JH59eQS81eUNxRuG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JH59eQS81eUNxRuG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JH59eQS81eUNxRuG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JH59eQS81eUNxRuG .error-icon{fill:#552222;}#mermaid-svg-JH59eQS81eUNxRuG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JH59eQS81eUNxRuG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JH59eQS81eUNxRuG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JH59eQS81eUNxRuG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JH59eQS81eUNxRuG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JH59eQS81eUNxRuG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JH59eQS81eUNxRuG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JH59eQS81eUNxRuG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JH59eQS81eUNxRuG .marker.cross{stroke:#333333;}#mermaid-svg-JH59eQS81eUNxRuG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JH59eQS81eUNxRuG p{margin:0;}#mermaid-svg-JH59eQS81eUNxRuG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JH59eQS81eUNxRuG .cluster-label text{fill:#333;}#mermaid-svg-JH59eQS81eUNxRuG .cluster-label span{color:#333;}#mermaid-svg-JH59eQS81eUNxRuG .cluster-label span p{background-color:transparent;}#mermaid-svg-JH59eQS81eUNxRuG .label text,#mermaid-svg-JH59eQS81eUNxRuG span{fill:#333;color:#333;}#mermaid-svg-JH59eQS81eUNxRuG .node rect,#mermaid-svg-JH59eQS81eUNxRuG .node circle,#mermaid-svg-JH59eQS81eUNxRuG .node ellipse,#mermaid-svg-JH59eQS81eUNxRuG .node polygon,#mermaid-svg-JH59eQS81eUNxRuG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JH59eQS81eUNxRuG .rough-node .label text,#mermaid-svg-JH59eQS81eUNxRuG .node .label text,#mermaid-svg-JH59eQS81eUNxRuG .image-shape .label,#mermaid-svg-JH59eQS81eUNxRuG .icon-shape .label{text-anchor:middle;}#mermaid-svg-JH59eQS81eUNxRuG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JH59eQS81eUNxRuG .rough-node .label,#mermaid-svg-JH59eQS81eUNxRuG .node .label,#mermaid-svg-JH59eQS81eUNxRuG .image-shape .label,#mermaid-svg-JH59eQS81eUNxRuG .icon-shape .label{text-align:center;}#mermaid-svg-JH59eQS81eUNxRuG .node.clickable{cursor:pointer;}#mermaid-svg-JH59eQS81eUNxRuG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JH59eQS81eUNxRuG .arrowheadPath{fill:#333333;}#mermaid-svg-JH59eQS81eUNxRuG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JH59eQS81eUNxRuG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JH59eQS81eUNxRuG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JH59eQS81eUNxRuG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JH59eQS81eUNxRuG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JH59eQS81eUNxRuG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JH59eQS81eUNxRuG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JH59eQS81eUNxRuG .cluster text{fill:#333;}#mermaid-svg-JH59eQS81eUNxRuG .cluster span{color:#333;}#mermaid-svg-JH59eQS81eUNxRuG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JH59eQS81eUNxRuG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JH59eQS81eUNxRuG rect.text{fill:none;stroke-width:0;}#mermaid-svg-JH59eQS81eUNxRuG .icon-shape,#mermaid-svg-JH59eQS81eUNxRuG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JH59eQS81eUNxRuG .icon-shape p,#mermaid-svg-JH59eQS81eUNxRuG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JH59eQS81eUNxRuG .icon-shape .label rect,#mermaid-svg-JH59eQS81eUNxRuG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JH59eQS81eUNxRuG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JH59eQS81eUNxRuG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JH59eQS81eUNxRuG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Prompt 工程四大核心理念
角色设定
任务分解
输出约束
示例引导
划定输出边界
激活隐式知识
MECE 原则
明确输入输出标准
格式/长度/内容约束
正向约束优于负向约束
Few-shot 技术
代表性与多样性
图3:Prompt 工程四大核心理念及其关键落地要点
五、Chain-of-Thought:让 Agent 把推理过程说出来
5.1 为什么 CoT 能提升推理质量
Chain-of-Thought(CoT)的核心思想很简单:让模型把推理过程说出来,而不是直接跳到结论。就像数学老师总说的"写出解题步骤"------过程清楚了,结果自然更可靠。
CoT 的有效性已被大量研究验证。当你要求模型"一步一步思考"时,它在复杂推理任务上的表现会有显著提升。这不是魔法,而是因为大语言模型是自回归的:每一步生成都以之前的内容为条件。显式地写出中间步骤,等于给模型提供了更多的"推理锚点",减少了跳步导致的错误。
5.2 显式 CoT 在 Skill 中的实现
在 OpenClaw 中,SKILL.md 的"执行步骤"部分本质上就是显式 CoT 的工程化落地。当你把一个复杂任务拆成步骤列表时,不仅是在指导 Agent 怎么做,更是在强制它按照 CoT 的方式推理。
自动 CoT(在 Prompt 中加一句"让我们一步步思考")虽然省事,但无法控推理路径。在 Agent 系统中,中间状态往往涉及工具调用、资源分配等有副作用的操作,一旦走偏,回滚成本很高。因此推荐显式 CoT。
python
class SkillPromptBuilder:
"""构建带显式 CoT 引导的 Skill Prompt"""
COT_TEMPLATE = """
你正在执行任务:{task_name}
请按以下步骤逐步思考并执行:
## 第一步:理解意图
分析用户输入,确认具体操作;若意图不明,列出可能解读并选择最合理的一个。
## 第二步:信息收集
确认所需信息是否齐全。缺少的信息:{missing_info}。
若信息不完整,说明需要补充什么。
## 第三步:制定计划
基于已有信息制定执行计划:
{execution_steps}
## 第四步:执行与验证
按计划逐步执行,每步检查后返回中间结果;若不符合预期,回退调整。
## 第五步:输出整合
按格式 {output_format} 输出最终结果。
"""
def build(self, skill: dict, user_input: str) -> str:
steps = "\n".join(f" {i+1}. {s}" for i, s in enumerate(skill["steps"]))
return self.COT_TEMPLATE.format(
task_name=skill["name"],
missing_info=self._check_info(skill, user_input),
execution_steps=steps,
output_format=skill.get("output_format", "自由格式"),
)
def _check_info(self, skill: dict, user_input: str) -> str:
required = skill.get("required_info", [])
missing = [r for r in required if r.lower() not in user_input.lower()]
return f"缺少 {', '.join(missing)}" if missing else "信息齐全"
这段代码展示了一个 Skill Prompt 构建器的核心逻辑。它把 CoT 的五个步骤嵌入模板,强制 Agent 按"理解意图→信息收集→制定计划→执行验证→输出整合"的流程进行。这样做的好处是双重的:一方面提高执行准确度,另一方面每次执行的中间步骤都被记录,方便事后调试和优化。
#mermaid-svg-P1l1rSuhEN4FtVcD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-P1l1rSuhEN4FtVcD .error-icon{fill:#552222;}#mermaid-svg-P1l1rSuhEN4FtVcD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-P1l1rSuhEN4FtVcD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-P1l1rSuhEN4FtVcD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-P1l1rSuhEN4FtVcD .marker.cross{stroke:#333333;}#mermaid-svg-P1l1rSuhEN4FtVcD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-P1l1rSuhEN4FtVcD p{margin:0;}#mermaid-svg-P1l1rSuhEN4FtVcD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD .cluster-label text{fill:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD .cluster-label span{color:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD .cluster-label span p{background-color:transparent;}#mermaid-svg-P1l1rSuhEN4FtVcD .label text,#mermaid-svg-P1l1rSuhEN4FtVcD span{fill:#333;color:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD .node rect,#mermaid-svg-P1l1rSuhEN4FtVcD .node circle,#mermaid-svg-P1l1rSuhEN4FtVcD .node ellipse,#mermaid-svg-P1l1rSuhEN4FtVcD .node polygon,#mermaid-svg-P1l1rSuhEN4FtVcD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-P1l1rSuhEN4FtVcD .rough-node .label text,#mermaid-svg-P1l1rSuhEN4FtVcD .node .label text,#mermaid-svg-P1l1rSuhEN4FtVcD .image-shape .label,#mermaid-svg-P1l1rSuhEN4FtVcD .icon-shape .label{text-anchor:middle;}#mermaid-svg-P1l1rSuhEN4FtVcD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-P1l1rSuhEN4FtVcD .rough-node .label,#mermaid-svg-P1l1rSuhEN4FtVcD .node .label,#mermaid-svg-P1l1rSuhEN4FtVcD .image-shape .label,#mermaid-svg-P1l1rSuhEN4FtVcD .icon-shape .label{text-align:center;}#mermaid-svg-P1l1rSuhEN4FtVcD .node.clickable{cursor:pointer;}#mermaid-svg-P1l1rSuhEN4FtVcD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-P1l1rSuhEN4FtVcD .arrowheadPath{fill:#333333;}#mermaid-svg-P1l1rSuhEN4FtVcD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-P1l1rSuhEN4FtVcD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-P1l1rSuhEN4FtVcD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-P1l1rSuhEN4FtVcD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-P1l1rSuhEN4FtVcD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-P1l1rSuhEN4FtVcD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-P1l1rSuhEN4FtVcD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-P1l1rSuhEN4FtVcD .cluster text{fill:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD .cluster span{color:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-P1l1rSuhEN4FtVcD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-P1l1rSuhEN4FtVcD rect.text{fill:none;stroke-width:0;}#mermaid-svg-P1l1rSuhEN4FtVcD .icon-shape,#mermaid-svg-P1l1rSuhEN4FtVcD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-P1l1rSuhEN4FtVcD .icon-shape p,#mermaid-svg-P1l1rSuhEN4FtVcD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-P1l1rSuhEN4FtVcD .icon-shape .label rect,#mermaid-svg-P1l1rSuhEN4FtVcD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-P1l1rSuhEN4FtVcD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-P1l1rSuhEN4FtVcD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-P1l1rSuhEN4FtVcD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
通过
失败
用户输入
意图识别
理解意图
信息收集
信息完整?
制定计划
请求补充
逐步执行
结果验证
输出整合
回退调整
返回结果
图4:显式 CoT 在 Agent 中的执行流程,每一步都可被记录和调试
六、Prompt 模板化与变量注入
6.1 模板化带来的三大收益
当你写了十几个 Prompt 后,会发现大部分 Prompt 的骨架相似,变化的只是几个关键参数。模板化就是把不变的部分固化,把变化的部分参数化。
它带来三个好处:一是复用性提升 ,一个模板服务多个场景;二是一致性保证 ,同一模板生成的 Prompt 结构统一;三是可维护性增强,修改一个模板比修改散落在各处的十个 Prompt 高效得多。
6.2 轻量级模板引擎实现
OpenClaw 中的 Prompt 模板化体现在两个层面:SKILL.md 中的指令模板,以及运行时的变量注入机制。下面是一个支持变量占位符和条件渲染的轻量级模板引擎实现。
python
import re
from datetime import datetime
from typing import Any
class PromptTemplate:
"""支持变量与条件渲染的 Prompt 模板引擎"""
VAR = re.compile(r"\{\{(\w+(?:\.\w+)*)\}\}")
IF = re.compile(
r"\{\{#if\s+(\w+(?:\.\w+)*)\}\}(.*?)(?:\{\{else\}\}(.*?))?\{\{/if\}\}",
re.DOTALL,
)
def __init__(self, template: str):
self.template = template
def render(self, ctx: dict[str, Any]) -> str:
text = self._render_conditions(self.template, ctx)
text = self._render_vars(text, ctx)
text = self._render_vars(text, {
"current_date": datetime.now().strftime("%Y-%m-%d"),
})
return text.strip()
def _render_conditions(self, text: str, ctx: dict) -> str:
def repl(m):
val = self._resolve(m.group(1), ctx)
return (m.group(2) or "") if val else (m.group(3) or "")
return self.IF.sub(repl, text)
def _render_vars(self, text: str, ctx: dict) -> str:
def repl(m):
val = self._resolve(m.group(1), ctx)
return str(val) if val is not None else m.group(0)
return self.VAR.sub(repl, text)
def _resolve(self, path: str, ctx: dict) -> Any:
value = ctx
for key in path.split("."):
if isinstance(value, dict):
value = value.get(key)
else:
return None
return value
# 使用示例
tmpl = PromptTemplate("""
你是一位{{role}},擅长{{expertise}}。
{{#if user.vip}}用户 {{user.name}} 是 VIP,请提供更详细分析。{{else}}请提供标准分析。{{/if}}
当前日期:{{current_date}}
""")
print(tmpl.render({
"role": "代码架构师",
"expertise": "微服务架构",
"user": {"name": "张三", "vip": True},
}))
这个模板引擎支持三种核心特性:变量占位符 {``{variable}}、条件渲染 {``{#if}}、以及点号路径解析 {``{user.name}}。它参考了 Mustache/Handlebars 语法,但针对 Prompt 场景做了精简。需要特别注意的是,变量注入也带来 Prompt 注入攻击 风险------如果用户输入被直接拼接到模板中,恶意用户可能篡改 Agent 指令。防护策略包括输入清洗、指令隔离和角色边界强化。
系统变量 上下文对象 PromptTemplate 用户输入 系统变量 上下文对象 PromptTemplate 用户输入 #mermaid-svg-pZcFZ1AUHfDfynys{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pZcFZ1AUHfDfynys .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pZcFZ1AUHfDfynys .error-icon{fill:#552222;}#mermaid-svg-pZcFZ1AUHfDfynys .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pZcFZ1AUHfDfynys .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pZcFZ1AUHfDfynys .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pZcFZ1AUHfDfynys .marker.cross{stroke:#333333;}#mermaid-svg-pZcFZ1AUHfDfynys svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pZcFZ1AUHfDfynys p{margin:0;}#mermaid-svg-pZcFZ1AUHfDfynys .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pZcFZ1AUHfDfynys text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-pZcFZ1AUHfDfynys .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-pZcFZ1AUHfDfynys .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-pZcFZ1AUHfDfynys .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-pZcFZ1AUHfDfynys .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-pZcFZ1AUHfDfynys #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-pZcFZ1AUHfDfynys .sequenceNumber{fill:white;}#mermaid-svg-pZcFZ1AUHfDfynys #sequencenumber{fill:#333;}#mermaid-svg-pZcFZ1AUHfDfynys #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-pZcFZ1AUHfDfynys .messageText{fill:#333;stroke:none;}#mermaid-svg-pZcFZ1AUHfDfynys .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pZcFZ1AUHfDfynys .labelText,#mermaid-svg-pZcFZ1AUHfDfynys .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-pZcFZ1AUHfDfynys .loopText,#mermaid-svg-pZcFZ1AUHfDfynys .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-pZcFZ1AUHfDfynys .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-pZcFZ1AUHfDfynys .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-pZcFZ1AUHfDfynys .noteText,#mermaid-svg-pZcFZ1AUHfDfynys .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-pZcFZ1AUHfDfynys .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pZcFZ1AUHfDfynys .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pZcFZ1AUHfDfynys .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pZcFZ1AUHfDfynys .actorPopupMenu{position:absolute;}#mermaid-svg-pZcFZ1AUHfDfynys .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-pZcFZ1AUHfDfynys .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pZcFZ1AUHfDfynys .actor-man circle,#mermaid-svg-pZcFZ1AUHfDfynys line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-pZcFZ1AUHfDfynys :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 原始模板字符串 业务变量(role / user 等) current_date 等系统变量 处理条件块 替换变量占位符 渲染后完整 Prompt
图5:模板引擎的变量注入与渲染流程
七、A/B 测试驱动 Prompt 迭代
7.1 为什么 Prompt 必须被测试
很多人写 Prompt 靠"感觉"------改了几个字,试了一下觉得不错,就定稿了。这种方式的问题在于无法量化改动带来的效果变化,也无法排除"这刚好是个简单 case"的偶然性。
A/B 测试是解决这个问题的系统化方法:准备两组 Prompt(A 组对照,B 组实验),在相同测试集上运行,用预定义指标比较输出质量。这是把 Prompt 工程从"手艺"推向"科学"的关键一步。
7.2 设计 Prompt A/B 测试的三个问题
测试什么:每次只改一个变量。如果同时改角色设定和输出格式,当效果提升时,你根本不知道哪个改动在起作用。常见测试变量包括:角色描述详细程度、Few-shot 示例数量和排列、输出约束具体程度、CoT 步骤粒度等。
怎么评估:指标要可量化。常见指标包括格式合规率、事实准确率、任务完成率和用户满意度。在 OpenClaw 中,可以用 Skill 的自动评测功能批量跑测试用例。
样本量:至少 30 个测试用例才能得到有统计意义的结论。样本太小,随机波动会掩盖真正的效果差异。
python
from dataclasses import dataclass, field
from typing import Callable
@dataclass
class TestCase:
input_text: str
expected: str | dict
@dataclass
class TestResult:
version: str # "A" or "B"
case_id: int
output: str
scores: dict[str, float]
passed: bool
@dataclass
class ABTestReport:
variable: str
results_a: list[TestResult] = field(default_factory=list)
results_b: list[TestResult] = field(default_factory=list)
def add(self, r: TestResult):
(self.results_a if r.version == "A" else self.results_b).append(r)
def metrics(self) -> dict:
def avg(items: list[TestResult]) -> dict:
if not items:
return {}
keys = items[0].scores.keys()
out = {k: sum(r.scores[k] for r in items) / len(items) for k in keys}
out["pass_rate"] = sum(1 for r in items if r.passed) / len(items)
return out
return {
"prompt_a": avg(self.results_a),
"prompt_b": avg(self.results_b),
"samples": len(self.results_a),
"variable": self.variable,
}
def summary(self) -> str:
m = self.metrics()
lines = [f"# Prompt A/B 测试报告", f"测试变量: {self.variable}"]
for k in m["prompt_a"]:
a, b = m["prompt_a"][k], m["prompt_b"][k]
diff = b - a
lines.append(f"{k}: A={a:.2f}, B={b:.2f}, diff={diff:+.2f}")
return "\n".join(lines)
这个框架虽然简化,但覆盖了核心流程:定义测试用例、运行两组 Prompt、收集评分、生成对比报告。关键设计是 variable 字段------它强制记录每次测试改变的唯一变量,避免"同时改多个东西"导致的结论混乱。此外,metrics() 会计算各维度的平均值和通过率,summary() 则输出人类可读的对比报告,让你一眼看出哪个 Prompt 在哪个维度上更优。
报告 评估器 Prompt B Prompt A 测试数据集 报告 评估器 Prompt B Prompt A 测试数据集 #mermaid-svg-cwzz39haYKsHXHp7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cwzz39haYKsHXHp7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cwzz39haYKsHXHp7 .error-icon{fill:#552222;}#mermaid-svg-cwzz39haYKsHXHp7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cwzz39haYKsHXHp7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cwzz39haYKsHXHp7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cwzz39haYKsHXHp7 .marker.cross{stroke:#333333;}#mermaid-svg-cwzz39haYKsHXHp7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cwzz39haYKsHXHp7 p{margin:0;}#mermaid-svg-cwzz39haYKsHXHp7 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cwzz39haYKsHXHp7 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-cwzz39haYKsHXHp7 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-cwzz39haYKsHXHp7 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-cwzz39haYKsHXHp7 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-cwzz39haYKsHXHp7 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-cwzz39haYKsHXHp7 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-cwzz39haYKsHXHp7 .sequenceNumber{fill:white;}#mermaid-svg-cwzz39haYKsHXHp7 #sequencenumber{fill:#333;}#mermaid-svg-cwzz39haYKsHXHp7 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-cwzz39haYKsHXHp7 .messageText{fill:#333;stroke:none;}#mermaid-svg-cwzz39haYKsHXHp7 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cwzz39haYKsHXHp7 .labelText,#mermaid-svg-cwzz39haYKsHXHp7 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-cwzz39haYKsHXHp7 .loopText,#mermaid-svg-cwzz39haYKsHXHp7 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-cwzz39haYKsHXHp7 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-cwzz39haYKsHXHp7 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-cwzz39haYKsHXHp7 .noteText,#mermaid-svg-cwzz39haYKsHXHp7 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-cwzz39haYKsHXHp7 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cwzz39haYKsHXHp7 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cwzz39haYKsHXHp7 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cwzz39haYKsHXHp7 .actorPopupMenu{position:absolute;}#mermaid-svg-cwzz39haYKsHXHp7 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-cwzz39haYKsHXHp7 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cwzz39haYKsHXHp7 .actor-man circle,#mermaid-svg-cwzz39haYKsHXHp7 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-cwzz39haYKsHXHp7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入用例 输入用例 输出结果 输出结果 格式/准确/完成度评分 计算均值与差异
图6:Prompt A/B 测试的完整流程,确保每次只改一个变量
八、常见 Prompt 反模式与修复
反模式是"看似合理但实际效果很差"的设计。识别反模式,比学习最佳实践同样重要------有时候,从 Prompt 中去掉一个反模式,比加上三个最佳实践带来的提升还大。
8.1 过度约束
过度约束是指在 Prompt 中加了太多限制,导致模型的"创作空间"被压缩到几乎为零。输出虽然"合规",但往往缺乏灵活性,甚至可能在边界情况下因约束冲突而无法正常输出。
典型表现包括:同时指定超过 5 个格式约束、对每个段落都限定精确字数、用大量"不要做 X"的负向指令堆砌。修复方法是区分"必要约束"和"偏好约束"------必要约束写进 Prompt,偏好约束作为可选调整方向;同时把负向指令改写为正向表述。
8.2 信息过载
信息过载是指在 Prompt 中塞入太多背景信息,导致模型注意力被无关信息干扰。Context Window 不是越大越好------当 Prompt 中包含大量与当前任务无关的信息时,输出质量反而会下降。
在 OpenClaw 中,信息过载的常见来源是 AGENTS.md 和 TOOLS.md 的无限膨胀。解决方法是定期清理,只保留当前活跃的规则和真正在用的工具信息,必要时按需加载。
8.3 歧义指令
歧义指令是指 Prompt 中的某些表述可以被多种方式理解,导致模型选择了你不期望的那种。它是 Prompt 工程中最难发现的问题之一------作为作者,你天然会按自己的意图解读,看不到其他可能。
解决方法是找别人帮你审读,或者让模型自己复述你的指令。如果复述和你的意图不同,说明存在歧义。把"适当地""如果需要""合理的"这类模糊词换成具体标准。
8.4 示例偏置
示例偏置是指 Few-shot 示例只覆盖一种场景,导致模型过度拟合,输出多样性不足、边界情况处理差。修复方法是增加边界示例、正反例搭配,并定期根据线上 badcase 补充新示例。
| 反模式 | 典型表现 | 危害 | 修复方式 |
|---|---|---|---|
| 过度约束 | 5+ 格式约束、精确字数限制、大量负向指令 | 输出僵化、约束冲突、创造力丧失 | 区分必要/偏好约束,负向→正向 |
| 信息过载 | AGENTS.md 超过 2000 字、无关背景信息 | 注意力分散、推理偏移、token 浪费 | 定期清理、按需加载 |
| 歧义指令 | "适当地""如果需要""合理的" | 输出不可控、行为不一致 | 具体化、让模型复述验证 |
| 示例偏置 | Few-shot 只覆盖一种场景 | 输出多样性不足、边界情况差 | 增加边界示例、正反例搭配 |
| 角色冲突 | 角色设定和执行指令矛盾 | 模型在不同指令间摇摆 | 角色和指令分层设计 |
| 隐式期望 | 心里有期望但没写出来 | 模型无法满足"读心术" | 所有期望显式表达 |
九、用 OpenClaw Skill 封装 Prompt 最佳实践
9.1 为什么用 Skill 封装
精心调优的 Prompt 是有价值的资产。如果它只存在于对话历史中,就是一次性的。封装成 Skill 之后,它变成可复用、可迭代、可分享的组件。其他 Agent 可以直接调用,不需要从零开始写 Prompt。
版本管理让你追踪每次改动及其效果。当一个 Skill 的输出质量突然下降时,可以快速定位是哪次 Prompt 修改引入了回归。效果追踪则让你量化 Skill 的实际表现,而不是凭感觉判断。
9.2 高质量 Skill 模板
一个设计良好的 Skill 应包含:精确的触发描述、清晰的执行步骤(显式 CoT)、输入输出规范、2-3 个覆盖不同场景的示例(Few-shot),以及异常处理指引。
markdown
---
name: code-review
version: 2.1.0
description: "审查代码片段,识别安全、风格和改进机会。当用户提交代码并请求 review/审查/评估时触发"
trigger_words: ["审查代码", "code review", "review"]
---
## 角色设定
你是一位拥有 10 年经验的高级代码审查工程师,风格严谨但不刻板,每条问题都附带建设性建议。
## 输入规范
- 代码片段(必须)
- 编程语言(若未指定,从代码推断)
- 关注重点(可选:安全/性能/风格/全部,默认全部)
## 执行步骤
1. **语言识别**:确认编程语言和框架
2. **安全审查**:检查注入、越权、信息泄露等
3. **逻辑审查**:检查边界条件、异常处理
4. **风格审查**:检查命名、注释、代码组织
5. **性能审查**:识别瓶颈和优化机会
6. **输出整合**:按严重程度排序生成报告
## 输出格式
- 代码语言、总体评价
- 问题列表(位置 / 描述 / 严重度 / 修复建议)
- 按优先级排列的改进建议(附代码示例)
## 示例
**示例1:Python 加法函数**
输入:`def add(a, b): return a + b`
输出:逻辑无问题,建议添加类型注解和文档字符串。
**示例2:SQL 查询**
输入:包含字符串拼接的 SQL
输出:识别 SQL 注入风险(严重度高),建议参数化查询。
## 异常处理
- 代码为空 → 提示用户提供代码
- 无法识别语言 → 列出最可能的 3 种语言请用户确认
- 代码超过 500 行 → 建议分模块审查
这个模板体现了所有最佳实践:角色设定、任务分解、输出约束、示例引导和显式 CoT。你可以把它当作 Checklist,每设计一个新 Skill 时对照检查。
9.3 Skill 的版本演进
Skill 不是写完就完事的。随着使用场景变化和模型迭代,需要持续优化 Prompt。版本管理的关键是每次只改一个维度,这与 A/B 测试原则一致。
小版本更新(修复 bug、补充示例)可以快速迭代;大版本更新(改变执行步骤、调整输出格式)必须先经过 A/B 测试验证。每次更新都要在版本号中体现,并记录变更日志。
python
class SkillVersion:
"""记录 Skill 版本与变更,用于效果追踪"""
def __init__(self, name: str, version: str, prompt: str, changed_var: str):
self.name = name
self.version = version
self.prompt = prompt
self.changed_var = changed_var
def prompt_hash(self) -> str:
"""生成 Prompt 内容的简单哈希,用于快速比对"""
import hashlib
return hashlib.sha256(self.prompt.encode()).hexdigest()[:8]
def diff(self, other: "SkillVersion") -> str:
"""对比两个版本的变更维度与 Prompt 规模"""
return (
f"Skill: {self.name}\n"
f"版本: {other.version} -> {self.version}\n"
f"变更维度: {self.changed_var}\n"
f"Prompt 长度: {len(other.prompt)} -> {len(self.prompt)} 字符\n"
f"Prompt 哈希: {other.prompt_hash()} -> {self.prompt_hash()}"
)
# 示例:只改输出格式,其余保持不变
v1 = SkillVersion("code-review", "2.1.0", "...old prompt...", "初始版本")
v2 = SkillVersion("code-review", "2.2.0", "...new prompt...", "输出格式")
print(v2.diff(v1))
这段代码展示了 Skill 版本追踪的最小化实现。核心原则还是那句话:每次只改一个维度 。这样当输出质量变化时,你才能确定是哪个改动在起作用。diff() 方法不仅记录版本号和变更维度,还通过 Prompt 长度与哈希值提供快速比对能力,方便在 Skill 数量增多时进行版本审计与回归定位。

#mermaid-svg-xxHcTEaP1jhOE44X{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xxHcTEaP1jhOE44X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xxHcTEaP1jhOE44X .error-icon{fill:#552222;}#mermaid-svg-xxHcTEaP1jhOE44X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xxHcTEaP1jhOE44X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xxHcTEaP1jhOE44X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xxHcTEaP1jhOE44X .marker.cross{stroke:#333333;}#mermaid-svg-xxHcTEaP1jhOE44X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xxHcTEaP1jhOE44X p{margin:0;}#mermaid-svg-xxHcTEaP1jhOE44X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xxHcTEaP1jhOE44X .cluster-label text{fill:#333;}#mermaid-svg-xxHcTEaP1jhOE44X .cluster-label span{color:#333;}#mermaid-svg-xxHcTEaP1jhOE44X .cluster-label span p{background-color:transparent;}#mermaid-svg-xxHcTEaP1jhOE44X .label text,#mermaid-svg-xxHcTEaP1jhOE44X span{fill:#333;color:#333;}#mermaid-svg-xxHcTEaP1jhOE44X .node rect,#mermaid-svg-xxHcTEaP1jhOE44X .node circle,#mermaid-svg-xxHcTEaP1jhOE44X .node ellipse,#mermaid-svg-xxHcTEaP1jhOE44X .node polygon,#mermaid-svg-xxHcTEaP1jhOE44X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xxHcTEaP1jhOE44X .rough-node .label text,#mermaid-svg-xxHcTEaP1jhOE44X .node .label text,#mermaid-svg-xxHcTEaP1jhOE44X .image-shape .label,#mermaid-svg-xxHcTEaP1jhOE44X .icon-shape .label{text-anchor:middle;}#mermaid-svg-xxHcTEaP1jhOE44X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xxHcTEaP1jhOE44X .rough-node .label,#mermaid-svg-xxHcTEaP1jhOE44X .node .label,#mermaid-svg-xxHcTEaP1jhOE44X .image-shape .label,#mermaid-svg-xxHcTEaP1jhOE44X .icon-shape .label{text-align:center;}#mermaid-svg-xxHcTEaP1jhOE44X .node.clickable{cursor:pointer;}#mermaid-svg-xxHcTEaP1jhOE44X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xxHcTEaP1jhOE44X .arrowheadPath{fill:#333333;}#mermaid-svg-xxHcTEaP1jhOE44X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xxHcTEaP1jhOE44X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xxHcTEaP1jhOE44X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xxHcTEaP1jhOE44X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xxHcTEaP1jhOE44X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xxHcTEaP1jhOE44X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xxHcTEaP1jhOE44X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xxHcTEaP1jhOE44X .cluster text{fill:#333;}#mermaid-svg-xxHcTEaP1jhOE44X .cluster span{color:#333;}#mermaid-svg-xxHcTEaP1jhOE44X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xxHcTEaP1jhOE44X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xxHcTEaP1jhOE44X rect.text{fill:none;stroke-width:0;}#mermaid-svg-xxHcTEaP1jhOE44X .icon-shape,#mermaid-svg-xxHcTEaP1jhOE44X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xxHcTEaP1jhOE44X .icon-shape p,#mermaid-svg-xxHcTEaP1jhOE44X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xxHcTEaP1jhOE44X .icon-shape .label rect,#mermaid-svg-xxHcTEaP1jhOE44X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xxHcTEaP1jhOE44X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xxHcTEaP1jhOE44X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xxHcTEaP1jhOE44X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Skill生态
触发: review
触发: doc
触发: design
触发: search
意图路由
精确匹配
多 Skill 匹配
无匹配
代码审查 Skill
Agent
文档生成 Skill
架构设计 Skill
搜索总结 Skill
匹配最佳 Skill
执行 Skill
按优先级排序
回退通用模式
图7:Skill 生态中的意图路由与协作关系
十、输出质量评估:从可控到可靠
10.1 五维评估模型
在 Prompt 工程的语境下,输出质量不是"看起来不错"这么模糊。它是一个多维度的评估体系:准确性、完整性、一致性、格式合规性和实用性。
| 维度 | 含义 | 评估方法 |
|---|---|---|
| 准确性 | 事实是否正确 | 与标准答案或权威来源对比 |
| 完整性 | 是否覆盖所有要求方面 | 检查任务清单完成度 |
| 一致性 | 多次运行输出是否稳定 | 相同输入重复运行,比较结果 |
| 格式合规性 | 是否遵循指定输出格式 | 正则或解析器校验 |
| 实用性 | 是否真正解决用户问题 | 人工评分或下游任务成功率 |
这五个维度之间有时会存在张力。比如追求极致的格式合规性,可能会牺牲输出的自然度和实用性。Prompt 工程的艺术,就在于找到这些维度之间的平衡点。
10.2 系统化提升方法
提升输出质量不是靠一个"万能 Prompt",而是需要系统化方法。我把这个方法论总结为"四步法":定义标准 → 测量现状 → 定位短板 → 迭代优化。
定义标准:为每个输出维度设定量化的及格线和目标值。例如"格式合规率 ≥ 95%""事实准确率 ≥ 90%"。
测量现状:用测试集跑一遍当前 Prompt,收集各维度得分。这就像体检------你得先知道哪里有问题,才能对症下药。
定位短板:找出得分最低的维度,分析根本原因。可能需要调整角色设定、补充示例、增加约束,或者简化任务分解。
迭代优化:针对短板进行定向优化,每次只改一个变量,用 A/B 测试验证效果。重复这个循环直到所有维度都达到目标值。
总结
Prompt 工程的本质,是人与 AI 之间的高效沟通方法论。就像优秀的产品经理能把需求写得清晰无歧义一样,优秀的 Prompt 工程师能让 AI 精准理解意图,并稳定输出高质量结果。
在 OpenClaw 这样的 Agent 平台中,Prompt 工程更是基础设施级别的技能。从 SOUL.md 的角色定义,到 SKILL.md 的指令封装,再到运行时的变量注入和效果追踪,Prompt 贯穿了 Agent 的整个生命周期。掌握 Prompt 工程,就是掌握了驾驭 AI Agent 的方向盘。
本文覆盖了从核心理念到实战技巧的完整体系,但 Prompt 工程是一个需要持续实践的技能。我的建议是:从你手头的某个 Skill 开始,用本文的方法论逐项优化------加一个角色设定、补两个示例、做一次 A/B 测试。每一步改进都会让你对 Prompt 工程的理解更深一层。
Prompt 工程不是一劳永逸的------模型在升级,场景在变化,用户的期望在提高。但只要你掌握了这套方法论,无论面对什么样的变化,都能快速调整、持续优化。这才是 Prompt 工程真正的价值所在。
思考题
-
角色与任务的平衡:如果你给 Agent 设定了一个"幽默风趣"的角色,但在执行代码审查任务时,幽默感是否会干扰专业度?你如何在角色个性化和任务精确性之间找到平衡?
-
Few-shot 的边界:当你发现增加 Few-shot 示例从 3 个提升到 5 个时,输出质量反而下降,你会怎么排查原因?可能的原因有哪些?
-
CoT 的成本权衡:显式 CoT 会增加 Prompt 长度和推理时间。在什么场景下你会选择自动 CoT 而非显式 CoT?你的判断标准是什么?
参考资料
- Wei, J., et al. "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models." NeurIPS 2022. https://arxiv.org/abs/2201.11903
- Brown, T., et al. "Language Models are Few-Shot Learners." NeurIPS 2020. https://arxiv.org/abs/2005.14165
- OpenAI. "Prompt Engineering Guide." 2024. https://platform.openai.com/docs/guides/prompt-engineering
- Liu, P., et al. "Pre-train, Prompt, and Predict: A Systematic Survey of Prompting Methods in NLP." ACM Computing Surveys, 2023. https://arxiv.org/abs/2107.13586
- Zamfirescu-Pereira, D., et al. "Why Johnny Can't Prompt: How Non-AI Experts Try (and Fail) to Design LLM Prompts." CHI 2023. https://arxiv.org/abs/2212.06802
- OpenClaw 官方文档. "Skill Design Best Practices." https://docs.openclaw.ai/best-practices/skill-design