AGENT_SKILLS_IMPLEMENTATION_GUIDE.md 39 KB

Agent Skills 落地架构与实践指南

作者视角:资深架构师
目标读者:技术负责人、架构师、高级开发者
文档定位:从工程化、架构设计、最佳实践角度,提供 Agent Skills 落地的深度指南


目录

  1. 引言:从工具调用到技能工程
  2. 核心架构设计
  3. 技能开发标准化流程
  4. 架构师视角的深度思考
  5. 落地实施策略
  6. 性能优化与可扩展性
  7. 安全与合规控制
  8. 质量保证与持续改进
  9. 案例研究:Maven 搜索专家技能
  10. 总结与展望

引言:从工具调用到技能工程

范式转变

传统的 Tool Calling(工具调用) 模式存在以下问题:

  • 碎片化:每个工具都是独立的 API 封装,缺乏统一标准
  • 上下文丢失:工具调用之间缺乏语义关联,难以形成连贯的工作流
  • 可组合性差:难以将多个工具组合成复杂的业务能力
  • 维护成本高:每个工具都需要单独维护文档和示例

Agent Skills(智能体技能) 代表了从"工具调用"到"技能工程"的范式转变:

  1. 标准化(Standardization):遵循统一的 Agent Skills 规范,确保技能的可发现性、可组合性和可维护性
  2. 语义化(Semanticization):技能不仅是代码,还包含领域知识、工作流程和最佳实践
  3. 模块化(Modularization):通过原子化的技能构建复杂的业务能力
  4. 确定性(Determinism):通过严格的输入输出校验和明确的触发条件,降低大模型生成的随机性风险

核心价值

Agent Skills 的核心价值在于将系统提示词(System Prompt)、工具集(Tools)与领域知识(Context)封装成一个独立的专家模块,使得大模型能够从单纯的"响应者"转变为具备特定职业能力的"专家"。

关键指标

  • 开发效率提升:将原本需要 3 分钟的浏览器搜索过程缩短为 5 秒钟的对话
  • 错误率降低:通过标准化的工作流程和输入校验,减少人为错误
  • 知识沉淀:将专家经验代码化、工具化,形成可复用的组织资产

核心架构设计

1. 领域驱动设计(DDD)的引入

Agent Skills 的组织应参考 DDD(领域驱动设计) 模式,按业务边界进行划分。

分层架构

┌─────────────────────────────────────────┐
│  触发器层 (Trigger Layer)                │
│  - 协议转换(MCP / HTTP / WebSocket)    │
│  - 意图识别与路由                        │
│  - 权限校验                              │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  应用层 (Application Layer)              │
│  - 技能编排与组合                        │
│  - 上下文管理                            │
│  - 工作流引擎                            │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  领域层 (Domain Layer)                  │
│  - 技能核心逻辑                          │
│  - 业务模型定义                          │
│  - 领域规则                              │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  基础设施层 (Infrastructure Layer)      │
│  - 工具执行引擎                          │
│  - 数据持久化                            │
│  - 外部服务集成                          │
└─────────────────────────────────────────┘

限界上下文(Bounded Context)

按技能类别划分限界上下文,例如:

  • development-skills:开发相关技能(前端、后端、移动端)
  • document-skills:文档处理技能(Word、PDF、图表绘制)
  • architecture-skills:架构设计技能(DDD、微服务、架构图)
  • testing-skills:测试技能(单元测试、E2E 测试)

每个限界上下文内部:

  • 使用统一语言(Ubiquitous Language)
  • 定义清晰的技能边界
  • 通过事件或消息进行跨上下文通信

2. 技能元数据规范

每个技能必须包含完整的定义,指导大模型何时以及如何调用。

元数据结构

---
name: maven-search                    # 唯一标识符(kebab-case)
description: |                        # 触发机制(关键!)
  Provides comprehensive guidance for searching and retrieving 
  Maven components from Maven Central Repository. 
  Use when the user needs to find, verify, or retrieve Maven 
  dependencies, check component versions, analyze dependency 
  trees, or work with Maven coordinates.
license: Complete terms in LICENSE.txt
---

