从零开发 OpenClaw Agent 技能:手把手教你写一个可直接运行的天气查询 Skill

27次阅读
没有评论

在大模型智能体Agent)的落地实践中,模块化、可复用的技能(Skill) 是核心能力单元。OpenClaw 作为轻量化、高扩展的 Agent 框架,让技能开发变得极简高效 —— 无需复杂配置,只需遵循标准规范,就能快速实现一个稳定、可集成的实用技能。

本篇博文将带你从零开发一个天气查询 Skill,包含完整代码、核心原理、异常处理和使用教程,新手也能直接上手运行。

一、先搞懂:OpenClaw Skill 是什么?

简单来说,OpenClaw Skill 就是智能体的「专项能力模块」,就像人类的专业技能一样,每个 Skill 只负责一件事(查天气、查快递、写代码、控设备等)。

一个标准的 OpenClaw Skill 必须包含 4 个核心部分:

  1. 技能元信息:名称、描述、版本、作者(让 Agent 识别和调用)
  2. 参数校验:规范输入格式,避免无效调用
  3. 执行逻辑:技能的核心功能实现
  4. 标准化响应:统一输出格式,方便 Agent 解析

二、开发前准备

1. 环境依赖安装

打开终端,执行一行命令安装所需库:

bash

运行

pip install openclaw pydantic requests

2. 必备工具(免费)

我们调用高德地图天气 API获取数据,只需注册免费开发者账号,获取 API 密钥即可:

  • 前往高德开放平台注册
  • 创建应用 → 申请「天气 API」权限 → 复制 API Key

三、完整代码:天气查询 Skill(直接复制可用)

这是一个生产级别的 Skill,包含参数校验、网络请求、异常处理、结果格式化,可直接集成到你的 OpenClaw Agent 中。

python

运行

import requests
from typing import Dict, Any, Optional
from pydantic import BaseModel, Field
from openclaw.core.skill import BaseSkill, SkillResponse
from openclaw.core.constants import SkillStatus

# ====================== 第一步:定义技能输入参数(自动校验) ======================
class WeatherQueryParams(BaseModel):
    """天气查询技能参数模型,Pydantic自动校验类型和必填项"""
    # 必填参数:城市名称
    city: str = Field(..., description="要查询的城市,例如:北京、上海、广州")
    # 可选参数:自定义API密钥
    api_key: Optional[str] = Field(None, description="高德地图API密钥(全局配置可省略)")

# ====================== 第二步:实现核心技能 ======================
class WeatherQuerySkill(BaseSkill):
    """
    OpenClaw 天气查询技能
    功能:查询指定城市的实时温度、天气状况、风力、湿度等信息
    """
    # 【必填】技能基础信息(Agent靠这个识别你的技能)
    skill_name: str = "weather_query"       # 唯一技能名
    skill_desc: str = "查询城市实时天气,支持温度、风向、湿度等信息查询"  # 技能描述
    skill_version: str = "1.0.0"            # 版本号
    skill_author: str = "OpenClaw开发者"     # 作者
    # 绑定参数校验模型
    params_model = WeatherQueryParams

    # 全局配置(替换为你的高德API Key)
    DEFAULT_API_KEY = "你的高德地图API密钥"
    AMAP_API_URL = "https://restapi.amap.com/v3/weather/weatherInfo"

    def execute(self, params: Dict[str, Any]) -> SkillResponse:
        """
        【核心方法】技能执行入口,所有逻辑都在这里
        :param params: 已校验完成的输入参数
        :return: 标准化响应结果
        """
        try:
            # 1. 解析输入参数
            city = params["city"]
            api_key = params.get("api_key") or self.DEFAULT_API_KEY

            # 2. 调用天气API
            res = requests.get(
                url=self.AMAP_API_URL,
                params={
                    "key": api_key,
                    "city": city,
                    "extensions": "base",  # base=实时天气,all=天气预报
                    "output": "json"
                },
                timeout=10
            )
            res.raise_for_status()  # 捕获HTTP请求异常
            data = res.json()

            # 3. 处理API返回结果
            if data.get("status") != "1":
                return SkillResponse(
                    status=SkillStatus.FAILED,
                    message=f"查询失败:{data.get('info', '未知错误')}",
                    data={}
                )

            # 提取核心天气数据
            lives = data.get("lives", [])
            if not lives:
                return SkillResponse(
                    status=SkillStatus.FAILED,
                    message=f"未找到{city}的天气信息",
                    data={}
                )

            info = lives[0]
            result = {
                "城市": info.get("city"),
                "温度": info.get("temperature") + "℃",
                "天气": info.get("weather"),
                "风向": info.get("winddirection"),
                "风力": info.get("windpower") + "级",
                "湿度": info.get("humidity") + "%",
                "更新时间": info.get("reporttime")
            }

            # 4. 返回成功响应
            return SkillResponse(
                status=SkillStatus.SUCCESS,
                message=f"✅ 成功获取{city}实时天气",
                data=result
            )

        # 网络异常捕获
        except requests.exceptions.RequestException as e:
            return SkillResponse(
                status=SkillStatus.FAILED,
                message=f"❌ 网络请求失败:{str(e)}",
                data={}
            )
        # 通用异常捕获(保证技能不崩溃)
        except Exception as e:
            return SkillResponse(
                status=SkillStatus.FAILED,
                message=f"❌ 技能执行异常:{str(e)}",
                data={}
            )

