Skip to content

feat(controller): add read-only skill catalog endpoint for workbench - #1211

Draft
LUOSENGWA wants to merge 1 commit into
agentscope-ai:mainfrom
LUOSENGWA:feat/skill-catalog-api
Draft

feat(controller): add read-only skill catalog endpoint for workbench#1211
LUOSENGWA wants to merge 1 commit into
agentscope-ai:mainfrom
LUOSENGWA:feat/skill-catalog-api

Conversation

@LUOSENGWA

@LUOSENGWA LUOSENGWA commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Read-only skill catalog endpoint

Summary

There was no controller API for listing which skills a deployment makes available to workers. The Dashboard Skill Center reads its own private storage (unreachable by user-facing clients), and the Worker CRD only records skills already assigned, not what is available to assign. Workbench UIs that let a team manage its workers' capabilities had no catalog to browse.

This PR adds GET /api/v1/skills, a single read-only endpoint that returns:

  • Builtin skills — scanned from the same agent-template directories the deployer uses when provisioning workers (default worker template, copaw/hermes runtime variants, team-leader template). Each skills/<skill>/SKILL.md frontmatter contributes name and description; the directory name is the fallback. A skill shipped by several templates is reported once, with the providing templates in agents.
  • Remote registry skills — every Worker's spec.remoteSkills is aggregated, so skills already referenced from a registry (e.g. Nacos) appear with their source. A skill available both builtin and from a registry gets a combined source (builtin+nacos).

The endpoint is metadata-only: no skill content, no registry network calls, no credentials. Output is sorted by name.

What's included

  • internal/server/skills_handler.go (new) — catalog assembly (builtin scan + remote aggregation) and a small SKILL.md frontmatter parser.
  • internal/server/http.goGET /api/v1/skills route; ServerDeps.WorkerAgentDir.
  • internal/app/app.go — wires the configured agent-template directory.
  • internal/auth/authorizer.go — new skills resource kind: list allowed for admins, managers, team leaders, and team-scoped humans; denied for worker service accounts.
  • docs/design/skill-catalog-api.md — design contract.
  • docs/usage/resource-management.md (+ zh-cn) — API reference section.

Data boundary

  • No new resources, no CRD or schema change, no write paths.
  • No network I/O: remote skills are enumerated from Worker specs, not from the registry — the endpoint cannot leak registry credentials and cannot stall on registry availability.
  • Frontmatter parsing reads only the name/description lines; skill bodies are never returned.
  • Missing template directories (deployments without some runtimes) are skipped silently; a backend read failure degrades to the builtin list.
  • Authorization: the catalog is deployment-wide metadata (no PII), so no scope filtering; per-worker assignment remains a separate write concern.

Tests

  • internal/server/skills_handler_test.go (new): builtin scan across template dirs with cross-template dedup and agents ordering; remote aggregation including the combined builtin+nacos source; stray non-directory files ignored; missing template dir → empty 200; empty WorkerAgentDir200; sorted output; frontmatter parser cases (valid / no frontmatter / name-only / empty / missing file).
  • go test ./internal/server/ ./internal/auth/ green; full go test ./...: 19 packages ok, the only failure is a pre-existing environment issue in internal/executor (unzip binary absent in the test container) untouched by this diff. gofmt/go vet clean.

Related


只读技能目录端点

摘要

此前没有任何 Controller API 可以列出部署中可用的技能。Dashboard Skill Center 读的是它自己的私有存储(用户侧客户端够不到),Worker CRD 只记录已分配的技能,不是可分配目录。需要管理团队技能配置的工作台 UI 没有候选池可浏览。

