Skip to main content

OpenClaw 自定义技能开发:打造专属 AI 能力

·4018 words·9 mins

前言
#

技能(Skills)是 OpenClaw 的核心扩展机制。通过自定义技能,你可以让 AI 助手掌握特定领域的专业能力,如运维监控、数据分析、自动化测试等。

本文将深入讲解:

  • 技能系统架构
  • 技能开发完整流程
  • 实战案例:服务器监控技能
  • 技能测试与调试
  • 技能发布与共享

技能系统架构
#

技能 vs 插件
#

特性 技能(Skills) 插件(Plugins)
定位 AI 能力扩展 功能模块扩展
触发 语义识别自动激活 工具调用
配置 SKILL.md 定义 package.json 定义
依赖 可调用工具 可注册工具
示例 天气查询技能 天气 API 插件

技能目录结构
#

my-skill/
├── SKILL.md              # 技能定义(必需)
├── script.sh             # 执行脚本(可选)
├── config.json           # 配置文件(可选)
└── assets/               # 资源文件(可选)
    └── templates/        # 模板文件

技能开发流程
#

步骤 1:创建技能目录
#

# 在 workspace 中创建技能目录
mkdir -p ~/.openclaw/workspace/skills/server-monitor
cd ~/.openclaw/workspace/skills/server-monitor

步骤 2:编写 SKILL.md
#

SKILL.md 是技能的核心定义文件:

# Server Monitor Skill

## Description
监控服务器健康状态,包括 CPU、内存、磁盘、网络等指标。

## Location
/usr/lib/node_modules/openclaw/skills/healthcheck/SKILL.md

## Activation
当用户询问服务器状态、健康检查、性能监控时自动激活。

## Triggers
- "服务器状态"
- "健康检查"
- "CPU 使用率"
- "内存占用"
- "磁盘空间"
- "系统负载"

## Capabilities
- 实时指标采集
- 阈值告警
- 历史趋势分析
- 多服务器监控

## Configuration
在 TOOLS.md 中配置监控目标:

```markdown
### SSH Hosts

- prod-server → 47.252.1.11, user: root
- staging-server → 47.252.1.12, user: admin

Usage Examples
#

查询单台服务器:

检查 prod-server 的状态

查询所有服务器:

所有服务器健康检查

查询特定指标:

prod-server 的 CPU 使用率

Output Format
#

返回结构化监控数据:

{
  "hostname": "prod-server",
  "status": "healthy",
  "metrics": {
    "cpu": 45.2,
    "memory": 67.8,
    "disk": 52.1,
    "load": [1.2, 1.5, 1.8]
  },
  "alerts": []
}

### 步骤 3:编写执行脚本

创建 `script.sh`:

```bash
#!/bin/bash

# Server Monitor Skill Script
# 采集服务器监控指标

set -e

SERVER=${1:-"localhost"}

# 获取 CPU 使用率
get_cpu_usage() {
    top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
}

# 获取内存使用率
get_memory_usage() {
    free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}'
}

# 获取磁盘使用率
get_disk_usage() {
    df -h / | tail -1 | awk '{print $5}' | cut -d'%' -f1
}

# 获取系统负载
get_load_average() {
    cat /proc/loadavg | awk '{print $1, $2, $3}'
}

# 获取网络流量
get_network_io() {
    cat /proc/net/dev | grep -E "eth0|ens" | awk '{print $2, $10}'
}

