4. 技能描述符

4.1 概述

技能描述符(Skill Descriptor)是本协议的核心数据结构。它是一个 JSON 文档,完整描述单个技能的元数据,作为技能提供者与消费者之间的契约。

每个有效的 Skill Descriptor MUST 通过协议 Schema(见第 10 章)验证。

4.2 顶层结构

Skill Descriptor 是一个 JSON 对象,包含以下顶层字段:

必需字段

字段类型描述
protocolProtocolVersion该描述符所遵循的协议版本
idstring技能的全局唯一标识符
namestring技能的人类可读名称
versionstring技能版本(SemVer 格式)
capability_typeCapabilityType能力类型枚举
descriptionstring技能功能的人类可读描述
providerProviderInfo技能提供者信息
endpointInvocationEndpoint调用端点配置
inputsParameterDefinition[]输入参数定义数组(可为空数组)
outputOutputDefinition输出格式定义
authAuthConfig认证配置
accessAccessPolicy访问控制策略

可选字段

字段类型描述
tagsstring[]用于搜索和分类的标签
documentation_urlstring技能的人类可读文档 URL
created_atstring创建时间戳(ISO 8601)
updated_atstring最后更新时间戳(ISO 8601)

4.3 枚举类型

4.3.1 CapabilityType(能力类型)

值描述
plugin可嵌入的功能模块
api远程服务接口
knowledge结构化知识资源
task人类或 iFay 可执行的任务

4.3.2 AccessPolicy(访问控制策略)

值描述
public公开,任何人可发现和调用
restricted受限,可被发现但调用需认证
private私有,未认证时不可被发现

4.3.3 AuthType(认证类型)

值描述
none无需认证
api_key基于 API Key 的认证
oauth2OAuth 2.0 认证
custom自定义认证机制

4.3.4 ExecutionStatus(执行状态)

值描述
accepted调用请求已被接收,等待执行
running技能正在执行中
completed执行成功完成
failed执行失败
timeout执行超时

4.4 子结构

4.4.1 ProtocolVersion

interface ProtocolVersion {
  version: string;           // SemVer,必需
  changelog_url?: string;    // 变更日志 URL,可选
}

4.4.2 ProviderInfo

interface ProviderInfo {
  name: string;              // 提供者名称,必需
  url?: string;              // 提供者网站,可选
  contact?: string;          // 联系邮箱或 URL,可选
}

4.4.3 InvocationEndpoint

interface InvocationEndpoint {
  url: string;                                              // 必需
  method: "GET" | "POST" | "PUT" | "DELETE";                // 必需
  content_type?: string;                                    // 默认 "application/json"
  status_url?: string;                                      // 状态查询 URL 模板
  result_url?: string;                                      // 结果获取 URL 模板
  timeout_ms?: number;                                      // 调用超时(毫秒)
  retry?: {
    max_attempts: number;                                   // 最大重试次数
    backoff_ms: number;                                     // 退避延迟(毫秒)
  };
}

status_url 和 result_url MUST 包含 {execution_id} 占位符,由消费者在请求时替换为实际值。

4.4.4 ParameterDefinition

interface ParameterDefinition {
  name: string;              // 参数名,必需
  type: string;              // JSON Schema 类型,必需
  description: string;       // 参数描述,必需
  required: boolean;         // 是否必需,必需
  default?: unknown;         // 默认值,可选
  schema?: object;           // 嵌套 JSON Schema(用于复杂类型)
}

4.4.5 OutputDefinition

interface OutputDefinition {
  content_type: string;      // 必需,MIME 类型
  schema?: object;           // 描述输出结构的 JSON Schema
  description?: string;      // 输出的人类可读描述
}

4.4.6 AuthConfig

interface AuthConfig {
  type: AuthType;            // 必需
  description?: string;
  header?: string;           // type === "api_key" 时使用
  oauth2?: OAuth2Config;     // type === "oauth2" 时必需
  custom?: CustomAuthConfig; // type === "custom" 时必需
}

interface OAuth2Config {
  authorization_url: string;
  token_url: string;
  scopes: Record<string, string>;  // scope_name → description
}

interface CustomAuthConfig {
  instructions: string;
  parameters: ParameterDefinition[];
}

约束:

  • 当 type === "oauth2" 时,oauth2 字段 MUST 存在
  • 当 type === "custom" 时,custom 字段 MUST 存在
  • 当 type === "api_key" 时,header 字段 SHOULD 存在

4.5 字段约束

4.5.1 id 字段

  • MUST 在同一技能索引中全局唯一
  • MUST 仅包含字母、数字、点号(.)、连字符(-)和下划线(_)
  • SHOULD 使用反向域名加版本后缀的形式(如 com.example.translate-v1)
  • 长度 MUST 在 1 到 256 个字符之间

4.5.2 version 字段

  • MUST 符合 SemVer 2.0.0 格式
  • MUST 在每次破坏性变更时递增主版本号

4.5.3 description 字段

  • MUST 提供至少一个非空字符
  • SHOULD 使用基准语言(英语)撰写
  • MAY 包含 Markdown 格式

4.6 完整示例

{
  "protocol": {
    "version": "1.0.0",
    "changelog_url": "https://skill-sharing.org/changelog"
  },
  "id": "com.example.translate-v1",
  "name": "Universal Translator",
  "version": "2.1.0",
  "capability_type": "api",
  "description": "支持 100+ 语言的高质量文本翻译服务",
  "provider": {
    "name": "Example Corp",
    "url": "https://example.com",
    "contact": "skills@example.com"
  },
  "endpoint": {
    "url": "https://api.example.com/skills/translate/invoke",
    "method": "POST",
    "content_type": "application/json",
    "status_url": "https://api.example.com/skills/translate/status/{execution_id}",
    "result_url": "https://api.example.com/skills/translate/result/{execution_id}",
    "timeout_ms": 30000,
    "retry": {
      "max_attempts": 3,
      "backoff_ms": 1000
    }
  },
  "inputs": [
    {
      "name": "text",
      "type": "string",
      "description": "要翻译的文本",
      "required": true,
      "schema": { "minLength": 1, "maxLength": 10000 }
    },
    {
      "name": "target_language",
      "type": "string",
      "description": "目标语言代码(ISO 639-1)",
      "required": true
    }
  ],
  "output": {
    "content_type": "application/json",
    "schema": {
      "type": "object",
      "properties": {
        "translated_text": { "type": "string" },
        "source_language": { "type": "string" },
        "target_language": { "type": "string" }
      }
    }
  },
  "auth": {
    "type": "api_key",
    "header": "X-API-Key"
  },
  "access": "restricted",
  "tags": ["translation", "nlp"],
  "documentation_url": "https://docs.example.com/skills/translate",
  "created_at": "2025-01-15T08:00:00Z",
  "updated_at": "2025-03-20T14:30:00Z"
}