mcpField
W
working-with-skills

working-with-skills

github.com/posthogAgent 工作流76356 次安装今天更新
代码仓库

关于 working-with-skills

这是一个 PostHog 技能,指导 Agent 高效选择和使用 `skill-*` MCP 工具,涵盖技能发现、按需读取、编写、更新及版本安全流程。

主要功能

  1. 01渐进式读取技能内容
  2. 02指导选择合适的技能工具
  3. 03定向编辑正文与文件
  4. 04基于版本的更新流程
  5. 05大型技能的组织建议

适用场景

  1. 01先查找适用技能再读取正文
  2. 02仅查看任务所需的文件
  3. 03创建或修改技能
  4. 04避免替换整个文件包来更新技能

MCP 相关

该技能说明 Agent 如何使用 PostHog 的 `skill-*` MCP 工具来发现、查看、创建和更新技能。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/skills --skill working-with-skills

安装后在 Claude Code 中输入/working-with-skills确认已加载。

附带文件references/skill-patterns.md

详细介绍

使用 PostHog 技能

此技能将教 Agent 如何高效使用 skill-* MCP 工具——尽可能减少上下文、往返次数和错误。如果你还不熟悉这些工具本身,请先阅读 skills-store 技能,了解目录。本文介绍的是_如何在工具之间做出选择_,以及当技能变得庞大时_如何扩展工作流_。

操作原则

  1. 渐进式披露不可妥协。 列表工具返回描述,get 工具返回正文和清单,file-get 工具返回单个文件。切勿“以防万一”而预加载捆绑文件——对于实际任务而言,每个预加载的脚本都是浪费的上下文。
  2. 选择能完成任务的最小写入操作。 与完整替换正文或整个文件包相比,针对性的 edits 或 file_edits 更省资源、更安全,也能让版本历史更清晰。
  3. 读取成本低,并发覆盖则不然。 调用任何写入工具前,务必先从 skill-get(或上一次写入的响应)获取最新的 version,并将其作为 base_version 传入。
  4. 创作时遵循 Agent Skills 规范。 name 使用 kebab-case,描述中包含丰富的触发词,正文保持简短,冗长内容放在捆绑文件中。

决策树:我应该调用哪个工具?

Need to know what's available?
  └─► skill-list                    (names + descriptions only)

Need to use / inspect a specific skill?
  └─► skill-get                     (body + file manifest, NO file contents)
        └─► skill-file-get          (one file, on demand, only as referenced)

Authoring a brand new skill?
  └─► skill-create                  (body + all initial files in one call)

Editing an existing skill?
  ├─ Body change?
  │    ├─ Substantial rewrite ............. update(body=...)
  │    └─ Surgical tweak .................. update(edits=[{old, new}, ...])
  ├─ Bundled file content change?
  │    └─ update(file_edits=[{path, edits:[...]}, ...])
  ├─ Add / remove / rename a file?
  │    ├─ Add ............................. skill-file-create
  │    ├─ Delete .......................... skill-file-delete
  │    └─ Rename .......................... skill-file-rename
  └─ Wholesale bundle reset (rare!) ....... update(files=[...])  # replaces ALL files

Renaming the skill itself?
  └─► skill-rename                  (keeps versions, files, and owners)

Want a fork as the starting point?
  └─► skill-duplicate               (then update the copy)

Done with a skill entirely?
  └─► skill-archive                 (hides ALL versions; cannot be undone)

如果你发现自己要使用 update(body=...),再附上冗长的 files=[...],只为修改一个段落和一个脚本,请停下来——这应该拆成两个更精简的调用(update(edits=[...]) 加 update(file_edits=[...])),或者甚至只需一次同时包含 edits 和 file_edits 的 update 调用。

获取内容前先查找

posthog:skill-list
{ "search": "fractal" }

要“查找某项技能”,正确的工具是 skill-list——它只返回名称和描述。阅读描述正是整个流程的重点:先选出合适的技能,再获取正文。如果 search 无法充分缩小范围,就不带它列出结果并逐项浏览,但不要盲目开始获取候选技能的正文。

每项技能在每个任务中只应调用一次 skill-get,而不是每个问题调用一次。将正文缓存在工作记忆中;只有在怀疑技能内容已发生变化时才重新获取(例如写入时遇到 409——见下文“并发控制”)。

