# 异步运行智能体

`POST` `/api/agent/run/async`

提交任务后立即返回 requestId，客户端通过 /run/stream 接口读取 SSE 事件流。支持通过urlAttachments传入最多10个HTTPS URL附件，并可与attachmentIds同时使用。任务提交成功不代表URL附件已经导入完成，导入进度和失败结果需通过SSE事件或任务状态获取。可通过 capabilityConfig 限制本次运行可调用的工具和 Skill；不传时沿用智能体配置，传入时只能进一步收窄智能体已有能力。Finx服务传入非空白名单或黑名单时限制本次运行可用范围，白名单优先；空集合或不传时沿用智能体配置；限制会由本次运行派生的定时任务自动继承。可通过 environmentId 指定本次运行使用的沙箱环境（仅在隐式创建新会话时生效，已有会话沿用其原绑定环境），环境必须归属当前租户/应用，否则返回无权访问错误。未传 sessionId 和 bizKey 时可通过 projectId 创建项目会话；projectId 与二者互斥。vaultIds 可在隐式创建新会话时绑定当前应用空间密钥；已有会话沿用原密钥绑定，不传或空列表时不绑定密钥；密钥不归属当前租户/应用时返回无权访问错误。可通过 knowledgeLibraryIds 指定本次运行使用的知识库，非空时覆盖智能体已启用的集合，不传或空数组时回落到智能体已启用的集合；传入的知识库必须全部属于当前应用空间，只要有一个不属于本应用空间则整个请求返回无权访问。

可通过 virtualTools 声明本次运行的客户端展示工具，让模型产出一次结构化的渲染指令，由您的终端渲染图表、卡片等界面元素：服务端不执行您的任何代码，模型发起调用时按 parameters 校验参数，返回预设 mockResponse；省略或null使用默认success回执；调用内容从既有 SSE 事件流的 TOOL_CALL_GENERATING、TOOL_START、TOOL_COMPLETED 事件读取，渲染结果无需回传。该参数请求级生效，不写入会话默认工具也不被后续运行继承，重试失败运行时沿用原请求快照中的定义。工具定义整批由服务端校验，不合法时在运行启动之前整次请求失败并一次性返回全部问题，不会混进 SSE 事件流；不传时行为不变。

## 请求参数

### 请求头参数

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| X-Principal-Id | integer | 否 | 身份主体ID（Long类型）。通过API访问时必须传递以标识操作主体；通过页面访问时无需传递。可通过「身份主体」模块的创建接口获取。 |

### 请求体（JSON）

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| agentId | integer | 是 | 智能体ID |
| maxSteps | integer | 否 | 本次运行的最大执行轮数，必须为正整数，不传默认2000。一次模型决策及其工具执行计为一轮；异步挂起恢复和失败重试沿用原运行上限，不影响后续新请求。 |
| maxInputTokens | integer | 否 | 本次运行普通推理输入上下文预算，单位token，仅接受JSON整数，最小65536，最大为实际模型配置的输入上限。不传或null沿用默认。包含系统提示、工具、历史、输入及媒体，按估算管理并预留安全余量。摘要调用使用独立预算，可能超过本值；不限制输出、思考和累计费用。异步、重试及挂起恢复沿用，后续新请求不继承。 |
| enableSubagent | boolean | 否 | 是否允许本次运行创建或继续子智能体。仅接受JSON布尔值，true开启，不传、null或false均关闭；仍受智能体工具权限和系统运行条件限制。重试、挂起恢复沿用原值，后续新请求不继承。 |
| userInput | string | 是 | 用户输入内容，即发送给智能体的消息 |
| sessionId | integer | 否 | 会话ID，传入后将继续该会话的上下文对话 |
| projectId | integer | 否 | 项目ID。仅在未传sessionId和bizKey、需要隐式创建项目会话时使用 |
| bizKey | string | 否 | 用户自定义会话ID，传入后将继续该会话的上下文对话 |
| environmentId | integer | 否 | 沙箱环境ID，指定后本次运行在该沙箱环境中执行。