本 PR 新增 GET /api/v1/skills,单一只读端点,返回:

  • 内置技能 — 从 deployer provisioning Worker 时使用的同一套 agent 模板目录扫描(默认 worker 模板、copaw/hermes runtime 变体、team-leader 模板)。每个 skills/<skill>/SKILL.md frontmatter 提供 namedescription,目录名兜底。多个模板都带的技能只报告一次,agents 列出提供它的模板。
  • 远程注册表技能 — 聚合所有 Worker 的 spec.remoteSkills,已引用自注册表(如 Nacos)的技能带其 source 出现。内置与注册表都有的技能合并 source(builtin+nacos)。

端点只暴露元数据:不返回技能正文、不做注册表网络调用、不泄露凭据。输出按名称排序。

包含内容

  • internal/server/skills_handler.go(新)— 目录组装(内置扫描 + 远程聚合)与小型 SKILL.md frontmatter 解析器。
  • internal/server/http.goGET /api/v1/skills 路由;ServerDeps.WorkerAgentDir
  • internal/app/app.go — 接线配置的 agent 模板目录。
  • internal/auth/authorizer.go — 新 skills 资源类型:admin/manager/团队 Leader/团队范围人类用户可 list,worker 服务账号拒绝。
  • docs/design/skill-catalog-api.md — 设计契约。
  • docs/usage/resource-management.md(+ zh-cn)— API 参考节。

数据边界

  • 无新资源、无 CRD/schema 变更、无写路径。
  • 零网络 I/O:远程技能从 Worker spec 枚举而非连注册表——不会泄露注册表凭据,也不会被注册表可用性拖住。
  • frontmatter 解析只读 name/description 两行,技能正文永不返回。
  • 模板目录缺失(部署不含某些 runtime)静默跳过;后端读失败退化为内置列表。
  • 鉴权:目录是部署级元数据(无 PII),不做范围过滤;按 Worker 分配仍是独立的写操作。

测试

  • internal/server/skills_handler_test.go(新):跨模板目录的内置扫描与去重、agents 排序;远程聚合含 builtin+nacos 合并 source;非目录杂项文件被忽略;模板目录缺失 → 空 200;空 WorkerAgentDir200;输出排序;frontmatter 解析器用例(合法/无 frontmatter/仅 name/空文件/文件缺失)。
  • go test ./internal/server/ ./internal/auth/ 全绿;全量 go test ./...:19 包 ok,唯一失败为 internal/executor 预存环境问题(测试容器缺 unzip),与本 diff 无关。gofmt/go vet 干净。

相关

@shiyiyue1102 shiyiyue1102 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution. I think we should pause the current implementation and clarify the overall Skill Center design before deciding how this API should be implemented.

The main concern is the source of truth. Worker.spec.skills and Worker.spec.remoteSkills represent skills already assigned to individual Workers; they should not be used to reconstruct the deployment-wide catalog of skills available for assignment. A catalog should come from a shared, authoritative location and remain independent of the current Worker instances.

Please first prepare or update a design document and discuss the following points with the maintainers:

  1. What is the authoritative public catalog, and which component owns it?
  2. How are builtin, uploaded, marketplace, and remote-registry Skills represented?
  3. What is the boundary between catalog metadata, per-Worker assignment state, and the Worker’s runtime copy?
  4. What are the team visibility, tenant isolation, and credential-redaction rules?
  5. How is the catalog updated when Skills are added, updated, or removed?

The current implementation enumerates all Workers and exposes data derived from their remoteSkills. Besides making catalog contents depend on existing assignments, this can expose cross-team registry details and credential-bearing source URIs. The authorization branch also needs to enforce ActionList explicitly rather than allowing every action for the skills resource.

Once the Skill Center design and data boundaries are agreed upon, we can review how this endpoint and its tests should be adjusted.


感谢贡献。建议先暂停当前实现,在决定这个 API 如何落地之前,先把 Skill Center 的整体设计梳理清楚并完成讨论。

目前最主要的问题是权威数据源。Worker.spec.skillsWorker.spec.remoteSkills 表示已经分配给具体 Worker 的技能,不应该用来反向构建部署级的可分配技能目录。可分配目录应来自统一、公共、权威的位置,并且不依赖当前存在哪些 Worker。

