Claude Code 的 Agent Skills 是什么?如何使用?

265 阅读5分钟

Claude Code 的 Agent Skills 使用指南

什么是 Agent Skills?

Agent Skills 是 Claude API 中的工具调用(Tool Use)机制,允许 Claude 自主决策并调用外部函数完成任务。核心特性:

  • 自主决策 - Claude 判断是否需要调用工具及调用参数
  • 循环执行 - 支持多轮工具调用,逐步完成复杂任务
  • 结构化通信 - 基于 JSON Schema 定义工具接口规范

核心实现流程

1. 定义工具(Tool Definition)

import anthropic

tools = [
    {
        "name": "execute_python",
        "description": "执行 Python 代码并返回输出结果。用于数据处理、计算、文件操作等。",
        "input_schema": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "description": "要执行的 Python 代码片段(不包含输入提示)"
                }
            },
            "required": ["code"]
        }
    },
    {
        "name": "read_file",
        "description": "读取指定路径的文件内容。支持文本和二进制文件。",
        "input_schema": {
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "文件的绝对或相对路径"
                },
                "encoding": {
                    "type": "string",
                    "description": "文件编码方式,默认 utf-8",
                    "default": "utf-8"
                }
            },
            "required": ["path"]
        }
    }
]

2. 初始化 Agent 请求

client = anthropic.Anthropic(api_key="your-api-key")

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=4096,
    tools=tools,
    messages=[
        {
            "role": "user",
            "content": "读取 data.csv 文件,计算销售总额和平均值"
        }
    ]
)

3. 循环处理工具调用

import subprocess
import json

def execute_tool(tool_name: str, tool_input: dict):
    """执行工具并返回结果"""
    if tool_name == "execute_python":
        try:
            # 安全执行:使用 subprocess 隔离环境
            result = subprocess.run(
                ["python", "-c", tool_input["code"]],
                capture_output=True,
                text=True,
                timeout=30
            )
            return result.stdout or result.stderr
        except subprocess.TimeoutExpired:
            return "错误: 代码执行超时(超过30秒)"
        except Exception as e:
            return f"错误: {str(e)}"
  
    elif tool_name == "read_file":
        try:
            with open(
                tool_input["path"],
                "r",
                encoding=tool_input.get("encoding", "utf-8")
            ) as f:
                return f.read()
        except FileNotFoundError:
            return f"错误: 文件不存在 - {tool_input['path']}"
        except Exception as e:
            return f"错误: {str(e)}"

# 持续循环直到 Agent 完成任务
messages = [
    {"role": "user", "content": "读取 data.csv 文件,计算销售总额和平均值"}
]

while True:
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=4096,
        tools=tools,
        messages=messages
    )
  
    # 检查是否有工具调用
    if response.stop_reason == "tool_use":
        # 找到工具调用块
        assistant_message = {"role": "assistant", "content": response.content}
        messages.append(assistant_message)
      
        # 处理所有工具调用
        tool_results = []
        for content_block in response.content:
            if content_block.type == "tool_use":
                tool_result = execute_tool(
                    content_block.name,
                    content_block.input
                )
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": content_block.id,
                    "content": tool_result
                })
      
        # 反馈工具结果
        messages.append({
            "role": "user",
            "content": tool_results
        })
    else:
        # Agent 已完成(stop_reason == "end_turn")
        break

# 提取最终文本响应
final_response = next(
    (b.text for b in response.content if hasattr(b, "text")),
    None
)
print("Agent 响应:", final_response)

实战案例:完整的数据分析 Agent

import anthropic
import subprocess
import json
import os