关键设计原则

  1. 描述即触发器description 字段是技能的主要触发机制,必须包含:

    • 技能的核心功能
    • 明确的触发条件("Use when...")
    • 关键词和同义词(支持中英文)
  2. 渐进式披露:采用三层加载机制管理上下文:

    • Level 1 - 元数据:始终在上下文中(~100 words)
    • Level 2 - SKILL.md 主体:技能触发时加载(<5k words)
    • Level 3 - 资源文件:按需加载(scripts、references、assets)

3. 技能目录结构

标准化的目录结构确保技能的可维护性和可扩展性:

skill-name/
├── SKILL.md                    # 必需:技能定义和说明
├── LICENSE.txt                 # 必需:许可证文件
├── examples/                   # 可选:使用示例
│   ├── example-1.md
│   └── example-2.md
├── api/                        # 可选:API 参考文档
│   └── api-reference.md
├── reference/                  # 可选:领域知识库
│   ├── standards.md
│   └── best-practices.md
├── templates/                  # 可选:输出模板
│   └── template-1.md
├── scripts/                    # 可选:可执行脚本
│   └── script.py
└── assets/                     # 可选:资源文件(不加载到上下文)
    └── logo.png

设计原则

  • SKILL.md 保持精简:控制在 500 行以内,详细内容放在 reference/examples/
  • 避免重复:信息只存在于一个地方,要么在 SKILL.md,要么在资源文件中
  • 按需加载:通过明确的引用和描述,让大模型知道何时加载哪些资源文件

4. 通信协议与数据流

协议选择

  • SSE (Server-Sent Events):适用于单向流式响应(推荐)
  • WebSocket:适用于双向实时通信
  • HTTP REST:适用于简单的请求-响应模式

数据流设计

用户请求
  ↓
意图识别(基于 description)
  ↓
技能选择与加载
  ↓
参数校验(JSON Schema)
  ↓
技能执行(Scripts / Tools)
  ↓
结果格式化
  ↓
流式返回(SSE)

关键特性

  1. 实时进度推送:通过 progress 事件反馈当前执行步骤

    {
     "type": "progress",
     "step": "正在连接 Maven 仓库",
     "progress": 30
    }
    
  2. 思考过程展示(Reasoning):在技能执行前,允许 Agent 输出其选择该技能的推理路径

    {
     "type": "reasoning",
     "skill": "maven-search",
     "reason": "用户需要查找 Maven 依赖,maven-search 技能专门处理此类请求"
    }
    

技能开发标准化流程

第一步:需求分析与用例设计

1.1 理解技能的使用场景

通过具体用例明确技能的功能边界:

示例:Maven 搜索技能

  • 用例 1:用户说"查找 Spring Boot 的最新版本"

    • 触发条件:包含"查找"、"Maven"、"版本"等关键词
    • 执行流程:搜索 → 版本筛选 → 返回最新版本
    • 输出格式:Maven 坐标(groupId:artifactId:version)
  • 用例 2:用户说"帮我添加 Guava 依赖到 pom.xml"

    • 触发条件:包含"添加"、"依赖"、"pom.xml"等关键词
    • 执行流程:搜索 → 选择版本 → 生成 XML 片段
    • 输出格式:XML 代码块

1.2 识别可复用资源

分析每个用例,识别可复用的资源:

资源类型 何时包含 示例
Scripts 需要确定性执行或重复编写相同代码 scripts/search_maven.py
References 需要领域知识或 API 文档 reference/maven-coordinates.md
Assets 需要模板或资源文件 assets/pom-template.xml
Examples 需要展示使用模式 examples/search-by-name.md

第二步:技能初始化

使用标准化工具初始化技能结构:

python scripts/init_skill.py maven-search --path ./skills/

生成的内容

  • 标准化的目录结构
  • SKILL.md 模板(包含 YAML frontmatter)
  • 示例资源目录和文件

第三步:实现可复用资源

3.1 Scripts 开发

原则

  • 确定性:相同输入产生相同输出
  • 可测试性:必须通过实际运行验证
  • 文档化:包含清晰的参数说明和示例

示例

#!/usr/bin/env python3
"""
Maven Central Repository 搜索脚本

用法:
    python search_maven.py <query> [--limit N]

参数:
    query: 搜索关键词(groupId 或 artifactId)
    --limit: 返回结果数量限制(默认 10)
"""
import sys
import requests
import json

def search_maven(query, limit=10):
    """搜索 Maven Central Repository"""
    url = "https://search.maven.org/solrsearch/select"
    params = {
        "q": query,
        "rows": limit,
        "wt": "json"
    }
    response = requests.get(url, params=params)
    return response.json()

