Prompt工程在Skill设计中的应用

Prompt工程不只是写一段好提示词,而是一门关于如何与AI有效沟通的系统学科。当Prompt工程遇上Skill设计,事情变得更有意思:Skill是反复使用的操作手册,Prompt是让AI执行操作的指令。两者的结合点在于,如何把Prompt工程的最佳实践固化到Skill里,让每次调用都稳定产出高质量结果。

Skill设计的核心挑战不是”怎么写一段好Prompt”,而是”怎么写一段能重复用好、能被不同AI理解、能在各种场景下保持稳定的Prompt”。这篇文章会从Prompt模板、变量注入、上下文组装、少样本学习、思维链、结构化输出和A/B测试七个方面,讲清楚Prompt工程在Skill设计中的具体应用。

Prompt模板:从即兴创作到标准化生产

没有模板的Prompt就像每次做饭都凭感觉放盐:有时候刚好,有时候咸得要命。Skill作为可复用的能力单元,它的Prompt必须基于模板。模板的作用是定义Prompt的结构和固定部分,让可变部分通过变量注入。

一个典型的Skill Prompt模板通常包含这几个部分:角色定义、任务描述、输入格式、处理规则、输出格式、约束条件和示例。不是每个Skill都需要全部七个部分,但少了任何一个,都可能在某些场景下出问题。

# Skill Prompt 模板结构
system:
  role: "你是一位专业的代码审查员"
  expertise: ["TypeScript", "React", "性能优化"]
  style: "直接、具体、以风险为导向"

task:
  description: "审查给定的代码变更,识别潜在问题"
  scope: "只关注{{review_scope}}范围内的文件"
  
input:
  format: |
    文件路径:{{file_path}}
    变更类型:{{change_type}}
    代码差异:
    ```diff
    {{diff_content}}
    ```

rules:
  - "优先识别安全风险和数据泄漏"
  - "关注性能瓶颈和内存泄漏"
  - "检查错误处理是否完善"
  - "验证边界条件覆盖"
  
output:
  format: "JSON"
  schema:
    type: "object"
    properties:
      findings:
        type: "array"
        items:
          type: "object"
          properties:
            severity: { enum: ["critical", "high", "medium", "low"] }
            category: { enum: ["security", "performance", "correctness", "maintainability"] }
            description: { type: "string" }
            suggestion: { type: "string" }
            line_numbers: { type: "array", items: { type: "number" } }
      summary: { type: "string" }
      risk_level: { enum: ["high", "medium", "low"] }

constraints:
  - "不要评论代码风格问题"
  - "必须引用具体的行号"
  - "优先讲风险,其次讲改进建议"

模板的好处显而易见。首先,它把Prompt的组织方式标准化了。同一个团队的不同Skill,遵循相同的模板结构,阅读和维护成本大幅降低。其次,它把固定内容和可变内容分离。角色定义、处理规则、约束条件通常是固定的,输入数据和范围则是每次调用时注入的。

变量注入不是简单的字符串替换。好的模板引擎应该支持条件渲染、默认值、列表展开和嵌套引用。比如有些约束只在特定条件下生效,有些规则在调试模式下需要展开详细说明。

interface TemplateEngine {
  render(template: string, variables: Record<string, unknown>): string;
}

class SkillTemplateEngine implements TemplateEngine {
  render(template: string, variables: Record<string, unknown>): string {
    // 支持 {{variable}} 基本替换
    // 支持 {{#if condition}}...{{/if}} 条件渲染
    // 支持 {{#each items}}...{{/each}} 列表展开
    // 支持 {{variable | default("fallback")}} 默认值
    return this.processTemplate(template, variables);
  }

  private processTemplate(template: string, variables: Record<string, unknown>): string {
    // 实现模板处理逻辑
    // 处理变量替换
    let result = template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
      const value = variables[key];
      return value !== undefined ? String(value) : match;
    });

    // 处理条件块
    result = result.replace(
      /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g,
      (match, condition, content) => {
        return variables[condition] ? content : '';
      }
    );

    return result;
  }
}

变量注入:让Prompt从静态走向动态

静态Prompt的问题是缺乏灵活性。一个代码审查Skill不可能每次审查同样的文件,一个数据分析Skill也不可能每次处理同样的数据集。变量注入让Skill能够根据具体任务动态生成Prompt。