class DataAnalysisAgent:
    def __init__(self):
        self.client = anthropic.Anthropic()
        self.tools = self._define_tools()
  
    def _define_tools(self):
        return [
            {
                "name": "execute_python",
                "description": "执行 Python 代码进行数据处理和分析",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "code": {
                            "type": "string",
                            "description": "Python 代码(可导入 pandas, numpy, matplotlib)"
                        }
                    },
                    "required": ["code"]
                }
            },
            {
                "name": "read_file",
                "description": "读取文件内容",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "path": {"type": "string", "description": "文件路径"}
                    },
                    "required": ["path"]
                }
            },
            {
                "name": "list_files",
                "description": "列出目录中的文件",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "directory": {
                            "type": "string",
                            "description": "目录路径,默认当前目录",
                            "default": "."
                        }
                    }
                }
            }
        ]
  
    def _execute_tool(self, tool_name: str, tool_input: dict) -> str:
        """执行工具"""
        if tool_name == "execute_python":
            # 预配置 imports
            code = f"""
import pandas as pd
import numpy as np
import json

{tool_input['code']}
"""
            try:
                result = subprocess.run(
                    ["python", "-c", code],
                    capture_output=True,
                    text=True,
                    timeout=30,
                    cwd=os.getcwd()
                )
                if result.returncode != 0:
                    return f"执行错误:\n{result.stderr}"
                return result.stdout or "(无输出)"
            except subprocess.TimeoutExpired:
                return "错误: 执行超时"
            except Exception as e:
                return f"错误: {str(e)}"
      
        elif tool_name == "read_file":
            try:
                with open(tool_input["path"], "r", encoding="utf-8") as f:
                    content = f.read()
                    # 限制输出长度
                    return content[:5000] if len(content) > 5000 else content
            except FileNotFoundError:
                return f"文件不存在: {tool_input['path']}"
            except Exception as e:
                return f"读取错误: {str(e)}"
      
        elif tool_name == "list_files":
            try:
                directory = tool_input.get("directory", ".")
                files = os.listdir(directory)
                return json.dumps(files, ensure_ascii=False, indent=2)
            except Exception as e:
                return f"列表错误: {str(e)}"
      
        return "未知工具"
  
    def run(self, user_task: str):
        """运行 Agent"""
        messages = [{"role": "user", "content": user_task}]
      
        iteration = 0
        max_iterations = 10
      
        while iteration < max_iterations:
            iteration += 1
          
            response = self.client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=4096,
                tools=self.tools,
                messages=messages
            )
          
            print(f"\n--- 迭代 {iteration} ---")
            print(f"停止原因: {response.stop_reason}")
          
            if response.stop_reason == "end_turn":
                # Agent 完成
                final_text = next(
                    (b.text for b in response.content if hasattr(b, "text")),
                    None
                )
                print(f"\n✓ Agent 完成响应:\n{final_text}")
                return final_text
          
            elif response.stop_reason == "tool_use":
                # 添加 Assistant 消息
                messages.append({"role": "assistant", "content": response.content})
              
                # 执行所有工具调用
                tool_results = []
                for block in response.content:
                    if block.type == "tool_use":
                        print(f"  → 调用工具: {block.name}")
                        print(f"    参数: {json.dumps(block.input, ensure_ascii=False)}")
                      
                        result = self._execute_tool(block.name, block.input)
                        print(f"    结果: {result[:200]}..." if len(result) > 200 else f"    结果: {result}")
                      
                        tool_results.append({
                            "type": "tool_result",
                            "tool_use_id": block.id,
                            "content": result
                        })
              
                messages.append({"role": "user", "content": tool_results})
            else:
                print(f"意外的停止原因: {response.stop_reason}")
                break
      
        print(f"\n✗ 超过最大迭代次数 ({max_iterations})")
        return None

# 使用示例
if __name__ == "__main__":
    agent = DataAnalysisAgent()
  
    task = """
    1. 列出当前目录的文件
    2. 如果存在 sales.csv,读取前10行
    3. 计算该文件中销售额的总和、平均值和最大值
    4. 生成一份简要报告
    """
  
    agent.run(task)

工具定义最佳实践

维度最佳实践反面示例
描述清晰度"执行 Python 代码进行数据处理""运行代码"
参数验证使用required 数组明确必填项依赖可选参数
输出限制返回不超过 10000 字符的结果返回大型数据集
错误处理返回结构化错误信息不处理异常
命名规范snake_case(execute_python)混合大小写

关键注意事项

安全隔离

# ✓ 推荐:使用 subprocess 隔离执行环境
subprocess.run(
    ["python", "-c", code],
    capture_output=True,
    timeout=30
)

# ✗ 避免:直接 exec/eval
exec(code)  # 危险!

成本控制

# 限制单次请求的 token 数
response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=2048,  # 设置合理上限
    tools=tools,
    messages=messages
)

# 限制迭代次数
for iteration in range(10):  # 最多10轮
    if response.stop_reason == "end_turn":
        break

结果验证

# 验证工具结果的有效性
if len(tool_result) > 50000:
    tool_result = tool_result[:50000] + "\n[输出已截断]"

# 捕获所有异常
try:
    result = execute_tool(tool_name, tool_input)
except Exception as e:
    result = f"工具执行失败: {str(e)}"

Agent Skills 的核心在于明确的工具定义 + 完善的错误处理 + 高效的循环管理。遵循上述模式可快速构建可靠的自动化工作流。

博主的个人网站接入了claude haiku 4.5模型,欢迎访问:micefind.com