Agent Skills 和工具使用:构建专业化 AI 能力
Agent Skills, Tools, AI Agent

Agent Skills 和工具使用:构建专业化 AI 能力

深入探讨 Anthropic 的 Agent Skills 系统和工具使用最佳实践,打造模块化、可重用的 Agent 能力。

0次点击7分钟阅读

引言

Agent Skills 是 Anthropic 推出的革命性功能,它允许开发者构建专业化、模块化、可重用的 Agent 能力。本文将详细介绍如何使用 Agent Skills 和设计高效的工具系统。

什么是 Agent Skills

Agent Skills 是一种组织 Agent 能力的新方式:

  • 专业化能力包:将特定领域的知识和工具组织在一起
  • 动态发现:Agent 可以自动发现可用的 Skills
  • 按需加载:只在需要时加载相关 Skills
  • 可重用:在不同 Agent 和项目间共享

Skills 的结构

skills/
├── code-review/
│   ├── instructions.md        # Skill 说明
│   ├── checklist.json         # 检查清单
│   ├── examples/              # 示例
│   │   ├── good-example.md
│   │   └── bad-example.md
│   └── tools/                 # 相关工具
│       └── linter-config.json
├── data-analysis/
│   ├── instructions.md
│   ├── templates/
│   │   └── analysis-report.md
│   └── scripts/
│       ├── clean_data.py
│       └── visualize.py
└── api-testing/
    ├── instructions.md
    ├── test-cases/
    └── tools/
        └── test-runner.ts

创建 Agent Skill

1. 基础 Skill 模板

1# Code Review Skill
2
3## 目的
4提供专业的代码审查能力,帮助识别代码质量问题、安全漏洞和性能瓶颈。
5
6## 能力范围
7- 代码质量评估
8- 安全漏洞检测
9- 性能分析
10- 最佳实践检查
11
12## 使用场景
131. Pull Request 审查
142. 代码重构前的评估
153. 新人代码指导
164. 生产问题分析
17
18## 审查标准
19
20### 代码质量
21- [ ] 命名是否清晰
22- [ ] 函数是否单一职责
23- [ ] 是否有重复代码
24- [ ] 注释是否充分
25
26### 性能
27- [ ] 时间复杂度是否合理
28- [ ] 是否有不必要的计算
29- [ ] 数据库查询是否优化
30- [ ] 是否有内存泄漏风险
31
32### 安全
33- [ ] 输入是否验证
34- [ ] 是否有 SQL 注入风险
35- [ ] 敏感数据是否加密
36- [ ] 权限检查是否完整
37
38## 输出格式
39
40### 问题报告
41{
42  "severity": "high | medium | low",
43  "category": "quality | performance | security",
44  "location": "file:line",
45  "description": "问题描述",
46  "suggestion": "改进建议",
47  "example": "代码示例"
48}
49
50## 相关资源
51- OWASP Top 10: https://owasp.org/www-project-top-ten/
52- Clean Code: https://github.com/ryanmcdermott/clean-code-javascript

2. 实现 Skill 加载器

1import os
2import json
3from pathlib import Path
4
5class SkillLoader:
6    def __init__(self, skills_dir="./skills"):
7        self.skills_dir = Path(skills_dir)
8        self.loaded_skills = {}
9
10    def discover_skills(self):
11        """发现所有可用的 Skills"""
12        skills = []
13
14        for skill_dir in self.skills_dir.iterdir():
15            if skill_dir.is_dir():
16                instructions_file = skill_dir / "instructions.md"
17                if instructions_file.exists():
18                    skill_info = {
19                        "name": skill_dir.name,
20                        "path": str(skill_dir),
21                        "instructions": instructions_file.read_text()
22                    }
23
24                    # 读取元数据(如果存在)
25                    metadata_file = skill_dir / "metadata.json"
26                    if metadata_file.exists():
27                        skill_info["metadata"] = json.loads(
28                            metadata_file.read_text()
29                        )
30
31                    skills.append(skill_info)
32
33        return skills
34
35    def load_skill(self, skill_name):
36        """加载特定 Skill"""
37        if skill_name in self.loaded_skills:
38            return self.loaded_skills[skill_name]
39
40        skill_path = self.skills_dir / skill_name
41        if not skill_path.exists():
42            raise ValueError(f"Skill '{skill_name}' 不存在")
43
44        # 读取指令
45        instructions = (skill_path / "instructions.md").read_text()
46
47        # 读取工具
48        tools = self._load_tools(skill_path / "tools")
49
50        # 读取示例
51        examples = self._load_examples(skill_path / "examples")
52
53        skill = {
54            "name": skill_name,
55            "instructions": instructions,
56            "tools": tools,
57            "examples": examples
58        }
59
60        self.loaded_skills[skill_name] = skill
61        return skill
62
63    def _load_tools(self, tools_dir):
64        """加载 Skill 相关的工具"""
65        if not tools_dir.exists():
66            return []
67
68        tools = []
69        for tool_file in tools_dir.glob("*.json"):
70            tool_config = json.loads(tool_file.read_text())
71            tools.append(tool_config)
72
73        return tools
74
75    def _load_examples(self, examples_dir):
76        """加载示例"""
77        if not examples_dir.exists():
78            return []
79
80        examples = []
81        for example_file in examples_dir.glob("*.md"):
82            examples.append({
83                "name": example_file.stem,
84                "content": example_file.read_text()
85            })
86
87        return examples
88
89# 使用
90loader = SkillLoader()
91
92# 发现所有 Skills
93available_skills = loader.discover_skills()
94print(f"发现 {len(available_skills)} 个 Skills:")
95for skill in available_skills:
96    print(f"- {skill['name']}")
97
98# 加载特定 Skill
99code_review_skill = loader.load_skill("code-review")