变量可以来自多个来源:用户输入、运行时上下文、配置文件、前序步骤的输出。Skill设计时要明确每个变量的来源、类型、约束和默认值。

interface VariableDefinition {
  name: string;
  type: "string" | "number" | "boolean" | "array" | "object";
  source: "user_input" | "context" | "config" | "previous_step";
  required: boolean;
  default?: unknown;
  validation?: ValidationRule[];
  description: string;
}

const reviewSkillVariables: VariableDefinition[] = [
  {
    name: "file_path",
    type: "string",
    source: "context",
    required: true,
    description: "要审查的文件路径"
  },
  {
    name: "diff_content",
    type: "string",
    source: "previous_step",
    required: true,
    description: "Git diff 格式的代码变更内容"
  },
  {
    name: "review_scope",
    type: "string",
    source: "config",
    required: false,
    default: "all",
    description: "审查范围:all、security、performance"
  },
  {
    name: "strict_mode",
    type: "boolean",
    source: "user_input",
    required: false,
    default: false,
    description: "是否启用严格模式,增加检查项"
  }
];

变量注入时要注意类型安全。一个被声明为数字的变量,如果注入了字符串,可能导致Prompt语义完全改变。Skill框架应该在注入前做类型检查和转换。

另一个常见问题是注入内容过长。如果用户传入了一个一万行的diff,直接注入会让Prompt超出模型的上下文窗口。这时候需要摘要、截断或分块处理。

function injectVariable(
  prompt: string,
  variable: VariableDefinition,
  value: unknown,
  maxLength: number = 4000
): string {
  let processedValue: string;

  if (typeof value === "string" && value.length > maxLength) {
    // 对长文本进行智能截断
    processedValue = smartTruncate(value, maxLength);
  } else {
    processedValue = JSON.stringify(value);
  }

  const placeholder = `{{${variable.name}}}`;
  return prompt.replace(placeholder, processedValue);
}

function smartTruncate(text: string, maxLength: number): string {
  if (text.length <= maxLength) return text;

  // 保留开头和结尾,中间用省略号连接
  const headLength = Math.floor(maxLength * 0.6);
  const tailLength = Math.floor(maxLength * 0.3);

  return `${text.slice(0, headLength)}\n\n... [中间省略 ${text.length - headLength - tailLength} 字符] ...\n\n${text.slice(-tailLength)}`;
}

上下文组装:不是所有信息都要告诉AI

Agent执行任务时,往往掌握了大量上下文信息:项目结构、历史对话、用户偏好、系统状态、前序步骤的输出。把所有信息都塞进Prompt,既浪费Token,又会稀释关键信号的浓度。上下文组装的艺术在于:只给AI它需要的信息,按重要性排序,让AI第一眼就能看到关键内容。

上下文组装通常遵循”倒金字塔”原则:最重要的信息放在最前面,次要信息依次排列,背景信息放在最后。这和新闻写作的结构一样,因为AI读取Prompt的方式和人类读文章类似:注意力在前几句最集中。

interface ContextAssembler {
  assemble(context: ExecutionContext): string;
}

class HierarchicalContextAssembler implements ContextAssembler {
  assemble(context: ExecutionContext): string {
    const parts: string[] = [];

    // 第一层:任务指令(最高优先级)
    parts.push(this.formatTaskInstruction(context.task));

    // 第二层:关键约束(不可违反的规则)
    if (context.constraints.length > 0) {
      parts.push(this.formatConstraints(context.constraints));
    }

    // 第三层:输入数据(本次处理的内容)
    parts.push(this.formatInput(context.input));

    // 第四层:相关历史(前序步骤的关键结果)
    if (context.history.length > 0) {
      parts.push(this.formatRelevantHistory(context.history));
    }

    // 第五层:背景信息(项目结构、术语表等)
    if (context.background) {
      parts.push(this.formatBackground(context.background));
    }

    return parts.join("\n\n");
  }

  private formatTaskInstruction(task: Task): string {
    return `## 任务\n${task.description}\n`;
  }

  private formatConstraints(constraints: Constraint[]): string {
    const items = constraints.map(c => `- ${c.description}`).join("\n");
    return `## 约束条件(必须遵守)\n${items}\n`;
  }

  private formatInput(input: unknown): string {
    return `## 输入数据\n${JSON.stringify(input, null, 2)}\n`;
  }

