mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-06-06 05:50:41 +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:
198
skills/registering-services/SKILL.md
Normal file
198
skills/registering-services/SKILL.md
Normal file
@@ -0,0 +1,198 @@
|
||||
---
|
||||
name: registering-services
|
||||
description: >-
|
||||
Register an external HTTP/MCP service to the global Application & Service
|
||||
Catalog so that other Agents (and the human user) can discover and call it.
|
||||
Use when the user mentions adding a new service, registering an API, or
|
||||
publishing a backend you control to the team's catalog. 新增服务、注册 API、把后端发布到团队目录时使用。
|
||||
version: 1.0.0
|
||||
type: meta
|
||||
risk_level: medium
|
||||
status: enabled
|
||||
disable-model-invocation: true
|
||||
tags:
|
||||
- service
|
||||
- registration
|
||||
- catalog
|
||||
- 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: 把外部 HTTP/MCP 服务登记到全局应用与服务目录
|
||||
description: >-
|
||||
把外部 HTTP/MCP 服务登记到全局应用与服务目录,让其他 Agent 与人类用户都能发现并调用。
|
||||
Use when 用户提到要新增服务、注册 API 或把你掌握的后端发布到团队目录。
|
||||
body: ./SKILL.zh-CN.md
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Register Services
|
||||
short_desc: Register external HTTP/MCP services into the global catalog
|
||||
description: >-
|
||||
Register an external HTTP/MCP service to the global Application & Service Catalog so that other Agents (and the human user) can discover and call it. Use when the user mentions adding a new service, registering an API, or publishing a backend you control to the team's catalog.
|
||||
body: ./SKILL.md
|
||||
translated_by: human
|
||||
market:
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
verified: true
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# registering-services Skill
|
||||
|
||||
## L0: One-line Summary
|
||||
|
||||
Tell the Agent how to register an external HTTP/MCP service into the global
|
||||
catalog with human governance.
|
||||
|
||||
## L1: Overview
|
||||
|
||||
This meta-skill teaches you (the Agent) **how** to add a new service to the
|
||||
shared "Apps & Services" catalog. It does **not** invoke external services
|
||||
itself — once registered, use the per-service Skill at `~/.desirecore/skills/svc-<id>/`
|
||||
or the `using-services` meta-skill to actually call them.
|
||||
|
||||
### When to use this skill
|
||||
|
||||
- The user asks to register an API or service (e.g. "add the Acme search
|
||||
endpoint to our catalog")
|
||||
- You just deployed a backend you want other Agents to be able to reach
|
||||
- You discover a useful public API and want to make it shareable
|
||||
|
||||
### When NOT to use it
|
||||
|
||||
- One-off HTTP calls that nobody else needs to repeat — just call `HttpRequest`
|
||||
directly
|
||||
- Adding an MCP server to **your own** agent only — POST to
|
||||
`/api/agents/<your-id>/mcp-servers` instead, no catalog entry needed
|
||||
- Modifying an existing catalog entry — the user must promote/reject through
|
||||
the Store UI
|
||||
|
||||
## L2: How to register a service
|
||||
|
||||
### Step 1 — Gather the required fields
|
||||
|
||||
Before calling the API, collect:
|
||||
|
||||
| Field | Required | Notes |
|
||||
|------|----------|-------|
|
||||
| `id` | yes | kebab-case, globally unique (e.g. `acme-search-api`) |
|
||||
| `name` | yes | Human-readable display name |
|
||||
| `description` | yes | One sentence — what it does |
|
||||
| `protocol` | yes | `'http'` or `'mcp'` |
|
||||
| `tags` | yes | Searchable list, e.g. `['search', 'web']` |
|
||||
| `registeredBy` | yes | **Your own agent id** |
|
||||
| `endpoint` | **required when `protocol='http'`** | Base URL of the API |
|
||||
| `riskLevel` | recommended | `low` / `medium` / `high` / `critical` |
|
||||
| `auth` | when API requires auth | `{ type, secretRef }` — see below |
|
||||
| `operations` | recommended | Operations list for the per-service Skill |
|
||||
| `capabilities` | optional | What this service can do |
|
||||
|
||||
### Step 2 — Choose `riskLevel` honestly
|
||||
|
||||
`riskLevel` decides whether **future calls** to this service trigger an
|
||||
approval gate:
|
||||
|
||||
- `low` — read-only data that's safe to invoke without prompting (e.g. public weather API)
|
||||
- `medium` — default for most APIs; first invoke per session may prompt
|
||||
- `high` — services that move money, send emails, mutate user data
|
||||
- `critical` — services that can cause irreversible harm; **every** call requires human approval
|
||||
|
||||
**Bias toward higher risk if uncertain.** Under-classifying is worse than over-classifying.
|
||||
|
||||
### Step 3 — Reference credentials with `secretRef`, never inline
|
||||
|
||||
**Do not put API keys/tokens into the catalog entry.** The catalog is global,
|
||||
visible in the Store UI, and may be inspected by future people. Instead:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"secretRef": "secrets/api-keys/acme" // pointer, not the actual key
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`HttpRequest` resolves `secretRef` at call time. If the secret doesn't exist
|
||||
yet, ask the user to provide it through their own secrets manager — not
|
||||
through the chat.
|
||||
|
||||
### Step 4 — Call the registration API
|
||||
|
||||
Use the `HttpRequest` tool to POST to the local Agent Service:
|
||||
|
||||
```yaml
|
||||
tool: HttpRequest
|
||||
parameters:
|
||||
url: http://127.0.0.1:<agent-service-port>/api/registry/agent-services
|
||||
method: POST
|
||||
body:
|
||||
id: acme-search-api
|
||||
name: "Acme Search API"
|
||||
description: "Full-text search across Acme's product catalog"
|
||||
protocol: http
|
||||
endpoint: https://api.acme.example/search
|
||||
tags: ["search", "products"]
|
||||
registeredBy: "<your-agent-id>"
|
||||
riskLevel: medium
|
||||
auth:
|
||||
type: bearer
|
||||
secretRef: secrets/api-keys/acme
|
||||
operations:
|
||||
- name: search
|
||||
method: GET
|
||||
path: /v1/items
|
||||
description: "Search products by query string"
|
||||
- name: getDetail
|
||||
method: GET
|
||||
path: /v1/items/{id}
|
||||
description: "Get a single product by id"
|
||||
```
|
||||
|
||||
(The Agent Service port is available via the runtime; ask `request-help`
|
||||
skill if you're unsure how to discover it.)
|
||||
|
||||
### Step 5 — Wait for human approval
|
||||
|
||||
The endpoint triggers a **service-approval** request to the human user. The
|
||||
HTTP call will block until they approve or reject through the Store UI.
|
||||
|
||||
- **Approved** → entry is written to
|
||||
`~/.desirecore/config/registry-agent-services.json` with
|
||||
`reviewStatus: 'pending'`. While `pending`, **only you** (the registering
|
||||
Agent) can call it.
|
||||
- **Rejected** → the API returns 403; do not retry, ask the user how to
|
||||
proceed.
|
||||
|
||||
After approval, the human can later **promote** the entry from `pending` to
|
||||
`approved` in the Store UI. Promotion makes the service callable by all
|
||||
Agents and triggers `service-skill-generator` to write
|
||||
`~/.desirecore/skills/svc-<id>/SKILL.md` with concrete examples derived
|
||||
from the `operations` you provided.
|
||||
|
||||
### Step 6 — Don't re-register
|
||||
|
||||
If `POST /api/registry/agent-services` returns `409 Conflict`, the service
|
||||
already exists. Do not try alternative ids unless the user explicitly asks
|
||||
you to register a separate variant — silently shadowing an existing service
|
||||
is a governance failure.
|
||||
|
||||
## Failure modes
|
||||
|
||||
- **Endpoint blocked by SSRF guard**: the registration API rejects private
|
||||
network addresses (10.x / 172.16-31.x / 192.168.x / 169.254.x) except
|
||||
localhost. Public IPs and DNS names are allowed.
|
||||
- **Missing `registeredBy`**: the API returns 400. Always include your own
|
||||
agent id — there is no anonymous registration.
|
||||
- **Approval timeout**: the broker times out after the user is idle long
|
||||
enough; treat this as `rejected`.
|
||||
135
skills/registering-services/SKILL.zh-CN.md
Normal file
135
skills/registering-services/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,135 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# 注册服务(registering-services)
|
||||
|
||||
## L0:一句话总结
|
||||
|
||||
教会 Agent 如何把一个外部 HTTP/MCP 服务安全地登记进全局"应用与服务目录",
|
||||
并经人类用户审批。
|
||||
|
||||
## L1:概述
|
||||
|
||||
这是一个 **元技能**,告诉你(Agent)**怎么** 把新服务添加进共享的"应用与服务目录"。
|
||||
本技能 **不负责** 调用外部服务 —— 注册成功且 approved 后,请用
|
||||
`~/.desirecore/skills/svc-<id>/` 下的专属 Skill 或者 `using-services`
|
||||
元技能来真正发起调用。
|
||||
|
||||
### 何时使用
|
||||
|
||||
- 用户让你"把 X API 注册到目录里"
|
||||
- 你刚部署了某个后端,希望别的 Agent 能用到
|
||||
- 你发现一个有用的公共 API,想让团队共享
|
||||
|
||||
### 何时不要用
|
||||
|
||||
- 一次性 HTTP 调用,别人不需要重复用 —— 直接 `HttpRequest` 即可
|
||||
- 只给 **自己这个 Agent** 加 MCP 服务 —— 直接 POST `/api/agents/<your-id>/mcp-servers`,无需目录条目
|
||||
- 修改已有目录条目 —— 必须由用户在 Store UI 提升 / 拒绝
|
||||
|
||||
## L2:如何注册一个服务
|
||||
|
||||
### Step 1 — 收集必填字段
|
||||
|
||||
调用 API 前,先准备好:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | 是 | kebab-case,全局唯一(如 `acme-search-api`) |
|
||||
| `name` | 是 | 显示名 |
|
||||
| `description` | 是 | 一句话功能描述 |
|
||||
| `protocol` | 是 | `'http'` 或 `'mcp'` |
|
||||
| `tags` | 是 | 搜索标签数组,如 `['search', 'web']` |
|
||||
| `registeredBy` | 是 | **你自己的 agent id** |
|
||||
| `endpoint` | `protocol='http'` 时必填 | API 基础 URL |
|
||||
| `riskLevel` | 推荐 | `low` / `medium` / `high` / `critical` |
|
||||
| `auth` | 服务需要鉴权时 | `{ type, secretRef }` — 见下文 |
|
||||
| `operations` | 推荐 | 操作清单,会被 per-service Skill 渲染成示例 |
|
||||
| `capabilities` | 可选 | 能力标签 |
|
||||
|
||||
### Step 2 — 诚实地选择 `riskLevel`
|
||||
|
||||
`riskLevel` 决定 **未来调用** 该服务时是否触发审批闸门:
|
||||
|
||||
- `low` — 只读数据,调用无副作用(如公开天气 API)
|
||||
- `medium` — 大多数 API 的默认值;同一会话首次调用可能提示
|
||||
- `high` — 涉及金钱、发邮件、修改用户数据等的服务
|
||||
- `critical` — 可能造成不可逆后果;**每次** 调用都要人类审批
|
||||
|
||||
**不确定时倾向于更高风险等级。** 低估比高估更糟。
|
||||
|
||||
### Step 3 — 用 `secretRef` 引用凭据,**不要** 内联明文
|
||||
|
||||
**不要把 API key/token 写进目录条目。** 目录是全局可见的,Store UI 任何人都能查看,
|
||||
未来还可能被审计。正确做法:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"secretRef": "secrets/api-keys/acme" // 指针,不是真正的 key
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`HttpRequest` 在调用时解引用 `secretRef`。如果对应 secret 还不存在,请通过
|
||||
用户自己的凭据管理流程让他/她填好 —— 不要在聊天里收明文。
|
||||
|
||||
### Step 4 — 调用注册 API
|
||||
|
||||
用 `HttpRequest` 工具 POST 到本机 Agent Service:
|
||||
|
||||
```yaml
|
||||
tool: HttpRequest
|
||||
parameters:
|
||||
url: http://127.0.0.1:<agent-service-port>/api/registry/agent-services
|
||||
method: POST
|
||||
body:
|
||||
id: acme-search-api
|
||||
name: "Acme 搜索 API"
|
||||
description: "对 Acme 产品库做全文搜索"
|
||||
protocol: http
|
||||
endpoint: https://api.acme.example/search
|
||||
tags: ["search", "products"]
|
||||
registeredBy: "<your-agent-id>"
|
||||
riskLevel: medium
|
||||
auth:
|
||||
type: bearer
|
||||
secretRef: secrets/api-keys/acme
|
||||
operations:
|
||||
- name: search
|
||||
method: GET
|
||||
path: /v1/items
|
||||
description: "按 query 搜索商品"
|
||||
- name: getDetail
|
||||
method: GET
|
||||
path: /v1/items/{id}
|
||||
description: "按 id 获取单个商品"
|
||||
```
|
||||
|
||||
(Agent Service 端口由运行时提供;不确定如何获取时用 `request-help` 技能问。)
|
||||
|
||||
### Step 5 — 等待人类批准
|
||||
|
||||
该端点会触发 **service-approval** 请求,HTTP 调用会一直阻塞,直到用户在
|
||||
Store UI 批准或拒绝。
|
||||
|
||||
- **批准** → 条目写入 `~/.desirecore/config/registry-agent-services.json`,
|
||||
状态为 `reviewStatus: 'pending'`。pending 期间 **只有你**(注册者)能调用。
|
||||
- **拒绝** → API 返回 403;不要重试,问用户下一步怎么办。
|
||||
|
||||
人类后续可以在 Store UI 把条目从 `pending` **提升(promote)** 为 `approved`。
|
||||
提升后该服务对所有 Agent 可调,且会触发 `service-skill-generator` 生成
|
||||
`~/.desirecore/skills/svc-<id>/SKILL.md`,里头有基于 `operations` 的示例。
|
||||
|
||||
### Step 6 — 不要重复注册
|
||||
|
||||
如果 `POST /api/registry/agent-services` 返回 `409 Conflict`,说明该服务已存在。
|
||||
除非用户明确要求注册一个独立变种,否则不要换个 id 静默注册 —— 偷偷影子覆盖
|
||||
已有服务是治理失败。
|
||||
|
||||
## 常见失败模式
|
||||
|
||||
- **SSRF 拦截**:注册 API 拒绝私网地址(10.x / 172.16-31.x / 192.168.x / 169.254.x),
|
||||
本机环回除外。公网 IP 与 DNS 域名允许。
|
||||
- **缺 `registeredBy`**:API 返回 400。必须带上你自己的 agent id —— 不允许匿名注册。
|
||||
- **审批超时**:broker 等待用户太久会超时,按 `rejected` 处理。
|
||||
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