请先整理或更新设计文档,并与维护者讨论以下问题:

  1. 公共技能目录的权威数据源是什么,由哪个组件维护?
  2. 内置、上传、市场和远程注册表 Skill 分别如何表达?
  3. Catalog 元数据、Worker 分配状态和 Worker 运行时副本之间的边界是什么?
  4. 团队可见性、租户隔离和凭据脱敏规则是什么?
  5. Skill 新增、更新和删除后,Catalog 如何保持同步?

当前实现会遍历全部 Worker,并从其 remoteSkills 中聚合数据。这不仅会使目录内容依赖现有分配状态,还可能暴露跨团队的注册表信息以及包含凭据的 source URI。另外,skills 资源的鉴权也应明确只允许 ActionList,不能直接放行所有 Action。

等 Skill Center 的设计和数据边界讨论确认后,再继续评审这个接口及其测试应该如何调整。

@LUOSENGWA

Copy link
Copy Markdown
Contributor Author

@shiyiyue1102
Agreed on all points — pausing this PR for the Skill Center design, as requested.

Concretely:

  1. Source of truth. You're right that aggregating Worker.spec.skills / spec.remoteSkills is the wrong basis for a catalog: it couples catalog contents to current assignment state and — worse — exposes cross-team registry details and credential-bearing source URIs to any scoped reader. Proposal in the new design issue Design: Skill Center — catalog source of truth, representation, assignment state, and sync #1221: the catalog is the deployment-level shared skill store (built-in templates + shared uploads), read directly by the controller, independent of Worker instances. Worker.spec.skills remains per-worker assignment state; the worker's local copy remains a runtime mirror. Catalog reads redact credentials from source URIs (a storage invariant, not a permission).
  2. Authorization. Done, independently of the design outcome: the skills resource now enforces an explicit action list (no wildcard) — see commit a45d104 on this branch.
  3. Design document. The consolidated design answering your five questions (catalog representation, three-layer boundary: catalog metadata / assignment state / runtime copy, team visibility & credential-redaction rules, update sync) is Design: Skill Center — catalog source of truth, representation, assignment state, and sync #1221, cross-referenced with Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220 (the L2 permission & capability matrix that governs who may assign from the catalog). Happy to fold in whatever shape the discussion lands on; this branch stays paused until then.

各点同意——按要求暂停本 PR,先做 Skill Center 整体设计。

  1. 权威数据源:你说得对,用 Worker.spec.skills / spec.remoteSkills 聚合目录是错误基础——目录内容会依赖当前分配状态,更糟的是会把跨团队注册表细节和带凭据的 source URI 暴露给任意 scoped 读者。新设计 issue Design: Skill Center — catalog source of truth, representation, assignment state, and sync #1221 里的提案:catalog = 部署级共享技能库(内置模板 + 共享上传),controller 直接读,与 Worker 实例无关;Worker.spec.skills 保持 per-worker 分配状态;worker 本地副本是运行时镜像;catalog 读时脱敏 source URI 凭据(是无条件存储不变量,不是权限项)。
  2. 鉴权:已修,不依赖设计结论——skills 资源显式 action 列表(无 wildcard),见本分支 commit a45d104
  3. 设计文档:逐条回应五个问题的合并设计(catalog 表达、三层边界:catalog 元数据/分配状态/运行时副本、团队可见性与凭据脱敏规则、更新同步)在 Design: Skill Center — catalog source of truth, representation, assignment state, and sync #1221,并与 Design: L2 permission & capability model (worker config, channels, approval, skill catalog) #1220(L2 权限与能力矩阵,约束"谁能从 catalog 分配")互引。讨论定成什么样我们照改;本分支在此之前保持暂停。

@LUOSENGWA
LUOSENGWA marked this pull request as draft September 3, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants