# 导入一问一答会话

`POST` `/api/session/importQaPair`

将一组用户问题和模型回答导入为一轮完整对话，适用于不包含工具调用过程的历史数据。同一外部会话有多轮问答时，应使用相同bizKey或sessionId并按原始对话顺序逐次调用。bizKey命中时追加、未命中时新建；仅传sessionId时追加到指定会话；两者都不传时新建；两者都传时bizKey优先。追加时principalId和agentId必须与目标会话一致，正在执行或等待权限确认的会话不允许追加。需要还原历史时间线时，可传userMessageTime和assistantMessageTime（格式yyyy-MM-dd HH:mm:ss，另兼容ISO的T分隔符与省略秒两种等价写法）；assistantMessageTime不传时继承userMessageTime且不能早于它，两者都不传时行为与旧版完全一致；时间不能晚于当前时间、不能早于2000-01-01，追加导入时也不能早于目标会话已有最后一条消息的时间。本接口非幂等，重复调用会重复导入；发生超时后请先查询目标会话，禁止无条件重试。

**关联定时任务历史运行**：本接口每次只导入一轮对话，响应中的 messageMappings 固定只有一项，其 turnIndex 恒为1（只在本次调用内计数，不是会话内的累计轮次）。迁移原本由定时任务产生的历史对话时，先调用本接口导入问答，再用该项的 assistantMessageId 调用「定时任务」模块的「迁移历史运行记录」接口补齐执行历史。

## 请求参数

### 请求头参数

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

### 请求体（JSON）

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| agentId | integer | 是 | 归属智能体ID；智能体必须存在且处于启用状态 |
| sessionId | integer | 否 | 追加导入的目标会话ID；bizKey为空时生效，不传则新建会话 |
| bizKey | string | 否 | 外部会话的业务键。命中已有会话时追加，未命中时新建并绑定；与sessionId同时传入时优先使用bizKey。建议包含来源系统和租户前缀并保证唯一 |
| title | string | 否 | 新建会话的标题，最多100个字符；追加到已有会话时不生效，新建且不传时根据用户输入生成 |
| modelName | string | 否 | 本轮回答使用的模型名称，用于记录到会话和助手消息；不传则不记录 |
| userInput | string | 是 | 需要导入的用户问题 |
| assistantReply | string | 是 | 需要导入的模型回答 |
| userMessageTime | string | 否 | 用户提问的真实发生时间，格式 yyyy-MM-dd HH:mm:ss（另兼容ISO的T分隔符与省略秒两种写法，不支持时间戳数字）；用于历史会话迁移时还原原始时间线，不传则取导入时刻。不能晚于当前时间、不能早于2000-01-01；追加导入时不能早于目标会话已有最后一条消息的时间 |
| assistantMessageTime | string | 否 | 模型回答的真实发生时间，格式和限制与userMessageTime一致；不传则继承userMessageTime，且不能早于userMessageTime。需与userMessageTime配套传入：仅传本字段时用户消息会取导入时刻，传历史时间将因时间倒挂被拒绝 |

## 响应

### 200

| 参数名 | 类型 | 说明 |
|--------|------|------|
| httpStatusCode | integer | HTTP状态码 |
| message | string | 响应消息 |
| data | SessionImportResultVO | 响应数据 |
|     sessionId | integer | 导入目标会话ID，包括本次新建或追加的会话 |
|     sessionCreated | boolean | 本次是否新建会话；true表示新建，false表示追加到已有会话 |
|     importedTurns | integer | 成功导入的对话轮数 |
|     importedMessages | integer | 成功导入的消息数量 |
|     importedParts | integer | 成功导入的消息片段数量 |
|     skippedSystemMessages | integer | 导入时被忽略的system消息数量 |
|     droppedTrailingUserMessage | boolean | 是否丢弃了轨迹尾部没有assistant回答的user消息 |
|     firstMessageTime | string | 本次导入内容的最早消息时间，格式 yyyy-MM-dd HH:mm:ss（与导入时传入的时间格式一致）；新建会话时即会话创建时间 |
|     lastMessageTime | string | 本次导入内容的最晚消息时间，格式同 firstMessageTime；已写入会话的最后活跃时间，决定会话列表排序；分批追加导入时可直接回填为下一批消息时间的下界参考 |
|     messageMappings | array | 本次实际导入的每轮对话与本地消息ID的映射，按导入顺序返回。

只包含真正落库的轮次：被忽略的system消息、以及被丢弃的尾部无回答user消息都不会出现在这里，因此正常情况下该列表长度与 importedTurns 一致。
如果服务端版本尚未支持返回映射，本字段会是空列表，此时 importedTurns 仍大于0，调用方不能据此判定没有导入成功；按映射迁移历史运行前请先核对两者是否一致。
迁移定时任务历史运行时，取其中的 assistantMessageId 作为「迁移历史运行记录」接口的入参。 |
|         turnIndex | integer | 本次调用内实际导入的轮次序号，从1开始。该序号只在本次调用内计数，不是会话内的累计轮次；分批追加导入同一会话时，每次调用都会重新从1开始 |
|         userMessageId | integer | 本轮用户消息的本地消息ID |
|         assistantMessageId | integer | 本轮助手消息的本地消息ID，可直接用作「迁移历史运行记录」接口的 assistantMessageId |
|     warnings | array | 导入转换告警，例如外部图片降级、未知内容片段忽略或工具结果缺失；调用方应检查并妥善处理 |
| success | boolean | 是否成功 |
| requestId | string | 上游请求ID，用于跨系统链路追踪排查问题 |
| errCode | string | 上游错误码，前端可据此做特殊UI处理 |

### 400

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

### 500

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