  private formatRelevantHistory(history: HistoryItem[]): string {
    const relevant = history
      .filter(h => h.importance === "high")
      .map(h => `- ${h.step}: ${h.summary}`)
      .join("\n");
    return `## 相关历史\n${relevant}\n`;
  }

  private formatBackground(background: BackgroundInfo): string {
    return `## 背景信息\n${background.summary}\n`;
  }
}

上下文组装还要考虑时效性。一个三天前的对话记录,可能对当前任务毫无意义,甚至会误导AI。Skill应该根据任务类型,定义上下文的有效期和相关性评分规则。

少样本学习:用例子教AI做事

少样本学习(Few-shot Learning)是Prompt工程中最有效的技巧之一。它的原理很简单:给AI几个输入和期望输出的例子,让它照着样子做。这比单纯用文字描述规则更直观,尤其对于那些难以精确形式化的任务。

在Skill设计中,少样本示例应该作为模板的固定部分,随Skill一起分发。示例的选择很重要:要覆盖主要场景,要展示边界情况,要包含正反两面的例子。

## 示例

### 示例1:简单的类型错误
输入:
```typescript
function greet(name: string) {
  return "Hello, " + name.toUppercase();
}

输出:

{
  "findings": [
    {
      "severity": "medium",
      "category": "correctness",
      "description": "调用了不存在的方法 toUppercase,正确方法名应为 toUpperCase",
      "suggestion": "将 name.toUppercase() 改为 name.toUpperCase()",
      "line_numbers": [2]
    }
  ],
  "summary": "存在一个拼写错误导致的类型问题",
  "risk_level": "low"
}

示例2:安全漏洞

输入:

app.get("/user", (req, res) => {
  const query = `SELECT * FROM users WHERE id = ${req.query.id}`;
  db.execute(query).then(users => res.json(users));
});

输出:

{
  "findings": [
    {
      "severity": "critical",
      "category": "security",
      "description": "SQL注入漏洞:用户输入直接拼接到SQL查询中",
      "suggestion": "使用参数化查询,如 db.execute('SELECT * FROM users WHERE id = ?', [req.query.id])",
      "line_numbers": [2, 3]
    }
  ],
  "summary": "发现严重的SQL注入安全风险,需要立即修复",
  "risk_level": "high"
}

少样本示例的数量有讲究。太少不足以展示模式,太多会占用宝贵的上下文窗口。通常3到5个精心挑选的例子效果最好。示例应该多样化,覆盖不同类型的输入和输出格式。

示例的质量比数量更重要。一个模糊的、有歧义的示例,会让AI学到错误模式。每个示例都要有明确的输入、输出和解释,让AI理解"为什么这样输出"。

## 思维链:让AI展示思考过程

思维链(Chain of Thought)是一种让AI在给出最终答案之前,先展示推理过程的技巧。这对于复杂任务特别有用,因为它让AI的决策过程变得透明,也更容易调试和优化。

在Skill设计中,思维链通常通过两种方式实现:显式要求AI列出思考步骤,或者在系统提示中嵌入"先分析,后回答"的指令。

```text
## 思考流程

在给出最终回答之前,请按以下步骤思考:

1. 理解需求:明确用户想要什么,是否有隐含要求
2. 分析输入:检查输入数据的完整性、格式和潜在问题
3. 制定方案:列出可行的处理方法,比较优缺点
4. 执行处理:按照选定方案处理数据
5. 验证结果:检查结果是否符合预期,是否有遗漏
6. 总结输出:用清晰的方式呈现最终结果

请在回复中先展示你的思考过程,用 ---THOUGHT--- 标记开始,
用 ---END THOUGHT--- 标记结束。然后用 ---OUTPUT--- 标记开始输出最终结果。

思维链的好处是显而易见的。首先,它迫使AI进行结构化思考,减少跳步和遗漏。其次,当AI输出错误结果时,可以通过查看思维链定位问题出在哪一步。最后,思维链的输出可以作为训练数据,用于进一步优化模型或Skill。

不过,思维链也有成本。它增加了输出长度,消耗更多Token,也延长了响应时间。对于简单任务,强制使用思维链反而是负担。好的Skill设计应该根据任务复杂度,动态决定是否启用思维链。

interface ThinkingModeConfig {
  enabled: boolean;
  complexityThreshold: number;  // 复杂度阈值,超过才启用
  maxThinkingSteps: number;
  requiredSteps: string[];
}

function shouldEnableThinking(
  task: Task,
  config: ThinkingModeConfig
): boolean {
  if (!config.enabled) return false;

  const complexity = estimateComplexity(task);
  return complexity >= config.complexityThreshold;
}

function estimateComplexity(task: Task): number {
  let score = 0;
  score += task.inputSize > 1000 ? 2 : 0;
  score += task.requiresReasoning ? 2 : 0;
  score += task.hasMultipleSteps ? 1 : 0;
  score += task.ambiguousRequirements ? 1 : 0;
  return score;
}

结构化输出:从自由文本到机器可读

让AI输出自由文本很容易,但让AI输出结构化的、可解析的数据很难。而Skill的执行结果往往需要被后续步骤消费,所以结构化输出是Skill设计的关键能力。

结构化输出有几种实现方式。最简单的是在Prompt里明确要求输出JSON格式,并给出Schema定义。这种方式对小模型效果不错,对大模型基本够用。

## 输出格式

你必须以JSON格式输出结果,严格遵循以下Schema:

{
  "type": "object",
  "properties": {
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": { "type": "string", "enum": ["critical", "high", "medium", "low"] },
          "category": { "type": "string", "enum": ["security", "performance", "correctness", "maintainability"] },
          "description": { "type": "string", "maxLength": 500 },
          "suggestion": { "type": "string", "maxLength": 500 },
          "line_numbers": { "type": "array", "items": { "type": "number" } }
        },
        "required": ["severity", "category", "description"]
      }
    },
    "summary": { "type": "string", "maxLength": 1000 },
    "risk_level": { "type": "string", "enum": ["high", "medium", "low"] }
  },
  "required": ["findings", "summary", "risk_level"]
}

注意:
- 不要输出JSON之外的任何内容
- 所有字符串必须使用双引号
- 数组可以为空,但字段不能省略
- line_numbers 必须是准确的整数

但这种方式有个问题:AI偶尔会输出一些JSON之外的内容,比如解释性文字、Markdown标记、或者格式不完整的JSON。为了解决这个问题,可以结合输出解析和修复策略。

interface StructuredOutputParser<T> {
  schema: JSONSchema;
  parse(raw: string): T;
  validate(data: unknown): ValidationResult;
}

class JSONOutputParser<T> implements StructuredOutputParser<T> {
  constructor(
    public schema: JSONSchema,
    private maxRepairAttempts: number = 3
  ) {}

  parse(raw: string): T {
    // 第一步:尝试直接解析
    try {
      const cleaned = this.extractJSON(raw);
      const parsed = JSON.parse(cleaned);
      const validation = this.validate(parsed);
      if (validation.valid) {
        return parsed as T;
      }
      // 验证失败,尝试修复
      return this.attemptRepair(parsed, validation.errors);
    } catch (error) {
      // 解析失败,尝试更激进的修复
      return this.attemptAggressiveRepair(raw);
    }
  }

  private extractJSON(raw: string): string {
    // 尝试提取 JSON 代码块
    const codeBlockMatch = raw.match(/```(?:json)?\s*([\s\S]*?)```/);
    if (codeBlockMatch) return codeBlockMatch[1].trim();

    // 尝试匹配最外层的大括号
    const jsonMatch = raw.match(/(\{[\s\S]*\})/);
    if (jsonMatch) return jsonMatch[1].trim();

    return raw.trim();
  }

  private attemptRepair(parsed: unknown, errors: ValidationError[]): T {
    // 根据验证错误尝试修复
    let repaired = parsed;
    for (const error of errors) {
      repaired = this.applyFix(repaired, error);
    }
    return repaired as T;
  }

  private attemptAggressiveRepair(raw: string): T {
    // 更激进的修复策略
    // 移除所有非JSON内容,补全缺失的括号等
    let cleaned = raw.replace(/^[^{]*/, "").replace(/[^}]*$/, "");
    return JSON.parse(cleaned) as T;
  }

  validate(data: unknown): ValidationResult {
    // 使用 JSON Schema 验证
    return validateAgainstSchema(data, this.schema);
  }

  private applyFix(data: unknown, error: ValidationError): unknown {
    // 根据错误类型应用修复
    return data;
  }
}

对于支持函数调用的模型,更好的方式是使用Function Calling或Tool Use API。这种方式下,模型直接输出结构化的函数调用参数,不需要从自由文本中解析JSON。准确率更高,格式更稳定。

A/B测试:用数据说话

Prompt工程最怕的就是”我觉得这个版本更好”。人的直觉在评估Prompt质量时很不靠谱。同一个Prompt,换一批测试用例,效果可能就完全不同。A/B测试是优化Prompt的唯一可靠方法。

在Skill设计中,A/B测试意味着维护多个Prompt版本,用相同的测试集评估它们的表现,然后用数据决定哪个版本更好。

interface PromptVariant {
  id: string;
  name: string;
  template: string;
  metadata: {
    createdAt: Date;
    hypothesis: string;  // 这个变体想验证什么假设
  };
}

interface TestCase {
  id: string;
  input: unknown;
  expectedOutput?: unknown;
  evaluationCriteria: EvaluationCriterion[];
}

interface EvaluationCriterion {
  name: string;
  weight: number;
  evaluate(actual: unknown, expected?: unknown): number;  // 返回0-1的分数
}

class PromptABTest {
  constructor(
    private variants: PromptVariant[],
    private testCases: TestCase[]
  ) {}

  async run(): Promise<TestResult> {
    const results: VariantResult[] = [];

    for (const variant of this.variants) {
      const caseResults: CaseResult[] = [];

      for (const testCase of this.testCases) {
        // 渲染Prompt
        const prompt = this.renderVariant(variant, testCase.input);

        // 调用模型
        const response = await this.callModel(prompt);

        // 评估结果
        const scores = testCase.evaluationCriteria.map(criterion => ({
          criterion: criterion.name,
          score: criterion.evaluate(response, testCase.expectedOutput),
          weight: criterion.weight
        }));

        const weightedScore = scores.reduce(
          (sum, s) => sum + s.score * s.weight,
          0
        ) / scores.reduce((sum, s) => sum + s.weight, 0);

        caseResults.push({
          testCaseId: testCase.id,
          scores,
          weightedScore,
          response
        });
      }

      const averageScore = caseResults.reduce(
        (sum, r) => sum + r.weightedScore,
        0
      ) / caseResults.length;

      results.push({
        variantId: variant.id,
        variantName: variant.name,
        averageScore,
        caseResults
      });
    }

    // 按平均分排序
    results.sort((a, b) => b.averageScore - a.averageScore);

    return {
      variants: results,
      winner: results[0],
      timestamp: new Date()
    };
  }

  private renderVariant(variant: PromptVariant, input: unknown): string {
    // 使用模板引擎渲染
    return templateEngine.render(variant.template, { input });
  }

  private async callModel(prompt: string): Promise<unknown> {
    // 调用底层模型API
    return modelClient.complete(prompt);
  }
}

测试用例的设计是A/B测试成败的关键。测试集要覆盖Skill的主要使用场景,要包含边界情况,要有明确的成功标准。评估标准可以是客观的(比如输出是否合法JSON、字段是否完整),也可以是主观的(比如由人工或更强的模型打分)。

A/B测试不是一次性的。Skill上线后,要持续收集真实使用数据,定期跑回归测试。当发现新的失败模式时,要把对应的用例加入测试集,防止 regression。

实际案例:智能客服Skill的Prompt工程

让我们通过一个实际案例,看看上述技术如何综合运用。假设我们要为一个电商网站设计一个智能客服Skill,它需要理解用户问题,查询订单状态,处理退换货请求,并在必要时转接人工。

首先,设计Prompt模板:

system:
  role: "你是一位专业的电商客服助手"
  expertise: ["订单查询", "退换货政策", "物流跟踪", "产品咨询"]
  style: "友好、专业、高效"
  constraints:
    - "不要编造订单信息"
    - "不确定时主动询问用户"
    - "退换货必须符合平台政策"
    - "涉及敏感操作时需验证用户身份"

task:
  description: "处理用户的客服请求"
  
input:
  user_message: "用户输入的消息"
  conversation_history: "最近5轮对话记录"
  user_context:
    user_id: "用户ID"
    vip_level: "会员等级"
    recent_orders: "最近3个订单摘要"

