Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 53 additions & 14 deletions docs/mkdocs/en/skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -2143,17 +2143,56 @@ The **Dynamic Tool Selection** mechanism has been fully implemented and verified
- ❌ All tools need to be available simultaneously
- ❌ Token cost is not a primary concern

## References and Examples

- Background:
- Blog:
https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- Open repository: https://github.com/anthropics/skills
- This repository:
- Interactive demo: [examples/skills/run_agent.py](../../../examples/skills/run_agent.py)
- Dynamic tool selection full example: [examples/skills_with_dynamic_tools/run_agent.py](../../../examples/skills_with_dynamic_tools/run_agent.py)
- Example structure guide: [examples/skills/README.md](../../../examples/skills/README.md)
- Example skills:
- [examples/skills/skills/python-math/SKILL.md](../../../examples/skills/skills/python-math/SKILL.md)
- [examples/skills/skills/file_tools/SKILL.md](../../../examples/skills/skills/file_tools/SKILL.md)
- [examples/skills/skills/user_file_ops/SKILL.md](../../../examples/skills/skills/user_file_ops/SKILL.md)
## Skill Hub - Discovering and Fetching Skills from Remote Sources

**Skill Hub** (`trpc_agent_sdk.skills.hub`) is a set of adapters (`SkillSource`) for discovering and fetching skills from remote sources. It provides three capabilities: searching for available skills from a source (GitHub, ClawHub, skills.sh, and others), inspecting metadata for a specific skill, and downloading the complete file contents for that skill. Users can also implement the `SkillSource` interface to integrate their own skill source.

### `SkillSource` Contract

Every adapter implements the same four-method interface:

```python
from trpc_agent_sdk.skills.hub import SkillSource, SkillMeta, SkillBundle

class SkillSource(ABC):
def source_id(self) -> str: ...
def search(self, query: str, limit: int = 10) -> list[SkillMeta]: ...
def inspect(self, identifier: str) -> SkillMeta | None: ...
def fetch(self, identifier: str) -> SkillBundle | None: ...
```

- `SkillMeta` - lightweight search/inspect result (`name`, `description`, `source`, `identifier`, plus optional `repo`/`path`/`tags`/`extra`)
- `SkillBundle` - the downloaded skill (`name`, `files: dict[str, str | bytes]`, `source`, `identifier`, `metadata`)

`fetch()` only returns an in-memory `SkillBundle`. Writing it to disk (including overwrite policy, atomic writes, and concurrency safety) is the **caller's** responsibility, because different harnesses have different installation semantics. For this purpose, the SDK also exports three path validation functions:

```python
from trpc_agent_sdk.skills.hub import validate_skill_name, validate_category_name, validate_bundle_rel_path
```

### Built-in Adapters