注意：仅在本次运行隐式创建新会话时生效；传入 sessionId 或命中已有 bizKey 会话时，沿用该会话原绑定的环境，不会切换到本次传入的环境。环境必须归属当前租户/应用，否则返回无权访问错误。不传时不绑定沙箱环境，保持原有行为。 |
| vaultIds | array | 否 | 本次隐式创建新会话时绑定的应用空间密钥ID列表。仅创建新会话时生效；传入 sessionId 或命中已有 bizKey 时沿用原绑定。密钥须归属当前租户/应用，否则返回无权访问错误；不传或空列表时不绑定密钥。重复ID按首次出现顺序去重。 |
| reasoningEffort | string | 否 | 推理力度档位（推荐使用，替代 enableThinking）。与模型无关，服务端自动适配各模型参数差异。

**可选值（大小写不敏感）：**
- disabled：关闭思考，适用于简单问答、追求极致响应速度
- low：1,024 token 预算，适用于日常轻任务
- medium：4,096 token 预算，适用于一般任务
- high：16,384 token 预算（默认档），适用于复杂分析
- xhigh：32,768 token 预算，适用于最难任务（深度数学/代码推演）

不传时依次取智能体级默认档位（租户控制台『默认模型』卡片配置）、系统默认 high。参数优先级：thinkingBudget > reasoningEffort > enableThinking > 智能体级默认档位。 |
| thinkingBudget | integer | 否 | 思维链 token 预算（精确控制），直接指定思维链 token 数量上限。面向需要精确成本控制的调用方。服务端自动校验修正：低于1抬到1，超过模型上限压到上限，任何取值都不会导致调用报错。

参数优先级：thinkingBudget > reasoningEffort > enableThinking > 智能体级默认档位。

注意：想关闭思考请传 reasoningEffort=disabled；thinkingBudget表示开启思考并限制长度。 |
| enableThinking | boolean | 否 | 是否启用思考模式（已废弃，请改用 reasoningEffort 参数）。

本参数仍可正常使用，但新代码建议改用 reasoningEffort 以获得更精细的推理控制能力。
显式传入时优先于智能体级默认档位：true 等效 reasoningEffort=high，false 等效 disabled；
不传时依次取智能体级默认档位（租户控制台配置）、系统默认 high。
显式传 null 与不传字段等效，均视为未指定，由智能体级默认档位/系统默认 high 决定。

参数优先级：thinkingBudget > reasoningEffort > enableThinking > 智能体级默认档位。 |
| temperature | number | 否 | 模型温度参数，值越高输出越随机，取值范围 0~2，不传时默认 1.0 |
| model | string | 否 | 指定模型名称，不传时使用智能体默认模型 |
| attachmentIds | array | 否 | 附件ID列表，传入的附件ID需要是当前用户上传且属于对应会话的附件 |
| urlAttachments | array | 否 | 通过HTTPS URL导入的附件列表，仅异步运行支持，最多10个。可与attachmentIds同时传入；接口提交成功仅表示任务已创建，附件导入失败会通过SSE事件或任务状态返回 |
|     fileName | string | 是 | 导入后的文件名，最多255个字符，不得包含路径分隔符，建议保留原文件扩展名 |
|     fileUrl | string | 是 | 待导入文件的HTTPS地址，仅支持HTTPS协议，最多4096个字符 |
| triggerSource | TriggerSource | 否 | 触发来源配置，标识本次运行的触发方式。为null时系统根据访问模式自动推断（用户模式默认human_message，应用模式默认api_call）。

**字段说明：**
- sourceType：触发源类型（必填），可选值：human_message（人类消息）、scheduled_task（定时任务）、api_call（API调用）、internal（内部调用）
- channelType：通道类型（可选），sourceType为human_message时使用，可选值：im
- channelProvider：通道提供商（可选），sourceType为human_message时使用，可选值：dingtalk、wecom、wechat、feishu |
|     sourceType | string | 否 | - |
|     channelType | string | 否 | - |
|     channelProvider | string | 否 | - |
| visible | boolean | 否 | 是否对用户可见，false时本次运行不出现在用户列表中 |
| runtimeVariables | object | 否 | 运行时变量，键值对形式。调用方传入后，智能体运行期间技能和工具可通过变量名读取对应值。

key 为变量名（仅支持字母、数字、下划线），value 为变量值（字符串）。 |
| supportedOutputFormats | array | 否 | 调用方终端支持的输出格式列表，用于声明终端渲染能力。