# ====================== 第三步:本地测试技能 ======================
if __name__ == "__main__":
    # 初始化技能
    skill = WeatherQuerySkill()
    # 测试参数
    test_params = {"city": "北京"}
    # 执行技能
    response = skill.execute(test_params)
    
    # 打印结果
    print("="*50)
    print(f"执行状态:{response.status}")
    print(f"提示信息:{response.message}")
    print(f"天气数据:{response.data}")
    print("="*50)

四、代码核心解析(新手必看)

1. 参数校验:拒绝无效输入

我们用Pydantic定义参数模型,框架会自动校验

  • 必须传入city,否则直接报错
  • 自动生成参数描述,方便 Agent 理解调用规则

2. 技能基类:规范就是生产力

所有 Skill 必须继承BaseSkill,这是 OpenClaw 的统一规范:

  • 必须定义skill_name等元信息
  • 必须实现execute方法(技能唯一入口)
  • 必须返回SkillResponse(统一输出)

3. 异常处理:让技能更稳定

代码中做了三层异常防护:

  • HTTP 请求异常(断网、接口超时)
  • API 业务异常(城市错误、密钥无效)
  • 通用未知异常(避免技能崩溃)

4. 标准化响应

SkillResponse包含三个关键字段,Agent 可直接解析:

  • status:执行状态(成功 / 失败 / 运行中)
  • message:人性化提示信息
  • data:结构化结果数据

五、运行效果展示

替换代码中的DEFAULT_API_KEY后,直接运行脚本,输出结果如下:

plaintext

==================================================
执行状态:SUCCESS
提示信息:✅ 成功获取北京实时天气
天气数据:{'城市': '北京', '温度': '15℃', '天气': '晴', '风向': '北', '风力': '3级', '湿度': '45%', '更新时间': '2026-03-27 14:30:00'}
==================================================

六、一键扩展:你的 Skill 还能这么改

这个模板是通用万能模板,只需修改execute方法,就能快速开发任意技能:

  1. 快递查询:替换 API 为快递 100 接口,修改参数为快递单号
  2. 股票行情:调用股票 API,参数改为股票代码
  3. 文本翻译:接入翻译接口,参数为待翻译文本
  4. 设备控制:调用硬件 SDK,实现智能家居控制

七、总结

OpenClaw Skill 开发的核心逻辑,总结为 3 句话:

  1. 继承基类:遵循规范,快速接入框架
  2. 校验参数:保证输入合法,减少报错
  3. 标准化输出:让 Agent 轻松解析和使用

这个天气查询 Skill 不仅可以直接使用,更是你开发其他技能的「脚手架」。按照这个模式,10 分钟就能开发一个生产可用的 Agent 技能。

后续我会分享 OpenClaw 技能注册、多技能编排、Agent 一键调用等进阶内容,关注不迷路~

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)