| Adapter | Source | Identifier format |
| --- | --- | --- |
| `GitHubSource` | GitHub repos, via the Contents / Git Trees API | `"owner/repo/path/to/skill-dir"` |
| `WellKnownSkillSource` | Any domain exposing `/.well-known/skills/index.json` | `well-known:{base_url}/{skill_name}` or a raw HTTPS URL |
| `HermesIndexSource` | A centralized, pre-crawled skills catalog | Same identifiers as the underlying `GitHubSource` entries |
| `SkillsShSource` | [skills.sh](https://skills.sh) | `skills-sh/{owner}/{repo}/{skill_path}` |
| `ClawHubSource` | [ClawHub](https://clawhub.ai) | slug, e.g. `"notion"` |
| `ClaudeMarketplaceSource` | Claude Code marketplace repos (`.claude-plugin/marketplace.json`) | Resolves to a `GitHubSource` identifier |
| `LobeHubSource` | LobeHub agent marketplace (converted to synthetic `SKILL.md`) | `lobehub/{agent_id}` |

### Minimal Usage

```python
from trpc_agent_sdk.skills.hub import GitHubAuth, GitHubSource

source = GitHubSource(GitHubAuth()) # no authentication is required for public repositories
meta = source.inspect("anthropics/skills/skills/skill-creator")
bundle = source.fetch("anthropics/skills/skills/skill-creator")
# bundle.files: {"SKILL.md": "...", "scripts/...": "...", ...}
```

### Full Example

See the complete Skill Hub usage example: [examples/skills_hub/run_agent.py](../../../examples/skills_hub/run_agent.py)
115 changes: 101 additions & 14 deletions docs/mkdocs/zh/skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -2141,17 +2141,104 @@ Tools:
- ❌ 所有工具都需要同时可用
- ❌ Token 成本不是主要考虑因素

## 参考和示例

- 背景:
- 博客:
https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- 开放仓库:https://github.com/anthropics/skills
- 本仓库:
- 交互式演示:[examples/skills/run_agent.py](../../../examples/skills/run_agent.py)
- 动态工具选择完整示例:[examples/skills_with_dynamic_tools/run_agent.py](../../../examples/skills_with_dynamic_tools/run_agent.py)
- 示例结构说明:[examples/skills/README.md](../../../examples/skills/README.md)
- 示例技能:
- [examples/skills/skills/python-math/SKILL.md](../../../examples/skills/skills/python-math/SKILL.md)
- [examples/skills/skills/file_tools/SKILL.md](../../../examples/skills/skills/file_tools/SKILL.md)
- [examples/skills/skills/user_file_ops/SKILL.md](../../../examples/skills/skills/user_file_ops/SKILL.md)
## Skill Hub —— 从远程来源发现并获取 Skill

**Skill Hub**(`trpc_agent_sdk.skills.hub`)是一组用于从远程来源发现和获取 skill 的适配器(`SkillSource`)。它能做三件事:搜索某个来源(GitHub、ClawHub、skills.sh 等)上有哪些 skill、查看某个 skill 的元信息、下载它的完整文件内容。用户也可以实现SkillSource 接口来对接自己的skill source.

### `SkillSource` 契约

每个适配器都实现同样的四方法接口:

```python
from trpc_agent_sdk.skills.hub import SkillSource, SkillMeta, SkillBundle

class SkillSource(ABC):
def source_id(self) -> str: ...
def search(self, query: str, limit: int = 10) -> list[SkillMeta]: ...
def inspect(self, identifier: str) -> SkillMeta | None: ...
def fetch(self, identifier: str) -> SkillBundle | None: ...
```

- `SkillMeta` —— 轻量的 search/inspect 结果(`name`、`description`、`source`、`identifier`,以及可选的 `repo`/`path`/`tags`/`extra`)
- `SkillBundle` —— 下载到的 skill(`name`、`files: dict[str, str | bytes]`、`source`、`identifier`、`metadata`)

`fetch()` 只会返回内存中的 `SkillBundle`。如果要使用远程 skill,需要先安装到本地目录。SDK 提供了 `SkillSpec`、`SkillSpecsConfig` 和 `create_default_skill_repository(additional_skill_specs=...)` 的联动入口:把要下载的 `SkillSpec` 列表和 `install_path` 打包成一个 `SkillSpecsConfig`,构造 repository 时先原子写入 `install_path`,再像普通本地 skill 一样扫描索引。`install_path` 可省略,默认落到系统临时目录下的 `trpc_agent_skills`。SDK 也导出了三个路径校验函数,供自定义安装逻辑复用:

```python
from trpc_agent_sdk.skills.hub import validate_skill_name, validate_category_name, validate_bundle_rel_path
```

### 内置适配器

| 适配器 | 来源 | 标识符格式 |
| --- | --- | --- |
| `GitHubSource` | GitHub 仓库,如 https://github.com/anthropics/skills | `owner/repo/path/to/skill-dir`,例如 `"anthropics/skills/skills/skill-creator"` |
| `WellKnownSkillSource` | 暴露 `/.well-known/skills/index.json` 的站点,如 https://www.mintlify.com/docs/.well-known/skills/index.json | HTTPS URL,例如 `"https://example.com/.well-known/skills/plan"` |
| `HermesIndexSource` | [Hermes Skills Index](https://hermes-agent.nousresearch.com/docs/api/skills-index.json) | `owner/repo/path`,例如 `"anthropics/skills/skills/skill-creator"` |
| `SkillsShSource` | [skills.sh](https://skills.sh) | `skills-sh/{owner}/{repo}/{skill_path}`,例如 `"skills-sh/owner/repo/plan"` |
| `ClawHubSource` | [ClawHub](https://clawhub.ai) | `{slug}`,例如 `notion` |
| `ClaudeMarketplaceSource` | 含 `.claude-plugin/marketplace.json` 的 GitHub marketplace 仓库,如 https://github.com/anthropics/skills | `owner/repo/path`,例如 `"anthropics/skills/plugins/docx"` |
| `LobeHubSource` | [LobeHub agent marketplace](https://chat-agents.lobehub.com/index.json) | `lobehub/{agent_id}`,例如 `lobehub/writer-bot` |

### 用法
下面介绍一下 Skill Hub 的基础用法:

```python
from trpc_agent_sdk.skills.hub import GitHubAuth, GitHubSource

# GitHubAuth 不传 token 时按未认证方式访问(限流 60 次/时,仅公开仓库)。
# search 需要 taps 声明"搜哪些仓库";fetch/inspect 直接吃完整 identifier,无需 taps。
source = GitHubSource(
GitHubAuth(),
taps=[{"repo": "anthropics/skills", "path": "skills/"}],
)

# 1) 搜索:在 taps 里匹配关键词,返回一组轻量的 SkillMeta
for meta in source.search("skill", limit=5):
print(meta.name, "-", meta.identifier)

# 2) 查看元信息:只取某个 skill 的 SKILL.md 元数据用于预览
meta = source.inspect("anthropics/skills/skills/skill-creator")
print(meta.name, meta.description)

# 3) 下载:把完整文件内容拉到内存里的 SkillBundle(不落盘)
bundle = source.fetch("anthropics/skills/skills/skill-creator")
if bundle is not None:
print(bundle.name, "共", len(bundle.files), "个文件")
print(bundle.files["SKILL.md"][:200]) # files 是 {相对路径: 内容}
```

`fetch()` 拿到的只是内存里的 `SkillBundle`。要把它接到 agent 用,下面介绍如何把 Skill Hub 和现有的 skill repository 连接起来:

```python
from trpc_agent_sdk.skills import SkillSpec
from trpc_agent_sdk.skills import SkillSpecsConfig
from trpc_agent_sdk.skills import SkillToolSet
from trpc_agent_sdk.skills import create_default_skill_repository
from trpc_agent_sdk.skills.hub import ClawHubSource, GitHubAuth, GitHubSource

repository = create_default_skill_repository(
additional_skill_specs=SkillSpecsConfig(
specs=[
# 每个 SkillSpec 对应一个来源;要从多个来源各取一个 skill,
# 就在 specs 里多放几个 SkillSpec。
SkillSpec(
source=GitHubSource(GitHubAuth()),
identifier="anthropics/skills/skills/skill-creator",
name="skill-creator",
),
SkillSpec(
source=ClawHubSource(),
identifier="notion",
name="notion",
),
],
install_path="data/skills/.downloaded", # 省略则默认落到系统临时目录: <system-temp>/trpc_agent_skills/
),
)
skill_toolset = SkillToolSet(repository=repository)
```

### 完整示例

查看完整的 Skill Hub 使用示例:[examples/skills_hub/run_agent.py](../../../examples/skills_hub/run_agent.py)
8 changes: 8 additions & 0 deletions examples/skills_hub/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Set TRPC_AGENT_API_KEY、TRPC_AGENT_BASE_URL、TRPC_AGENT_MODEL_NAME
TRPC_AGENT_API_KEY=your-api-key
TRPC_AGENT_BASE_URL=your-base-url
TRPC_AGENT_MODEL_NAME=your-model-name

# Optional: a GitHub personal access token (raises the unauthenticated
# 60 req/hr GitHub API limit to 5,000/hr). Not required to run this demo.
# GITHUB_TOKEN=
1 change: 1 addition & 0 deletions examples/skills_hub/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data
51 changes: 51 additions & 0 deletions examples/skills_hub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Skill Hub 示例

本示例演示 `trpc_agent_sdk.skills.hub`(Skill Hub):在启动 `LlmAgent` 之前,通过 `SkillSpecsConfig`(打包 `SkillSpec` + `install_path`)+ `create_default_skill_repository(additional_skill_specs=...)` 从 GitHub 上按需拉取一个技能(Anthropic 官方的 `skill-creator`),写入本地技能目录,再像本地技能一样交给 `SkillToolSet` 使用。

## 什么是 Skill Hub

Skill Hub(`trpc_agent_sdk.skills.hub`)把"从各种来源发现并获取 skill"统一到同一个接口后面。每个来源都是一个 `SkillSource` 适配器,对外提供一致的 `search` / `inspect` / `fetch` 三种能力:

| 适配器 | 来源 |
| --- | --- |
| `GitHubSource` | GitHub 仓库目录(本示例使用) |
| `WellKnownSkillSource` | 站点 `.well-known/skills` |
| `HermesIndexSource` | Hermes 内置 skill index |
| `SkillsShSource` | skills.sh |
| `ClawHubSource` | ClawHub registry |
| `ClaudeMarketplaceSource` | Claude Skills Marketplace |
| `LobeHubSource` | LobeHub |

`SkillSource.fetch()` 只返回内存中的 `SkillBundle`(`name` + `files` + `metadata`)。SDK 提供 `SkillSpec` 声明、`SkillSpecsConfig`(`specs` + `install_path`,`install_path` 省略时默认落到系统临时目录)和 `create_default_skill_repository(additional_skill_specs=...)`,在构造 repository 时把远程 skill 写入 `install_path`,再交给标准 `FsSkillRepository` 扫描。

## 关键特性

- `GitHubSource(GitHubAuth(token))` 无需认证即可拉取公开仓库(60 次/小时限额,足够本示例使用;设置 `GITHUB_TOKEN` 可提升到 5000 次/小时)
- 安装逻辑内部复用 SDK 导出的路径校验,避免恶意 `SkillBundle` 写出到目标目录之外
- 已安装的技能会被跳过,除非 `SkillSpec(replace_if_exists=True)`
- 拉取完成后,技能通过标准的 `create_default_skill_repository` + `SkillToolSet` 链路对 agent 可见,和本地技能没有区别

## Agent 层级结构说明

- 根节点:`LlmAgent`(`skill_hub_demo_agent`),挂载 `SkillToolSet` 与 `skill_repository`
- 无子 Agent;单智能体通过 `skill_load` / `skill_list_docs` 等技能工具完成任务

## 关键代码解释

- `agent/hub.py`:
- `create_skill_tool_set()`:用 `SkillSpecsConfig` 打包 GitHub `SkillSpec` 与 `install_path`,调用 `create_default_skill_repository(additional_skill_specs=...)` 完成安装 + 索引
- `agent/agent.py`:`create_agent(skills_dir)` 把返回的 `skill_repository` / `skill_tool_set` 绑定到 `LlmAgent`
- `run_agent.py`:清空 `data/` 目录(保证每次都重新走一遍 Skill Hub 拉取流程),创建 agent,跑一轮 `skill_load` + 总结的对话,并打印实际下载到的文件列表

## 环境与运行

- Python 3.10+;仓库根目录执行 `pip install -e .`
- 配置 `TRPC_AGENT_API_KEY`、`TRPC_AGENT_BASE_URL`、`TRPC_AGENT_MODEL_NAME`(可用 `.env`)
- 可选:`GITHUB_TOKEN`,用于提高 GitHub API 限额(本示例只读取公开仓库,不设置也能跑)

```bash
cd examples/skills_hub
python3 run_agent.py
```

运行后会在 `data/skills/.downloaded/hub/skill-creator/` 下看到从 GitHub 拉取的真实文件(`SKILL.md`、`scripts/`、`references/` 等)。
5 changes: 5 additions & 0 deletions examples/skills_hub/agent/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Tencent is pleased to support the open source community by making tRPC-Agent-Python available.
#
# Copyright (C) 2026 Tencent. All rights reserved.
#
# tRPC-Agent-Python is licensed under Apache-2.0.
43 changes: 43 additions & 0 deletions examples/skills_hub/agent/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Tencent is pleased to support the open source community by making tRPC-Agent-Python available.
#
# Copyright (C) 2026 Tencent. All rights reserved.
#
# tRPC-Agent-Python is licensed under Apache-2.0.
""" Agent that demonstrates fetching a skill from the Skill Hub before running. """

from pathlib import Path

from trpc_agent_sdk.agents import LlmAgent
from trpc_agent_sdk.models import LLMModel
from trpc_agent_sdk.models import OpenAIModel

from .config import get_model_config
from .hub import create_skill_tool_set
from .prompts import INSTRUCTION


def _create_model() -> LLMModel:
""" Create a model"""
api_key, url, model_name = get_model_config()
model = OpenAIModel(model_name=model_name, api_key=api_key, base_url=url)
return model


def create_agent(skills_dir: Path) -> LlmAgent:
"""Fetch a skill from GitHub via the Skill Hub, then build an agent that can use it.

Args:
skills_dir: Local directory to install fetched skills into. Populated
by `create_default_skill_repository(additional_skill_specs=...)`
before the agent is constructed.
"""
skill_tool_set, skill_repository = create_skill_tool_set(skills_dir)

return LlmAgent(
name="skill_hub_demo_agent",
description="An assistant that fetches skills on demand from the Skill Hub.",
model=_create_model(),
instruction=INSTRUCTION,
tools=[skill_tool_set],
skill_repository=skill_repository,
)
19 changes: 19 additions & 0 deletions examples/skills_hub/agent/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Tencent is pleased to support the open source community by making tRPC-Agent-Python available.
#
# Copyright (C) 2026 Tencent. All rights reserved.
#
# tRPC-Agent-Python is licensed under Apache-2.0.
""" Agent config module"""

import os


def get_model_config() -> tuple[str, str, str]:
"""Get model config from environment variables"""
api_key = os.getenv('TRPC_AGENT_API_KEY', '')
url = os.getenv('TRPC_AGENT_BASE_URL', '')
model_name = os.getenv('TRPC_AGENT_MODEL_NAME', '')
if not api_key or not url or not model_name:
raise ValueError('''TRPC_AGENT_API_KEY, TRPC_AGENT_BASE_URL,
and TRPC_AGENT_MODEL_NAME must be set in environment variables''')
return api_key, url, model_name
49 changes: 49 additions & 0 deletions examples/skills_hub/agent/hub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Tencent is pleased to support the open source community by making tRPC-Agent-Python available.
#
# Copyright (C) 2026 Tencent. All rights reserved.
#
# tRPC-Agent-Python is licensed under Apache-2.0.
"""Skill Hub glue: declare a remote skill and build a repository for it."""

from __future__ import annotations

import os
from pathlib import Path

from trpc_agent_sdk.code_executors import create_local_workspace_runtime
from trpc_agent_sdk.skills import BaseSkillRepository
from trpc_agent_sdk.skills import SkillToolSet
from trpc_agent_sdk.skills import create_default_skill_repository
from trpc_agent_sdk.skills.hub import GitHubAuth
from trpc_agent_sdk.skills.hub import GitHubSource
from trpc_agent_sdk.skills.hub import SkillSpec
from trpc_agent_sdk.skills.hub import SkillSpecsConfig

# `skill-creator` is Anthropic's own skill for building and iterating on
# skills -- a fitting "meta" skill to fetch through the Skill Hub for a demo.
GITHUB_SKILL_IDENTIFIER = "anthropics/skills/skills/skill-creator"
GITHUB_SKILL_NAME = "skill-creator"


def create_skill_tool_set(skills_dir: Path) -> tuple[SkillToolSet, BaseSkillRepository]:
"""Build a `SkillToolSet` backed by a GitHub skill installed through the repository factory."""
workspace_runtime = create_local_workspace_runtime()
# Unauthenticated requests are capped at 60 req/hr, which is plenty for
# this demo. Set GITHUB_TOKEN to raise that limit for repeated runs.
source = GitHubSource(GitHubAuth(os.getenv("GITHUB_TOKEN") or None))
repository = create_default_skill_repository(
additional_skill_specs=SkillSpecsConfig(
specs=[
SkillSpec(
source=source,
identifier=GITHUB_SKILL_IDENTIFIER,
name=GITHUB_SKILL_NAME,
on_error="raise",
),
],
install_path=str(skills_dir / ".downloaded"),
),
workspace_runtime=workspace_runtime,
)
skill_toolset = SkillToolSet(repository=repository)
return skill_toolset, repository
19 changes: 19 additions & 0 deletions examples/skills_hub/agent/prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Tencent is pleased to support the open source community by making tRPC-Agent-Python available.
#
# Copyright (C) 2026 Tencent. All rights reserved.
#
# tRPC-Agent-Python is licensed under Apache-2.0.
""" prompts for agent"""

INSTRUCTION = """
Be a concise, helpful assistant that can use Agent Skills.

A skill named "skill-creator" was just fetched on demand from GitHub via the
Skill Hub (`trpc_agent_sdk.skills.hub`) and installed locally before you were
started, so it is available like any other local skill.

When asked about a skill, call skill_load to load its documentation, then
skill_list_docs to see what documentation and files are available. Summarize
what you find concisely; do not run any of the skill's scripts unless
explicitly asked to.
"""
Loading
Loading