例如传入 "echarts" 表示终端可渲染 ECharts 图表，模型在分析型任务中会输出 ```echarts 代码块（内容为 ECharts option 严格 JSON），由调用方终端负责渲染；不传时模型不会输出此类内容，无渲染能力的调用方无需改动。 |
| virtualTools | array | 否 | 本次运行的客户端展示工具列表，用于让模型产出结构化的渲染指令，由您的终端自行渲染图表、卡片等界面元素。

**字段说明（每个数组元素）：**
- name：工具名称（必填），需匹配正则 [A-Za-z_][A-Za-z0-9_-]{0,63}，不得与同批其它工具、平台全局工具或保留名 finx、skill、knowledge_search 冲突
- description：工具说明（必填），非空且 UTF-8 编码不超过 2KiB，模型据此判断何时调用
- parameters：原生 JSON Schema 对象（必填），不是 JSON 字符串；根节点必须显式 type=object；方言为 draft-07；禁止任何 $ref（含本地引用），禁止根级 allOf/anyOf/oneOf/not/if/then/else/enum/const；仅接受服务端白名单内的 draft-07 关键词与 format，未知关键词会被拒绝；单项 Schema 不超过 16KiB、整批不超过 256KiB、JSON 深度不超过 16
- mockResponse：可选字符串，作为模拟结果原样返回；省略或null使用默认回执，空字符串保留，计入整批大小限制

**行为要点：**
- 请求级、只对本次运行有效，不写入会话默认工具，也不会被后续运行继承；重试失败运行时沿用原请求快照里的定义，无需重传
- 服务端不执行您的代码：模型发起调用时只按 parameters 校验参数，然后返回预设 mockResponse，未指定时返回默认回执 {"status":"success"} 让主循环继续；返回内容不代表您的终端已完成渲染，也不证明外部业务实际执行
- 调用内容从既有 SSE 事件流获取：TOOL_CALL_GENERATING（逐帧增量）、TOOL_START / TOOL_COMPLETED 的 toolName 与 arguments，渲染结果无需回传
- 单次最多 16 项。定义不合法时整次请求失败并一次性返回全部问题，错误定位按 virtualTools[下标] 与您传入的顺序对齐；校验发生在运行启动之前，不会混进 SSE 事件流

不传、传 null 或空数组时行为与不使用该能力完全一致。 |
|     name | string | 是 | 工具名称，需匹配正则 [A-Za-z_][A-Za-z0-9_-]{0,63}；不得与同批其它工具、平台全局工具或保留名 finx、skill、knowledge_search 冲突 |
|     description | string | 是 | 工具说明，非空且 UTF-8 编码不超过 2KiB；模型据此判断何时调用该工具 |
|     parameters | object | 是 | 工具参数的原生 JSON Schema 对象，直接写 JSON 对象，写成 JSON 字符串会在请求解析阶段即返回参数错误。根节点必须显式 type=object，方言为 draft-07；禁止任何 $ref（含本地引用），禁止根级 allOf/anyOf/oneOf/not/if/then/else/enum/const；仅接受服务端白名单内的 draft-07 关键词与 format；单项不超过 16KiB、整批不超过 256KiB、JSON 深度不超过 16 |
|     mockResponse | string | 否 | 预设模拟返回文本（可选）。参数校验通过后原样作为 TOOL_COMPLETED 的 output 返回；省略或 null 时使用默认回执，空字符串和空白原样保留。支持纯文本、Markdown 或 JSON 文本，不接受直接传入对象、数组、数字或布尔值；计入整批定义 256KiB 限制。该内容为模拟结果，不代表外部业务实际执行或客户端已完成渲染。 |
| capabilityConfig | AgentRunCapabilityConfigRequest | 否 | 本次运行的工具和Skill能力限制。未传时沿用智能体配置；传入后仅对本次运行及其派生的定时任务生效。请求配置只能收窄智能体能力，不能重新启用智能体已禁用的工具或Skill |
|     toolsEnabled | boolean | 否 | 是否允许调用工具。false时包括Skill在内的所有工具均不可调用；true不能重新启用智能体已禁用的工具 |
|     disabledTools | array | 否 | 本次运行额外禁用的工具内部名称列表，名称必须与系统注册名称精确匹配 |
|     enabledToolsOnly | array | 否 | 本次运行仅允许使用的工具内部名称列表，传入非空集合时采用白名单模式。需要调用Skill时必须包含skill |
|     skillsEnabled | boolean | 否 | 是否启用Skill。false表示禁用所有Skill；true不能突破智能体配置和工具层限制 |
|     disabledSkills | array | 否 | 本次运行额外禁用的Skill内部名称列表，名称必须与系统注册名称精确匹配 |
|     enabledSkillsOnly | array | 否 | 本次运行仅允许使用的Skill内部名称列表，传入非空集合时采用白名单模式 |
|     disabledFinxServices | array | 否 | 本次运行禁用的Finx服务内部名称列表，传入非空集合时采用黑名单模式。enabledFinxServicesOnly传入非空集合时，以白名单模式为准。 |
|     enabledFinxServicesOnly | array | 否 | 本次运行仅允许使用的Finx服务内部名称列表，传入非空集合时采用白名单模式。该字段优先级高于disabledFinxServices；同一服务同时出现在两个集合中时，以本字段为准。 |
| knowledgeLibraryIds | array | 否 | 本次运行显式指定的知识库ID列表，仅对本次运行生效。

非空时优先生效并覆盖智能体已启用的知识库集合；不传或为空数组时回落到智能体已启用的集合。
传入的知识库必须全部属于当前应用空间，只要有一个不属于本应用空间则整个请求返回无权访问（不会静默跳过越界项）。
最多 200 个。 |

## 响应

### 200

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | HTTP状态码 |
| message | string | 响应消息 |
| data | AgentRunAsyncResponse | 响应数据 |
|     requestId | string | - |
|     sessionId | integer | - |
| success | boolean | 是否成功 |
| requestId | string | 上游请求ID，用于跨系统链路追踪排查问题 |
| errCode | string | 上游错误码，前端可据此做特殊UI处理 |

### 400

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | HTTP状态码 |
| message | string | 响应消息 |
| data | object | 响应数据 |
| success | boolean | 是否成功 |
| requestId | string | 上游请求ID，用于跨系统链路追踪排查问题 |
| errCode | string | 上游错误码，前端可据此做特殊UI处理 |

### 409

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | - |
| success | boolean | - |
| errCode | string | - |
| message | string | - |
| data | object | - |
| requestId | string | 业务错误可能返回；入口解密错误不保证存在 |

### 413

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | - |
| success | boolean | - |
| errCode | string | - |
| message | string | - |
| data | object | - |
| requestId | string | 业务错误可能返回；入口解密错误不保证存在 |

### 415

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | - |
| success | boolean | - |
| errCode | string | - |
| message | string | - |
| data | object | - |
| requestId | string | 业务错误可能返回；入口解密错误不保证存在 |

### 500

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | HTTP状态码 |
| message | string | 响应消息 |
| data | object | 响应数据 |
| success | boolean | 是否成功 |
| requestId | string | 上游请求ID，用于跨系统链路追踪排查问题 |
| errCode | string | 上游错误码，前端可据此做特殊UI处理 |

### 503

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | - |
| success | boolean | - |
| errCode | string | - |
| message | string | - |
| data | object | - |
| requestId | string | 业务错误可能返回；入口解密错误不保证存在 |

## 加密请求（application/jose）

可选请求格式：`Content-Type: application/jose`，`Accept: application/json`。
仍使用 `Authorization: Bearer <APPLICATION_API_KEY>` 和 `X-Principal-Id: <PRINCIPAL_ID>`，加密不替代认证。
将本接口原 JSON 请求对象整体加密（字段、校验和含义不变），发送 JWE Compact 五段字符串；不要添加 JSON 引号或外层对象。
使用平台交付的租户 RSA 公钥（至少 3072 位）及配套 kid；公钥指纹是 SPKI DER 字节的 SHA-256 十六进制摘要。
协议 `dj-jwe-v1`：`alg=RSA-OAEP-256`（OAEP/MGF1 均为 SHA-256），`enc=A256GCM`。
每次重新生成 32 字节 CEK 和 12 字节 IV；RSA 加密原始 CEK；Tag 为 16 字节；AAD 是第一段 Base64URL 字符串的 ASCII 字节。
五段均使用无填充 Base64URL。下面受保护头中的身份、公钥标识、受众和时间必须替换为实际值：

```json
{"alg":"RSA-OAEP-256","enc":"A256GCM","kid":"<KID>","typ":"JOSE","cty":"application/json","dj":{"v":1,"tenant":"<TENANT_ID>","caller":"<APP_ID>","principal":"<PRINCIPAL_ID>","aud":"<AUDIENCE>","op":"agent.run.async","iat":1793232000,"exp":1793232300,"jti":"44df537b-8097-4a3a-901c-07ba405c14c5"}}
```

`dj.principal` 必须与请求身份一致；`dj.caller`、`dj.tenant` 必须匹配 API Key 所属应用、租户；`dj.op` 必须匹配本接口。
iat/exp 为 Unix 秒，exp > iat 且间隔不超过 300 秒，允许 60 秒时钟偏差；jti 每次唯一，建议 UUID v4。
头字段集合固定，不允许额外字段、重复 JSON 键、zip 或 crit。密文整体上限 6 MiB，解密 JSON 上限 4 MiB，受保护头上限 4096 字节。
不发送 Content-Encoding（包括 identity）；不支持 application/jose+json。
普通会话允许下一轮通过 JOSE 升级；已加密会话必须继续使用 JOSE。补充输入须与对应 requestId 的运行模式一致，content 最多 10000 字符。
成功响应仍使用原 JSON 结构；SSE 订阅方式和事件格式不变，不需要解密响应。

错误响应沿用 ApiResponse：success=false，errCode、message 为错误标识；普通媒体类型错误仍为 HTTP 400 / message=Media type not supported（沿用原响应，不额外设置 errCode）。
JOSE 格式、解密或上下文校验失败：HTTP 400 / CRYPTO_INVALID_MESSAGE。
补充输入模式不一致：HTTP 400 / errCode=400 / message=SUPPLEMENTARY_INPUT_TRANSPORT_MISMATCH。
新增的 409/413/415/503 说明见本接口响应列表。下方五段示例仅展示格式，须替换为实际加密结果。

```bash
curl 'https://router.fis.aliyuncs.com/finx/api/agent/run/async' \
  -H 'Authorization: Bearer <APPLICATION_API_KEY>' \
  -H 'X-Principal-Id: <PRINCIPAL_ID>' \
  -H 'Content-Type: application/jose' -H 'Accept: application/json' \
  --data-binary '<protected>.<encryptedKey>.<iv>.<ciphertext>.<tag>'