# 主函数
main() {
    echo "=== Server Monitor: $SERVER ==="
    echo ""
    
    CPU=$(get_cpu_usage)
    MEMORY=$(get_memory_usage)
    DISK=$(get_disk_usage)
    LOAD=$(get_load_average)
    
    echo "📊 CPU Usage: ${CPU}%"
    echo "📊 Memory Usage: ${MEMORY}%"
    echo "📊 Disk Usage: ${DISK}%"
    echo "📊 Load Average: ${LOAD}"
    echo ""
    
    # 状态判断
    STATUS="healthy"
    ALERTS=()
    
    if (( $(echo "$CPU > 80" | bc -l) )); then
        ALERTS+=("⚠️  High CPU usage: ${CPU}%")
        STATUS="warning"
    fi
    
    if (( $(echo "$MEMORY > 80" | bc -l) )); then
        ALERTS+=("⚠️  High memory usage: ${MEMORY}%")
        STATUS="warning"
    fi
    
    if (( $(echo "$DISK > 85" | bc -l) )); then
        ALERTS+=("⚠️  High disk usage: ${DISK}%")
        STATUS="warning"
    fi
    
    if [ ${#ALERTS[@]} -gt 0 ]; then
        echo "⚠️  Alerts:"
        for alert in "${ALERTS[@]}"; do
            echo "  - $alert"
        done
    else
        echo "✅ All systems healthy"
    fi
    
    echo ""
    echo "Status: $STATUS"
}

main "$@"

步骤 4:配置技能权限
#

openclaw.json 中添加技能配置:

{
  "skills": {
    "entries": {
      "server-monitor": {
        "enabled": true,
        "location": "/root/.openclaw/workspace/skills/server-monitor",
        "config": {
          "checkInterval": 300,
          "thresholds": {
            "cpu": 80,
            "memory": 80,
            "disk": 85
          }
        }
      }
    }
  }
}

实战案例:完整的监控技能
#

案例背景
#

为阿里云服务器集群开发监控技能,支持:

  • 多服务器批量检查
  • 关键指标阈值告警
  • 历史数据记录
  • 飞书消息推送

完整 SKILL.md
#

# Aliyun Server Monitor Skill

## Description
阿里云服务器集群监控技能,支持 ECS 实例健康检查、性能指标采集、告警推送。

## Location
/root/.openclaw/workspace/skills/aliyun-monitor/SKILL.md

## Activation
当用户询问服务器状态、ECS 监控、健康检查时自动激活。

## Triggers
- 服务器相关:"服务器"、"ECS"、"实例"、"主机"
- 监控相关:"监控"、"状态"、"健康"、"检查"
- 指标相关:"CPU"、"内存"、"磁盘"、"网络"、"负载"

## Capabilities
- ✅ 单实例状态查询
- ✅ 多实例批量检查
- ✅ 关键指标阈值告警
- ✅ 历史趋势分析
- ✅ 飞书消息推送
- ✅ 定时巡检任务

## Configuration

### TOOLS.md 配置

```markdown
### Aliyun ECS

- prod-web-01 → i-bp1234567890, region: cn-hangzhou
- prod-db-01 → i-bp0987654321, region: cn-hangzhou
- staging-01 → i-bp1122334455, region: cn-shanghai

openclaw.json 配置
#

{
  "skills": {
    "aliyun-monitor": {
      "enabled": true,
      "config": {
        "accessKeyId": "LTAI5t...",
        "accessKeySecret": "...",
        "region": "cn-hangzhou",
        "checkInterval": 300,
        "alertChannels": ["feishu"],
        "thresholds": {
          "cpu_critical": 90,
          "cpu_warning": 80,
          "memory_critical": 90,
          "memory_warning": 80,
          "disk_critical": 90,
          "disk_warning": 85
        }
      }
    }
  }
}

Usage Examples
#

查询单台服务器:

prod-web-01 状态怎么样?
检查 i-bp1234567890 的健康状态

查询所有服务器:

所有服务器健康检查
批量检查 ECS 实例

查询特定指标:

prod-db-01 的 CPU 使用率
所有服务器的内存占用

设置监控:

开启 prod-web-01 的定时监控
每 5 分钟检查一次 staging-01

Output Format
#

单实例响应
#

📊 **prod-web-01** 健康状态

✅ 状态:正常

**关键指标:**
- CPU: 45.2% (正常)
- 内存:67.8% (正常)
- 磁盘:52.1% (正常)
- 负载:1.2, 1.5, 1.8

**实例信息:**
- 实例 ID: i-bp1234567890
- 区域:cn-hangzhou
- 规格:ecs.c6.xlarge
- 运行时间:45 天 12 小时

多实例响应
#

📊 **服务器集群健康报告**

| 实例 | 状态 | CPU | 内存 | 磁盘 |
|------|------|-----|------|------|
| prod-web-01 | ✅ | 45% | 68% | 52% |
| prod-db-01 | ✅ | 32% | 71% | 68% |
| staging-01 | ⚠️ | 82% | 75% | 45% |

**告警:**
- staging-01: CPU 使用率偏高 (82%)

Dependencies
#

  • aliyun-cli: 阿里云命令行工具
  • jq: JSON 处理工具
  • bc: 计算器(用于阈值比较)

### 完整脚本实现

创建 `script.sh`:

```bash
#!/bin/bash

# Aliyun Server Monitor Skill
# 支持单实例查询、批量检查、告警推送

set -e

# 配置
ACCESS_KEY_ID="${ALIYUN_ACCESS_KEY_ID:-}"
ACCESS_KEY_SECRET="${ALIYUN_ACCESS_KEY_SECRET:-}"
REGION="${ALIYUN_REGION:-cn-hangzhou}"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 配置阿里云 CLI
configure_aliyun() {
    if [ -n "$ACCESS_KEY_ID" ] && [ -n "$ACCESS_KEY_SECRET" ]; then
        aliyun configure set \
            --profile default \
            --mode AK \
            --access-key-id "$ACCESS_KEY_ID" \
            --access-key-secret "$ACCESS_KEY_SECRET" \
            --region "$REGION"
    fi
}

# 获取实例信息
get_instance_info() {
    local instance_id=$1
    
    aliyun ecs DescribeInstances \
        --RegionId "$REGION" \
        --InstanceIds "[\"$instance_id\"]" \
        --output json | jq '.Instances.Instance[0]'
}

# 获取监控数据
get_monitor_data() {
    local instance_id=$1
    local metric=$2
    local period=300
    
    local end_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local start_time=$(date -u -d "5 minutes ago" +"%Y-%m-%dT%H:%M:%SZ")
    
    aliyun cms DescribeMetricLast \
        --Namespace acs_ecs_dashboard \
        --MetricName "$metric" \
        --Dimensions "{\"instanceId\":\"$instance_id\"}" \
        --Period "$period" \
        --output json | jq '.Datapoints[0].Average // 0'
}

# 检查单实例
check_instance() {
    local instance_id=$1
    local instance_name=$2
    
    log_info "Checking instance: $instance_name ($instance_id)"
    
    # 获取监控数据
    local cpu=$(get_monitor_data "$instance_id" "CPUUtilization")
    local memory=$(get_monitor_data "$instance_id" "MemoryUtilization")
    local disk=$(get_monitor_data "$instance_id" "DiskUtilization")
    
    # 状态判断
    local status="healthy"
    local alerts=()
    
    # CPU 检查
    if (( $(echo "$cpu > 90" | bc -l) )); then
        alerts+=("CPU 临界:${cpu}%")
        status="critical"
    elif (( $(echo "$cpu > 80" | bc -l) )); then
        alerts+=("CPU 警告:${cpu}%")
        status="warning"
    fi
    
    # 内存检查
    if (( $(echo "$memory > 90" | bc -l) )); then
        alerts+=("内存临界:${memory}%")
        status="critical"
    elif (( $(echo "$memory > 80" | bc -l) )); then
        alerts+=("内存警告:${memory}%")
        [ "$status" != "critical" ] && status="warning"
    fi
    
    # 磁盘检查
    if (( $(echo "$disk > 90" | bc -l) )); then
        alerts+=("磁盘临界:${disk}%")
        status="critical"
    elif (( $(echo "$disk > 85" | bc -l) )); then
        alerts+=("磁盘警告:${disk}%")
        [ "$status" != "critical" ] && status="warning"
    fi
    
    # 输出结果
    echo ""
    echo "📊 **$instance_name** 健康状态"
    echo ""
    
    case $status in
        "healthy")
            echo "✅ 状态:正常"
            ;;
        "warning")
            echo "⚠️  状态:警告"
            ;;
        "critical")
            echo "🚨 状态:临界"
            ;;
    esac
    
    echo ""
    echo "**关键指标:**"
    echo "- CPU: ${cpu}% $([ $(echo "$cpu > 80" | bc -l) -eq 1 ] && echo "(偏高)" || echo "(正常)")"
    echo "- 内存:${memory}% $([ $(echo "$memory > 80" | bc -l) -eq 1 ] && echo "(偏高)" || echo "(正常)")"
    echo "- 磁盘:${disk}% $([ $(echo "$disk > 85" | bc -l) -eq 1 ] && echo "(偏高)" || echo "(正常)")"
    
    if [ ${#alerts[@]} -gt 0 ]; then
        echo ""
        echo "**告警:**"
        for alert in "${alerts[@]}"; do
            echo "- $alert"
        done
    fi
    
    echo ""
}

# 批量检查
batch_check() {
    local instances_file="$1"
    
    echo "📊 **服务器集群健康报告**"
    echo ""
    echo "| 实例 | 状态 | CPU | 内存 | 磁盘 |"
    echo "|------|------|-----|------|------|"
    
    while IFS='|' read -r name instance_id; do
        [ -z "$name" ] && continue
        
        local cpu=$(get_monitor_data "$instance_id" "CPUUtilization")
        local memory=$(get_monitor_data "$instance_id" "MemoryUtilization")
        local disk=$(get_monitor_data "$instance_id" "DiskUtilization")
        
        local status_icon="✅"
        local status="healthy"
        
        if (( $(echo "$cpu > 90" | bc -l) )) || (( $(echo "$memory > 90" | bc -l) )) || (( $(echo "$disk > 90" | bc -l) )); then
            status_icon="🚨"
            status="critical"
        elif (( $(echo "$cpu > 80" | bc -l) )) || (( $(echo "$memory > 80" | bc -l) )) || (( $(echo "$disk > 85" | bc -l) )); then
            status_icon="⚠️"
            status="warning"
        fi
        
        echo "| $name | $status_icon | ${cpu}% | ${memory}% | ${disk}% |"
    done < "$instances_file"
}

# 发送飞书告警
send_feishu_alert() {
    local webhook="$1"
    local title="$2"
    local content="$3"
    
    curl -X POST "$webhook" \
        -H "Content-Type: application/json" \
        -d "{
            \"msg_type\": \"interactive\",
            \"card\": {
                \"header\": {
                    \"title\": {
                        \"tag\": \"plain_text\",
                        \"content\": \"$title\"
                    },
                    \"template\": \"red\"
                },
                \"elements\": [
                    {
                        \"tag\": \"markdown\",
                        \"content\": \"$content\"
                    }
                ]
            }
        }"
}

