FastGPT ChatAgent 辅助生成接入 Agent Skill:子 Skill 元数据存储与运行态对齐方案解析
2026/9/10 1:20:34 网站建设 项目流程

FastGPT ChatAgent 辅助生成接入 Agent Skill:子 Skill 元数据存储与运行态对齐方案解析

【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT

导读

本文围绕 FastGPT 开源仓库中的设计文档 skill-assist-generation-integration.md,完整解析 ChatAgent 的“辅助生成”(HelperBot TopAgent)如何接入 Agent Skill 能力:从权限查询、资源列表与 Prompt 约束、生成结果回填、sandbox 自动联动,到发布阶段结构化存储包内子 Skill 元数据(runtimeSkills/currentRuntimeSkills),再到运行态 Skill 应用名与子 Skill 的两层信息对齐。读者读完可以掌握该方案的完整数据流、Schema 变更点、校验规则与兼容策略,并能在当前仓库中找到对应的真实实现位置。

说明:设计文档中的topAgentParamsSchema/TopAgentFormDataSchema在仓库实际实现中对应 auxiliaryGeneration/type.ts 中的ChatAgentHelperMetadataSchemaChatAgentConfigFormDataSchema,文中以当前仓库实际代码为准。

背景:辅助生成链路缺少 Skill 维度

ChatAgent 是 FastGPT 中面向 LLM 的轻量 Agent 应用形态。用户在 ChatAgent 编辑页可切换“辅助生成”(Helper Bot)与“对话调试”两个标签页(见 ChatTest.tsx)。辅助生成的作用是:把应用已有的系统提示词、工具、知识库、文件上传状态、虚拟机(sandbox)状态传入一条独立的 LLM 链路,让模型基于这些预设资源为用户生成一整套 ChatAgent 配置并回填到表单。

设计文档指出该链路存在一个明显缺口:辅助生成只认识工具和知识库,不认识 Agent Skill。具体现状如下:

  • 前端构建topAgentMetadata时没有携带appForm.selectedAgentSkills
  • 辅助生成的入参/出参 Schema 中没有 Skill 字段。
  • generateResourceList()只生成工具与知识库资源列表,Prompt 也只描述这两类资源。
  • Skill 创建/发布时,Mongo 只保存平台 Skill 主表信息和版本包指针(storageKey),没有结构化保存包内多个SKILL.mdname/description

因此辅助生成既无法基于当前用户可访问的 Skill 做规划,也无法把生成结果回填到应用的 Skill 关联中。

当前数据模型