```


```text
<protected>.<encryptedKey>.<iv>.<ciphertext>.<tag>
```

### 加密相关错误响应

#### HTTP 400

Bad Request

#### HTTP 409

CRYPTO_REPLAY：同一 jti 重复提交。普通 JSON 续接加密会话：errCode=409，message=SESSION_REQUIRES_JOSE_ENCRYPTED_REQUEST，data.reason=SESSION_TRANSPORT_CONFLICT；请使用 JOSE 重新提交。原业务 409 冲突语义保持不变。

```json
{
  "httpStatusCode": 409,
  "message": "CRYPTO_REPLAY",
  "errCode": "CRYPTO_REPLAY",
  "success": false
}
```

```json
{
  "httpStatusCode": 409,
  "errCode": "409",
  "data": {
    "reason": "SESSION_TRANSPORT_CONFLICT"
  },
  "success": false,
  "message": "SESSION_REQUIRES_JOSE_ENCRYPTED_REQUEST"
}
```

#### HTTP 413

CRYPTO_PAYLOAD_TOO_LARGE：JOSE 请求体超过 6 MiB 或解密后的 JSON 超过 4 MiB。

```json
{
  "httpStatusCode": 413,
  "message": "CRYPTO_PAYLOAD_TOO_LARGE",
  "errCode": "CRYPTO_PAYLOAD_TOO_LARGE",
  "success": false
}
```

#### HTTP 415

CRYPTO_UNSUPPORTED_MEDIA_TYPE：application/jose 请求携带不支持的 Content-Encoding（包括 identity）。text/plain、application/jose+json 等不支持的 Content-Type 仍返回 HTTP 400 / Media type not supported。

```json
{
  "httpStatusCode": 415,
  "message": "CRYPTO_UNSUPPORTED_MEDIA_TYPE",
  "errCode": "CRYPTO_UNSUPPORTED_MEDIA_TYPE",
  "success": false
}
```

#### HTTP 500

Internal Server Error

#### HTTP 503

CRYPTO_UNAVAILABLE：入口加密暂不可用，请稍后使用新的 jti 和密文重试；不要自动改发明文。

```json
{
  "httpStatusCode": 503,
  "message": "CRYPTO_UNAVAILABLE",
  "errCode": "CRYPTO_UNAVAILABLE",
  "success": false
}
```