# 主函数
main() {
    local command=${1:-"help"}
    shift || true
    
    case $command in
        "check")
            check_instance "$@"
            ;;
        "batch")
            batch_check "$@"
            ;;
        "alert")
            send_feishu_alert "$@"
            ;;
        *)
            echo "Usage: $0 {check|batch|alert} [args...]"
            echo ""
            echo "Commands:"
            echo "  check <instance_id> [instance_name]  - 检查单实例"
            echo "  batch <instances_file>               - 批量检查"
            echo "  alert <webhook> <title> <content>    - 发送告警"
            ;;
    esac
}

# 配置阿里云 CLI
configure_aliyun

# 执行主函数
main "$@"

技能测试
#

单元测试
#

创建 test.sh

#!/bin/bash

# 测试脚本

echo "Running skill tests..."

# 测试 CPU 获取
cpu=$(./script.sh get_cpu)
if [ -n "$cpu" ]; then
    echo "✅ CPU check passed"
else
    echo "❌ CPU check failed"
    exit 1
fi

# 测试内存获取
memory=$(./script.sh get_memory)
if [ -n "$memory" ]; then
    echo "✅ Memory check passed"
else
    echo "❌ Memory check failed"
    exit 1
fi

echo "All tests passed!"

集成测试
#

# 测试单实例检查
./script.sh check i-bp1234567890 prod-web-01

