6. 调用协议

6.1 概述

调用协议定义了技能消费者如何远程调用已发现的技能。本协议采用基于 HTTP 的异步调用模型,通过执行 ID 关联请求与结果。

6.2 三步调用模型

步骤HTTP 方法端点说明
1. 发起调用POSTendpoint.url提交请求,获得 execution_id
2. 查询状态GETendpoint.status_url(替换 {execution_id})轮询执行状态
3. 获取结果GETendpoint.result_url(替换 {execution_id})获取最终结果

6.3 调用请求

6.3.1 请求结构

interface InvocationRequest {
  caller: {
    id: string;                 // 必需,调用者唯一标识
    type: string;               // 必需,如 "ifay" / "service" / "user"
    credentials?: object;       // 可选,认证凭据
  };
  skill_id: string;             // 必需,目标技能 ID
  inputs: Record<string, unknown>; // 必需,输入参数
  context?: {
    trace_id?: string;          // 链路追踪 ID
    priority?: "low" | "normal" | "high";
    timeout_ms?: number;        // 客户端超时建议
  };
}

6.3.2 请求示例

POST /skills/translate/invoke HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-API-Key: sk-xxxxx

{
  "caller": {
    "id": "ifay-instance-001",
    "type": "ifay"
  },
  "skill_id": "com.example.translate-v1",
  "inputs": {
    "text": "Hello, world!",
    "target_language": "zh-CN"
  },
  "context": {
    "trace_id": "trace-abc-123",
    "priority": "normal"
  }
}

6.4 调用响应

6.4.1 即时响应(202 Accepted)

提供者接受请求后 MUST 立即返回 HTTP 202 状态码:

interface AcceptedResponse {
  execution_id: string;              // 必需
  status: "accepted";                // 必需
  skill_id: string;                  // 必需
  timestamps: {
    created_at: string;              // ISO 8601
    updated_at: string;              // ISO 8601
  };
}

6.4.2 状态查询响应

interface InvocationResponse {
  execution_id: string;              // 必需
  status: ExecutionStatus;           // 必需
  skill_id: string;                  // 必需
  output?: unknown;                  // status === "completed" 时存在
  error?: ErrorObject;               // status === "failed" 或 "timeout" 时存在
  timestamps: {
    created_at: string;              // 必需
    updated_at: string;              // 必需
    completed_at?: string;           // status 为终态时存在
  };
}

6.4.3 完成响应示例

{
  "execution_id": "exec-789-xyz",
  "status": "completed",
  "skill_id": "com.example.translate-v1",
  "output": {
    "translated_text": "你好,世界!",
    "source_language": "en",
    "target_language": "zh-CN"
  },
  "timestamps": {
    "created_at": "2025-03-20T14:30:00Z",
    "updated_at": "2025-03-20T14:30:02Z",
    "completed_at": "2025-03-20T14:30:02Z"
  }
}

6.5 状态机

                    ┌─────────────┐
       (创建)        │             │
   ─────────────────►│  accepted   │
                    │             │
                    └──────┬──────┘
                           │
                           │ (开始执行)
                           ▼
                    ┌─────────────┐
                    │             │◄────────┐
                    │   running   │         │ (持续中)
                    │             │─────────┘
                    └──────┬──────┘
                           │
            ┌──────────────┼──────────────┐
            │              │              │
            ▼              ▼              ▼
     ┌──────────┐   ┌──────────┐   ┌──────────┐
     │completed │   │  failed  │   │ timeout  │
     │ (终态)    │   │ (终态)    │   │ (终态)   │
     └──────────┘   └──────────┘   └──────────┘

进入终态后状态 MUST NOT 再次变更。

6.6 轮询策略

消费者 SHOULD 实现指数退避轮询策略:

第 1 次:1000 ms
第 2 次:2000 ms
第 3 次:4000 ms
...
第 N 次:min(initial × 2^(N-1), max_interval)

推荐 max_interval 为 30 秒。