3. Agent 中使用 Skills

1class SkillfulAgent:
2    def __init__(self):
3        self.skill_loader = SkillLoader()
4        self.active_skills = []
5
6    async def activate_skill(self, skill_name):
7        """激活一个 Skill"""
8        skill = self.skill_loader.load_skill(skill_name)
9        self.active_skills.append(skill)
10
11        # 将 Skill 指令添加到 Agent 上下文
12        await self.add_to_context(skill["instructions"])
13
14        # 注册 Skill 工具
15        for tool in skill["tools"]:
16            await self.register_tool(tool)
17
18        return f"已激活 Skill: {skill_name}"
19
20    async def execute_with_skill(self, task, skill_name):
21        """使用特定 Skill 执行任务"""
22        # 激活 Skill
23        await self.activate_skill(skill_name)
24
25        # 构建提示词
26        prompt = self._build_prompt_with_skill(task, skill_name)
27
28        # 执行任务
29        response = await self.call_claude(prompt)
30
31        return response
32
33    def _build_prompt_with_skill(self, task, skill_name):
34        skill = next(s for s in self.active_skills if s["name"] == skill_name)
35
36        prompt = f"""
37        <skill>
38        {skill["instructions"]}
39        </skill>
40
41        <examples>
42        {self._format_examples(skill["examples"])}
43        </examples>
44
45        <task>
46        {task}
47        </task>
48
49        请使用上述 Skill 的指导完成任务。
50        """
51
52        return prompt
53
54# 使用
55agent = SkillfulAgent()
56
57# 审查代码
58review_result = await agent.execute_with_skill(
59    task="审查这个 Pull Request",
60    skill_name="code-review"
61)

工具设计最佳实践

1. 工具定义规范

1def create_tool_definition(
2    name: str,
3    description: str,
4    parameters: dict,
5    examples: list = None
6):
7    """创建标准化的工具定义"""
8    return {
9        "name": name,
10        "description": f"""
11        {description}
12
13        使用场景:
14        {parameters.get('use_cases', '通用场景')}
15
16        最佳实践:
17        {parameters.get('best_practices', '按照文档使用')}
18
19        注意事项:
20        {parameters.get('warnings', '无')}
21
22        示例:
23        {format_examples(examples) if examples else '参见文档'}
24        """,
25        "input_schema": {
26            "type": "object",
27            "properties": parameters.get("properties", {}),
28            "required": parameters.get("required", [])
29        }
30    }
31
32# 示例:创建搜索工具
33search_tool = create_tool_definition(
34    name="web_search",
35    description="搜索互联网获取实时信息",
36    parameters={
37        "use_cases": """
38        - 查找最新资讯
39        - 研究技术文档
40        - 验证事实数据
41        """,
42        "best_practices": """
43        - 使用具体的搜索词
44        - 包含时间范围
45        - 避免过于宽泛
46        """,
47        "warnings": """
48        - 搜索结果可能不准确
49        - 需要人工验证重要信息
50        """,
51        "properties": {
52            "query": {
53                "type": "string",
54                "description": "搜索查询"
55            },
56            "num_results": {
57                "type": "integer",
58                "default": 5
59            }
60        },
61        "required": ["query"]
62    },
63    examples=[
64        {
65            "query": "Claude 4 发布时间",
66            "num_results": 3
67        }
68    ]
69)

2. 工具错误处理

