跳转至

tRPC-Agent-Go Skills:Anthropic Agent Skills 规范的 Go 原生实现

tRPC-Agent-Go 框架第一时间支持了 Anthropic 风格的 Agent Skills。本文将从“如何使用”到“设计实现”依次展开,帮助你在实际业务中自如地启用和扩展这一能力。

tRPC-Agent-Go 是面向 Go 语言的自主式多 Agent 框架,具有工具调用、会话与记忆管理、制品管理、多 Agent 协同、图编排、知识库与可观测等能力。tRPC-Agent-Go 的成长离不开大家的支持,欢迎 Star 项目。

在很多基于大语言模型(Large Language Model,LLM)的 Agent 项目里,真正的挑战并不只是“让模型变聪明”,而是如何把一整套任务知识沉淀成可复用的技能,用按需加载的方式喂给模型,并在受控环境中安全落地执行。Anthropic 提出的 Agent Skills 提供了一条很清晰的路径:把可复用的任务封装为技能目录,用 SKILL.md 描述目标与流程,用文档和脚本补充细节,由系统在对话过程中按需加载这些信息,并在工作区中完成实际操作。

tRPC-Agent-Go 在框架层对齐了这套设计:一方面提供 Skill 仓库存取、概览与正文注入等上下文能力,另一方面结合 Workspace 抽象,把技能涉及的脚本放进隔离工作区中安全运行,让“任务知识 + 文档 + 可选脚本”成为一个统一、可控的 Agent 能力层。

本文会从零开始,带你理解: - Agent Skills 的整体思路和典型使用场景 - tRPC-Agent-Go 中如何按需加载 Skill 的上下文 - Skills 与执行环境结合后的能力边界 - 作为业务方,如何快速启用并扩展这一能力

后文会先梳理背景与概念,再给出一个最小使用示例,最后展开框架内部的设计与实现,帮助你把 Skill 看清楚、用得稳。

背景

传统痛点

在没有 Agent Skills 之前,我们通常这样给 LLM“加能力”:把一堆“操作手册”“命令示例”写在提示词里,再让模型按这些说明生成代码或操作步骤,由人类或外部系统去执行。

这种方式有两个明显问题:

  1. 上下文爆炸:所有步骤、脚本都写在提示词里,上下文窗口(Context Window)被快速占满,成本高、可维护性差。
  2. 执行环境割裂:模型只“说”脚本,不真正“跑”脚本,执行结果需要人工搬运,难以形成闭环,也不利于审计和回溯。

Anthropic 在文章 Equipping agents for the real world with Agent Skills 中提出了一套统一的解决方案:把可复用的任务封装为 Skill 目录,用 SKILL.md 描述目标与流程,用文档和脚本补充细节,由系统管理技能的发现、加载和执行。开源仓库 anthropics/skills 中提供了大量示例 Skill,如 PDF 处理、PPT 生成等。

tRPC-Agent-Go 在设计 Skill 能力时,完全对齐了这套语义:SKILL.md 的格式和含义与 Anthropic 官方一致,技能目录结构也与上述示例仓库兼容,你可以直接把 Claude Skills 仓库指给 tRPC-Agent-Go 使用,而不需要改写 SKILL.md

三层模型

先看一个极简的技能目录示例,帮助你对 Skill 的“长什么样”有一个直观印象。

1
2
3
4
5
6
skills/
  report-summary/
    SKILL.md
    USAGE.md
    scripts/
      summarize.py

其中 SKILL.md 的内容可以非常简单,例如:

---
name: report-summary
description: Summarize long reports into short bullet points.
---

Usage

- When the user asks to summarize a long report into a concise outline.

Steps

1) Read the input file from $WORK_DIR/inputs/report.txt
2) Run: python3 scripts/summarize.py > $OUTPUT_DIR/summary.txt
3) Return a short natural language summary and mention summary.txt

