Skip to content

Commit 1fb321a

Browse files
Rhosmarieagentkit-git
authored andcommitted
feat: align remote skills sample with skill sandbox
GitOrigin-RevId: e61b7423feafdccdfea13ca03a644b709e7fbf1c
1 parent 2f5725b commit 1fb321a

5 files changed

Lines changed: 434 additions & 0 deletions

File tree

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# RemoteSkills Proxy
2+
3+
本示例演示 Runtime Agent 如何只暴露 RemoteSkill 的名称、描述和输入 Schema,
4+
真实 Skill 实现仍留在远端 AgentKit Skills Sandbox 中,通过统一 A2A 路径执行。
5+
6+
## 核心边界
7+
8+
- Runtime Agent 只加载 `remote_skills.json`,把每个 RemoteSkill 包装成一个工具。
9+
- Agent 看到的是工具描述和参数 Schema,看不到 `SKILL.md`、脚本、依赖和执行流程。
10+
- 工具被调用时,VeADK 组装 `QueryInput`,并复用 `execute_skills()` 走 Skills Sandbox `/a2a`
11+
- Skills Sandbox 根据 `skill_name` 在远端选择并执行真实 Skill,然后把结果返回给 Agent。
12+
13+
## 目录结构
14+
15+
```text
16+
remote_skills_proxy/
17+
├── README.md
18+
├── agent.py
19+
├── pyproject.toml
20+
├── remote_skills.json
21+
└── tests/
22+
└── test_remote_skills_proxy.py
23+
```
24+
25+
## 配置 RemoteSkills
26+
27+
`remote_skills.json` 只放 Agent 可见的元数据:
28+
29+
```json
30+
{
31+
"remote_skills": [
32+
{
33+
"name": "pdf",
34+
"description": "远程处理 PDF 文档,包括文本和表格提取、生成 PDF、合并拆分、表单识别与填写等批量 PDF 任务。",
35+
"input_schema": {
36+
"type": "object",
37+
"properties": {
38+
"operation": {"type": "string"},
39+
"input_files": {"type": "array", "items": {"type": "string"}}
40+
},
41+
"required": ["operation"]
42+
}
43+
}
44+
]
45+
}
46+
```
47+
48+
这个 sample 的 manifest 来自 `agentkit-skill` 镜像内置的本地 Skills:
49+
`docx``pdf``pptx``xlsx``tos-file-access``skill-creator`
50+
本地 manifest 不保存这些 Skill 的 `SKILL.md`、脚本或依赖。
51+
52+
## 本地检查
53+
54+
本地检查只验证装配,不会真实访问云端 Skills Sandbox:
55+
56+
```bash
57+
cd python/advanced/remote_skills_proxy
58+
uv run --no-sync python -m unittest discover -s tests -v
59+
```
60+
61+
## 真实调用
62+
63+
### 1. 启动 Runtime Agent
64+
65+
```bash
66+
cd python/advanced/remote_skills_proxy
67+
export VOLCENGINE_ACCESS_KEY=<your-volcengine-access-key>
68+
export VOLCENGINE_SECRET_KEY=<your-volcengine-secret-key>
69+
export AGENTKIT_TOOL_ID_SKILLS=<your-skills-sandbox-tool-id>
70+
export REMOTE_SKILLS_MANIFEST=remote_skills.json
71+
uv run python agent.py
72+
```
73+
74+
启动成功后会看到:
75+
76+
```
77+
INFO: Uvicorn running on http://0.0.0.0:8000
78+
```
79+
80+
### 2. 创建本地 Session
81+
82+
```bash
83+
curl -sS -X POST \
84+
http://127.0.0.1:8000/apps/remote_skills_proxy_agent/users/u1/sessions/s1 \
85+
-H 'Content-Type: application/json' \
86+
-d '{}'
87+
```
88+
89+
成功返回:
90+
91+
```json
92+
{"id":"s1","appName":"remote_skills_proxy_agent","userId":"u1","state":{},"events":[],"lastUpdateTime":...}
93+
```
94+
95+
### 3. 发起 RemoteSkill 调用
96+
97+
下面用 `docx` 这个 RemoteSkill 举例。该请求会让远端 Skills Sandbox 创建一个法律文书风格的文档。
98+
99+
```bash
100+
curl -N -X POST http://127.0.0.1:8000/run_sse \
101+
-H 'Content-Type: application/json' \
102+
-d '{
103+
"appName": "remote_skills_proxy_agent",
104+
"userId": "u1",
105+
"sessionId": "s1",
106+
"newMessage": {
107+
"role": "user",
108+
"parts": [
109+
{
110+
"text": "用 docx skill 创建一个法律文书风格的文档"
111+
}
112+
]
113+
},
114+
"streaming": true
115+
}'
116+
```
117+
118+
### 预期现象
119+
120+
- 本地 Runtime Agent 会收到 `/run_sse` 请求。
121+
- Agent 根据 `remote_skills.json` 选择 `docx` 工具。
122+
- `remote_skill` 工具内部调用 `execute_skills()`
123+
- `execute_skills()` 再向远端 Skills Sandbox 的 `/a2a` 发送 `message/send`,并通过 `tasks/get` 轮询结果。
124+
125+
工具内部发送给远端沙箱的 `QueryInput` 形如:
126+
127+
```json
128+
{
129+
"skill_name": "pdf",
130+
"query": "提取这份 PDF 的表格,并输出为 Markdown 表格",
131+
"arguments": {
132+
"operation": "extract",
133+
"input_files": ["/home/gem/workspace/report.pdf"],
134+
"output_requirements": "返回 Markdown 表格和关键结论"
135+
},
136+
"request_id": "req_xxx"
137+
}
138+
```
139+
140+
## 设计取舍
141+
142+
这个方案适合需要保护 Skill 实现、依赖和执行流程的场景。它不适合高频低延迟
143+
的小函数调用,因为每次调用都要经过远端 Sandbox 和 A2A 任务轮询。
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import annotations
16+
17+
import os
18+
from pathlib import Path
19+
20+
from veadk import Agent
21+
from veadk.tools.builtin_tools.remote_skills import (
22+
build_remote_skill_tools,
23+
load_remote_skill_definitions,
24+
)
25+
26+
27+
MANIFEST_PATH = Path(
28+
os.getenv("REMOTE_SKILLS_MANIFEST", Path(__file__).with_name("remote_skills.json"))
29+
)
30+
31+
remote_skill_definitions = load_remote_skill_definitions(MANIFEST_PATH)
32+
remote_skill_tools = build_remote_skill_tools(remote_skill_definitions)
33+
34+
root_agent = Agent(
35+
name="remote_skills_proxy_agent",
36+
description="An agent that calls protected RemoteSkills through Skills Sandbox A2A.",
37+
model_name=os.getenv("MODEL_AGENT_NAME", "deepseek-v4-pro-260425"),
38+
instruction=(
39+
"Use the available RemoteSkills when they match the user's task. "
40+
"You can see only each RemoteSkill description and input schema; "
41+
"the actual implementation runs in the remote Skills Sandbox."
42+
),
43+
tools=remote_skill_tools,
44+
)
45+
46+
47+
if __name__ == "__main__":
48+
from agentkit.apps import AgentkitAgentServerApp
49+
from veadk.memory.short_term_memory import ShortTermMemory
50+
51+
agent_server_app = AgentkitAgentServerApp(
52+
agent=root_agent,
53+
short_term_memory=ShortTermMemory(backend="local"),
54+
)
55+
agent_server_app.run(host="0.0.0.0", port=8000)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[project]
2+
name = "remote-skills-proxy"
3+
version = "0.1.0"
4+
description = "Expose protected RemoteSkills to a Runtime Agent and execute them through Skills Sandbox A2A"
5+
readme = "README.md"
6+
requires-python = ">=3.12,<3.14"
7+
dependencies = [
8+
"agentkit-sdk-python==0.8.1",
9+
"google-adk==2.2.0",
10+
"litellm",
11+
"urllib3<2.0.0",
12+
"veadk-python>=1.1.4",
13+
"volcengine-python-sdk>=4.0.33",
14+
]
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
{
2+
"remote_skills": [
3+
{
4+
"name": "docx",
5+
"display_name": "DOCX 文档处理",
6+
"description": "远程创建、编辑、分析 Word .docx 文档,支持修订、批注、格式保留和文本提取等专业文档任务。",
7+
"input_schema": {
8+
"type": "object",
9+
"properties": {
10+
"operation": {
11+
"type": "string",
12+
"enum": ["create", "edit", "analyze", "extract_text", "comment", "redline"],
13+
"description": "期望执行的文档操作"
14+
},
15+
"input_files": {
16+
"type": "array",
17+
"items": {"type": "string"},
18+
"description": "远端沙箱可访问的 .docx 文件路径或文件 URL"
19+
},
20+
"output_requirements": {
21+
"type": "string",
22+
"description": "输出格式、命名、修订/批注等要求"
23+
}
24+
},
25+
"required": ["operation"]
26+
},
27+
"timeout_seconds": 1800
28+
},
29+
{
30+
"name": "pdf",
31+
"display_name": "PDF 处理",
32+
"description": "远程处理 PDF 文档,包括文本和表格提取、生成 PDF、合并拆分、表单识别与填写等批量 PDF 任务。",
33+
"input_schema": {
34+
"type": "object",
35+
"properties": {
36+
"operation": {
37+
"type": "string",
38+
"enum": ["extract", "create", "merge", "split", "fill_form", "analyze"],
39+
"description": "期望执行的 PDF 操作"
40+
},
41+
"input_files": {
42+
"type": "array",
43+
"items": {"type": "string"},
44+
"description": "远端沙箱可访问的 PDF 文件路径或文件 URL"
45+
},
46+
"output_requirements": {
47+
"type": "string",
48+
"description": "输出文件、表格、表单字段或分析结果要求"
49+
}
50+
},
51+
"required": ["operation"]
52+
},
53+
"timeout_seconds": 1800
54+
},
55+
{
56+
"name": "pptx",
57+
"display_name": "PPTX 演示文稿处理",
58+
"description": "远程创建、编辑和分析 PowerPoint .pptx 演示文稿,支持版式、备注、批注、内容修改和结构化抽取。",
59+
"input_schema": {
60+
"type": "object",
61+
"properties": {
62+
"operation": {
63+
"type": "string",
64+
"enum": ["create", "edit", "analyze", "extract_text", "add_notes", "add_comments"],
65+
"description": "期望执行的演示文稿操作"
66+
},
67+
"input_files": {
68+
"type": "array",
69+
"items": {"type": "string"},
70+
"description": "远端沙箱可访问的 .pptx 文件路径或文件 URL"
71+
},
72+
"output_requirements": {
73+
"type": "string",
74+
"description": "页数、风格、版式、备注或输出文件要求"
75+
}
76+
},
77+
"required": ["operation"]
78+
},
79+
"timeout_seconds": 1800
80+
},
81+
{
82+
"name": "xlsx",
83+
"display_name": "XLSX 表格处理",
84+
"description": "远程创建、编辑和分析电子表格,支持公式、格式、数据分析、可视化、模板保留和公式重算。",
85+
"input_schema": {
86+
"type": "object",
87+
"properties": {
88+
"operation": {
89+
"type": "string",
90+
"enum": ["create", "edit", "analyze", "visualize", "recalculate", "extract_data"],
91+
"description": "期望执行的表格操作"
92+
},
93+
"input_files": {
94+
"type": "array",
95+
"items": {"type": "string"},
96+
"description": "远端沙箱可访问的 .xlsx、.xlsm、.csv 或 .tsv 文件路径/URL"
97+
},
98+
"output_requirements": {
99+
"type": "string",
100+
"description": "公式、格式、图表、分析维度或输出文件要求"
101+
}
102+
},
103+
"required": ["operation"]
104+
},
105+
"timeout_seconds": 1800
106+
},
107+
{
108+
"name": "tos-file-access",
109+
"display_name": "TOS 文件访问",
110+
"description": "远程上传文件或目录到 TOS 兼容对象存储,或从 URL 下载文件供沙箱后续处理。",
111+
"input_schema": {
112+
"type": "object",
113+
"properties": {
114+
"operation": {
115+
"type": "string",
116+
"enum": ["upload_file", "upload_directory", "download_file"],
117+
"description": "上传或下载操作"
118+
},
119+
"paths_or_urls": {
120+
"type": "array",
121+
"items": {"type": "string"},
122+
"description": "需要上传的沙箱路径,或需要下载的 URL"
123+
},
124+
"output_requirements": {
125+
"type": "string",
126+
"description": "期望返回签名 URL、TOS 路径或本地保存路径"
127+
}
128+
},
129+
"required": ["operation", "paths_or_urls"]
130+
},
131+
"timeout_seconds": 1800
132+
},
133+
{
134+
"name": "skill-creator",
135+
"display_name": "Skill 创建与更新",
136+
"description": "远程指导创建或更新 Skill,包括需求澄清、内容规划、初始化、编辑、打包和快速校验。",
137+
"input_schema": {
138+
"type": "object",
139+
"properties": {
140+
"operation": {
141+
"type": "string",
142+
"enum": ["create", "update", "package", "validate", "review"],
143+
"description": "期望执行的 Skill 工作流"
144+
},
145+
"skill_name": {
146+
"type": "string",
147+
"description": "要创建或更新的 Skill 名称"
148+
},
149+
"requirements": {
150+
"type": "string",
151+
"description": "Skill 的触发场景、能力范围、资源和输出要求"
152+
}
153+
},
154+
"required": ["operation"]
155+
},
156+
"timeout_seconds": 1800
157+
}
158+
]
159+
}

0 commit comments

Comments
 (0)