1class RobustTool:
2    def __init__(self, tool_func, max_retries=3):
3        self.tool_func = tool_func
4        self.max_retries = max_retries
5        self.call_history = []
6
7    async def execute(self, **kwargs):
8        """执行工具,包含错误处理"""
9        for attempt in range(self.max_retries):
10            try:
11                # 验证输入
12                validated_input = self.validate_input(kwargs)
13
14                # 记录调用
15                self.call_history.append({
16                    "attempt": attempt + 1,
17                    "input": validated_input,
18                    "timestamp": time.time()
19                })
20
21                # 执行工具
22                result = await self.tool_func(**validated_input)
23
24                # 验证输出
25                validated_output = self.validate_output(result)
26
27                return {
28                    "success": True,
29                    "result": validated_output,
30                    "attempt": attempt + 1
31                }
32
33            except ValidationError as e:
34                # 输入验证失败,不重试
35                return {
36                    "success": False,
37                    "error": f"输入验证失败: {str(e)}",
38                    "error_type": "validation"
39                }
40
41            except Exception as e:
42                # 执行失败,可能重试
43                if attempt < self.max_retries - 1:
44                    # 等待后重试
45                    await asyncio.sleep(2 ** attempt)
46                    continue
47                else:
48                    return {
49                        "success": False,
50                        "error": f"执行失败: {str(e)}",
51                        "error_type": "execution",
52                        "attempts": self.max_retries
53                    }
54
55    def validate_input(self, kwargs):
56        """验证输入参数"""
57        # 实现输入验证逻辑
58        return kwargs
59
60    def validate_output(self, result):
61        """验证输出结果"""
62        # 实现输出验证逻辑
63        return result

3. 工具组合

1class ToolChain:
2    """将多个工具链接成流水线"""
3
4    def __init__(self, tools):
5        self.tools = tools
6
7    async def execute(self, initial_input):
8        """顺序执行所有工具"""
9        current_input = initial_input
10
11        for i, tool in enumerate(self.tools):
12            print(f"执行工具 {i+1}/{len(self.tools)}: {tool.name}")
13
14            # 执行工具
15            result = await tool.execute(**current_input)
16
17            # 检查是否成功
18            if not result.get("success"):
19                return {
20                    "success": False,
21                    "failed_at": i,
22                    "error": result.get("error")
23                }
24
25            # 将输出作为下一个工具的输入
26            current_input = result["result"]
27
28        return {
29            "success": True,
30            "final_result": current_input
31        }
32
33# 示例:创建工具链
34tool_chain = ToolChain([
35    FetchWebpageTool(),
36    ExtractContentTool(),
37    SummarizeTool(),
38    TranslateTool()
39])
40
41# 执行
42result = await tool_chain.execute({
43    "url": "https://example.com/article"
44})

高级工具模式

1. 条件工具使用

1class ConditionalToolRouter:
2    """根据条件选择工具"""
3
4    def __init__(self, tools_map):
5        self.tools_map = tools_map
6
7    async def route_and_execute(self, context, task):
8        """根据上下文路由到合适的工具"""
9
10        # 分析任务类型
11        task_type = await self.analyze_task_type(task)
12
13        # 选择工具
14        if task_type not in self.tools_map:
15            return {
16                "success": False,
17                "error": f"没有找到处理 '{task_type}' 的工具"
18            }
19
20        tool = self.tools_map[task_type]
21
22        # 执行工具
23        return await tool.execute(context=context, task=task)
24
25    async def analyze_task_type(self, task):
26        """分析任务类型"""
27        prompt = f"""
28        分析以下任务的类型:
29
30        {task}
31
32        可能的类型:
33        - web_search: 需要搜索网络
34        - data_analysis: 需要分析数据
35        - code_generation: 需要生成代码
36        - file_operation: 需要操作文件
37
38        只返回类型名称。
39        """
40
41        response = await call_claude(prompt)
42        return response.strip()
43
44# 使用
45router = ConditionalToolRouter({
46    "web_search": WebSearchTool(),
47    "data_analysis": DataAnalysisTool(),
48    "code_generation": CodeGenerationTool(),
49    "file_operation": FileOperationTool()
50})
51
52result = await router.route_and_execute(
53    context=current_context,
54    task="搜索 Claude 4 的最新功能"
55)

2. 并行工具执行

