# 创建云端任务

## 基本信息

| 名称 | 描述 |
| --- | --- |
| HTTP Path | `/api/task/v1/developer/create_remote_task` |
| HTTP Method | POST |
| Content-Type | `application/json` |
| 鉴权 | `X-DB-AccessToken` + `X-DB-SessionToken` |

新任务使用 `business-templates.yaml.task_templates[].template_id` 选择模板。`remote_normal_v1` 仅保留给存量调用，不用于新增业务模板能力。

## 请求头

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `X-DB-AccessToken` | 是 | 使用 AppID/AppSecret 获取的应用级 Token |
| `X-DB-SessionToken` | 是 | 从平台调用开发者 MCP Tool 时携带的会话 Header 中规范化得到的纯 token |
| `Content-Type` | 是 | 固定为 `application/json` |

AccessToken、SessionToken、任务模板和目标用户必须属于同一应用与环境。

开发态 MCP 调用传入的 SessionToken Header 固定为复合值：

```text
token=sess.<payload>.<signature>;expire_in=<seconds>
```

调用本接口前必须拆分这个复合值：校验 `token` 和 `expire_in` 字段，取 `token=` 后、分号前的完整非空值。发送给本接口的 `X-DB-SessionToken` 必须只有纯 token，例如 `sess.<payload>.<signature>`，不能包含 `token=`、`;expire_in=...` 或其它伴随元数据。

不要用无上限的 `split("=")` 解析 token，也不要记录原始或规范化后的 token。`expire_in` 是输入侧伴随元数据；尤其不能根据开发态示例中的 `expire_in=0` 自行推断 token 永久有效或立即失效。

## 请求体

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `out_task_id` | 是 | 开发者侧稳定任务实例 ID，最长 64，用于幂等和关联 |
| `task_template` | 是 | `business-templates.yaml` 中远程任务的 `template_id` |
| `task_detail` | 是 | JSON 字符串；内部使用新版业务模板任务详情 |

`task_detail` 解析后的字段：

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `expire_in_sec` | 是 | 正整数，任务有效期，单位秒 |
| `display_data.title_scene_key` | 否 | 标题文案 scene key；省略时使用模板 fallback title |
| `display_data.sub_title_scene_key` | 否 | 副标题文案 scene key；省略时使用模板 fallback subtitle |
| `progress_data.progress` | 否 | 进度整数，范围 `0–100` |
| `progress_data.text_scene_key` | 否 | 进度文案 scene key |
| `progress_data.remaining_seconds` | 否 | 预估剩余秒数 |
| `variables` | 否 | `map<string,string>`，供本次所选文案模板渲染 |
| `jump_page_data.path` | 否 | 当前智能服务内部 Page 路径，必须以 `/` 开头 |
| `jump_page_data.query` | 否 | Page 查询字符串，端内按平台约定解码 |

不要传原始 `title`、`sub_title` 或 `progress_text` 绕过模板。scene key 必须属于所选模板，variables 必须满足所选文案需要。

## 请求示例

内层任务详情：

```json
{
  "expire_in_sec": 1800,
  "display_data": {
    "title_scene_key": "preparing_title",
    "sub_title_scene_key": "preparing_subtitle"
  },
  "progress_data": {
    "progress": 30,
    "text_scene_key": "preparing_progress",
    "remaining_seconds": 180
  },
  "variables": {
    "name": "珍珠奶茶",
    "pickup_code": "A018",
    "minutes": "3"
  },
  "jump_page_data": {
    "path": "/pages/order/detail",
    "query": "order_id=20260722-001"
  }
}
```

HTTP 请求中的 `task_detail` 是上面对象序列化后的字符串：

```bash
curl -X POST 'https://hello.doubao-dev.com/api/task/v1/developer/create_remote_task' \
  -H 'X-DB-AccessToken: <access_token>' \
  -H 'X-DB-SessionToken: sess.<payload>.<signature>' \
  -H 'Content-Type: application/json' \
  -d '{
    "out_task_id": "milk-tea-order-20260722-001",
    "task_template": "milk_tea_preparing",
    "task_detail": "{\"expire_in_sec\":1800,\"display_data\":{\"title_scene_key\":\"preparing_title\",\"sub_title_scene_key\":\"preparing_subtitle\"},\"progress_data\":{\"progress\":30,\"text_scene_key\":\"preparing_progress\",\"remaining_seconds\":180},\"variables\":{\"name\":\"珍珠奶茶\",\"pickup_code\":\"A018\",\"minutes\":\"3\"}}"
  }'
```

实现代码使用 JSON 库分别序列化内层 detail 和外层请求，不手工拼接转义文本。

## 响应

通用响应：

| 字段 | 说明 |
| --- | --- |
| `code` | `0` 表示业务成功 |
| `msg` | 结果说明 |
| `log_id` | 平台排障 ID |
| `data.task_id` | 平台任务 ID |
| `data.push_token.token` | 首次更新使用的推送凭证 |
| `data.push_token.expires_in` | 推送凭证有效期，单位秒 |

示例：

```json
{
  "code": 0,
  "msg": "success",
  "log_id": "202607220001",
  "data": {
    "task_id": "platform_task_123456",
    "push_token": {
      "token": "pt_xxxxxxxxxxxxxxxx",
      "expires_in": 86400
    }
  }
}
```

只有 `code == 0` 且 `task_id`、`push_token.token` 非空时标记创建成功。立即持久化任务关联和 token；不要把 token 返回前端或写入日志。

## 幂等与校验

- 同一用户和 `out_task_id` 重试时复用同一业务任务；不要为超时请求自动换 ID。
- 已存在任务的模板必须与本次 `task_template` 一致。
- `task_template` 必须存在、当前环境可用且类型为 remote。
- 创建时 `expire_in_sec` 必须大于 0。
- 进度必须在 `0–100`。
- scene key 必须存在于模板，变量必须满足所选文案模板。
- 跳转只允许当前智能服务内部 Page。

调用完整流程和 Sandbox 验证读取 [多任务管理接入指南](../../../task-management.md)。
