编写 agent skill
抱歉,我需要您提供要翻译的具体文本内容(除保留的 Source 链接外)。请把文章的正文粘贴在这里,我就可以为您完成简体中文翻译。
DRY 原则
DRY(Don’t Repeat Yourself)原则已经存在很久了。
如果你在多个地方复制粘贴代码,而出现了 bug,你必须在所有地方都修复它。重复越多,修复时遗漏的可能性就越大。
编码助手中的 DRY
在使用编码助手时,DRY 的含义有所不同:
- 你不需要在每次会话中都让助手分析你的项目。
- 你不必每次都重复你的语言的编码约定。
- 你不需要提醒助手你的项目倾向于不可变性。
当新开发者加入一个优秀的项目时,他们会被告知项目的特性、架构和约定。在优秀的项目中,这些约定会 以书面形式正式化,并且有时会保持最新。你的编码助手就像其他团队成员一样:它需要书面文档。
我使用的两款编码助手都支持使用此类指令(我假设所有助手都支持)。例如,GitHub Copilot 会自动读取 .github/instructions.md 文件。
保持指令文件小巧
如果助手自动读取指令且范围过于宽泛,就会用无关数据污染上下文。
结论: 保持文件相对较小,并专注于 通用 信息。
大小建议
| Source | Recommendation |
|---|---|
docs.factory.ai | 700 行太长 |
我的建议:从小开始,必要时逐步增加,分析结果,并在文件变得过大时进行重构。
令牌才是真正的资源
如今,关键资源不再是 CPU、RAM 或存储,而是 令牌。令牌是有限且昂贵的。我预测开发者很快将以令牌使用量来衡量:使用最少令牌而实现相似结果的开发者将被视为更优秀。
大多数代理加载默认指令文件:
- GitHub Copilot →
AGENTS.md - Claude →
CLAUDE.md
文件越小,在上下文中消耗的令牌就越少。
一个好的上下文应包含 所有必要的令牌,但不多余——这正是 技能 发挥作用的地方。
Source:
代理技能
代理技能 是一组指令、脚本和资源的文件夹,代理可以发现并使用它们,以更准确、更高效地工作。
技能不同于 AGENTS.md,因为它们不会自动加载,从而不会占用上下文空间。根据编码助手的不同,技能可能会被自动发现并加载,也可能不会。
调用技能
- 默认情况下,你和 Claude 都可以调用任何技能。
- 输入
/skill-name可直接调用。 - 当 Claude 认为技能与对话相关时,它可以自动加载该技能。
Claude 如何判断何时调用技能
Claude 会将每个 SKILL.md 文件的 front‑matter 转换为工具定义。下面是我创建的 Kotlin 技能的 front‑matter:
---
name: kotlin
description: |
Use this skill when working with Kotlin code in any capacity:
- Reading, writing, editing, or reviewing Kotlin files (*.kt, *.kts)
- Running Gradle tasks for Kotlin modules
- Writing or debugging Kotlin/JS code that targets Node.js
- Working with external JavaScript libraries from Kotlin
- Writing tests for Kotlin code (@Test, @BeforeTest, @AfterTest)
- Setting up dependency injection or mocking in Kotlin
- Dealing with multiplatform Kotlin projects (common, jsMain, jsTest, jvmMain)
- Troubleshooting Kotlin compilation or runtime errors
- Any task involving Kotlin/JS modules targeting Node.js
This skill provides Kotlin/JS technical knowledge (especially JS interop gotchas)
and coding‑style preferences beyond the official conventions.
---
上述内容为 Claude 提供了决定何时加载该工具所需的信息。显然,这个技能是关于 Kotlin 和 Kotlin/JS 的。
技能内容
遵循与普通 AGENTS.md 文件相同的规则:
- 你可以引用位于技能文件夹本地或在线可访问的其他文档(文本或其他形式)。
- 我已将完整的 Kotlin 编码规范复制到一个专门的文件中。
SKILL.md概述了主要条目并链接到这些规范。 - 完整的规范已在此技能目录下的
kotlin-coding-conventions.md中本地缓存。
关键提醒(Kotlin)
- 首选
val而非var—— 优先考虑不可变性 - 使用不可变的集合接口(
List、Set、Map,而不是MutableList等) - 对简短的 lambda 使用
it;对嵌套或复杂的 lambda 使用具名参数 - 优先使用表达式形式的
if、when、try,而非语句形式 - 优先使用函数式风格(
filter、map)而非命令式循环
1. External Interfaces vs. Kotlin Classes
问题: Kotlin 类的方法位于其原型上。外部接口期望方法直接挂在对象上。不能使用 unsafeCast 在两者之间进行转换。
// ❌ WRONG: This will fail at runtime
class MockSql {
fun unsafe(query: String) = /* … */
}
val sql: Sql = mockSql.unsafeCast() // Throws: sql.unsafe is not a function
// ✅ CORRECT: Use an extension function to build a plain JS object
fun MockSql.toExternal(): Sql {
val obj = Any().asDynamic()
val mock = this
obj.unsafe = { query: String -> mock.unsafe(query) }
obj.end = { mock.end() }
return obj.unsafeCast()
}
// Then use it:
val sql: Sql = mockSql.toExternal()
✅ 正确:使用扩展函数来构建普通的 JS 对象
然后使用它:
val sql: Sql = mockSql.toExternal()
Bottom line
技能对于避免一次又一次重复相同指令非常有用。技能 与 指令 的主要区别在于,当不需要时,技能 不会膨胀上下文。明智地使用它们,保持指令文件小巧,并观察你的 token 使用量下降。
进一步了解
代理技能
- 为 Claude 添加技能
- 方法论开发技能
- 超赞技能
最初发表于 A Java Geek,2026年3月15日。