Add a shared transparent OrganizationAgentConfigFolder tree for grouping agent roles and skills in the admin UI without affecting identity, bindings, run loading, or slash commands.
4.0 KiB
ADR 0028: Agent Configuration Folder Tree
Status
Accepted.
Context
ADR-0017/0018 made Agent roles and skills Organization-scoped dynamic runtime
configuration, managed without process restarts. The org admin surfaces for
them (/admin/roles and /admin/skills) render every
role/skill as one large editor card in a single flat list. As an Organization
accumulates roles and skills, the management pages degrade into an endless
scroll with no grouping affordance.
The project explorer already solves the analogous problem for projects with transparent folders (ADR-0021): org-scoped navigation nodes that are not permission resources. Roles and skills need the same affordance, but their semantics differ from projects in one crucial way: skill names and role IDs are referenced by role→skill bindings, run-time skill snapshot loading, and Feishu slash commands. Any grouping mechanism must not leak into those resolution paths.
Decision
Introduce an Organization-scoped folder tree shared by Agent roles and Agent skills:
- One folder tree per Organization is shared by both roles and skills (e.g. a
"高三化学组" folder groups that team's roles and its skills together). It is
a distinct entity from the project explorer
Folderof ADR-0021 — the two trees are managed independently and never reference each other. - Folders are transparent organization nodes, following the ADR-0021 project-folder precedent: they exist for management-surface navigation and grouping only, are not permission resources, and hold no grants.
- Folder membership is not part of role/skill identity or resolution:
- skill
nameand roleroleIdremain unique per Organization regardless of folder membership; - role→skill bindings, run admission's frozen role snapshot, run-scoped skill loading, and Feishu slash commands never reference folders.
- skill
- Each role/skill sits in at most one folder; membership is optional (unfiled items remain first-class). Folders nest arbitrarily.
- Folder assignment is a label-class change in the ADR-0017 sense: it never archives Agent sessions, because the execution surface (model, prompt, tools, skill content) is untouched.
- A folder can be deleted only when empty — no child folders, no roles, no skills. Relocating items out of a folder is an explicit user action, so no orphan-placement rule is needed yet.
- Admin web renders both pages as a left folder tree plus the item list of
the selected folder ("all" and "unfiled" included). The host-console CLI is
unchanged: folder management lives in the web surface, and CLI
upsert-role/install-skillnever touch folder assignment.
Consequences
- New DB entity
OrganizationAgentConfigFolder(org-scoped, self-nesting viaparentId, delete restricted while referenced) plus nullablefolderIdonOrganizationAgentRoleandOrganizationAgentSkill(SetNull on folder delete, though the service refuses to delete non-empty folders). - The spec pins the transparency and single-membership semantics in
Spec.System.AgentRole(AgentConfigFolder), so future implementors do not re-derive them differently (e.g. path-style names or per-folder uniqueness). - Org admin APIs gain folder CRUD plus role/skill folder-assignment endpoints that skip session archival by construction.
- Moving a role/skill between folders changes nothing about authorization, run resolution, or audit-visible configuration lineage beyond the folder assignment event itself.
Open Questions / Deferred
- Drag-and-drop assignment and bulk moves are deferred; assignment is a per-item select for now.
- Folder-level usage aggregation for roles/skills is deferred (project folders already aggregate usage under ADR-0021; agent configuration has no usage dimension yet).
- CLI flags for folder assignment are deferred until a console workflow asks for them.
- Folder-scoped default-role policies (e.g. per-folder defaults) are rejected for now: the Organization keeps exactly one active default role (ADR-0017/0018 invariant) regardless of folder structure.