Skip to main content
ClaudeWave
Skill1.3k estrellas del repoactualizado today

zh

This Claude Code skill implements a three-tier information architecture for efficiently managing reusable agent tasks in the trpc-agent-go framework. Use it when building AI agents that need to dynamically load task documentation and scripts on demand, selectively inject content into prompts based on actual requirements, and execute scripts in isolated workspaces while minimizing token consumption and context overhead.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/trpc-group/trpc-agent-go /tmp/zh && cp -r /tmp/zh/docs/mkdocs/zh ~/.claude/skills/zh
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

skill.md

# Skill

Agent Skills 把可复用的任务封装为“技能目录”,用 `SKILL.md`
描述目标与流程,并配套脚本与文档。在对话中,Agent 只注入
“低成本的概览”,在确有需要时再按需载入正文与文档,并在
隔离工作区中安全执行脚本,从而降低上下文占用与泄漏风险。

参考背景:
- Anthropic 工程博客:
  https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- 开源 Skills 示例库(结构与约定可借鉴):
  https://github.com/anthropics/skills

## 概览

### 🎯 能力一览

- 🔎 自动注入技能“概览”(名称与描述),引导模型选择
- 📥 `skill_load` 按需注入 `SKILL.md` 正文与选定文档
- 📚 `skill_select_docs` 增/改/清除文档选择
- 🧾 `skill_list_docs` 列出可用文档
- 🧪 执行路径:`skill_load` 会在 `/skills/<name>/` 下物化出可写的
  技能工作副本,脚本通过 `workspace_exec` 执行(只要配置了 code
  executor 即可)
- 🗂️ 按通配符收集输出文件并回传内容与 MIME 类型
- 🧩 可选择本地或容器工作区执行器(默认本地)

### 核心概念:三层信息模型

1) 初始“概览”层(极低成本)
   - 仅注入 `SKILL.md` 的 `name` 与 `description` 到系统消息。
   - 让模型知道“有哪些技能、各做什么”,但不占用正文篇幅。

2) 正文层(按需注入)
   - 当任务确实需要某技能时,模型调用 `skill_load`,框架把该
     技能的 `SKILL.md` 正文物化到下一次模型请求中(详见下文
     Prompt Cache 小节)。

3) 文档/脚本层(精确选择 + 隔离执行)
   - 关联文档按需选择(通过 `skill_load` 或 `skill_select_docs`),
     仅把文本内容物化到提示词;脚本不会被内联,而是在工作区中
     执行,并回传结果与输出文件。

### Token 成本

如果把一个技能仓库的全部内容(所有 `SKILL.md` 正文与 docs)
一股脑塞进提示词,往往会让 prompt token 占用变得非常高,甚至
直接超过模型上下文窗口。