1class ParallelToolExecutor:
2    """并行执行多个工具"""
3
4    def __init__(self, tools):
5        self.tools = tools
6
7    async def execute_all(self, inputs):
8        """并行执行所有工具"""
9        tasks = [
10            tool.execute(**input_data)
11            for tool, input_data in zip(self.tools, inputs)
12        ]
13
14        results = await asyncio.gather(*tasks, return_exceptions=True)
15
16        # 处理结果
17        processed_results = []
18        for i, result in enumerate(results):
19            if isinstance(result, Exception):
20                processed_results.append({
21                    "tool_index": i,
22                    "success": False,
23                    "error": str(result)
24                })
25            else:
26                processed_results.append({
27                    "tool_index": i,
28                    "success": True,
29                    "result": result
30                })
31
32        return processed_results
33
34# 示例:并行分析
35executor = ParallelToolExecutor([
36    SentimentAnalysisTool(),
37    KeywordExtractionTool(),
38    LanguageDetectionTool(),
39    TopicModelingTool()
40])
41
42results = await executor.execute_all([
43    {"text": article_text},
44    {"text": article_text},
45    {"text": article_text},
46    {"text": article_text}
47])

3. 自适应工具选择

1class AdaptiveToolSelector:
2    """根据历史表现自适应选择工具"""
3
4    def __init__(self, tools):
5        self.tools = tools
6        self.performance_history = {
7            tool.name: {"success": 0, "failure": 0, "avg_time": 0}
8            for tool in tools
9        }
10
11    async def select_and_execute(self, task):
12        """选择最佳工具并执行"""
13
14        # 让 Agent 评估每个工具
15        evaluations = await self.evaluate_tools(task)
16
17        # 结合历史表现评分
18        scored_tools = []
19        for tool_name, ai_score in evaluations.items():
20            history = self.performance_history[tool_name]
21
22            # 计算综合评分
23            success_rate = (
24                history["success"] /
25                (history["success"] + history["failure"])
26                if (history["success"] + history["failure"]) > 0
27                else 0.5
28            )
29
30            combined_score = 0.6 * ai_score + 0.4 * success_rate
31
32            scored_tools.append((tool_name, combined_score))
33
34        # 选择得分最高的工具
35        best_tool_name = max(scored_tools, key=lambda x: x[1])[0]
36        best_tool = next(t for t in self.tools if t.name == best_tool_name)
37
38        # 执行并记录性能
39        start_time = time.time()
40        try:
41            result = await best_tool.execute(task=task)
42            success = True
43        except Exception as e:
44            result = {"error": str(e)}
45            success = False
46
47        execution_time = time.time() - start_time
48
49        # 更新历史
50        self.update_performance(best_tool_name, success, execution_time)
51
52        return result
53
54    async def evaluate_tools(self, task):
55        """让 AI 评估工具适用性"""
56        tool_descriptions = "\n".join([
57            f"- {tool.name}: {tool.description}"
58            for tool in self.tools
59        ])
60
61        prompt = f"""
62        任务:{task}
63
64        可用工具:
65        {tool_descriptions}
66
67        请为每个工具评分(0-1),表示它处理此任务的适合程度。
68
69        输出 JSON 格式:
70        {{
71            "tool_name": score,
72            ...
73        }}
74        """
75
76        response = await call_claude(prompt)
77        return json.loads(response)
78
79    def update_performance(self, tool_name, success, execution_time):
80        """更新工具性能记录"""
81        history = self.performance_history[tool_name]
82
83        if success:
84            history["success"] += 1
85        else:
86            history["failure"] += 1
87
88        # 更新平均执行时间
89        total_executions = history["success"] + history["failure"]
90        history["avg_time"] = (
91            (history["avg_time"] * (total_executions - 1) + execution_time)
92            / total_executions
93        )

实战案例:数据分析 Skill

