> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 处理流式响应

> 选择响应模式、解析 SSE 流、按事件类型分发处理，并在连接断开后恢复

> 本文档由 AI 自动翻译。如有任何不准确之处，请参考 [英文原版](/en/api-reference/guides/streaming)。

生成类接口既可一次性返回完整响应，也可返回 Server-Sent Events（SSE）流，由每次请求的 `response_mode` 决定。通常选流式返回：回复边生成边呈现，长时间运行也不会中途被切断。

## 选择响应模式

`blocking`（阻塞式返回）在生成结束后一次性返回一个 JSON 响应体。对简短、非交互的调用来说，它集成起来更简单，但长时间生成有被中断的风险：代理会切断长请求，Dify Cloud 的边缘代理约 100 秒后就会终止请求。

`streaming`（流式返回）以 SSE 事件的形式传送回复。面向用户的场景、长时间运行的任务，以及所有会因 [人工介入](/zh/api-reference/guides/human-input-flow) 暂停的流程，都应使用它。

<Info>
  Agent 和新 Agent 应用仅支持流式返回。
</Info>

## 解析事件流

每个事件以一行 `data: ` 的形式到达，携带一个 JSON 对象，并以一个空行结束。

根据 `event` 字段决定如何处理，并跳过所有不以 `data: ` 开头的行：保活用的 `ping` 每 10 秒到达一次，形式是一行不带 `data:` 载荷的 `event: ping`。

```python theme={null}
import json
import requests

body = {
    "query": "What are this month's top issues?",
    "inputs": {},
    "user": "customer-4821",
    "response_mode": "streaming",
}

with requests.post(url, headers=headers, json=body, stream=True) as r:
    for line in r.iter_lines(decode_unicode=True):
        if not line or not line.startswith("data: "):
            continue  # 跳过空行分隔符和 ping 行
        event = json.loads(line[len("data: "):])
        handle(event)
```

实际传输中，事件流如下所示：

```text theme={null}
data: {"event": "workflow_started", "task_id": "c3800678-…", "workflow_run_id": "fb47b2e6-…", "data": {…}}

event: ping

data: {"event": "node_finished", "task_id": "c3800678-…", "workflow_run_id": "fb47b2e6-…", "data": {…}}
```

## 按事件类型分发

会收到哪些事件取决于应用类型。事件契约详见 [发送对话消息](/zh/api-reference/chat-messages/send-chat-message)、[执行工作流](/zh/api-reference/workflow-runs/run-workflow) 和 [发送消息](/zh/api-reference/completion-messages/send-completion-message) 页面中的事件表。

通常至少要做到：

1. 按顺序拼接回复片段：

   * Chatbot 和 Chatflow 应用为 `message` 事件
   * Agent 和新 Agent 应用为 `agent_message` 事件

   新 Agent 应用在收尾时会额外返回一个重复完整回答的 `message` 事件，将其视为最终回答即可，不要再追加拼接。

2. 在正确的终止事件上收尾：
   * Chatbot、Agent 和新 Agent 应用为 `message_end`
   * Chatflow 应用为 `message_end` 后跟 `workflow_finished`（两个事件都会到达，且按此顺序）
   * Workflow 应用为 `workflow_finished`

3. 将 `error` 事件上报给调用方。

## 处理流中的错误

流打开之后再发生失败，HTTP 状态码不会改变：连接保持 `200`。失败以何种形式出现，取决于它发生在哪里：

* 工作流节点失败时，会收到 `status` 为 `"failed"` 的 `node_finished` 和 `workflow_finished` 事件。
* 其他失败会以一个携带 `status`、`code` 和 `message` 的 `error` 事件结束整个流。

两种情况都要处理，且都视为该请求的终点。

## 重连与恢复

有两个标识符很重要，且容易混淆：

* `task_id` 控制进行中的生成，是停止接口所需的参数（[停止响应](/zh/api-reference/chat-messages/stop-chat-message-generation)、[停止工作流任务](/zh/api-reference/workflow-runs/stop-workflow-task)）。
* `workflow_run_id` 指向持久化的运行记录。

两者都从流本身获得：除 `error` 外的每个事件都携带 `task_id`，工作流和节点事件还携带 `workflow_run_id`。收到 `workflow_run_id` 后立即保存：如果连接中途断开，它是重连或查询运行结果的唯一凭据。

对由工作流驱动的运行（Workflow 和 Chatflow 应用），连接断开并非致命问题。可用 [流式获取工作流事件](/zh/api-reference/workflow-runs/stream-workflow-events) 重新打开事件流，传入 `workflow_run_id` 和发起运行时所用的同一个 `user`。`user` 不一致会返回 404。

加上 `include_state_snapshot=true` 可先重放已执行节点的状态；加上 `continue_on_pause=true` 可在多次人工介入暂停间保持同一个流不断开。

重连到仍在运行的工作流后，用 [获取工作流执行情况](/zh/api-reference/workflow-runs/get-workflow-run-detail) 确认运行已完成，不要只依赖重连后事件流的最后一个事件。

其他类型的回复没有恢复接口：连接在回复中途断开时，重新发起请求即可。对话类应用可通过 [获取会话历史消息](/zh/api-reference/conversations/list-conversation-messages) 查看已保存到会话中的内容。

## 保持连接

将客户端的读取超时设置为明显大于 10 秒的 `ping` 间隔，事件之间的空闲期才不会导致连接被断开。`ping` 本身无需处理，跳过即可。