if __name__ == "__main__":
    query = sys.argv[1]
    limit = int(sys.argv[2]) if len(sys.argv) > 2 else 10
    results = search_maven(query, limit)
    print(json.dumps(results, indent=2))

3.2 References 编写

原则

  • 结构化:使用清晰的标题和列表
  • 完整性:覆盖所有关键概念和边界情况
  • 可检索性:包含关键词和索引

示例结构

# Maven 坐标参考

## 坐标格式

Maven 坐标由三部分组成:
- `groupId`:组织标识(如 `com.google.guava`)
- `artifactId`:项目标识(如 `guava`)
- `version`:版本号(如 `33.0.0`)

## 版本规范

- **发布版本**:遵循语义化版本(SemVer)
- **快照版本**:以 `-SNAPSHOT` 结尾
- **最新版本**:通过 `maven-metadata.xml` 查询

## 常见问题

### Q: 如何查找最新版本?
A: 查询 `{groupId}/{artifactId}/maven-metadata.xml`,解析 `<latest>` 标签

3.3 Examples 设计

原则

  • 覆盖主要用例:每个用例一个示例文件
  • 包含完整上下文:说明输入、输出和关键步骤
  • 链接到参考文档:便于深入理解

示例结构

# 按名称搜索 Maven 组件

## 使用场景

当用户提供组件名称或关键词时,使用此方法搜索。

## 执行步骤

1. 解析用户输入,提取搜索关键词
2. 调用 Maven Central Search API
3. 解析返回结果,提取关键信息
4. 格式化输出,包含坐标和最新版本

## 示例

**输入**:查找 Spring Boot

**输出**:

xml

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>3.2.0</version>


## 参考

- [Maven 坐标参考](reference/maven-coordinates.md)
- [Maven Central API](api/maven-central-api.md)

第四步:编写 SKILL.md

4.1 Frontmatter 编写

关键要点

  1. description 是核心:这是技能的唯一触发机制

    • 必须包含"Use when..."明确触发条件
    • 包含关键词和同义词(中英文)
    • 避免在 body 中重复"何时使用"信息
  2. 简洁而全面:在 100 词左右描述清楚技能的核心功能和触发条件

好的示例

description: |
  Provides comprehensive guidance for searching and retrieving Maven 
  components from Maven Central Repository. Use when the user needs 
  to find, verify, or retrieve Maven dependencies, check component 
  versions, analyze dependency trees, or work with Maven coordinates.

不好的示例

description: Maven search tool  # 太简单,缺乏触发条件

4.2 Body 编写

结构建议

# Skill Title

## When to use this skill

**ALWAYS use this skill when the user mentions:**
- [明确的触发场景 1]
- [明确的触发场景 2]

**Trigger phrases include:**
- [关键词列表]

## How to use this skill

**CRITICAL: [关键触发条件]**

1. **Identify the task type** from the user's request
2. **Load the appropriate example** from `examples/` directory
3. **Follow the specific instructions** in that example
4. **Execute the workflow** using scripts or tools
5. **Present the results** in a clear format

## API Endpoints and Usage

[API 文档链接和说明]

## Best Practices

[最佳实践和注意事项]

## Keywords

**English keywords:**
[关键词列表]

**Chinese keywords:**
[中文关键词列表]

编写原则

  • 使用命令式/不定式:Always use imperative/infinitive form
  • 避免冗余:Claude 已经很聪明,只添加它不知道的信息
  • 结构化组织:使用标题、列表、表格提高可读性
  • 提供示例:包含 2-3 个正向和负向案例

第五步:技能打包与验证

python scripts/package_skill.py ./skills/maven-search

验证内容

  • YAML frontmatter 格式和必需字段
  • 技能命名规范和目录结构
  • 描述完整性和质量
  • 文件组织和资源引用

架构师视角的深度思考

1. 状态管理与上下文压缩

问题

当多个技能(Multi-Expert Collaboration)被同时激活时,Token 消耗会急剧增加:

  • SKILL.md 主体:每个技能 ~5k tokens
  • Examples:每个示例 ~1k tokens
  • References:每个参考文档 ~2k tokens
  • 对话历史:累积增长

100 个技能 × 5k tokens = 500k tokens(超出大多数模型的上下文窗口)

解决方案