1# skills/data-analysis/instructions.md
2"""
3# Data Analysis Skill
4
5## 目的
6提供全面的数据分析能力,从数据清洗到可视化。
7
8## 工作流程
91. 数据加载和探索
102. 数据清洗和预处理
113. 统计分析
124. 可视化
135. 生成报告
14
15## 可用工具
16- load_data: 加载各种格式的数据
17- clean_data: 清洗和预处理
18- analyze_stats: 统计分析
19- create_visualization: 创建图表
20- generate_report: 生成分析报告
21"""
22
23class DataAnalysisSkill:
24    def __init__(self):
25        self.tools = {
26            "load_data": LoadDataTool(),
27            "clean_data": CleanDataTool(),
28            "analyze_stats": StatisticalAnalysisTool(),
29            "create_visualization": VisualizationTool(),
30            "generate_report": ReportGenerationTool()
31        }
32
33    async def analyze_dataset(self, dataset_path):
34        """完整的数据分析流程"""
35
36        # 1. 加载数据
37        print("加载数据...")
38        data = await self.tools["load_data"].execute(path=dataset_path)
39
40        # 2. 数据探索
41        print("探索数据...")
42        exploration_report = await self.explore_data(data)
43
44        # 3. 数据清洗
45        print("清洗数据...")
46        cleaned_data = await self.tools["clean_data"].execute(data=data)
47
48        # 4. 统计分析
49        print("统计分析...")
50        stats = await self.tools["analyze_stats"].execute(data=cleaned_data)
51
52        # 5. 创建可视化
53        print("创建可视化...")
54        visualizations = await self.create_visualizations(cleaned_data, stats)
55
56        # 6. 生成报告
57        print("生成报告...")
58        report = await self.tools["generate_report"].execute(
59            data=cleaned_data,
60            stats=stats,
61            visualizations=visualizations
62        )
63
64        return report
65
66    async def explore_data(self, data):
67        """探索数据特征"""
68        prompt = f"""
69        请探索这个数据集并提供概述:
70
71        数据形状:{data.shape}
72        列名:{list(data.columns)}
73        数据类型:{data.dtypes.to_dict()}
74        缺失值:{data.isnull().sum().to_dict()}
75
76        请提供:
77        1. 数据集概述
78        2. 潜在的数据质量问题
79        3. 建议的分析方向
80        """
81
82        response = await call_claude(prompt)
83        return response
84
85    async def create_visualizations(self, data, stats):
86        """创建多个可视化图表"""
87
88        # 决定需要哪些图表
89        viz_plan = await self.plan_visualizations(data, stats)
90
91        # 并行创建所有图表
92        viz_tasks = [
93            self.tools["create_visualization"].execute(
94                data=data,
95                type=viz["type"],
96                config=viz["config"]
97            )
98            for viz in viz_plan
99        ]
100
101        visualizations = await asyncio.gather(*viz_tasks)
102
103        return visualizations

工具生态系统

常用工具类别

  1. 数据获取工具

    • Web搜索
    • API 调用
    • 数据库查询
    • 文件读取
  2. 数据处理工具

    • 数据清洗
    • 格式转换
    • 数据验证
    • 数据聚合
  3. 分析工具

    • 统计分析
    • 机器学习
    • 文本分析
    • 图像处理
  4. 输出工具

    • 报告生成
    • 可视化
    • 文件写入
    • 通知发送

构建工具库

1class ToolRegistry:
2    """工具注册中心"""
3
4    def __init__(self):
5        self.tools = {}
6        self.categories = {}
7
8    def register(self, tool, category=None):
9        """注册工具"""
10        self.tools[tool.name] = tool
11
12        if category:
13            if category not in self.categories:
14                self.categories[category] = []
15            self.categories[category].append(tool.name)
16
17    def get_tool(self, name):
18        """获取工具"""
19        if name not in self.tools:
20            raise ValueError(f"工具 '{name}' 未注册")
21        return self.tools[name]
22
23    def list_tools(self, category=None):
24        """列出工具"""
25        if category:
26            if category not in self.categories:
27                return []
28            return [
29                self.tools[name]
30                for name in self.categories[category]
31            ]
32        return list(self.tools.values())
33
34    def search_tools(self, query):
35        """搜索工具"""
36        results = []
37        for tool in self.tools.values():
38            if query.lower() in tool.name.lower() or \
39               query.lower() in tool.description.lower():
40                results.append(tool)
41        return results
42
43# 使用
44registry = ToolRegistry()
45
46# 注册工具
47registry.register(WebSearchTool(), category="data_acquisition")
48registry.register(DatabaseQueryTool(), category="data_acquisition")
49registry.register(DataCleaningTool(), category="data_processing")
50registry.register(VisualizationTool(), category="output")
51
52# 查找工具
53search_tools = registry.search_tools("search")
54acquisition_tools = registry.list_tools(category="data_acquisition")

最佳实践总结

Skills 设计

  1. 单一职责:每个 Skill 聚焦一个专业领域
  2. 完整文档:提供清晰的说明和示例
  3. 模块化:Skill 之间低耦合
  4. 可测试:提供测试用例
  5. 版本管理:追踪 Skill 版本变化

工具设计

  1. 清晰描述:工具功能和使用场景
  2. 健壮性:错误处理和重试机制
  3. 性能优化:缓存和批处理
  4. 安全性:输入验证和权限检查
  5. 可监控:记录调用和性能指标

Agent 集成

  1. 按需加载:只加载必要的 Skills
  2. 上下文感知:根据任务选择 Skills
  3. 工具链接:组合多个工具完成复杂任务
  4. 持续学习:从使用中优化 Skills 和工具

总结

Agent Skills 和工具系统是构建强大 AI Agent 的基础。通过模块化、专业化的设计,我们可以创建可重用、可维护的 Agent 能力库,大幅提升 Agent 开发效率和质量。

参考资源

相关文章