Skill和工具动态管理和加载系统实现效果图开源1. 背景与目标在大模型应用开发中智能体需要灵活组合各种工具Tool与技能Skill来完成任务。NetCoreKevin 框架基于自主研发的AgentFramework底层提供了一套“数据驱动 文件热加载”的动态能力扩展方案让开发者无需修改核心代码即可为不同智能体按需配置工具和技能。本文深入剖析该方案的实现细节涵盖从数据库定义、动态注入AITool到.zip技能包的自动解压与加载全过程帮助读者快速理解底层架构并应用于实际项目。2. 整体架构概览NetCoreKevin 的能力管理分为两个维度工具Tool粒度小、无状态通过AIFunctionFactory将普通 C# 方法包装为 AI 可调用的函数直接注入ChatOptions.Tools列表。技能Skill有状态的复合能力单元以文件包.zip形式存储通过AgentSkillsProviderBuilder构建为AIContextProvider由 AgentFramework 负责调度。核心组件协作关系如下┌─────────────────────────────────────────────┐ │ ChatClientAgent │ │ (ChatOptions.Tools AIContextProviders) │ └───────┬──────────────────────┬─────────────┘ │Tools │Skills ▼ ▼ ┌──────────────┐ ┌───────────────────────┐ │AIAgentTool │ │AgentSkillsProvider │ │SkillService │ │Builder (AgentFramework)│ └──┬───┬───────┘ └───────────┬───────────┘ │ │ │ │ ▼ ▼ │ SysTools (静态工具) 文件系统 Skill 目录 │ IKevinAITaskService 等 ▼ AISkillToolManagementService (数据库)底层完全依赖 AgentFramework 提供的AgentSkillsProviderBuilder、AgentFileSkillsSourceOptionsAITool、AIFunctionFactoryPySubprocessScriptRunner等执行器3. 数据驱动的 Skill 与 Tool 定义框架将工具和技能统一存储在TAISkillToolManagement实体中由IAISkillToolManagementService提供管理服务。关键字段包括字段说明Name工具/技能唯一标识名SkillToolType枚举Tool / SkillClassMethod工具绑定的方法名如AddOrUpdateCronTaskDescription功能描述供大模型决策用ActiveStatus是否启用IsSystem是否系统内置禁止删除技能还附带一个.zip附件包含脚本文件、资源等通过文件服务管理。// 获取所有启用的工具 public async TaskListAISkillToolManagementDto GetAllTools() { return (await AISkillToolManagementRp.Query(...) .Where(t t.SkillToolType AISkillToolTypeEnums.Tool t.ActiveStatus InActiveStatusEnums.Active) .ToListAsync()) .MapToListTAISkillToolManagement, AISkillToolManagementDto(); }4. 工具的动态注入工具注入由AIAgentToolSkillService实现其核心流程为根据agentId查询绑定表IAISkillToolBindIdService获得该智能体允许使用的工具管理 ID。通过AISkillToolManagementService.GetAllTools()过滤出这些 ID 对应的工具记录提取ClassMethod名称。调用GetAITools将方法名转化为AITool实例。4.1 静态工具与动态工具的区分SysTools.Tools是一个预注册的全局字典存放所有“静态工具”无需依赖注入即可直接使用的工具。如果工具名存在于字典直接取出否则进入switch分支通过AIFunctionFactory.Create将具体服务方法包装为AITool。private async TaskListAITool GetAITools(object data, Liststring toolNames) { var aiTools new ListAITool(); _kevinAITaskService.InitData(data); foreach (var item in toolNames) { if (SysTools.Tools.ContainsKey(item)) { aiTools.Add(SysTools.Tools[item]); // 静态工具 } else { switch (item) { case AddOrUpdateCronTask: aiTools.Add(AIFunctionFactory.Create( _kevinAITaskService.AddOrUpdateCronTask, new AIFunctionFactoryOptions { Name AddOrUpdateCronTask, Description 创建或更新一个周期性自动任务 })); break; case RemoveCronTask: // ... 类似 break; // ... 更多工具 } } } return aiTools; }4.2 与智能体集成在构造ChatClientAgentOptions时如果配置启用了工具则从服务中获取工具列表合并到ChatOptions.Toolsif (aiapp.IsAITools) { chatAgOs.ChatOptions.Tools ?? new ListAITool(); chatAgOs.ChatOptions.Tools.AddRange( _aIAgentToolSkillService.GetUserAIAgentToolsAsync( new { AIChatsId add.AIChatsId }, aiapp.Id.ToString(), CurrentUser.UserId.ToString() ).Result ); }这样每个智能体实例都能拥有不同的工具集实现多租户级别的能力隔离。5. 技能文件的动态加载技能本质上是包含脚本.py、.sh、.ps1和资源文件的目录包。上传时打包为.zip由AISkillToolManagementService.AddEdit负责下载、解压并放置到应用根目录下的Skills/{技能名称}/路径中。// 处理技能 zip 包 if (data.SkillToolType AISkillToolTypeEnums.Skill) { var flieData _FileRp.Query().FirstOrDefault(t t.Table AISkillToolManagement t.Sign SkillZip t.TableId data.Id.ToString()); if (flieData ! null) { var path Path.Combine(AppContext.BaseDirectory, Skills, data.Name, data.Name); if (Directory.Exists(path)) Directory.Delete(path, true); Directory.CreateDirectory(path); _FileStorage.FileDownload(flieData.Url, path flieData.Name); using var fileStream File.OpenRead(path flieData.Name); FileZipHelper.ExtractZipStreamToDirectory(fileStream, path); File.Delete(path flieData.Name); // 删除原始 zip } }5.1 通过 AgentFramework 注册文件技能在构建智能体时从服务获取该智能体绑定的技能路径列表然后利用AgentSkillsProviderBuilder将它们逐一注册为FileSkillif (aiapp.IsSkill) { var skillPaths _aIAgentToolSkillService.GetUserAIAgentSkillsAsync(...).Result; var skillsProvider new AgentSkillsProviderBuilder() .UseFileScriptRunner(PySubprocessScriptRunner.StaticRunAsync) .UseOptions(options options.DisableCaching true); foreach (var skillPath in skillPaths) { skillsProvider.UseFileSkill( Path.Combine(AppContext.BaseDirectory, Skills, skillPath), new AgentFileSkillsSourceOptions { AllowedScriptExtensions [.py, .sh, .ps1], ScriptDirectories [scripts, tools, templates], }); } chatAgOs.AIContextProviders [skillsProvider.Build()]; }AgentSkillsProviderBuilder属于 AgentFramework 核心它负责扫描指定目录下的脚本文件并与PySubprocessScriptRunner等执行器关联生成可以响应大模型调用的技能上下文。6. 管理与绑定服务6.1 技能/工具管理服务AISkillToolManagementService提供标准 CRUD 操作分页查询支持按类型筛选新增/编辑时自动处理附件解压删除逻辑删除并对系统内置项进行保护。6.2 智能体绑定IAISkillToolBindIdService维护智能体与技能/工具管理 ID 的映射关系决定每个智能体可用的能力列表。AIAgentToolSkillService正是依赖此服务实现按agentId和userId的动态过滤。public async TaskListAITool GetAIAgentToolsAsync(object data, string agentId) { var agentBindIds (await _iAISkillToolBindIdService.GetListById(agentId)) .Select(t t.AISkillToolManagementId).ToList(); var tools (await _iAISkillToolManagementService.GetAllTools()) .Where(t agentBindIds.Contains(t.Id)).ToList(); return await GetAITools(data, tools.Select(t t.ClassMethod ?? ).ToList()); }这种方式使得能力配置完全与代码分离可通过后台管理界面灵活调整而无需重启服务。7. 总结NetCoreKevin 框架基于 AgentFramework通过数据库驱动 文件系统热加载实现了 AI 智能体工具与技能的动态管理。其核心优势在于工具注入方法名映射与AIFunctionFactory结合可零侵入地将业务方法暴露给大模型。技能加载.zip文件包上传自动解压再利用AgentSkillsProviderBuilder注册为上下文提供者支持脚本类技能的热插拔。