这个例子里:YAML 头部的 namedescription 提供“概览”,正文部分给出了使用时机和具体步骤,USAGE.md 作为补充说明,scripts/summarize.py 则是实际执行的脚本。真正做到“用起来像一个技能”,靠的就是对这些内容按需加载和执行。

在 Anthropic 的 Agent Skills 规范中,一个 Skill 目录本质上包含三层信息:

flowchart LR
    A[概览层 name + description]:::overview --> B[正文层 SKILL.md body]:::body
    B --> C[文档与脚本层 docs + scripts]:::docs

    classDef overview fill:#e1f5e1,stroke:#4caf50,stroke-width:2px
    classDef body fill:#e3f2fd,stroke:#2196f3,stroke-width:2px
    classDef docs fill:#fff3e0,stroke:#ff9800,stroke-width:2px
  1. 概览层:只包含 SKILL.md YAML 头部中的 namedescription,成本极低,可以在每轮对话一开始就注入,用来告诉模型“有哪些技能、各自做什么”。
  2. 正文层:SKILL.md 的 Markdown 正文,描述“何时使用”“具体步骤”“命令示例”,只在模型决策“要用这个 Skill”时,通过工具调用按需加载。
  3. 文档与脚本层:附加的 Markdown 文档和脚本文件,文档按需选取一部分注入,脚本只在工作区执行,不会被原样放进提示词。

这个“三层模型”是理解 Agent Skills 的核心:Agent 只在需要时才把更“重”的信息拉进上下文或执行环境,从而在“能力强”和“成本低”之间取得平衡。

快速开始

本节从“怎么用”出发,给出一个最小可运行示例,帮助你快速感受 tRPC-Agent-Go 的 Agent Skills 能力。

环境准备

  • Go 1.21+
  • 一个 OpenAI 兼容模型服务的 Key
  • 一个 Skills 目录(可以直接使用示例目录 examples/skillrun/skills

常用环境变量:

export OPENAI_API_KEY="your-api-key"
export SKILLS_ROOT=/path/to/your/skills   # 可选,默认使用 ./skills

入门示例

下面这段代码是简化版的技能对话示例,基于 examples/skillrun/main.go

package main

import (
    "trpc.group/trpc-go/trpc-agent-go/agent/llmagent"
    "trpc.group/trpc-go/trpc-agent-go/codeexecutor/local"
    "trpc.group/trpc-go/trpc-agent-go/model"
    "trpc.group/trpc-go/trpc-agent-go/model/openai"
    "trpc.group/trpc-go/trpc-agent-go/runner"
    "trpc.group/trpc-go/trpc-agent-go/skill"
)

func main() {
    mdl := openai.New("gpt-4o-mini")

    repo, _ := skill.NewFSRepository("./skills")
    exec := local.New()

    agent := llmagent.New(
        "skills-assistant",
        llmagent.WithModel(mdl),
        llmagent.WithSkills(repo),
        llmagent.WithCodeExecutor(exec),
    )

    r := runner.NewRunner("demo-app", agent)
    ch, _ := r.Run(
        context.Background(),
        "user1", "session1",
        model.NewUserMessage("请用合适的 Skill 总结一个文本文件"),
    )

    for ev := range ch {
        // 处理流式响应与工具调用,这里略去细节。
        _ = ev
    }
}

这段代码做了几件事:用 WithSkills(repo) 打开 Agent Skills 能力,用 WithCodeExecutor(exec) 接入执行环境,并通过 Runner 发起一次对话,让模型可以在需要时自动选择并调用技能相关工具。

在实际对话中,一个典型流程大致是:模型先通过概览了解有哪些技能,当你说“用某个 Skill 做 X”或描述一个技能适用的任务时,它调用技能工具加载正文与文档,然后在技能工作区中执行命令并返回结果或输出文件。

后续章节会从实现角度解释:这些行为在框架内部是如何串起来的。

架构总览

先看一张总览图,帮助你把几个关键模块对上号:

flowchart TB
    subgraph "对话入口"
        U[用户消息]:::user
        R[Runner]:::runner
    end

    subgraph "LLMAgent 层"
        LA[LLMAgent WithSkills + WithCodeExecutor]:::agent
        PR[SkillsRequestProcessor 请求预处理]:::proc
        TLoad[skill_load 等工具]:::tool
        TRun[skill_run 工具]:::tool
    end

    subgraph "Skills 仓库"
        REPO[skill.Repository FSRepository]:::repo
        FS[技能目录 + SKILL.md]:::fs
    end

    subgraph "执行层(codeexecutor)"
        ENG[Engine]:::exec
        LRT[local.Runtime]:::rt
        CRT[container.workspaceRuntime]:::rt
    end

    U --> R --> LA
    LA --> PR
    PR --> LA
    LA -->|工具调用| TLoad
    LA -->|工具调用| TRun
    TLoad --> REPO
    TRun --> REPO
    TRun --> ENG
    ENG --> LRT
    ENG --> CRT
    REPO --> FS

    classDef user fill:#fff3e0,stroke:#fb8c00,stroke-width:2px
    classDef runner fill:#e8f5e9,stroke:#43a047,stroke-width:2px
    classDef agent fill:#e3f2fd,stroke:#1e88e5,stroke-width:2px
    classDef proc fill:#fce4ec,stroke:#d81b60,stroke-width:2px
    classDef tool fill:#ede7f6,stroke:#5e35b1,stroke-width:2px
    classDef repo fill:#f1f8e9,stroke:#7cb342,stroke-width:2px
    classDef fs fill:#efebe9,stroke:#6d4c41,stroke-width:2px
    classDef exec fill:#e0f2f1,stroke:#00897b,stroke-width:2px
    classDef rt fill:#f3e5f5,stroke:#8e24aa,stroke-width:2px

可以大致理解为三层:

  • 对话层:Runner + LLMAgent,负责接收用户消息、调用模型和驱动工具流。
  • Skill 管理层:skill.Repository 负责发现并解析 SKILL.mdSkillsRequestProcessor 负责把概览、正文和文档按需注入。
  • 执行层:用统一的 Engine 抽象屏蔽“本地执行”和“容器执行”的差异,skill_run 只面对统一接口,不关心底层是本机还是容器。

接下来我们依次展开这些模块。

技能目录

目录结构

在 tRPC-Agent-Go 中,一个 Skill 目录通常类似下面这样:

1
2
3
4
5
6
7
8
my-skill/
  SKILL.md
  USAGE.md
  scripts/
    run.sh
    helper.py
  assets/
    logo.png

规范与 Anthropic 的 Agent Skills 规范保持一致,核心要点包括:目录名与 SKILL.md 中 YAML 头部的 name 一致;description 用自然语言描述“技能做什么、何时用”;正文部分是完全自由的 Markdown,用来写使用时机、步骤和命令示例。

在代码中,skill/repository.go 把这些规范落实到了具体实现:常量 skillFile = "SKILL.md" 定义了 Skill 入口文件名,EnvSkillsRoot 环境变量指定技能仓库根目录,FSRepository 会递归遍历技能根目录,寻找包含 SKILL.md 的子目录。

相关代码可以在 skill/repository.go 中查看。

加载流程

FSRepository 实现了 skill.Repository 接口,用于从文件系统加载技能:

  • Summaries:返回所有技能的 Summary,只包含 NameDescription,对应“概览层”。
  • Get:读取完整的 SKILL.md 正文,并收集同目录下所有 .md.txt 文档到 Docs 列表,对应“正文 + 文档层”。
  • Path:返回技能目录路径,供后续执行时把整个目录挂载到工作区。

这一层做的事情可以用下面的图来理解:

flowchart LR
    FSRoot[技能根目录 SKILLS_ROOT]:::fs --> Scan[FSRepository.scan]:::repo
    Scan --> Index[内存索引 name -> dir]:::repo
    Index --> Sum[Summaries 概览列表]:::repo
    Index --> Get[Get name Summary + Body + Docs]:::repo
    Index --> Path[Path name 技能目录路径]:::repo

    classDef fs fill:#efebe9,stroke:#6d4c41,stroke-width:2px
    classDef repo fill:#e3f2fd,stroke:#1e88e5,stroke-width:2px

这样,框架在读取和执行 Skill 时,都不需要理解 YAML 的细节,只要通过接口拿到“概览、正文、文档、目录路径”四类信息即可。

上下文注入

请求预处理

当你在创建 LLMAgent 时调用:

1
2
3
4
5
6
llm := llmagent.New(
    "skills-assistant",
    llmagent.WithModel(mdl),
    llmagent.WithSkills(repo),
    llmagent.WithCodeExecutor(exec),
)

框架内部会自动挂上一条请求预处理链 internal/flow/processor/skills.go 中的 SkillsRequestProcessor

它在每次发送给模型的请求前做两件事:

  1. 总是注入“技能概览”。处理器读取 repo.Summaries,生成诸如 Available skills: - name: description 的文本,并将其合并到系统消息(system message)中,同时追加一段“如何安全使用工作区和工具”的指导文案,明确 inputsout 等目录的约定。
  2. 按需注入已加载技能的正文和文档。处理器读取会话状态中的临时键 temp:skill:loaded:<name>temp:skill:docs:<name>,对每个被标记为已加载的技能,把 SKILL.md 正文整体拼接到系统消息中,并根据 docs 选择具体 .md.txt 文档,并加上 [Doc] 文件名 的前缀。

整个过程的时序大致如下:

sequenceDiagram
    participant U as 用户
    participant R as Runner
    participant A as LLMAgent
    participant P as SkillsRequestProcessor
    participant M as 模型(LLM)

    U->>R: 发送消息
    R->>A: 构造请求 Request
    A->>P: ProcessRequest
    P->>P: 注入技能概览与已加载正文文档
    P-->>A: 修改后的 Request
    A->>M: 调用模型 API
    M-->>A: 返回响应

这里有两个关键点:

  • 概览始终存在,让模型始终知道“有哪些技能可用”,但成本很低。
  • 正文与文档按需加载,只有当工具调用明确表明“要用这个技能”时才会注入,从而避免上下文浪费。

技能状态

SkillsRequestProcessor 本身并不决定“加载哪个技能”,它只读取会话状态。真正写入状态的是三个工具:

  • skill_load:声明“加载某个技能的正文,以及要用哪些文档”。
  • skill_select_docs:单独调整文档选择(增加、替换或清空)。
  • skill_list_docs:列出某技能下所有可选文档文件名。

这三个工具的实现位于以下文件:

它们的共同点是:不直接操作 Prompt,只读写 Session.State 中的临时键。这样可以保证“选择使用哪个 Skill 和哪些文档”与“如何把这些内容注入系统消息”是解耦的两个步骤:前者由工具负责,后者由请求处理器统一完成。

工具总览

工具注册

当你在创建 LLMAgent 时调用 llmagent.WithSkills(repo)agent/llmagent/llm_agent.go 会自动注册四个技能相关工具:

  • skill_load
  • skill_select_docs
  • skill_list_docs
  • skill_run

部分逻辑可以用下面的图来概括:

flowchart LR
    O[LLMAgent 选项 WithSkills]:::agent
    O --> T1[NewLoadTool]:::tool
    O --> T2[NewSelectDocsTool]:::tool
    O --> T3[NewListDocsTool]:::tool
    O --> T4[NewRunTool + CodeExecutor]:::tool

    classDef agent fill:#e3f2fd,stroke:#1e88e5,stroke-width:2px
    classDef tool fill:#ede7f6,stroke:#5e35b1,stroke-width:2px

如果你还配置了 WithCodeExecutor(exec),框架会把这个执行器传给 skill_run 工具;如果没有显式配置,skill_run 会自动退回到默认的本地执行器。

工具职责

结合 docs/mkdocs/zh/skill.mdtool/skill/*.go 源码,每个工具的职责大致如下:

  • skill_load:输入为 skill(必填)、可选的 docsinclude_all_docs,行为是写入 temp:skill:loaded:<name>temp:skill:docs:<name>,标记“本轮对话需要该技能正文和哪些文档”。
  • skill_select_docs:输入为 skilldocsinclude_all_docsmode,行为是更新 temp:skill:docs:<name>,支持追加、替换或清空。
  • skill_list_docs:输入为 skill,输出为该技能下可用文档文件名列表,方便模型做选择。
  • skill_run:输入为 skillcommandcwdenvoutput_filesinputsoutputstimeout 等,行为是在隔离的 Workspace 中执行命令,收集输出文件,并在需要时保存为 Artifact(工件)。

前三个工具解决“模型知道用哪个 Skill、读哪些文档”的问题,最后一个 skill_run 则负责“真正把脚本跑起来”,是连接技能和执行环境的关键一环。

执行环境

要实现类似 Claude 的 Skills 体验,有一个关键原则:Skill 本身只依赖一个干净的执行接口,而不关心后台到底是本机还是容器。tRPC-Agent-Go 把这一层抽象集中在 codeexecutor/workspace.gocodeexecutor/metadata.go 中。

一个简化的结构图可以帮助理解执行抽象内部的组成:

flowchart TB
    subgraph Engine
        WM[WorkspaceManager]:::exec
        WFS[WorkspaceFS]:::exec
        PR[ProgramRunner]:::exec
    end

    classDef exec fill:#e0f2f1,stroke:#00897b,stroke-width:2px

执行接口

codeexecutor 包中,执行接口由一组职责清晰的组件组成:

  • Workspace 表示一个隔离的执行空间,包含 ID 和物理路径。
  • WorkspaceManager 负责创建与清理 Workspace。
  • WorkspaceFS 负责在 Workspace 中放置文件、挂载目录、收集输出。
  • ProgramRunner 在 Workspace 中运行具体命令。
  • Engine 把上述三个接口打包在一起,对外提供统一的执行能力。

另外还有一个辅助接口 EngineProvider,允许已有的 CodeExecutor 暴露内部的 Engine,供 skill_run 复用。

Workspace 的标准目录结构(由 EnsureLayout 保证)包括:skills 目录存放只读技能树、work 目录存放可写中间文件、runs 目录存放每次执行的临时目录、out 目录存放收集后的输出文件、metadata.json 记录已挂载技能与输入输出记录。

运行时会注入一组环境变量,例如 WORKSPACE_DIRSKILLS_DIRWORK_DIROUTPUT_DIRRUN_DIR 和当前技能名 SKILL_NAME。Skill 文档可以直接使用这些变量来描述文件路径,例如“从 $WORK_DIR/inputs 读取输入,把结果写入 $OUTPUT_DIR”。

本地执行

本地执行器的 Workspace 实现在 codeexecutor/local/workspace_runtime.go。它的职责包括:为每个执行 ID 创建工作目录并初始化标准子目录与元数据,将指定的技能目录或输入目录复制或链接到 Workspace,通过 exec.CommandContext 在 Workspace 中运行命令,注入前面提到的环境变量,并根据通配符收集输出文件,在大小或数量超过限制时设置 LimitsHit 标志。

本地 Runtime 默认启用 AutoInputs,可以把指定的宿主机目录映射到 work/inputs 下,方便 Skill 直接访问外部文件。

容器执行

容器执行器的 Workspace 实现在 codeexecutor/container/workspace_runtime.go。相比本地执行,它额外做了几件事:为每个 Workspace 在容器内创建一个独立目录,尽可能利用已有的 bind mount(例如把整个 Skills 仓库挂到 /opt/trpc-agent/skills)以“容器内复制”的方式快速挂载技能,通过 Docker 的 Exec 接口运行命令,带有超时与资源限制,并使用 glob 展开和 tar 流将输出文件拉回宿主机。

skill_run 而言,这些差异都是透明的,只要拿到一个实现了 Engine 接口的对象,就能统一调度本地和容器执行环境。

执行流程

入口解析

skill_run 的核心实现位于 tool/skill/run.go。工具首先解析 JSON 参数,校验 skillcommand 是否为空,然后通过技能仓库解析技能根目录。

在选择 Engine 时,skill_run 会优先尝试从外部注入的 CodeExecutor 中获取 Engine(当执行器实现了 EngineProvider 接口时),否则退回到一个基于本地 Runtime 的默认 Engine。这样既兼顾了易用性,又允许业务侧按需替换执行后端。

技能挂载

RunTool 内部维护了一个 WorkspaceRegistry,对应代码在 codeexecutor/registry.go,用于按会话 ID 复用 Workspace。这样同一对话中的多次 skill_run 调用可以共享一个 Workspace,中间产出保留在 workout 下,便于技能之间串联。

挂载 Skill 目录的大致流程是:通过 repo.Path 找到技能根目录,调用 codeexecutor.DirDigest 计算目录摘要,读取 Workspace 的 metadata.json 判断是否已经挂载过相同摘要的技能,如果是则跳过复制,否则将技能目录挂载到 Workspace 的 skills/<name>,在技能根目录下创建指向 outworkwork/inputs 的符号链接,最后把技能目录树(除符号链接外)设为只读。

从命令行视角看,技能脚本认为自己的根目录就是 skills/<name>,但写入 outworkinputs 实际上都落在 Workspace 共享目录中,既安全又方便多个技能协同。

结果收集

skill_run 支持两种输出收集方式:

  1. 传统的 output_files:传入通配符列表(例如 ["out/*.txt"]$OUTPUT_DIR/*.csv),底层通过 WorkspaceFS.Collect 收集匹配文件,并返回文件名、内容和 MIME 类型。
  2. 声明式的 outputs:通过 OutputSpec 指定通配符、是否内联内容、是否保存为 Artifact,以及最大文件数和大小,底层通过 CollectOutputs 返回 OutputManifest,并在需要时调用 Artifact 服务保存文件。

输入通过 inputs 数组声明,每个 InputSpec 可以来自 artifact://host://workspace://skill:// 等不同来源。具体实现分布在 codeexecutor 包和本地、容器 runtime 中。

最终,skill_run 返回一个结构化结果 runOutput,包括 stdoutstderrexit_codetimed_outduration_msoutput_files 以及可选的 artifact_files

整个执行链可以用以下时序图概括:

sequenceDiagram
    participant M as 模型(LLM)
    participant T as skill_run 工具
    participant E as Engine
    participant WM as WorkspaceManager
    participant FS as WorkspaceFS
    participant PR as ProgramRunner

    M->>T: 工具调用 {skill, command, ...}
    T->>T: parseRunArgs 校验参数
    T->>E: ensureEngine
    T->>WM: Acquire Workspace
    WM-->>T: Workspace
    T->>FS: StageDirectory 挂载技能目录
    T->>FS: StageInputs 映射外部输入
    T->>PR: RunProgram
    PR-->>T: RunResult
    T->>FS: Collect 或 CollectOutputs
    FS-->>T: 文件和 Manifest
    T-->>M: runOutput JSON

交互示例

仓库中提供了一个完整的交互式技能对话示例工程 examples/skillrun。这个示例展示了如何在命令行下与具备 Skills 能力的 Agent 进行对话。

它做了几件事:使用 OpenAI 兼容的模型客户端 model/openai/openai.go,通过 skill.NewFSRepository 加载技能仓库(默认 ./skills,也可通过 SKILLS_ROOT 指定),根据命令行参数选择本地或容器执行器,创建带 Skills 的 LLMAgent 并注入指导性系统提示词,使用 Runner 流式消费模型输出,同时打印工具调用和工具响应,包括 skill_run 返回的 artifact_files

如果你希望体验 Anthropic 官方示例 Skill,可以将仓库 anthropics/skills 克隆到本地,把环境变量 SKILLS_ROOT 指向该目录,然后在 examples/skillrun 下运行示例,就可以在 tRPC-Agent-Go 中直接使用这些 Skills。

需要注意的是,Skill 的语义完全来自 SKILL.md 和文档本身,框架只是提供“按需注入 + 安全执行”的基础能力。编写 Skill 时,你只需要关注如何用自然语言清楚描述任务及步骤,以及如何组织 scriptsout 目录保证命令可重现。

扩展运行

如果你希望在现有的本地和容器实现之外,再接入新的运行时(例如 Kubernetes Pod、远程沙箱等),可以沿着下面的思路来做。

  1. 实现 Workspace 接口三件套:实现自定义的 WorkspaceManagerWorkspaceFSProgramRunner,负责创建与清理 Workspace、管理文件和目录、在 Workspace 内运行命令。
  2. 封装为 Engine:使用 codeexecutor.NewEngine 把上述三个组件打包成一个新的 Engine
  3. 通过 LLMAgent 注入:将新的 CodeExecutor 或 Engine 注入 LLMAgent.WithCodeExecutor,或者直接在自定义 Agent 中以 Engine 形式传给 skill_run

由于 skill_run 完全基于 Engine 抽象工作,一旦新的执行后端实现了 Workspace 接口,所有现有 Skill 都可以无缝迁移,无需改动 SKILL.md

能力对比

除了 Skills,tRPC-Agent-Go 还内置了一条“自动执行代码块”的路径,处理模型回答中的代码块并自动执行,对应的逻辑在 internal/flow/processor/codeexecution.go 中。

两者的区别和定位大致如下:

  • 自动代码执行适合“临时写点代码试试”的轻量场景:模型在回答中输出三引号代码块(例如 ```python),框架自动提取并运行,返回结果。
  • Skill 执行适合“可复用的任务模板”:脚本始终存放在技能目录中,模型只写命令,不写脚本正文,通过 skill_run 在 Workspace 中执行,并可收集输出文件和 Artifact。

从实现上看,两者都复用 codeexecutor 的 Workspace 抽象,只是入口不同:自动代码执行从模型响应处理器进入,skill_run 从工具调用进入。

总结

回顾全文,tRPC-Agent-Go 的 Agent Skills 能力可以总结为几条主线:

  • 信息组织:用 SKILL.md 配合文档和脚本构成三层信息模型,概览始终存在,正文与文档按需注入,脚本只在工作区执行。
  • 请求注入:SkillsRequestProcessor 基于会话状态自动把概览、已加载技能正文和选定文档合并进系统消息。
  • 工具协作:skill_loadskill_select_docsskill_list_docs 负责“选用哪一个 Skill 和哪些文档”,skill_run 负责“在 Workspace 中真正执行命令并收集结果”。
  • 执行抽象:codeexecutor 用 Workspace 与 Engine 抽象屏蔽本地与容器差异,让 Skill 只依赖统一执行接口。
  • 扩展能力:只要实现 Workspace 三件套并封装为新 Engine,所有现有 Skill 都可以迁移到新的执行后端,无需改写 SKILL.md

对使用者而言,你只需要:准备好符合规范的 Skills 目录,在 LLMAgent 上配置 WithSkills 与合适的 CodeExecutor,像普通聊天一样与 Agent 交互,自然表达你的需求或希望使用的技能,模型会在合适的时机自行选择并调用相关工具。

其余的发现、注入、执行、收集与持久化工作,都由 tRPC-Agent-Go 在框架层统一完成。

欢迎大家在实际业务中试用 Agent Skills 能力,把高频任务沉淀为可复用的技能包,逐步构建自己的技能库。如需更多使用示例和最佳实践,可参考以下文档与仓库。

代码仓库: - tRPC-Agent-Go 仓库

Skills 相关文档: - Skills 功能说明与用法示例:docs/mkdocs/zh/skill.md - 交互式示例工程:examples/skillrun

欢迎通过 GitHub Issues 交流框架使用经验、分享实践案例、讨论改进建议。