mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-06-06 07:10:44 +08:00
feat: 新增 registering-services / using-services 两个元技能 (#17)
## 概要
为 Skill-first "应用与服务目录" 路线图新增两个元技能,作为 builtin 同步到用户
~/.desirecore/skills/:
- registering-services — 教 Agent 安全注册外部 HTTP/MCP 服务(riskLevel
选择、secretRef、SSRF、人类审批)
- using-services — 教 Agent 发现并调用目录服务(status/reviewStatus 过滤、HTTP/MCP
两条路径、不绕开治理)
## 改动
- skills/registering-services/{SKILL.md, SKILL.zh-CN.md}
- skills/using-services/{SKILL.md, SKILL.zh-CN.md}
- builtin-skills.json 加 2 个技能 id
- manifest.json totalSkills 22 → 24(已 rebase 到含 #18 tech-diagram 的 main)
- SKILL.zh-CN.md 采用 `<!-- locale: zh-CN -->` body 格式(移除冗余 frontmatter,对齐
docs/I18N.md 约定)
## 配套
主仓库 PR 同步引入:schema 扩展、新存储层、注册/治理路由、service-approval、http-request
治理闸门、per-service Skill 生成器、docker-app 派生 + service-health、前端徽章/治理
UI/派生服务面板。
## CLA
- [x] I have read and agree to the Contributor License Agreement
This commit is contained in:
184
skills/using-services/SKILL.md
Normal file
184
skills/using-services/SKILL.md
Normal file
@@ -0,0 +1,184 @@
|
||||
---
|
||||
name: using-services
|
||||
description: >-
|
||||
Discover and invoke HTTP/MCP services already registered in the global
|
||||
catalog. Use when the user asks the Agent to call an API, search for an
|
||||
existing service, or query a backend that was registered via the
|
||||
registering-services skill. 调用某个 API、查找已有服务、访问已注册的后端服务时使用。
|
||||
version: 1.0.0
|
||||
type: meta
|
||||
risk_level: low
|
||||
status: enabled
|
||||
disable-model-invocation: true
|
||||
tags:
|
||||
- service
|
||||
- catalog
|
||||
- http
|
||||
- mcp
|
||||
- meta
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-28'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 使用服务
|
||||
short_desc: 发现并调用全局目录中已注册的服务
|
||||
description: >-
|
||||
发现并调用全局应用与服务目录中已经注册过的 HTTP/MCP 服务。Use when 用户让 Agent 调用某个 API、查找已有服务,或访问通过 registering-services 注册的后端。
|
||||
body: ./SKILL.zh-CN.md
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Using Services
|
||||
short_desc: Discover and invoke registered services from the catalog
|
||||
description: >-
|
||||
Discover and invoke HTTP/MCP services already registered in the global catalog. Use when the user asks the Agent to call an API, search for an existing service, or query a backend that was registered via the registering-services skill.
|
||||
body: ./SKILL.md
|
||||
translated_by: human
|
||||
market:
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
verified: true
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# using-services Skill
|
||||
|
||||
## L0: One-line Summary
|
||||
|
||||
Teach the Agent how to look up and call services from the global
|
||||
"Apps & Services" catalog.
|
||||
|
||||
## L1: Overview
|
||||
|
||||
The "Apps & Services" catalog stores all registered HTTP/MCP services. This
|
||||
meta-skill is your manual for **finding** the right service and **invoking**
|
||||
it correctly. Each non-trivial registered service also has its own
|
||||
`svc-<id>` Skill auto-generated from its operations — prefer that when it
|
||||
exists; this meta-skill is the fallback for ad-hoc discovery.
|
||||
|
||||
### When to use
|
||||
|
||||
- The user asks you to do something that might already have a registered service
|
||||
(e.g. "search the product database", "send a notification")
|
||||
- You see `svc-<id>` Skill in your available skills list — activate it directly
|
||||
- You need to call an HTTP API and want to check if it's been registered (to
|
||||
benefit from governance, credential injection, and audit)
|
||||
|
||||
### When NOT to use
|
||||
|
||||
- The user gives you a one-off URL to fetch — use `HttpRequest` directly
|
||||
- You already have the per-service `svc-<id>` Skill activated — follow it
|
||||
instead, it's more specific
|
||||
|
||||
## L2: How to discover and call
|
||||
|
||||
### Step 1 — List the catalog
|
||||
|
||||
Fetch the registry:
|
||||
|
||||
```yaml
|
||||
tool: HttpRequest
|
||||
parameters:
|
||||
url: http://127.0.0.1:<agent-service-port>/api/registry/services
|
||||
method: GET
|
||||
```
|
||||
|
||||
Response shape (excerpt):
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"services": [
|
||||
{
|
||||
"id": "acme-search-api",
|
||||
"name": "Acme Search API",
|
||||
"protocol": "http",
|
||||
"endpoint": "https://api.acme.example/search",
|
||||
"tags": ["search", "products"],
|
||||
"status": "online",
|
||||
"origin": "agent",
|
||||
"reviewStatus": "approved",
|
||||
"riskLevel": "medium",
|
||||
"operations": [...]
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"source": "official"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2 — Pick a candidate
|
||||
|
||||
Filter by `tags`, `protocol`, `name`. Important checks **before** invoking:
|
||||
|
||||
- `status === 'online'` → safe to call
|
||||
- `status === 'offline'` / `'error'` → tell the user the service is down,
|
||||
**don't** retry blindly
|
||||
- `status === 'degraded'` → degrade gracefully, mention it to the user
|
||||
- `reviewStatus === 'pending'` (only `origin='agent'`) → you can only call it
|
||||
if `registeredBy` is you; otherwise ask the user to promote it
|
||||
- `riskLevel === 'critical'` → expect a human approval prompt on every call
|
||||
|
||||
### Step 3 — Build the request (HTTP services)
|
||||
|
||||
If the service has `operations`, prefer them — they define stable contract
|
||||
points. Build the URL as `<endpoint><operation.path>`.
|
||||
|
||||
```yaml
|
||||
tool: HttpRequest
|
||||
parameters:
|
||||
url: https://api.acme.example/search/v1/items?q=widget
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer ${secrets/api-keys/acme}" # resolved at call time
|
||||
```
|
||||
|
||||
If the service declares `auth.secretRef`, **do not** prompt the user for the
|
||||
secret value during chat. The `HttpRequest` tool resolves it automatically.
|
||||
|
||||
### Step 4 — Build the request (MCP services)
|
||||
|
||||
MCP services aren't called via `HttpRequest` — they are tools exposed through
|
||||
the Agent's `mcp_servers` config:
|
||||
|
||||
1. If you haven't added the MCP service to your Agent yet, POST to
|
||||
`http://127.0.0.1:<agent-service-port>/api/agents/<your-id>/mcp-servers` with `{ serverId: '<service.id>', config: <connection> }`
|
||||
2. Next query, MCP discovery will auto-expose tools from the server
|
||||
3. Call the tools by their MCP-declared names directly
|
||||
|
||||
### Step 5 — Handle the response
|
||||
|
||||
- 2xx → parse and use
|
||||
- 4xx → likely a client error (bad params, missing auth); fix the request,
|
||||
then retry once; if it still fails, report to the user
|
||||
- 5xx → server-side problem, report `status` of the service back so the user
|
||||
knows
|
||||
- **Service-approval rejected** → response will contain `"decision":"rejected"`;
|
||||
do not retry, ask the user how to proceed
|
||||
|
||||
### Step 6 — Don't fall through to raw URL fetching
|
||||
|
||||
If the catalog has a service for what you need, **use it**. Don't bypass
|
||||
governance by calling an undeclared URL directly — `HttpRequest` will still
|
||||
work, but you lose:
|
||||
|
||||
- Approval gating for high-risk operations
|
||||
- Credential injection (you'd need to ask the user for keys yourself)
|
||||
- Audit trail and `lastUsed` tracking
|
||||
- Other Agents being able to reuse your call patterns
|
||||
|
||||
## Failure modes
|
||||
|
||||
- **Catalog read fails**: just fall back to direct `HttpRequest` and warn the
|
||||
user that governance is bypassed.
|
||||
- **No matching service**: ask the user if they want to **register** a new
|
||||
one — activate `registering-services` skill.
|
||||
- **`status === 'offline'`**: report the situation, suggest checking the
|
||||
underlying service, **don't** call anyway.
|
||||
122
skills/using-services/SKILL.zh-CN.md
Normal file
122
skills/using-services/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,122 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# 使用服务(using-services)
|
||||
|
||||
## L0:一句话总结
|
||||
|
||||
教会 Agent 如何从全局"应用与服务目录"里查找并正确调用服务。
|
||||
|
||||
## L1:概述
|
||||
|
||||
"应用与服务目录"存放所有已注册的 HTTP/MCP 服务。本元技能是你的 **使用手册**:
|
||||
帮你 **找到** 合适的服务、**正确** 调用它。每个非平凡的注册服务还会自动生成
|
||||
专属 `svc-<id>` Skill —— 优先用专属技能;本元技能是临时发现的兜底。
|
||||
|
||||
### 何时使用
|
||||
|
||||
- 用户让你做某件事,目录里可能有现成服务(如"搜产品库"、"发通知")
|
||||
- 你看到可用技能里有 `svc-<id>` —— 直接激活它
|
||||
- 你打算调用一个 HTTP API,想先查目录,借力治理、凭据注入和审计
|
||||
|
||||
### 何时不要用
|
||||
|
||||
- 用户给了一次性 URL —— 直接 `HttpRequest` 即可
|
||||
- 你已激活了 `svc-<id>` 专属 Skill —— 跟着它走,更具体
|
||||
|
||||
## L2:如何发现并调用
|
||||
|
||||
### Step 1 — 列目录
|
||||
|
||||
拉取注册表:
|
||||
|
||||
```yaml
|
||||
tool: HttpRequest
|
||||
parameters:
|
||||
url: http://127.0.0.1:<agent-service-port>/api/registry/services
|
||||
method: GET
|
||||
```
|
||||
|
||||
响应(节选):
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"services": [
|
||||
{
|
||||
"id": "acme-search-api",
|
||||
"name": "Acme 搜索 API",
|
||||
"protocol": "http",
|
||||
"endpoint": "https://api.acme.example/search",
|
||||
"tags": ["search", "products"],
|
||||
"status": "online",
|
||||
"origin": "agent",
|
||||
"reviewStatus": "approved",
|
||||
"riskLevel": "medium",
|
||||
"operations": [...]
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"source": "official"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2 — 选候选
|
||||
|
||||
按 `tags`、`protocol`、`name` 过滤。调用 **前** 必须检查:
|
||||
|
||||
- `status === 'online'` → 可以调
|
||||
- `status === 'offline'` / `'error'` → 告诉用户服务下线,**别** 盲目重试
|
||||
- `status === 'degraded'` → 降级使用,告诉用户
|
||||
- `reviewStatus === 'pending'`(仅 `origin='agent'`)→ 只有当 `registeredBy`
|
||||
就是你自己时才能调;否则请用户在 Store UI 提升后再用
|
||||
- `riskLevel === 'critical'` → 每次调用都会触发人类审批
|
||||
|
||||
### Step 3 — 构造请求(HTTP 服务)
|
||||
|
||||
如果服务声明了 `operations`,优先用 —— 它们是稳定契约点。URL 拼成
|
||||
`<endpoint><operation.path>`。
|
||||
|
||||
```yaml
|
||||
tool: HttpRequest
|
||||
parameters:
|
||||
url: https://api.acme.example/search/v1/items?q=widget
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer ${secrets/api-keys/acme}" # 调用时解引用
|
||||
```
|
||||
|
||||
如果服务带 `auth.secretRef`,**不要** 在聊天里向用户索要明文凭据。
|
||||
`HttpRequest` 工具会自动解引用。
|
||||
|
||||
### Step 4 — 构造请求(MCP 服务)
|
||||
|
||||
MCP 服务不走 `HttpRequest`,它通过 Agent 的 `mcp_servers` 配置暴露成工具:
|
||||
|
||||
1. 若你的 Agent 还没接入该 MCP,POST `http://127.0.0.1:<agent-service-port>/api/agents/<your-id>/mcp-servers`
|
||||
传 `{ serverId: '<service.id>', config: <connection> }`
|
||||
2. 下轮 query 时 MCP discovery 会自动暴露该服务器的工具
|
||||
3. 直接用 MCP 工具名调用即可
|
||||
|
||||
### Step 5 — 处理响应
|
||||
|
||||
- 2xx → 解析使用
|
||||
- 4xx → 多半是客户端错(参数错、缺鉴权);修好后可重试一次,仍失败就告诉用户
|
||||
- 5xx → 服务端问题,把目录里的 `status` 一并告诉用户
|
||||
- **service-approval 拒绝** → 响应里会有 `"decision":"rejected"`;不要重试,问用户怎么办
|
||||
|
||||
### Step 6 — 不要绕开目录
|
||||
|
||||
如果目录里有该服务,**就用目录**。直接调未声明的 URL 虽然 `HttpRequest`
|
||||
也能成功,但你会失去:
|
||||
|
||||
- 高风险操作的审批闸门
|
||||
- 凭据注入(你得自己问用户要 key)
|
||||
- 审计追踪与 `lastUsed` 统计
|
||||
- 其他 Agent 复用你的调用模式
|
||||
|
||||
## 常见失败模式
|
||||
|
||||
- **目录读取失败**:降级直接 `HttpRequest`,并告诉用户已绕开治理。
|
||||
- **没匹配上**:问用户要不要 **注册** 一个新的 —— 激活 `registering-services`。
|
||||
- **`status === 'offline'`**:汇报情况,建议检查底层服务,**不要** 强行调用。
|
||||
Reference in New Issue
Block a user