available_tools:
  - name: "query_order"
    description: "查询订单详情"
  - name: "request_refund"
    description: "发起退款申请"
  - name: "check_inventory"
    description: "查询商品库存"
  - name: "transfer_to_human"
    description: "转接人工客服"

output:
  format: "JSON"
  schema:
    type: "object"
    properties:
      response_type:
        type: "string"
        enum: ["answer", "tool_call", "clarification", "escalation"]
      message: { type: "string" }
      tool_call: { type: "object" }
      confidence: { type: "number" }

然后,注入变量时组装上下文:

function assembleCustomerServiceContext(
  userMessage: string,
  history: Message[],
  userProfile: UserProfile
): string {
  const parts: string[] = [];

  // 任务指令
  parts.push(`用户消息:${userMessage}`);

  // 用户上下文
  parts.push(`用户ID:${userProfile.userId}`);
  parts.push(`会员等级:${userProfile.vipLevel}`);
  parts.push(`最近订单:\n${formatOrders(userProfile.recentOrders)}`);

  // 相关历史(只保留最近的3轮)
  const relevantHistory = history.slice(-3);
  if (relevantHistory.length > 0) {
    parts.push(`对话历史:\n${formatHistory(relevantHistory)}`);
  }

  // 可用工具
  parts.push(`可用工具:\n- query_order: 查询订单详情\n- request_refund: 发起退款\n- check_inventory: 查询库存\n- transfer_to_human: 转人工`);

  return parts.join("\n\n");
}

少样本示例教AI处理不同场景:

## 示例

示例1:查询订单
输入:我的订单怎么还没送到?
输出:
```json
{
  "response_type": "tool_call",
  "message": "我来帮您查询一下订单状态",
  "tool_call": {
    "name": "query_order",
    "parameters": { "user_id": "{{user_id}}", "recent": true }
  },
  "confidence": 0.95
}

示例2:请求退款(符合条件) 输入:这个手机我想退货 输出:

{
  "response_type": "tool_call",
  "message": "好的,我帮您发起退款申请。请确认是最近购买的iPhone 15 Pro吗?",
  "tool_call": {
    "name": "request_refund",
    "parameters": { "order_id": "最近的iPhone订单ID", "reason": "用户主动退货" }
  },
  "confidence": 0.88
}

示例3:模糊请求 输入:这东西有问题 输出:

{
  "response_type": "clarification",
  "message": "抱歉,请问您是指哪个订单的商品呢?另外具体遇到了什么问题?",
  "confidence": 0.6
}

这个案例展示了Prompt工程的完整流程:模板定义结构,变量注入动态数据,上下文组装控制信息量,少样本学习提供行为模式,结构化输出确保结果可用。通过A/B测试,我们可以不断优化模板和示例,提升Skill的准确率和用户体验。

## 总结与最佳实践

Prompt工程在Skill设计中的应用,本质上是把"如何与AI沟通"的经验沉淀为可复用的资产。以下是一些关键的最佳实践:

**模板优先,手写为辅**。所有Skill的Prompt都应该基于模板。模板不仅提高一致性,还能支持版本管理、A/B测试和动态注入。

**变量类型安全**。定义每个变量的类型、来源和约束,在注入前做验证和转换。不要让原始用户输入直接进Prompt。

**上下文分层**。按重要性组织上下文信息,最重要的放最前面。定期清理过期信息,避免上下文窗口被垃圾填满。

**示例要精选**。少样本示例贵精不贵多。每个示例都要展示一个有价值的模式,覆盖不同的场景和边界情况。

**思维链按需启用**。复杂任务强制思维链,简单任务跳过。思维链的输出要可解析,方便后续步骤消费或人工审查。

**结构化输出是底线**。Skill的输出必须结构化。如果模型不支持Function Calling,就用Prompt约束加解析修复的组合方案。

**A/B测试持续优化**。建立测试用例集,定期跑回归测试。用数据驱动Prompt优化,而不是凭感觉改动。

**监控真实表现**。上线后要跟踪Skill的成功率、错误类型和用户反馈。把真实失败案例加入测试集,形成优化闭环。

把这些原则贯彻到Skill设计中,Prompt工程就从一门"玄学"变成了一门"工程"。Skill的输出会更稳定、更可预测、更容易维护,Agent的能力边界也会随之大大扩展。