1. 动态注入(Dynamic Injection)

仅在检测到特定关键词或意图时才注入完整技能 Prompt:

def should_load_skill(user_input, skill_metadata):
    """判断是否需要加载完整技能"""
    keywords = extract_keywords(user_input)
    skill_keywords = skill_metadata.get('keywords', [])
    
    # 简单匹配:关键词重叠度
    overlap = len(set(keywords) & set(skill_keywords))
    threshold = skill_metadata.get('trigger_threshold', 2)
    
    return overlap >= threshold

2. 摘要机制(Summarization)

对长工具输出进行自动摘要:

def summarize_tool_output(output, max_tokens=500):
    """摘要工具输出,避免上下文溢出"""
    if estimate_tokens(output) <= max_tokens:
        return output
    
    # 提取关键信息
    summary = extract_key_points(output)
    return f"{summary}\n\n[完整输出已截断,共 {len(output)} 字符]"

3. 分层加载(Progressive Loading)

class SkillLoader:
    def load_skill(self, skill_name, level='metadata'):
        """按需加载技能内容"""
        if level == 'metadata':
            return self.load_metadata(skill_name)
        elif level == 'body':
            return self.load_body(skill_name)
        elif level == 'resources':
            return self.load_resources(skill_name, resource_type)

2. 多专家协作模式

场景

用户请求:"帮我创建一个 Spring Boot 项目,并添加 Guava 依赖"

这需要多个技能协作:

  1. spring-boot-project-creator:创建项目结构
  2. maven-search:查找 Guava 依赖
  3. pom-xml-editor:编辑 pom.xml

设计模式

1. 技能编排(Skill Orchestration)

class SkillOrchestrator:
    def execute_workflow(self, user_request):
        """编排多个技能完成复杂任务"""
        # 1. 意图识别
        intents = self.intent_recognizer.recognize(user_request)
        
        # 2. 技能选择
        skills = [self.skill_registry.get(skill_name) 
                  for skill_name in intents.required_skills]
        
        # 3. 执行顺序规划
        execution_plan = self.planner.plan(skills, intents)
        
        # 4. 顺序执行
        context = {}
        for step in execution_plan:
            result = step.skill.execute(step.input, context)
            context.update(result)
        
        return context

2. 标准化接口(Standardized Interface)

所有技能必须遵循统一的输入输出格式:

class SkillInterface:
    """技能标准接口"""
    
    def execute(self, input: dict, context: dict) -> dict:
        """
        执行技能
        
        Args:
            input: 用户输入(JSON Schema 验证)
            context: 上下文信息(来自其他技能)
        
        Returns:
            {
                "status": "success" | "error",
                "data": {...},
                "next_skills": [...],  # 建议的下一个技能
                "context_updates": {...}  # 更新上下文
            }
        """
        pass

3. 上下文传递(Context Passing)

class ContextManager:
    def __init__(self):
        self.context = {}
    
    def update(self, skill_name, output):
        """更新上下文"""
        self.context[f"{skill_name}_output"] = output
        self.context["last_skill"] = skill_name
    
    def get_relevant_context(self, skill_name):
        """获取相关上下文"""
        # 只返回与当前技能相关的上下文
        relevant = {}
        for key, value in self.context.items():
            if self.is_relevant(key, skill_name):
                relevant[key] = value
        return relevant

3. 技能发现与路由

问题

如何从 100+ 技能中快速找到最相关的技能?

解决方案

1. 基于描述的语义匹配

class SkillRouter:
    def __init__(self, skill_registry):
        self.skill_registry = skill_registry
        self.embeddings = self.load_embeddings()
    
    def find_relevant_skills(self, user_input, top_k=3):
        """找到最相关的技能"""
        # 1. 生成用户输入的嵌入向量
        input_embedding = self.embeddings.encode(user_input)
        
        # 2. 计算与所有技能描述的相似度
        similarities = []
        for skill in self.skill_registry.skills:
            skill_embedding = self.embeddings.encode(skill.description)
            similarity = cosine_similarity(input_embedding, skill_embedding)
            similarities.append((skill, similarity))
        
        # 3. 返回 Top-K
        similarities.sort(key=lambda x: x[1], reverse=True)
        return [skill for skill, _ in similarities[:top_k]]

2. 关键词匹配(快速路径)