# 测试批量检查
./script.sh batch instances.txt

# 测试告警推送
./script.sh alert "https://open.feishu.cn/open-apis/bot/v2/hook/xxx" \
    "服务器告警" "prod-web-01 CPU 使用率超过阈值"

技能调试技巧
#

启用调试日志
#

在 SKILL.md 中添加:

## Debug

启用调试模式:

```bash
export DEBUG=openclaw:skills:*
openclaw gateway start

### 查看技能激活日志

```bash
# 查看实时日志
tail -f ~/.openclaw/logs/gateway.log | grep -i skill

# 查看特定技能日志
tail -f ~/.openclaw/logs/gateway.log | grep server-monitor

模拟技能调用
#

# 使用 CLI 测试技能
openclaw skill server-monitor --action check --target prod-web-01

技能发布
#

发布到 ClawHub
#

# 初始化技能包
clawhub skill init

# 测试本地技能
clawhub skill test

# 发布技能
clawhub skill publish

编写发布说明
#

# Server Monitor Skill

实时监控服务器健康状态,支持多平台。

## 功能

- ✅ CPU、内存、磁盘监控
- ✅ 阈值告警
- ✅ 批量检查
- ✅ 飞书/钉钉/Telegram 推送

## 安装

```bash
clawhub skill install server-monitor

配置
#

在 TOOLS.md 中添加服务器列表,在 openclaw.json 中配置阈值。

使用
#

直接询问:

  • “服务器状态”
  • “检查 prod-web-01”
  • “所有服务器健康检查”

版本
#

  • v1.0.0 - 初始版本
  • v1.1.0 - 添加批量检查
  • v1.2.0 - 添加告警推送

## 最佳实践

### 1. 错误处理

```bash
# 始终检查命令返回值
if ! command -v aliyun &> /dev/null; then
    echo "❌ aliyun CLI not installed"
    exit 1