高效阅读大型技能

对于正文较长、捆绑文件较多的大型技能,延迟加载尤为重要。

  1. skill-get(skill_name=...)——读取 body 和 files[] 清单。
  2. 浏览正文中的目录/标题。正文应已说明哪些文件对应哪些任务——这正是正文要保持简短并按路径引用文件的原因。
  3. 对于正文明确指出与_当前任务_相关的每个文件,调用 skill-file-get(file_path=...)。跳过其他所有文件。
  4. 如果正文提到“少见情况 Y 请参阅 scripts/X”,而你当前并非遇到情况 Y,就不要获取 scripts/X。

拿不准时,少获取文件。你随时可以在下一轮再多获取一个。

创作新技能

使用一次 skill-create 调用,同时提供正文和初始文件——这样技能创建完成后就是 version: 1。不要先创建空技能,再调用 N 次 skill-file-create;那会徒增 N 个版本和 N 次往返,没有任何好处。

posthog:skill-create
{
  "name": "my-skill",
  "description": "What it does AND when to use it. Include trigger keywords.",
  "body": "# my-skill\n\n## When to use\n...\n## Workflow\n...",
  "license": "MIT",
  "compatibility": "Requires Python 3.10+",
  "allowed_tools": ["Bash", "Write"],
  "metadata": { "author": "me", "category": "..." },
  "files": [
    { "path": "scripts/foo.py", "content": "...", "content_type": "text/x-python" },
    { "path": "references/primer.md", "content": "...", "content_type": "text/markdown" }
  ]
}
编写规则参考
  • description 是发现入口。 这是 skill-list 返回的唯一内容。应使其包含丰富的触发条件(用户可能会怎么说),并准确说明范围(该技能能做什么、不能做什么)。
  • name — 使用 kebab-case,最多 64 个字符,不得以连字符开头或结尾,也不得连续使用连字符。规范验证器会拒绝其他格式。
  • 正文不超过约 500 行。 冗长的前言、详尽的 SQL、完整的示例负载和可运行代码应放在 references/、assets/ 或 scripts/ 中。正文应引导读者查看这些文件,而不是将内容直接写在正文中。
  • 文件布局约定 — scripts/ 用于可执行代码,references/ 用于说明文档和示例,assets/ 用于模板/数据。当 Agent 只有清单时,也可以依靠这一约定了解文件用途。
  • allowed_tools 列出该技能请求使用的工具。 这只是请求,而非授权:从文件读取技能的执行框架会将列表视为已预先批准;通过 MCP 加载技能的执行框架则会忽略该列表,直到用户批准授权。 只列出该技能实际使用的工具,因为填充无关工具会扩大请求范围。 未声明的工具不会被预先批准,接下来如何处理由执行框架决定:它可以询问用户、拒绝调用,或根本不提供该工具。 有些产品会自行强制执行此列表,因此在这些产品中,遗漏工具会导致调用失败。
  • 存在相关技能时,以 ## Related skills 作为结尾部分:列出简短的项目符号列表,每项为 `skill-name`,并用一句话说明何时应转而使用该技能,以便调用一个技能时也能发现后续技能。 只用名称引用技能(不含路径——相关技能通常位于其他产品中),并且只列出真正的后续步骤,不要罗列产品中的所有技能。

更新现有技能

最常见的错误是小改动时使用 update(body=..., files=[...])。这样虽然可行,但会将整个技能来回传输,导致版本历史中的差异难以阅读,并且如果 files 不完整,还可能丢失文件。应改用更小粒度的操作。

始终先读取,并记录 version
posthog:skill-get
{ "skill_name": "my-skill" }

记下返回的 version——每次写入时都将其作为 base_version 传入。成功写入后,响应中会包含新的 version;后续写入时应使用该版本。

正文:完整替换与增量编辑

重构正文时,使用完整替换:

posthog:skill-update
{ "skill_name": "my-skill", "body": "# my-skill\n\nNew body...", "base_version": 7 }

调整少数几行时,使用增量编辑(小改动时优先采用——更易审查,出错面更小):

posthog:skill-update
{
  "skill_name": "my-skill",
  "edits": [
    { "old": "Use Pillow for rendering.", "new": "Use Pillow ≥10.0 for rendering." },
    { "old": "## Old section title", "new": "## New section title" }
  ],
  "base_version": 7
}

每个 edits[].old 在当前正文中都必须恰好匹配一次,并且一次调用中 body 和 edits 不能同时使用。

捆绑文件内容编辑

file_edits 可原位修补一个或多个现有文件——未指定的文件会保持不变。调整脚本逻辑或修正文档中的错别字时,应使用此操作:

posthog:skill-update
{
  "skill_name": "my-skill",
  "file_edits": [
    {
      "path": "scripts/foo.py",
      "edits": [{ "old": "ITERATIONS = 100", "new": "ITERATIONS = 250" }]
    },
    {
      "path": "references/primer.md",
      "edits": [{ "old": "## Outdated header", "new": "## Updated header" }]
    }
  ],
  "base_version": 7
}

file_edits 不能添加、删除或重命名文件——只能修补现有文件。结构性更改请使用逐文件工具。

在一次调用中组合编辑

如果更改同时涉及正文和现有文件,可以在一次 skill-update 调用中组合使用 edits(正文)和 file_edits(现有文件),一次发布完整一致的版本:

posthog:skill-update
{
  "skill_name": "my-skill",
  "edits": [{ "old": "## Configuration", "new": "## Setup" }],
  "file_edits": [
    { "path": "scripts/run.py", "edits": [{ "old": "DEBUG = False", "new": "DEBUG = True" }] }
  ],
  "base_version": 7
}
文件路径参数命名(猜测前请先阅读)

同一个概念——捆绑文件的路径——会根据它在请求中的传递位置而采用不同的名称,这常常会让凭记忆操作的 Agent 混淆。规则只有一条:

  • file_path——当路径是 URL 的一部分时(skill-file-get、skill-file-delete)。这些工具会通过路径指定并读取/删除一个文件。两者也接受 path,并会将其规范化为 file_path,因此清单中的键也能正常使用。
  • path——当路径是请求正文中的字段时:skill-file-create、files=[{path, content, content_type}] 数组,以及 file_edits=[{path, edits}]。
  • old_path / new_path——skill-file-rename 中的请求正文字段。

记忆方法:path 是文件 对象 中的字段名(它与 content 并列),因此所有携带文件对象的工具都使用 path;通过 URL 指定文件的两个工具则使用 file_path。不确定时,请检查工具的输入架构,不要猜测。

添加、删除、重命名文件

每项操作都是一次独立调用,每次都会发布一个新版本:

posthog:skill-file-create
{ "skill_name": "my-skill", "path": "scripts/julia.py", "content": "...", "base_version": 7 }
posthog:skill-file-delete
{ "skill_name": "my-skill", "file_path": "scripts/old.py", "base_version": 8 }
posthog:skill-file-rename
{ "skill_name": "my-skill", "old_path": "scripts/julia.py", "new_path": "scripts/julia_set.py", "base_version": 9 }

skill-file-rename 是真正的移动操作——它会保留现有内容,无需重新发送。内容未更改时,始终优先使用它,而不是先删除再创建。

何时使用 update(files=[...])(很少)

将 files 传给 skill-update 会替换整个捆绑包——不在数组中的内容都会被移除。只有在你有意清空并重新填充捆绑包时(例如导入新的本地 SKILL.md 文件树),才适合使用此工具。几乎所有其他情况下,都应优先使用 file_edits 和逐文件 CRUD。

处理包含多个文件的大型技能

包含许多文件(10 个以上)的技能需要格外谨慎:

  • 将清单视为索引。 skill-get 的 files[] 是你的文件映射。将每个任务步骤对应到一个文件,并且只获取该文件。
  • 将结构性变更按顺序串联,而不是分叉。 如果要重命名三个文件,请依次执行:rename → rename → rename,每次都通过上一次响应中的 version 串联。这样会产生三个易于审阅的小版本,而不是一个庞大的 update(files=[...]) 数据块。
  • 让编辑保持局部。 使用 file_edits 针对五个文件执行一次 skill-update 没问题。一次 update(files=[...]) 携带十个完整文件正文,几乎总是说明你本该使用 file_edits。
  • 先重构正文内容本身。 如果正文已经超过约 500 行,下一步通常应该是将内容拆分到新的捆绑文件中,再添加更多材料。

并发:base_version

每个写入工具都接受 base_version。请始终传入它。

  • 服务端会将 base_version 与当前最新版本进行比较。如果匹配,写入成功,新版本为 base_version + 1。
  • 如果不匹配,写入将被拒绝(其他人已更新该技能)。请重新运行 skill-get,根据新正文协调你的更改,并使用最新的 version 重试。
  • 写入成功后,响应会包含新的 version。后续编辑请使用该版本串联——对于你控制的连续写入,不要在两次写入之间重新执行 get。

省略 base_version 并不会让操作变快——这只会把明确的“其他人抢先更新”错误,变成对其工作的静默覆盖。

常见陷阱

  • 不带搜索条件调用 skill-list,然后获取每个正文 — 这会破坏渐进式披露。先阅读描述。
  • 调用 skill-get 后预先获取每个捆绑文件 — 这是内层的同类错误。根据正文中的指示按需获取。
  • 用 update(body=..., files=[...]) 修复一行内容 — 这会往返传输整个技能,使差异难以阅读,还可能导致文件丢失。请使用 edits / file_edits。
  • 想添加一个文件,却使用 update(files=[...]) — 任何未包含的文件都会丢失。请改用 skill-file-create。
  • 删除后再创建,而不是重命名 — 会丢失内容历史记录,还会多消耗一次版本递增。
  • 链式写入后使用过时的 base_version — 使用上一次写入响应中的 version,而不是最初调用 get 时的版本。
  • 省略 base_version — 会接受静默覆盖。调用过 get 后,务必始终包含它。
  • description 为空或含糊 — 通过 skill-list 搜索几乎无法发现该技能。应将描述视为触发契约。
  • 正文很长,却没有捆绑文件 — 当正文超过约 500 行时,应重构并将内容移入 references/ 和 scripts/,而不是任其增长。
  • 在同一次更新调用中混用 body 和 edits — 两者不能同时使用。选其一即可。
  • 猜测应使用 path 还是 file_path — file-get 和 file-delete 使用 file_path (它位于 URL 中);create、rename(old_path/new_path)、files 和 file_edits 使用 path(它是请求正文中的字段)。请参阅上文的“文件路径参数命名”。

归档技能

skill-archive 会按名称隐藏某个技能的所有活动版本。它不针对特定版本,且无法撤销 — 整个团队都会在 skill-list 和 skill-get 中看不到该技能。

posthog:skill-archive
{ "skill_name": "my-skill" }

归档前,如果需要先检查或复制技能,请调用 skill-get。如果要彻底弃用某个技能,归档是合适的工具;要移除单个捆绑文件,请使用 skill-file-delete;要回滚内容,则应发布新版本,而不是归档。

将本地 SKILL.md 目录树迁移到 PostHog

迁移本地技能文件夹时(例如 my-skill/SKILL.md,以及 scripts/、references/、assets/):

  1. 阅读本地 SKILL.md。其中的 frontmatter 对应 name、description、 license、compatibility、allowed_tools、metadata。frontmatter 之后的正文会成为 body。
  2. 遍历捆绑的子目录,收集所有文件,并整理为 { path, content, content_type }。
  3. 调用一次 posthog:skill-create 并传入所有内容 — 技能会以完整的 version: 1 创建。不要将此操作拆分为一次 create 调用和 N 次 file-create 调用。

创建后,所有人都可以通过 skill-get 使用该技能。

模式:技能适用于哪些用途

技能库中的技能是一种共享的版本化记忆,有写入权限的 Agent 可以更新它。 因此,它的用途远不止提供说明:它可以是 Agent 跨会话维护的项目中心、团队负责的 PostHog 对象目录、随着每次调查不断扩充的运行手册、每日“哪些事情需要我处理”队列,或是队友的 Agent 可以直接加载的交接内容。

references/skill-patterns.md 是一份包含这些模式的实用指南,为每种模式提供文件布局、维护约定和起点。 当用户询问技能适用于哪些用途时,或在创建需要由 Agent 长期维护的技能之前,请阅读此文档。

何时不该使用技能

并非所有持久化提示词都适合放在技能库中:

  • 一次性任务说明应放在对话中,而不是技能里。
  • 个人临时记录应放在 Agent 记忆或本地文件中。
  • 代码不是技能 — 如果某项内容需要由服务运行,就应放在代码库中。

好的技能应可复用、能通过描述发现,并且值得长期投入精力以确保内容准确。

评论

支持 Markdown