第 19 期 | 社区生态与 Skill Marketplace 贡献指南
好的,这是为 Hermes Agent 教程撰写的第 19 期文章。
副标题:深入了解 Open Source 玩法:如何标准化封装并向 agentskills.io 商城发布自己开发的超酷开源 Skill。
学习目标
欢迎来到 Hermes Agent 教程的第 19 期!在本期中,我们将从 Skill 的“使用者”转变为“创造者”和“贡献者”。一个强大 Agent 的真正威力不仅在于其核心框架,更在于其繁荣的生态系统。本章将带领你深入了解 Hermes Agent 的社区生态,并手把手教你如何将自己开发的 Skill 标准化打包,最终发布到官方的 Skill Marketplace (agentskills.io),与全球的开发者共享你的智慧。
完成本期学习后,你将能够:
- 理解 Skill Marketplace 的核心价值:明白为什么一个标准化的 Skill 分发平台对整个生态至关重要。
- 掌握可发布 Skill 的标准结构:学习一个生产级 Skill 包所应包含的所有元素,特别是
skill.yaml清单文件。 - 精通
skill.yaml的配置:深入了解清单文件中每个字段的含义,包括元数据、入口点、依赖、参数和权限声明。 - 实战打包与发布流程:亲手将一个示例 Skill 从代码封装成可分发的
.tar.gz包,并使用hermesCLI 工具将其发布到 Marketplace。 - 了解社区贡献的最佳实践:学习如何编写清晰的文档、选择合适的许可证,让你的 Skill 更易被社区接受和使用。
核心概念讲解
在动手之前,我们需要理解几个支撑 Skill Marketplace 运作的核心概念。这不仅仅是技术细节,更是保证生态系统健康、有序发展的基石。
1. 为什么需要 Skill Marketplace?
想象一下,如果没有 App Store 或 PyPI,我们如何寻找和安装软件?我们可能需要去各种 GitHub 仓库,手动处理复杂的依赖关系,甚至面临安全风险。Skill Marketplace (我们虚构的官方商城为 agentskills.io) 解决了同样的问题:
- 发现与分发 (Discovery & Distribution):为开发者提供一个中心化的平台来展示他们的作品,也让用户能轻松地搜索、发现和一键安装所需的 Skill。
- 标准化与质量控制 (Standardization & Quality Control):通过定义一套标准的打包规范(例如,必须包含
skill.yaml),确保所有 Skill 的结构一致,易于 Agent 核心系统加载和管理。同时,发布前的审核流程可以保障 Skill 的质量和安全性。 - 版本管理 (Versioning):允许开发者迭代和更新他们的 Skill,用户也可以选择安装特定版本,或者平滑升级,避免了因 Skill 更新导致的兼容性问题。
- 依赖管理 (Dependency Management):Marketplace 可以自动处理 Skill 所需的 Python 库依赖,用户安装 Skill 时,Agent 会自动安装
requirements.txt中指定的库,极大简化了环境配置。 - 社区激励 (Community Incentive):开发者的贡献被看见、被使用、被点赞,这本身就是一种强大的激励。优秀的 Skill 开发者可以在社区中建立声誉,形成良性循环。
2. 可发布 Skill 的解剖学 (Anatomy of a Publishable Skill)
一个准备发布到 Marketplace 的 Skill 不再是你在本地开发时的一两个 Python 文件,而是一个结构严谨、信息完备的软件包。一个标准的 Skill 包通常包含以下文件结构:
my_awesome_skill/
├── __init__.py # Skill 的核心逻辑与入口点
├── skill.yaml # [核心] Skill 的清单文件,描述一切元数据
├── requirements.txt # Python 依赖列表
├── README.md # 详细的说明文档
├── LICENSE # 开源许可证文件
└── icon.png # (可选) 在 Marketplace 中显示的图标
其中,skill.yaml 是整个包的灵魂,它向 Hermes Agent 和 Marketplace 系统声明了关于这个 Skill 的一切。
3. skill.yaml 清单文件深度解析
skill.yaml 使用 YAML 格式,这是一种人类可读的数据序列化标准。它告诉系统如何加载、配置和执行你的 Skill。一个完整的 skill.yaml 文件可能包含以下字段:
# 基础元数据 (Basic Metadata)
name: "GitHubRepoInsights"
version: "1.0.0" # 遵循语义化版本 (Semantic Versioning)
author: "Your Name <[email protected]>"
description: "A skill to fetch and display key statistics (stars, forks, open issues) for a given GitHub repository."
# 执行配置 (Execution Configuration)
entry_point: "GitHubRepoInsightsSkill" # 在 __init__.py 中定义的 Skill 类名
# 依赖管理 (Dependency Management)
dependencies:
python: ">=3.8"
# requirements.txt 会被自动读取,这里是为更复杂的系统级依赖预留
system: []
# 参数定义 (Parameters Definition)
# 定义 Skill 在执行时可以接收的参数,这对于 UI 生成和 API 调用至关重要
parameters:
- name: "repo_url"
type: "string"
description: "The full URL of the public GitHub repository (e.g., https://github.com/torvalds/linux)."
required: true
default: ""
# 权限声明 (Permissions Declaration)
# 明确声明 Skill 需要的权限,增强安全性
permissions:
- "network.http_request" # 声明需要访问外部网络的权限
- "filesystem.read" # (示例) 声明需要读取本地文件的权限
name: Skill 的唯一标识符,通常使用驼峰式命名法 (CamelCase)。version: 必须遵循 SemVer (Semantic Versioning) 规范(MAJOR.MINOR.PATCH)。例如1.0.0。这对于依赖管理和更新至关重要。author&description: 不言而喻,作者信息和功能简介。entry_point: 指定__init__.py文件中,继承自BaseSkill的主类名。Agent 会通过这个入口点来实例化你的 Skill。dependencies: 声明对 Python 版本或其他系统工具的依赖。更常见的 Python 库依赖应放在requirements.txt中。parameters: 这是让你的 Skill 变得动态和可配置的关键。这里定义的参数可以在 Agent 的 UI 中自动生成输入框,或者在通过 API 调用 Skill 时作为必需的参数。每个参数都包含name,type,description,required等属性。permissions: 安全是第一位的。在这里明确声明你的 Skill 需要什么权限。比如,如果你的 Skill 需要访问互联网,就必须声明network.http_request。在安装时,用户会被提示授权这些权限,这给了用户最终的控制权。
💻 实战演示
现在,让我们从零开始,创建一个名为 GitHubRepoInsights 的 Skill,它能够接收一个 GitHub 仓库 URL,然后返回该仓库的 Star 数、Fork 数和 Open Issues 数。我们将完整地走过开发、打包和发布的全部流程。
第 1 步:创建 Skill 项目结构
首先,在你的工作目录下创建 Skill 的文件夹和必要的文件。
# 创建主目录
mkdir github_repo_insights
# 进入目录
cd github_repo_insights
# 创建必要的文件
touch __init__.py skill.yaml requirements.txt README.md LICENSE
现在你的目录看起来是这样的:
github_repo_insights/
├── __init__.py
├── LICENSE
├── README.md
├── requirements.txt
└── skill.yaml
第 2 步:编写 Skill 核心逻辑 (__init__.py)
打开 __init__.py 文件,我们将在这里编写与 GitHub API 交互的 Python 代码。
# __init__.py
import requests
import json
from hermes_agent.skills import BaseSkill, SkillResult
class GitHubRepoInsightsSkill(BaseSkill):
"""
A skill to fetch and display key statistics for a GitHub repository.
"""
def __init__(self):
# 调用父类的构造函数
super().__init__()
# 设置 GitHub API 的基础 URL
self.api_base_url = "https://api.github.com/repos/"
def _parse_repo_path(self, repo_url: str) -> str or None:
"""
Helper function to parse 'owner/repo' from a full GitHub URL.
Example: "https://github.com/torvalds/linux" -> "torvalds/linux"
"""
try:
parts = repo_url.strip().rstrip('/').split('/')
if len(parts) >= 2 and parts[-2] and parts[-1]:
return f"{parts[-2]}/{parts[-1]}"
return None
except Exception:
return None
def execute(self, parameters: dict) -> SkillResult:
"""
The main execution method for the skill.
"""
repo_url = parameters.get("repo_url")
if not repo_url:
return SkillResult(
success=False,
message="Error: 'repo_url' parameter is missing."
)
repo_path = self._parse_repo_path(repo_url)
if not repo_path:
return SkillResult(
success=False,
message=f"Error: Invalid GitHub repository URL format: {repo_url}"
)
# 构造完整的 API 请求 URL
api_url = f"{self.api_base_url}{repo_path}"
try:
# 发起网络请求,需要 network.http_request 权限
self.logger.info(f"Requesting data from: {api_url}")
response = requests.get(api_url, timeout=10)
# 检查请求是否成功
response.raise_for_status()
data = response.json()
# 提取所需信息
stars = data.get('stargazers_count', 'N/A')
forks = data.get('forks_count', 'N/A')
open_issues = data.get('open_issues_count', 'N/A')
# 格式化输出
result_message = (
f"📊 GitHub Repo Insights for '{repo_path}':\n"
f"⭐ Stars: {stars}\n"
f"🍴 Forks: {forks}\n"
f"🐞 Open Issues: {open_issues}"
)
return SkillResult(
success=True,
message=result_message,
data={
"stars": stars,
"forks": forks,
"open_issues": open_issues
}
)
except requests.exceptions.HTTPError as e:
error_msg = f"Error fetching data from GitHub API: {e.response.status_code} {e.response.reason}"
if e.response.status_code == 404:
error_msg = f"Repository '{repo_path}' not found. Please check the URL."
self.logger.error(error_msg)
return SkillResult(success=False, message=error_msg)
except Exception as e:
self.logger.error(f"An unexpected error occurred: {e}")
return SkillResult(success=False, message=f"An unexpected error occurred: {str(e)}")
代码要点:
- 我们继承了
BaseSkill并实现了execute方法。 execute方法从parameters字典中获取repo_url。- 我们添加了一个辅助函数
_parse_repo_path来从完整的 URL 中提取owner/repo部分。 - 使用了
requests库来调用 GitHub API,这正是我们需要在requirements.txt中声明的依赖。 - 返回一个
SkillResult对象,其中包含成功状态、给用户看的消息 (message) 和可供其他 Skill 使用的结构化数据 (data)。 - 包含了详细的错误处理和日志记录,这是一个良好实践。
第 3 步:定义依赖与清单文件
requirements.txt: 我们的代码用到了requests库,所以编辑requirements.txt文件,添加这一行:requests>=2.25.0skill.yaml: 现在,让我们来填写至关重要的清单文件。编辑skill.yaml:name: "GitHubRepoInsights" version: "1.0.0" author: "Hermes AI Labs <[email protected]>" description: "A skill to fetch and display key statistics (stars, forks, open issues) for a given public GitHub repository." entry_point: "GitHubRepoInsightsSkill" dependencies: python: ">=3.8" parameters: - name: "repo_url" type: "string" description: "The full URL of the public GitHub repository (e.g., https://github.com/torvalds/linux)." required: true permissions: - "network.http_request"这个文件完美地描述了我们的 Skill:它的身份、入口、参数和所需权限。
第 4 步:完善文档和许可证
README.md: 一个好的README文件能让你的 Skill 更受欢迎。# GitHub Repo Insights Skill This skill provides a quick way to get essential statistics for any public GitHub repository. ## Features - Fetches Star count - Fetches Fork count - Fetches Open Issue count ## Usage To use this skill, simply provide the full URL of a public GitHub repository. **Example Input:** `https://github.com/facebook/react` **Example Output:**📊 GitHub Repo Insights for 'facebook/react': ⭐ Stars: 215000 🍴 Forks: 45000 🐞 Open Issues: 1200
LICENSE: 选择一个开源许可证非常重要。MIT 许可证是一个流行且宽松的选择。将 MIT 许可证的文本(可以从网上轻松找到)复制到LICENSE文件中。
第 5 步:打包 Skill
所有文件都准备就绪了。现在我们需要将 github_repo_insights 文件夹打包成一个 .tar.gz 文件,这是 Marketplace 接受的标准格式。文件名应遵循 skill_name-version.tar.gz 的格式。
回到 github_repo_insights 的上一级目录,执行以下命令:
# 确保你在 github_repo_insights 文件夹的外面
# 将文件夹打包成 github_repo_insights-1.0.0.tar.gz
tar -czvf github_repo_insights-1.0.0.tar.gz github_repo_insights/
执行后,你会看到一个名为 github_repo_insights-1.0.0.tar.gz 的文件,这就是我们准备发布的 Skill 包。
第 6 步:发布到 Skill Marketplace
最后一步是使用 Hermes Agent 的命令行工具 hermes 来发布我们的 Skill。
登录开发者账户: 首先,你需要在
agentskills.io网站上注册一个开发者账户,并生成一个 API Key。然后通过 CLI 登录。hermes login终端会提示你输入从网站获取的 API Key。
Enter your API Key from agentskills.io: [your_api_key_here] Login successful. Your credentials have been saved.发布 Skill: 使用
hermes skills publish命令并指定你的包文件路径。hermes skills publish github_repo_insights-1.0.0.tar.gz如果一切顺利,你会看到类似下面的输出:
Verifying package integrity... [OK] Parsing skill.yaml manifest... [OK] Uploading package to agentskills.io... [OK] 🚀 Success! Your skill 'GitHubRepoInsights' (v1.0.0) has been submitted for review. You will receive an email notification once the review process is complete. Submission ID: skill-sub-xxxxxxxxxxxx
到此为止,你已经成功地将自己开发的 Skill 提交到了官方 Marketplace!接下来就是等待社区管理员的审核。审核通过后,全球的 Hermes Agent 用户就都能在 Marketplace 中找到并安装你的杰作了。
涉及命令
# 创建项目目录和文件
mkdir github_repo_insights
cd github_repo_insights
touch __init__.py skill.yaml requirements.txt README.md LICENSE
# 打包 Skill (在 github_repo_insights 的上级目录执行)
tar -czvf github_repo_insights-1.0.0.tar.gz github_repo_insights/
# 登录 Hermes 开发者账户
hermes login
# 发布 Skill 包
hermes skills publish github_repo_insights-1.0.0.tar.gz
要点回顾
- 生态系统是核心:Skill Marketplace 是连接开发者和用户的桥梁,是 Hermes Agent 生态繁荣的关键。
skill.yaml是灵魂:这个清单文件定义了 Skill 的一切,是 Agent 理解和运行你的 Skill 的唯一依据。务必保证其内容的准确和完整。- 结构标准化:遵循
__init__.py,skill.yaml,requirements.txt,README.md,LICENSE的标准文件结构,这是一种社区通用语言。 - 安全第一:通过
permissions字段明确声明 Skill 所需的权限,尊重用户的隐私和安全。 - 文档为王:清晰的
README.md是让你的 Skill 被他人理解和使用的最有效方式。 hermesCLI 是你的工具:熟练使用hermes login和hermes skills publish命令来与 Marketplace 交互。
恭喜你完成了这重要的一步!成为开源贡献者不仅能提升你的技术能力,更能让你在社区中找到归属感和成就感。期待在 agentskills.io 上看到你开发的更多超酷 Skill!
参考资料
- agentskills.io 开发者门户: https://agentskills.io/developers
skill.yaml完整规范文档: https://docs.hermes-agent.io/skills/manifest-spec- 语义化版本(Semantic Versioning)2.0.0: https://semver.org/
- Hermes Agent 社区论坛: https://community.hermes-agent.io/