返回博客

批量派发 AI agent 时,成功返回的 skill 文件竟是空壳

在做一次大规模的知识沉淀作业时,我同时派发了 12 个并行 agent,每个负责把一条候选 skill 写进知识库。11 个正常完成,1 个返回的文件看起来完全正常——文件存在,注册成功,名称也对——只是打开来,里面全是 [TODO: ...] 占位符,以及模板里原本应该被删掉的"Structuring This Skill"脚手架章节。

Agent 汇报的是"success"。错误发生在我没有检查的地方。

现象

批量创建完成后扫一眼 skill 列表,其中一条的 description 字段显示为:

Async Task Trigger Optimistic Ui

这正是 skill 名称的 Title Case,没有任何动词短语。正常的 description 应该是:

Fix X when Y. Use when: (1)..., (2)...

打开文件验证:

---
name: async-task-trigger-optimistic-ui
description: [TODO: Complete and informative explanation of what the skill does...]
---
 
# Async Task Trigger Optimistic Ui
 
## Overview
[TODO: 1-2 sentences explaining what this skill enables]
 
## Structuring This Skill
[TODO: Choose the structure that best fits this skill's purpose...]

文件大小 2KB,内容全是模板脚手架。

根因

skill-creator 工具本身工作正常——它加载了一个带有详细填写说明的模板,模板里明确写着"填完后删除 Structuring This Skill 章节"。问题出在 agent 的模板解读上:它把"加载模板 + 工具执行成功"等价于"任务完成",在没有实际填入内容的情况下就提交了文件。

这是 AI agent 常见的乐观成功判断陷阱——工具调用没有抛错,就认为结果可用。但"文件已写入"与"文件内容有效"是两件不同的事。

坑:agent 说成功,内容是模板占位符

并行 agent 无法互相校验输出。如果 agent 把"工具调用不报错"当作"任务完成",空壳文件可以无声地通过 file-exists 检查并进入注册表——而调用方若不主动核查内容,这个质量问题可以一直潜伏到真正使用时才暴露。

正解

检测:两条命令扫全量

# 检测 description 是 skill 名称 Title Case 的(弱描述)
cd ~/.claude/skills
for d in */; do
  name="${d%/}"
  desc=$(awk '/^description:/{sub(/^description: */,""); print; exit}' "$d/SKILL.md" 2>/dev/null)
  title_case=$(echo "$name" | sed 's/-/ /g' | \
    awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))} 1')
  if [ "$desc" = "$title_case" ]; then
    echo "WEAK: $name"
  fi
done
 
# 检测 TODO 占位符 / 模板脚手架
grep -rn "\[TODO:" ~/.claude/skills/*/SKILL.md
grep -rln "Structuring This Skill" ~/.claude/skills/*/SKILL.md

命中任何一条就需要重做。

修复:重做时绕过 skill-creator 工具

Re-do task — 上一个 agent 在 ~/.claude/skills/<name>/SKILL.md
创建了仅含模板的空壳文件。你的任务是用 Write 工具覆盖它,写入真实内容。

**关键约束**:
- 不要再调用 Skill(skill-creator),如果它产出 TODO,你无法填;
  改为先 Read 一个已完成的同类 skill 文件,模仿其结构。
- 用 Write 工具一次性创建最终文件,不要用 Edit 修改模板。
- description 必须以动词短语开头("Fix..."/"Prevent..."/"Detect..."),
  不是 Title Case 的 skill 名称。
- 禁止出现任何 [TODO: ...] 占位符。
- 返回:文件路径 + 行数 + 前 10 行(供调用方即时核验)。

返回前 10 行 这一步是核心——它强迫 agent 在汇报成功前看一眼自己写了什么,把"我以为写完了"转换为"我确认写了有效内容"。

预防:初始派发时就硬约束

在每一个 skill-creator 派发 prompt 的末尾加上:

Hard constraints:
- NO TODO placeholders
- NO "Structuring This Skill" section
- Use Write tool to produce final file in one shot
- description starts with verb phrase, NOT title-cased skill name
- Return: path + line count + first 10 lines for verification

实测:修复成功率一次即中;如果两次补做仍失败,说明这条候选 skill 的素材本身太模糊,不适合强行沉淀。

正解:让 agent 回传前 10 行作为验收证据

"返回文件前 10 行"是最轻量的输出质检门禁——成本几乎为零,但能在 agent 汇报成功的当场暴露空壳文件,而不是等到真正调用时才发现。

一句话外卖

AI agent 报告"工具调用成功"不等于"输出内容有效"——并行任务结束后,对所有输出做一次最小语义校验(哪怕只是 grep 一个 TODO),是防止静默空壳文件积压的最低成本质检门禁。