def quick_match(user_input, skill):
    """快速关键词匹配"""
    user_keywords = extract_keywords(user_input.lower())
    skill_keywords = skill.metadata.get('keywords', [])
    
    # 计算关键词重叠度
    overlap = len(set(user_keywords) & set(skill_keywords))
    total_keywords = len(set(user_keywords) | set(skill_keywords))
    
    return overlap / total_keywords if total_keywords > 0 else 0

3. 混合策略

def route_to_skill(user_input):
    """混合路由策略"""
    # 1. 快速路径:关键词匹配
    quick_matches = [s for s in skills if quick_match(user_input, s) > 0.5]
    if len(quick_matches) == 1:
        return quick_matches[0]
    
    # 2. 慢速路径:语义匹配
    semantic_matches = find_relevant_skills(user_input, top_k=3)
    
    # 3. 合并结果
    candidates = merge_and_rank(quick_matches, semantic_matches)
    
    # 4. 如果多个候选,询问用户或选择置信度最高的
    if len(candidates) > 1:
        return ask_user_or_select_best(candidates)
    
    return candidates[0]

落地实施策略

1. 技能开发流程

1.1 需求收集

方法

  • 用户访谈:了解真实使用场景
  • 数据分析:分析现有工具的使用模式
  • 竞品分析:研究类似技能的实现方式

输出

  • 用例文档(Use Cases)
  • 用户故事(User Stories)
  • 功能需求列表

1.2 技能设计

步骤

  1. 定义技能边界

    • 明确技能能做什么,不能做什么
    • 识别与其他技能的边界和协作点
  2. 设计工作流

    • 绘制流程图
    • 识别关键决策点
    • 定义错误处理策略
  3. 确定资源需求

    • Scripts:需要哪些可执行脚本?
    • References:需要哪些领域知识?
    • Assets:需要哪些模板或资源?

1.3 实现与测试

开发

  • 遵循标准化流程(见"技能开发标准化流程")
  • 编写单元测试
  • 进行集成测试

测试

  • 功能测试:验证技能是否按预期工作
  • 召回率测试:模拟不同用户提问,测试技能是否能被正确触发
  • 长链条回归:测试多个技能组合调用时,上下文信息是否会丢失

2. 技能市场(Marketplace)管理

2.1 分类组织

按技能种类组织,而非按岗位:

marketplace.json
├── development-skills(开发技能)
├── document-skills(文档技能)
├── architecture-skills(架构技能)
├── testing-skills(测试技能)
└── ...

优势

  • 灵活组合:用户可以按需安装
  • 独立维护:每个技能类别独立版本管理
  • 清晰边界:避免技能重叠和冲突

2.2 版本管理

{
  "name": "full-stack-skills",
  "metadata": {
    "version": "0.0.1",
    "description": "...",
    "skills_count": 171
  },
  "plugins": [
    {
      "name": "development-skills",
      "version": "1.0.0",
      "skills": [...]
    }
  ]
}

策略

  • 语义化版本:遵循 SemVer(主版本.次版本.修订版本)
  • 向后兼容:次版本和修订版本保持 API 兼容
  • 变更日志:记录每个版本的变更内容

3. 部署与分发

3.1 打包格式

技能打包为 .skill 文件(实际是 ZIP 文件):

maven-search.skill
├── SKILL.md
├── LICENSE.txt
├── examples/
├── api/
└── reference/

3.2 分发渠道

  1. GitHub Marketplace:通过 GitHub 发布和分发
  2. 私有仓库:企业内部使用
  3. CDN 分发:通过 CDN 加速下载

3.3 安装流程

# Claude Code / Cursor
/plugin install development-skills@full-stack-skills

# 或指定版本
/plugin install development-skills@full-stack-skills@1.0.0

性能优化与可扩展性

1. 延迟加载(Lazy Loading)

问题

当技能库达到上百个时,加载所有技能的元数据也会消耗大量 Token。

解决方案

按需加载技能元数据

class LazySkillRegistry:
    def __init__(self, marketplace_path):
        self.marketplace_path = marketplace_path
        self._skills_cache = {}
        self._metadata_cache = {}
    
    def get_skill_metadata(self, skill_name):
        """延迟加载技能元数据"""
        if skill_name not in self._metadata_cache:
            skill_path = self._resolve_skill_path(skill_name)
            metadata = self._load_metadata(skill_path)
            self._metadata_cache[skill_name] = metadata
        return self._metadata_cache[skill_name]
    
    def get_skill(self, skill_name):
        """延迟加载完整技能"""
        if skill_name not in self._skills_cache:
            skill_path = self._resolve_skill_path(skill_name)
            skill = self._load_skill(skill_path)
            self._skills_cache[skill_name] = skill
        return self._skills_cache[skill_name]

