Skip to content

Skills Agent

Skills Agent 是在 MCP 之上的高层抽象,为业务层提供更友好的接口。

概念

Skills Agent 将底层的"工具"概念封装为业务层的"技能",提供:

  • 统一的技能调用接口
  • 权限过滤机制
  • 参数自动填充
  • 执行日志记录

与 MCP 的关系

核心功能

创建代理

javascript
// 方式 1: 工厂函数
const agent = await createSkillsAgent({
  event: e,              // 消息事件
  presetId: 'default',   // 预设ID
  includeMcpTools: true,
  includeBuiltinTools: true
})

// 方式 2: 类构造
const agent = new SkillsAgent({
  userId: '123456',
  groupId: '789',
  userPermission: 'admin'
})
await agent.init()

获取可用技能

javascript
// 获取所有可执行技能
const skills = agent.getExecutableSkills()

// 按类别获取
const basicSkills = agent.getSkillsByCategory('basic')

// 获取技能定义(用于 AI 调用)
const toolDefinitions = agent.getToolDefinitions()

执行技能

javascript
// 执行单个技能
const result = await agent.execute('get_current_time', { timezone: 'Asia/Shanghai' })

// 并行执行多个技能
const results = await agent.executeParallel([
  { name: 'get_current_time', args: {} },
  { name: 'get_weather', args: { city: '北京' } }
])

权限过滤

Skills Agent 实现多层权限过滤:

配置过滤

yaml
builtinTools:
  enabledCategories:
    - basic
    - user
  disabledTools:
    - execute_command

预设过滤

yaml
# 预设文件
tools:
  allowedTools:
    - get_current_time
    - get_weather
  excludedTools: []

权限过滤

javascript
// 危险工具检查
if (tool.dangerous && !options.allowDangerous) {
  throw new PermissionError('Dangerous tool not allowed')
}

// 管理员工具检查
if (tool.adminOnly && !context.isAdmin) {
  throw new PermissionError('Admin permission required')
}

文档技能工具约束

除类别/预设/权限过滤外,文档技能(SKILL.md)可对工具集施加额外约束src/services/skills/SkillToolConstraints.js)。当某个技能文档被匹配激活时,其 allowedTools / disallowedTools 会进一步收窄模型可见的工具列表。

约束来源

buildDocument()SkillDocumentLoader.js)在解析技能文档时,会从 frontmatter/元数据中提取工具约束字段,并兼容多种命名写法:

规范化字段兼容的元数据键
allowedToolsallowedToolsallowed_toolsallowed-tools
disallowedToolsdisallowedToolsdisallowed_toolsdisallowed-tools
yaml
# SKILL.md frontmatter 示例
---
name: coding-assist
description: 编码辅助技能
allowed-tools:        # 该技能激活时仅暴露以下工具
  - read_file
  - write_file
  - execute_command
disallowed-tools:     # 从可用工具中排除以下工具
  - kick_member
---

约束收集与应用

getSkillToolConstraints() 收集当前匹配到的所有技能文档的约束并去重合并,applySkillToolConstraints() 再据此过滤工具列表:

匹配规则与优先级

  • 白名单优先收窄allowedTools 非空时,先只保留命中白名单的工具;随后再用 disallowedTools 从中剔除。两者可叠加(先白名单、后黑名单)
  • 匹配维度toolMatches() 同时按工具名(getToolDefinitionName)和 identity(getToolIdentity)匹配,任一命中即视为匹配
  • 空约束不生效allowedToolsdisallowedTools 均为空时,工具列表原样返回
  • 多技能合并:多个技能同时激活时,各自的 allowedTools/disallowedTools 会跨文档合并去重后统一应用

参数自动填充

Skills Agent 可以自动填充上下文参数:

javascript
// 工具定义
{
  name: 'send_group_message',
  parameters: {
    properties: {
      group_id: { type: 'string', description: '目标群号' },
      message: { type: 'string', description: '消息内容' }
    }
  }
}

// 调用时传入实际参数
agent.execute('send_group_message', { group_id: '456', message: 'Hello' })

静态方法 vs 实例方法

方法类型用途示例
静态方法MCP 服务器管理SkillsAgent.getMcpServers()
实例方法工具执行agent.execute('get_current_time', {})
javascript
// 静态方法 - 管理操作
const servers = SkillsAgent.getMcpServers()
await SkillsAgent.connectMcpServer('my-server', config)
await SkillsAgent.reloadAllTools()

// 实例方法 - 执行操作
const result = await agent.execute('send_group_message', { group_id: '456', message: 'Hello' })

执行日志

每次工具执行都会记录日志:

javascript
// 日志结构
{
  id: 'uuid',
  toolName: 'get_current_time',
  args: { timezone: 'Asia/Shanghai' },
  result: '2024-12-15 14:30:25',
  userId: '123456',
  groupId: '789',
  duration: 15,  // 毫秒
  timestamp: '2024-12-15T06:30:25.000Z'
}

查看日志:

javascript
const logs = await SkillsAgent.getExecutionLogs({
  limit: 100,
  toolName: 'get_current_time'
})

下一步

Skills 文件加载系统

文件扫描流程

懒加载机制

模型默认只能看到技能列表,需要通过内置工具显式加载:

上下文压缩与重注入

基于 MIT 许可发布