平台 Skill 主表(MongoAgentSkills

主表保存的是平台 Skill 应用层面的元信息:

{ parentId, // 所属文件夹,支持继承权限 type, // skill 或文件夹 inheritPermission, // 是否继承上级权限 source, // personal / system(store)等来源 name, // 平台 Skill 应用名 description, // 平台 Skill 应用描述 avatar, teamId, tmbId, // 归属团队与成员 category, createTime, updateTime, deleteTime, currentVersionId, // 当前生效版本指针 creationStatus, creationError, creationPayload // 异步创建状态 }

其中namedescription是 Skill 应用层面的名称和描述,不等同于包内子 Skill 的名称与描述。

Skill 版本表(MongoAgentSkillsVersion

版本表保存每次发布/导入产生的版本记录,真实包内容存放在对象存储,Mongo 仅保存storageKey

{ skillId, // 所属 Skill tmbId, // 创建者 versionName, storageKey, // 版本包在对象存储的 key importSource, // 导入来源(仅导入场景) createdAt }

在仓库实现中,该 Schema 已增加runtimeSkills字段(见 version/schema.ts),用于保存该版本包内实际包含的子 Skill 元数据,即本文第二阶段的核心落点。

应用关联结构

应用表单中关联 Skill 的结构为:

{ skillId: string; name: string; description: string; avatar?: string; isDeleted: boolean; }

该结构对应仓库中的SelectedAgentSkillItemTypeSchema(见 formEdit/type.ts),保存的是平台 Skill 应用信息,不包含子 Skill 信息。另有StoredSelectedAgentSkillItemTypeSchema只保留skillId,用于持久化存储场景。

目标与非目标

分两阶段落地:

  • 第一阶段:让辅助生成可以使用当前用户可访问的 Skill 应用——读取、展示、规划选择、回填selectedAgentSkills,并在选择 Skill 后自动保持useAgentSandbox = true
  • 第二阶段:在 Skill 创建/导入/保存发布时解析包内skills/**/SKILL.md的 frontmatter,把子 Skill 信息结构化写入 Mongo,让辅助生成展示更准确的子 Skill 能力。

明确的非目标(边界约束):

  • 不把每个子 Skill 拆成独立权限资源,应用仍然关联平台 Skill 应用。
  • 不在辅助生成请求时临时下载对象存储 zip 或解包读取SKILL.md(元数据前置落库)。
  • 不为了平台 Skilldescription接一层 LLM 摘要。
  • 不在第一阶段修改 Skill 发布/打包链路。

第一阶段:Skill 接入辅助生成

数据来源与权限查询

第一阶段只读取MongoAgentSkills的平台字段{ skillId, name, description, avatar },不读取版本包、不解析SKILL.md

关键约束是:不要在服务端辅助生成中直接调用/core/ai/skill/listAPI,而应把列表 API 中“当前成员可访问 Skill”的权限查询抽成 service/helper 复用。仓库中该列表接口位于 pages/api/core/ai/skill/list.ts,其核心逻辑委托给listReadableAgentSkills()(见 manage/list.ts)。从实现看,该查询具备以下权限语义:

  • 通过authUserPer校验用户读权限,父文件夹存在时再用authSkill校验;
  • 通过getResourcePermissionsByTeam汇总用户、组织、用户组权限(PerResourceTypeEnum.agentSkill);
  • 过滤deleteTime: null(见 manage/list.ts);
  • 支持source: personal/source: system的来源区分(见 manage/list.ts),设计建议第一版只接入source: personal,与现有应用选择器保持一致;
  • 默认只返回AgentSkillTypeEnum.skill,不把文件夹作为可选资源暴露给辅助生成。

设计文档建议新增的 service 签名:

type AccessibleSkillResource = { skillId: string; name: string; description: string; avatar?: string; }; async function getAccessibleSkillResources({ teamId, tmbId, isRoot }: { teamId: string; tmbId: string; isRoot: boolean; }): Promise<AccessibleSkillResource[]>;

metadata 与 Schema 变更

前端topAgentMetadata增加当前应用已选 Skill:selectedAgentSkills: appForm.selectedAgentSkills || []。仓库中该 metadata 的构建位于 ChatTest.tsx,chatAgentHelperMetadata已包含selectedAgentSkillsselectedToolsselectedDatasetsfileUploadenableSandbox等字段。

对应 Schema 在 auxiliaryGeneration/type.ts 中落地:

  • 入参ChatAgentHelperMetadataSchema增加selectedAgentSkills: z.array(SelectedAgentSkillItemTypeSchema).nullish()(第 23 行);
  • 出参ChatAgentConfigFormDataSchema增加selectedAgentSkills: z.array(SelectedAgentSkillItemTypeSchema).optional().default([])(第 61 行)。

这些预设 Skill 在 Prompt 中作为高优先级“已有配置”提示,不代表固定约束。

资源列表:新增 Skill 分区

generateResourceList()从“可用工具与知识库”扩展为“可用工具、知识库与 Skill”:

## 可用工具、知识库与 Skill ### 工具 ... ### 知识库 ... ### Skill - **skillId** [Skill]: name - description

没有可访问 Skill 时展示:

暂未配置 Skill

Prompt 约束

Prompt 需要让 TopAgent 明确知道:

  • Skill 是可选资源,适合表达可复用操作经验、项目规范、流程约束和领域方法;
  • 选择 Skill 时返回平台 Skill 的skillId
  • 不要求用户提供 Skill ID,TopAgent 应从资源列表中自行选择;
  • 如果资源列表里没有合适 Skill,不要强行选择;
  • 选择 Skill 后需要启用虚拟机,因为 Agent Skill 运行依赖 sandbox。

预设信息区增加:

**预设 Skill**: 搭建者已预先选择了以下 Skill ID: ...

生成结果 Schema 与权限过滤

辅助生成的计划资源提取从{ tools, knowledges }扩展为{ tools, knowledges, skills },并根据skills过滤出真实可访问 Skill,形成selectedAgentSkills

过滤逻辑必须按skillId校验当前用户仍有读权限,不能完全信任 LLM 输出——这是安全底线:即使 LLM 输出了无权限 Skill ID,也不能进入selectedAgentSkills

前端回填与 sandbox 联动

onApply(formData)增加:

selectedAgentSkills: formData.selectedAgentSkills

并且:

aiSettings.useAgentSandbox = enableSandboxEnabled || formData.selectedAgentSkills.length > 0

仓库实现中该逻辑位于 ChatTest.tsx:onApply会把formData.selectedAgentSkills写入setAppForm,同时计算useAgentSandbox: enableSandboxEnabled || (formData.selectedAgentSkills?.length || 0) > 0

如果当前套餐或系统配置不支持 sandbox,沿用现有checkAgentSkillSandboxUnavailable的提示与阻断逻辑。该函数位于 ChatAgent/utils.ts:当已选 Skill 且未开启 sandbox、且系统未展示 sandbox 或套餐不可用时,判定为“历史遗留的 Skill + 虚拟机不可用状态”,允许保存草稿但阻断发布/运行。

两条 Skill 选择路径

手动选择路径(已存在):

SkillSelectModal -> onAddAgentSkill(skill) -> appForm.selectedAgentSkills -> useAgentSkillSelect 自动保持 sandbox 开启

仓库中useAgentSkillSelect(见 useAgentSkillSelect.ts)负责管理 ChatAgent 表单中的 Skill 选择与 sandbox 开关联动:选择 Skill 时自动打开 sandbox;系统未配置或套餐不可用时不允许开启 sandbox,但保留关闭入口,避免历史配置无法自助修复。第一阶段不新增“辅助生成专用 Skill 选择器”,手动选择仍沿用该链路,辅助生成只需读取其结果作为预设信息。

辅助生成路径(第一阶段新增):

HelperBot TopAgent -> generateResourceList() 提供可访问 Skill 资源 -> LLM 规划并返回 selectedAgentSkills -> topAgentConfig SSE -> HelperBot onApply(formData) -> ChatAgent ChatTest.onApply -> setAppForm 写入 appForm.selectedAgentSkills

与工具回填的关键区别在于:Skill 回填不能只写 ID。前端应用表单需要完整保存:

{ skillId, name, description, avatar, isDeleted: false }

因此服务端生成TopAgentFormData时,必须把 LLM 输出的 Skill ID 重新映射成可访问 Skill 列表中的完整对象,前端不再额外请求 Skill 详情。这与工具的loadGeneratedTools()按工具 ID 补齐模板配置不同——Skill 不需要加载节点模板,权限必须在服务端生成阶段校验,且回填时需要同步开启useAgentSandbox

运行态 Skill 应用名与子 Skill 对齐

第一阶段还需解决一个关键的提示词对齐问题:

  • 辅助生成和调试预览阶段展示、回填的是平台 Skill 应用
  • 真正运行 Agent 时,sandbox 中可读取和执行的是该 Skill 应用包内展开后的一个或多个skills/**/SKILL.md子 Skill

如果运行态只把子 Skill 的name/description提供给模型,而不提供平台 Skill 应用名,就会出现错位:

系统提示词或辅助生成结果提到:数据分析助手 运行态可用技能列表只有:data-cleaning、chart-reporting 模型无法稳定判断><skill> <app_id>平台 Skill 应用 ID</app_id> <app_name>平台 Skill 应用名</app_name> <app_description>平台 Skill 应用描述</app_description> <name>子 Skill 名</name> <description>子 Skill 描述</description> <directory>子 Skill 目录</directory> <path>子 Skill 的 SKILL.md 路径</path> </skill>

并明确告诉模型:

  • 匹配用户任务、系统提示词和应用配置时,应同时参考app_name/app_description与子 Skill 的name/description
  • 如果用户任务或系统提示词提到某个平台 Skill 应用名,应在该应用下选择最匹配的子 Skill;
  • 执行时不能只凭平台 Skill 应用描述推断完整流程,仍必须读取最终选中的子 SkillSKILL.md
  • app_name/app_description只用于对齐应用层语义和辅助生成回填结果,实际执行入口仍然是子 Skill 的path

实现上,普通运行态应在注入 Skill 包后,把selectedAgentSkills中的平台应用信息合并到已部署版本信息,再传给getAgentSkillInfos();扫描子 Skill 时把匹配到的应用信息附加到每个DeployedSkillInfo,最后由buildAgentSkillsPrompt()输出上述字段和匹配规则。

仓库中该机制已有对应实现:getAgentSkillInfos(见 runtime/skill/core.ts)在 sandbox 中执行 find 命令扫描SKILL.md、解析 frontmatter,并在命中deployedVersion时把appIdappNameappDescription附加到每个 skill info(第 116-121 行);injectAgentSkillFilesToSandbox负责把已发布 Skill 包注入 sandbox 实例(含目录清理、authSkillByTmbId读权限校验与deleteTime: null过滤)。运行态入口统一从 runtime/skill/index.ts 导出getAgentSkillInfosinjectAgentSkillFilesToSandboxsyncBuiltinSkillsToSandboxrunAgentSkillVersionEntrypoints

这个方案属于第一阶段的运行态 prompt 对齐,不要求提前解析并落库子 Skill 元数据,也不要求辅助生成资源列表展示子 Skill 详情——后者放在第二阶段。

第一阶段验收清单

  • 辅助生成资源列表包含当前用户可访问 Skill;
  • 用户要求适合某个 Skill 的场景时,生成结果能自动关联该 Skill;
  • 已选 Skill 会作为预设信息进入下一轮辅助生成;
  • 无权限 Skill 即使被 LLM 输出,也不会进入selectedAgentSkills
  • 选择 Skill 后应用配置中自动开启 sandbox;
  • 手动选择的 Skill 会进入辅助生成预设信息;
  • 辅助生成选择的 Skill 会直接显示在 ChatAgent 编辑表单的 Skill 列表中,和手动选择效果一致;
  • 运行态 skill prompt 包含平台 Skill 应用app_name/app_description和子 Skillname/description
  • 当系统提示词或用户输入提到平台 Skill 应用名时,模型能在该应用下选择匹配的子 Skill,并读取对应SKILL.md

第二阶段:发布时保存子 Skill 元数据

目标

在创建、导入、保存发布 Skill 包时,解析包内所有skills/**/SKILL.md的 frontmatter,把子 Skill 信息结构化写入 Mongo。辅助生成后续直接从 Mongo 读取子 Skillname/description,不再需要临时解包。

子 Skill 元数据结构

新增公共类型:

type RuntimeSkillMetadata = { name: string; // 子 Skill 名(frontmatter name) description: string; // 子 Skill 描述 path: string; // 包内相对路径,如 skills/data-cleaning/SKILL.md };

示例:

runtimeSkills: [ { name: 'data-cleaning', description: '清洗表格中的缺失值、异常值和格式问题', path: 'skills/data-cleaning/SKILL.md' }, { name: 'chart-reporting', description: '根据数据生成图表和分析报告', path: 'skills/chart-reporting/SKILL.md' } ]

仓库中该类型已落地为RuntimeSkillMetadataSchema(见 global/core/ai/skill/type.ts),并被版本表 Schema 的runtimeSkills字段引用。

两层存储设计

  1. MongoAgentSkillsVersion.runtimeSkills(必须存):表示该版本包里实际包含的子 Skill,不同版本可以不同。仓库 Schema 已实现(见 version/schema.ts)。
  2. MongoAgentSkills.currentRuntimeSkills(建议存):缓存currentVersionId指向版本的子 Skill 列表,辅助生成和列表查询直接读主表,避免每次 join 当前版本表。

关键原则:“最新版本信息”以当前生效版本为准,而不是按createdAt最大的版本为准。现有版本模型中的相关事实:

  • MongoAgentSkills.currentVersionId是当前生效版本指针;
  • getCurrentVersion(skillId)先读主表currentVersionId,再查询对应版本(见 version/query.ts);
  • 保存发布新版本时,saveDeploySkillFromSandbox()通过updateCurrentVersion(skillId, versionId)切换当前版本;
  • 版本列表可按createdAt倒序展示历史版本,但用户也可通过版本切换把历史版本重新设为当前版本。

仓库中updateCurrentVersion(见 manage/update.ts)在一次updateOne内同时写currentVersionIdcurrentRuntimeSkills,并把creationStatus置为ready、清理creationError/creationPayload

因此第二阶段必须保证:新建版本时把解析出的子 Skill 元数据写入版本表runtimeSkills;当前版本变化时把目标版本的runtimeSkills同步写入主表currentRuntimeSkills;版本切换必须同步刷新currentRuntimeSkills,否则会出现currentVersionId已切换但辅助生成仍展示旧子 Skill 的不一致。

平台 Skill name/description 不被覆盖

  • 平台 Skillname不被子 Skill 覆盖,仍然是 Skill 应用名;
  • 平台 Skilldescription不由子 Skill 描述自动填充或覆盖:导入时用户填写什么就写入什么,未填写时保持空字符串。

原因是平台描述属于Skill 应用级元信息,子 Skill 描述属于运行时能力元信息。第二阶段只把子 Skill 信息写入runtimeSkills/currentRuntimeSkills,不反向改写平台 Skill 主表字段。

解析时机:覆盖所有产生版本包的入口

  • AI 创建初始包:completePendingSkillCreation()
  • 导入 Skill 包;
  • 复制 Skill;
  • 从编辑态 sandbox 保存发布:saveDeploySkillFromSandbox()

解析应在上传对象存储前完成,确保包内容和入库 metadata 来自同一份内容。

仓库中已实现的解析器为extractRuntimeSkillsFromPackage(见 skill/package/runtimeMetadata.ts),其行为与设计文档高度一致:

  • validateZipSafety校验 zip 安全(空包、危险路径、symlink、解压大小限制,见 skill/package/zipBuilder.ts);
  • 标准 workspace 读取skills/<skillDir>/SKILL.md;历史单 skill 包允许从根目录或一级目录SKILL.md兜底解析,并把 path 规范化为运行态可识别的skills/<name>/SKILL.md
  • 初始空白 workspace 可通过allowEmpty跳过空包校验(对应 AI 创建初始包场景)。

各发布入口已接入:completePendingSkillCreation(见 manage/creation/index.ts)在解析后调用updateCurrentVersion({ ... runtimeSkills })saveDeploySkillFromSandbox(见 sandbox/application/skillEdit/deploy.ts)同样在打包后解析并写入 runtimeSkills。

校验规则

发布包解析后需要校验:

  • 至少存在一个skills/**/SKILL.md
  • 每个SKILL.md必须有 frontmattername
  • description建议必填;若为兼容旧包允许为空,辅助生成展示时用空字符串;
  • 同一个包内子 Skillname不能重复;
  • path必须在skills/下,不能接受../等越界路径。

重复 name 不应静默覆盖,应发布失败并给出明确错误。仓库实现中均以抛错方式执行(如Duplicate runtime skill name: ${name}${path}: frontmatter name is requiredSkill package must contain at least one skills/<name>/SKILL.md)。

辅助生成展示升级

第一阶段资源列表:

- **skillId** [Skill]: 平台 Skill 名 - 平台描述

第二阶段升级为展示当前版本全部子 Skill:

- **skillId** [Skill]: 平台 Skill 名 - 平台描述 - **data-cleaning**: 清洗表格中的缺失值、异常值和格式问题 - **chart-reporting**: 根据数据生成图表和分析报告

模型选择时仍然只返回平台skillId,不返回子 Skill path

Prompt 长度控制策略

第二阶段资源列表完整展示当前版本里的所有子 Skill:

  • 不限制单个 Skill 展示的子 Skill 数量;
  • 不截断子 Skill 描述;
  • 不追加“还有 N 个子 Skill”这类摘要提示。

如果后续出现 prompt 过长问题,应先基于真实包规模和模型上下文窗口做数据评估,再单独设计压缩策略;第二阶段不提前加入展示限制。

数据迁移与兼容

第二阶段上线后,旧版本记录没有runtimeSkills。兼容策略:

  • 旧数据的runtimeSkills缺失时,辅助生成退回使用平台 Skillname/description
  • 不强制后台批量解包历史对象存储;
  • 用户下一次保存发布后,自动写入当前版本的runtimeSkills和主表缓存。

测试计划

第一阶段测试

  • ChatAgentHelperMetadataSchema(对应文档中的topAgentParamsSchema)支持selectedAgentSkills
  • ChatAgentConfigFormDataSchema(对应TopAgentFormDataSchema)支持selectedAgentSkills默认值;
  • generateResourceList()能输出 Skill 分区;无 Skill 时输出空提示;
  • 权限过滤只返回当前用户可读 Skill;
  • LLM 输出不存在或无权限 Skill ID 时被过滤;
  • 前端onApply能回填selectedAgentSkills;回填 Skill 时自动开启 sandbox;
  • 运行态buildAgentSkillsPrompt()输出app_idapp_nameapp_description
  • 运行态 prompt 明确要求用平台 Skill 应用信息匹配任务,再读取匹配子 Skill 的SKILL.md

第二阶段测试

  • 单个SKILL.md解析出一个 runtime skill;多个SKILL.md解析出多个 runtime skills;
  • 重复name发布失败;缺少name发布失败;无SKILL.md发布失败;
  • 导入 Skill 时不使用子 Skill 描述自动填充平台description
  • 保存发布新版本后:MongoAgentSkillsVersion.runtimeSkills写入、MongoAgentSkills.currentRuntimeSkills更新、currentVersionId正确切换;
  • 旧版本无runtimeSkills时辅助生成仍可使用平台描述。

实现状态对照与后续演进

对照设计文档与当前仓库代码可以发现,该方案的大部分骨架已在代码库中落地,可以作为继续开发与验证的基线:

设计要点仓库落地位置
metadata 携带已选 SkillChatTest.tsx
入参/出参 Schema 增加 Skill 字段auxiliaryGeneration/type.ts 与 auxiliaryGeneration/type.ts
前端回填 Skill 并联动 sandboxChatTest.tsx
sandbox 不可用判定ChatAgent/utils.ts
可访问 Skill 权限查询pages/api/core/ai/skill/list.ts 与 manage/list.ts
版本表runtimeSkills+ 主表currentRuntimeSkillsversion/schema.ts、manage/update.ts、global/core/ai/skill/type.ts
包内子 Skill 元数据解析与校验skill/package/runtimeMetadata.ts 与 skill/package/zipBuilder.ts
发布入口写入元数据manage/creation/index.ts、sandbox/application/skillEdit/deploy.ts
运行态两层信息(app 层 + 子 Skill 层)runtime/skill/core.ts

设计文档中列出的后续 TODO(如把可访问 Skill 查询进一步抽成独立 service 供generateResourceList()复用、扩展计划资源提取支持skill类型、运行态 prompt 的匹配规则补充、以及各发布入口/版本切换的测试覆盖)可作为该功能继续完善的方向。对运行态与辅助生成链路有更深入需求的读者,可以从上述源码文件继续追踪调用链。

【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询