2. 执行缓存

场景

对于幂等性的查询技能(如检索 Maven 坐标),建立结果缓存可以:

  • 提升响应速度
  • 降低 API 调用成本
  • 减少外部服务压力

实现

from functools import lru_cache
import hashlib
import json

class SkillCache:
    def __init__(self, ttl=3600):
        self.cache = {}
        self.ttl = ttl
    
    def get_cache_key(self, skill_name, input_params):
        """生成缓存键"""
        key_data = {
            "skill": skill_name,
            "input": input_params
        }
        key_str = json.dumps(key_data, sort_keys=True)
        return hashlib.md5(key_str.encode()).hexdigest()
    
    def get(self, skill_name, input_params):
        """获取缓存结果"""
        cache_key = self.get_cache_key(skill_name, input_params)
        if cache_key in self.cache:
            entry = self.cache[cache_key]
            if time.time() - entry['timestamp'] < self.ttl:
                return entry['result']
            else:
                del self.cache[cache_key]
        return None
    
    def set(self, skill_name, input_params, result):
        """设置缓存"""
        cache_key = self.get_cache_key(skill_name, input_params)
        self.cache[cache_key] = {
            "result": result,
            "timestamp": time.time()
        }

3. 可观测性(Observability)

指标收集

记录每个技能的调用情况:

class SkillMetrics:
    def __init__(self):
        self.metrics = {
            "call_count": defaultdict(int),
            "success_count": defaultdict(int),
            "error_count": defaultdict(int),
            "avg_duration": defaultdict(list),
            "token_usage": defaultdict(int)
        }
    
    def record_call(self, skill_name, duration, tokens, success):
        """记录技能调用"""
        self.metrics["call_count"][skill_name] += 1
        if success:
            self.metrics["success_count"][skill_name] += 1
        else:
            self.metrics["error_count"][skill_name] += 1
        
        self.metrics["avg_duration"][skill_name].append(duration)
        self.metrics["token_usage"][skill_name] += tokens
    
    def get_stats(self, skill_name):
        """获取技能统计"""
        return {
            "call_count": self.metrics["call_count"][skill_name],
            "success_rate": (
                self.metrics["success_count"][skill_name] / 
                self.metrics["call_count"][skill_name]
                if self.metrics["call_count"][skill_name] > 0 else 0
            ),
            "avg_duration": np.mean(self.metrics["avg_duration"][skill_name]),
            "total_tokens": self.metrics["token_usage"][skill_name]
        }

日志分析

通过日志分析不断优化技能描述:

class SkillAnalyzer:
    def analyze_failed_calls(self, skill_name):
        """分析失败的调用"""
        failed_calls = self.get_failed_calls(skill_name)
        
        # 分析失败原因
        reasons = {
            "wrong_skill_selected": 0,
            "parameter_error": 0,
            "execution_error": 0
        }
        
        for call in failed_calls:
            if call.error_type == "wrong_skill":
                reasons["wrong_skill_selected"] += 1
            elif call.error_type == "parameter":
                reasons["parameter_error"] += 1
            else:
                reasons["execution_error"] += 1
        
        # 如果错误主要是"技能选择错误",建议优化 description
        if reasons["wrong_skill_selected"] > len(failed_calls) * 0.5:
            return {
                "suggestion": "优化技能描述,增加更明确的触发条件",
                "confidence": "high"
            }

安全与合规控制

1. 权限沙箱(Permission Sandbox)

问题

Agent Skills 往往拥有读写文件或访问网络的能力,必须建立强隔离机制。

解决方案

1. 路径白名单

class PathValidator:
    def __init__(self):
        self.allowed_paths = [
            "/tmp/",
            "/workspace/",
            # 禁止访问系统目录
        ]
        self.blocked_paths = [
            "/etc/",
            "/sys/",
            "/proc/",
            "/root/",
        ]
    
    def validate_path(self, path):
        """验证路径是否允许访问"""
        # 检查是否在阻止列表中
        for blocked in self.blocked_paths:
            if path.startswith(blocked):
                raise PermissionError(f"Access to {path} is blocked")
        
        # 检查是否在白名单中
        for allowed in self.allowed_paths:
            if path.startswith(allowed):
                return True
        
        raise PermissionError(f"Access to {path} is not allowed")