想要**可复现、基于真实运行**的 token 对比(渐进披露 vs 全量注入),
可参考 [trpc-agent-go-benchmark/anthropic_skills/README.md](https://github.com/trpc-group/trpc-agent-go-benchmark/blob/main/anthropic_skills/README.md),并按其中说明运行
`token-report` 套件。

### Prompt Cache

一些模型服务支持 **prompt cache**:如果后续一次模型请求的开头
(token 前缀)与之前某次请求完全一致,服务端可以复用这段共同
前缀,从而减少计算,并降低延迟和/或输入 token 成本(取决于服务商)。

对于 Skills,“已加载的 `SKILL.md` / docs”落在消息序列的哪里,会影响
连续模型调用之间可复用的前缀长度:

- 旧行为(默认):把已加载内容追加到 **system message**。
  - 这会在 user/history 之前插入新 token,导致连续模型调用的共同前缀
    变短。
- Tool-result 物化(可选):把已加载内容追加到对应的 **tool result**
  消息(`skill_load` / `skill_select_docs`)。
  - system message 更稳定,早期消息更不容易“后移”,prompt cache 往往能
    命中更多前缀 token。

回退机制:如果对应的 tool result 消息不在本次请求的 history 里
(例如启用了 history suppression),框架可以回退为插入一条专用的
system message,确保模型仍能看到已加载内容。

Session summary 提醒:如果你启用了会话摘要注入
(`WithAddSessionSummary(true)`),并且本次请求里确实插入了摘要,
框架会尽量**跳过**这条回退 system message,避免把“已被 summary 掉的
内容”又塞回提示词里。如果对应的 tool result 仍在提示词里,回退会继续
保持关闭;如果 same-turn summary compaction 已经把这些 tool result
裁掉,回退会重新开启,保证模型仍能看到完整正文/文档。

启用方式:`llmagent.WithSkillsLoadedContentInToolResults(true)`。
如果你希望在 summary 场景恢复旧的回退行为:
`llmagent.WithSkipSkillsFallbackOnSessionSummary(false)`。

要在真实工具链路中测量提升,参见 [trpc-agent-go-benchmark/anthropic_skills](https://github.com/trpc-group/trpc-agent-go-benchmark/tree/main/anthropic_skills) 的
`prompt-cache` 套件。

与 `SkillLoadMode` 的关系(容易踩坑):

- 上面讨论的“缓存前缀变短/变长”,主要发生在同一次 `Runner.Run`
  里多次调用模型的场景(一次用户消息触发多个 tool call)。
- 如果你希望跨**多轮对话**继续复用“已加载技能的正文/文档”,需要把
  `SkillLoadMode` 设为 `session`。默认 `turn` 会在下一轮开始前清空
  该 agent 的 skill state key(`temp:skill:loaded_by_agent:<agent>/<name>` /
  `temp:skill:docs_by_agent:<agent>/<name>`),因此即使 history 里仍然
  有上一轮的 `skill_load` tool result(通常是 `loaded: <name>` 这种短
  stub),框架也不会再把正文/文档物化进去。

实践建议(尤其是 `WithSkillsLoadedContentInToolResults(true)` 时):

- 先确认你在讨论哪种“缓存”场景:
  - **同一轮对话内**(一次 `Runner.Run` 里多次调用模型):`turn` 与
    `session` 基本等价,因为它们都会让“本轮已加载内容”在该轮内可见。
    更关键的开关通常是“注入到 system 还是 tool result”。
  - **跨多轮对话**:`session` 可能更利于 prompt cache,因为你只需加载一次,
    后续不必反复 `skill_load`;但代价是上下文更大、需要更主动地管理清理。
- 经验法则:
  - 默认用 `turn`(最小权限、上下文更小、也更不容易触发截断/summary)。
  - 仅对“整段会话都会反复用到”的少量技能用 `session`,并严格控制 docs。
- 严格控制 docs 选择(尽量不要 `include_all_docs=true`),否则很容易把
  上下文塞爆,进而触发 history 截断/summary,导致回退为 system message,
  prompt cache 的收益会下降。

### 会话持久化

先区分两个概念:

- **Session(持久化)**:保存事件流(用户消息、助手消息、工具调用/结果)
  + 一份小的键值 **state map**。
- **模型请求(一次性的)**:本次发给模型的 `[]Message`,由 Session +
  运行时配置拼出来。

`skill_load` 只会把“已加载/已选文档”的**小状态**写入 Session(例如
`temp:skill:loaded_by_agent:<agent>/<name>`、
`temp:skill:docs_by_agent:<agent>/<name>`;旧版 key 也仍被支持)。
随后由请求处理器在
**下一次模型请求**里,把对应的 `SKILL.md` 正文/已选 docs **物化**
进去。

重要:物化不会把“扩展后的 tool result 内容”写回 Session。
所以如果你去看 Session 里保存的工具结果,`skill_load` 仍然通常是
一个很短的 stub(比如 `loaded: internal-comms`)。但模型在每次请求
里仍能看到完整正文/文档,因为它们是在构造请求时注入的。

补充:`SkillLoadMode` 控制的是这些 state key 的生命周期,所以也决定了
“下一轮对话”里是否还能继续物化正文/文档。

后续请求的稳定性:
- 在同一次工具链路里,每次模型调用前都会按同一套规则重新物化,
  所以只要 skills 仓库内容和选择状态不变,模型看到的 skill 内容
  就是稳定的。
- 如果本次请求的 history 里找不到对应的 `skill_load` /
  `skill_select_docs` tool result(常见原因:history suppression、
  会话摘要、或截断把这些 tool 消息移除),框架可以回退为插入一条专用
  system message(`Loaded skill context:`),把缺失的 skill 正文/文档
  补回来,确保模型仍能看到正确上下文。
  - 但这会改变 system 内容,prompt cache 的收益可能变小;因此当本次请求
    存在 session summary 时,该回退默认会被跳过(见上文)。

### 与业界实现对比

很多框架为了更友好地利用 prompt cache,会尽量避免在多步工具链路中
不断改写 system prompt,而是把动态上下文放到 **tool 消息**(工具结果)
里,让 system 更稳定。

一些例子:
- OpenClaw:system prompt 列出可用 skills,但选中 skill 的 `SKILL.md`
  会要求通过工具读取(正文落在 tool result 里):
  https://github.com/openclaw/openclaw/blob/0cf93b8fa74566258131f9e8ca30f313aac89d26/src/agents/system-prompt.ts
- OpenAI Codex:项目文档中渲染 skills 列表,并要求按需打开 `SKILL.md`
 (正文来自读文件工具的 tool result):
  https://github.com/openai/codex/blob/383b45279efda1ef611a4aa286621815fe656b8a/codex-rs/core/src/project_doc.rs

在 trpc-agent-go 中:
- 旧模式:把已加载的 skill 正文/文档追加到 **system message**
  (简单、兼容旧语义,但可能缩短可缓存的前缀)。
- 新模式(可选):保持 system 更稳定,把已加载内容物化到 `skill_load` /
  `skill_select_docs` 的 **tool result** 消息中(更接近“工具消息承载动态上下文”
  的主流模式)。

### 目录结构

```
skills/
  demo-skill/
    SKILL.md        # YAML 头信息(name/description) + Markdown 正文
    USAGE.md        # 可选文档(任意 .md/.txt)
    scripts/build.sh
    ...
```

仓库与解析: [skill/repository.go](https://github.com/trpc-group/trpc-agent-go/blob/main/skill/repository.go)

## 快速开始

### 1) 环境准备

- Go 1.21+
- 一个模型服务的 API Key(OpenAI 兼容)
- 可选:Docker(使用容器执行器时)

常用环境变量:

```bash
export OPENAI_API_KEY="your-api-key"
# 可选:指定技能根目录(容器执行器会只读挂载)
export SKILLS_ROOT=/path/to/skills
# 可选:也支持传入 HTTP(S) URL(例如 .zip/.tar.gz/.tgz/.tar 压缩包)
# export SKILLS_ROOT=https://example.com/skills.zip
# 可选:覆盖 URL 根目录的本地缓存目录
# export SKILLS_CACHE_DIR=/path/to/cache
```

### 2) 启用 Skills

在 `LLMAgent` 里提供技能仓库即可。

```go
import (
    "trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
    "trpc.group/trpc-go/trpc-agent-go/codeexe