fi

# 捕获异常
trap 'echo "Error occurred at line $LINENO"; exit 1' ERR

2. 配置管理
#

# 使用配置文件
CONFIG_FILE="${CONFIG_FILE:-~/.openclaw/skills/monitor/config.json}"

if [ -f "$CONFIG_FILE" ]; then
    THRESHOLD_CPU=$(jq -r '.thresholds.cpu' "$CONFIG_FILE")
else
    THRESHOLD_CPU=80
fi

3. 性能优化
#

# 使用缓存
CACHE_DIR="/tmp/monitor-cache"
CACHE_TTL=300  # 5 分钟

get_cached_data() {
    local key=$1
    local cache_file="$CACHE_DIR/$key"
    
    if [ -f "$cache_file" ] && [ $(($(date +%s) - $(stat -c %Y "$cache_file"))) -lt $CACHE_TTL ]; then
        cat "$cache_file"
        return 0
    fi
    
    return 1
}

4. 安全考虑
#

# 不硬编码密钥
if [ -z "$ACCESS_KEY_ID" ]; then
    echo "❌ ALIYUN_ACCESS_KEY_ID not set"
    exit 1
fi

# 限制脚本权限
chmod 700 script.sh
chown root:root script.sh

常见问题
#

Q: 技能不激活?
#

检查:

  1. SKILL.md 中 Triggers 定义完整
  2. 技能已启用(openclaw.json)
  3. 技能路径正确

Q: 脚本执行失败?
#

检查:

  1. 脚本有执行权限:chmod +x script.sh
  2. 依赖工具已安装
  3. 环境变量已配置

Q: 如何调试技能?
#

# 启用详细日志
export OPENCLAW_LOG_LEVEL=debug

# 查看技能加载
openclaw skills list --verbose

总结
#

自定义技能让你能够:

  • ✅ 扩展 AI 助手的专业能力
  • ✅ 集成内部系统和工具
  • ✅ 自动化复杂工作流
  • ✅ 分享团队最佳实践

下一步:

  1. 确定业务场景需求
  2. 设计技能触发规则
  3. 开发执行脚本
  4. 测试并优化
  5. 发布到 ClawHub

相关资源:

下一篇: 《OpenClaw API 集成指南:连接外部系统》