2. 网络访问控制

class NetworkValidator:
    def __init__(self):
        self.allowed_domains = [
            "repo1.maven.org",
            "api.github.com",
            # 只允许访问可信域名
        ]
    
    def validate_url(self, url):
        """验证 URL 是否允许访问"""
        from urllib.parse import urlparse
        parsed = urlparse(url)
        
        if parsed.netloc not in self.allowed_domains:
            raise PermissionError(f"Access to {parsed.netloc} is not allowed")
        
        return True

2. 输入校验(Input Validation)

使用 JSON Schema 严格校验大模型生成的参数:

from jsonschema import validate, ValidationError

class SkillInputValidator:
    def __init__(self, skill_schema):
        self.schema = skill_schema
    
    def validate(self, input_data):
        """验证输入数据"""
        try:
            validate(instance=input_data, schema=self.schema)
            return True, None
        except ValidationError as e:
            return False, str(e)

示例 Schema

{
  "type": "object",
  "properties": {
    "groupId": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_]*([.][a-z][a-z0-9_]*)*$"
    },
    "artifactId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-SNAPSHOT)?$"
    }
  },
  "required": ["groupId", "artifactId"]
}

3. 审计日志(Audit Logging)

记录所有技能调用的参数与响应,用于行为回溯:

class AuditLogger:
    def log_skill_call(self, skill_name, user_id, input_params, output, success):
        """记录技能调用"""
        log_entry = {
            "timestamp": datetime.now().isoformat(),
            "skill": skill_name,
            "user": user_id,
            "input": input_params,
            "output": output if success else None,
            "error": None if success else str(output),
            "success": success
        }
        
        # 写入审计日志(不可篡改)
        self.write_to_audit_log(log_entry)

4. 敏感词过滤

对技能的输出内容进行合规性扫描:

class ContentFilter:
    def __init__(self):
        self.sensitive_patterns = [
            r"password\s*[:=]\s*\S+",
            r"api[_-]?key\s*[:=]\s*\S+",
            r"secret\s*[:=]\s*\S+",
        ]
    
    def filter_output(self, content):
        """过滤敏感内容"""
        for pattern in self.sensitive_patterns:
            content = re.sub(pattern, "[REDACTED]", content, flags=re.IGNORECASE)
        return content

质量保证与持续改进

1. 技能质量评估

1.1 召回率测试(Recall Testing)

模拟不同用户提问,测试技能是否能被正确触发:

class RecallTester:
    def __init__(self, skill, test_cases):
        self.skill = skill
        self.test_cases = test_cases
    
    def test_recall(self):
        """测试召回率"""
        results = {
            "total": len(self.test_cases),
            "correct": 0,
            "false_positives": 0,
            "false_negatives": 0
        }
        
        for test_case in self.test_cases:
            user_input = test_case["input"]
            expected_skill = test_case["expected_skill"]
            
            # 模拟技能选择
            selected_skill = self.route_to_skill(user_input)
            
            if selected_skill == expected_skill:
                results["correct"] += 1
            elif selected_skill is None:
                results["false_negatives"] += 1
            else:
                results["false_positives"] += 1
        
        recall = results["correct"] / results["total"]
        return recall, results

1.2 精确率测试(Precision Testing)

测试技能被触发时,是否真的应该被触发:

class PrecisionTester:
    def test_precision(self, skill_name, negative_cases):
        """测试精确率"""
        false_positives = 0
        
        for case in negative_cases:
            # 这些用例不应该触发该技能
            if self.should_trigger(skill_name, case):
                false_positives += 1
        
        precision = 1 - (false_positives / len(negative_cases))
        return precision

2. A/B 测试

测试不同版本的技能描述,选择效果最好的:

class ABTester:
    def __init__(self, skill_variants):
        self.variants = skill_variants
        self.results = {variant: [] for variant in skill_variants}
    
    def test_variant(self, variant, user_input):
        """测试技能变体"""
        # 执行技能并记录结果
        result = self.execute_skill(variant, user_input)
        self.results[variant].append({
            "input": user_input,
            "result": result,
            "timestamp": time.time()
        })
    
    def get_best_variant(self):
        """获取最佳变体"""
        # 基于成功率、响应时间等指标选择最佳变体
        scores = {}
        for variant, results in self.results.items():
            success_rate = sum(1 for r in results if r["result"]["success"]) / len(results)
            avg_duration = np.mean([r["result"]["duration"] for r in results])
            scores[variant] = success_rate / avg_duration
        
        return max(scores, key=scores.get)

3. 持续改进流程

用户反馈
  ↓
问题分析
  ↓
技能优化(描述、示例、资源)
  ↓
A/B 测试
  ↓
部署新版本
  ↓
监控指标
  ↓
收集反馈(循环)

案例研究:Maven 搜索专家技能

1. 需求分析

问题:开发者经常需要查找 Maven 依赖的坐标,但:

  • 需要打开浏览器
  • 需要记住 Maven Central 的 URL
  • 需要手动复制坐标到 pom.xml

目标:将 3 分钟的手动过程缩短为 5 秒钟的对话

2. 技能设计

2.1 用例设计

用例 用户输入 预期输出
按名称搜索 "查找 Spring Boot" Spring Boot 的 Maven 坐标
按坐标查询 "Guava 的最新版本是什么?" 最新版本号和坐标
生成依赖代码 "帮我添加 Lombok 到 pom.xml" XML 代码块

2.2 资源规划

  • Scriptsscripts/search_maven.py(搜索逻辑)
  • Referencesreference/maven-coordinates.md(坐标规范)
  • Examples:6 个示例文件(覆盖主要用例)
  • APIapi/maven-central-api.md(API 文档)

3. 实现细节

3.1 SKILL.md 设计

Frontmatter

---
name: maven-search
description: |
  Provides comprehensive guidance for searching and retrieving Maven 
  components from Maven Central Repository. Use when the user needs 
  to find, verify, or retrieve Maven dependencies, check component 
  versions, analyze dependency trees, or work with Maven coordinates.
license: Complete terms in LICENSE.txt
---

Body 结构

  1. When to use this skill:明确的触发条件
  2. How to use this skill:工作流程和步骤
  3. API Endpoints:Maven Central API 说明
  4. Best Practices:最佳实践和注意事项
  5. Keywords:中英文关键词列表

3.2 脚本实现

#!/usr/bin/env python3
"""Maven Central Repository 搜索脚本"""
import requests
import json
import sys

def search_by_name(query, limit=10):
    """按名称搜索"""
    url = "https://search.maven.org/solrsearch/select"
    params = {"q": query, "rows": limit, "wt": "json"}
    response = requests.get(url, params=params)
    return response.json()

def get_latest_version(group_id, artifact_id):
    """获取最新版本"""
    metadata_url = f"https://repo1.maven.org/maven2/{group_id.replace('.', '/')}/{artifact_id}/maven-metadata.xml"
    # 解析 XML,提取 latest 标签
    # ...

4. 效果评估

指标

  • 召回率:95%(100 个测试用例中,95 个正确触发)
  • 精确率:98%(100 次触发中,98 次是正确的)
  • 平均响应时间:2.3 秒(从用户提问到返回结果)
  • 用户满意度:4.5/5.0

改进点

  • 优化 description,增加更多触发关键词
  • 添加更多示例,覆盖边界情况
  • 实现结果缓存,提升响应速度

总结与展望

核心要点

  1. 标准化是基础:遵循 Agent Skills 规范,确保技能的可发现性、可组合性和可维护性
  2. 渐进式披露:通过三层加载机制(元数据 → SKILL.md → 资源文件)管理上下文
  3. 领域驱动设计:按业务边界组织技能,使用统一语言和清晰的边界
  4. 安全第一:建立权限沙箱、输入校验、审计日志等安全机制
  5. 持续改进:通过 A/B 测试、指标监控、用户反馈不断优化技能

未来展望

  1. 技能市场生态:建立技能市场,促进技能共享和协作
  2. 自动化测试:开发自动化测试框架,提升技能质量
  3. 技能组合优化:通过机器学习优化技能选择和组合
  4. 跨平台支持:支持更多 AI 平台(Claude、GPT、Gemini 等)

参考资料


文档版本:1.0.0
最后更新:2024-12-19
维护者:Full-Stack-Skills Team