Files
social-app/docs/protocols/agent/sse-events.md
T

6.5 KiB

Agent SSE Events

本文档记录 Agent Runtime 产生的所有 Server-Sent Events (SSE) 事件,用于前端实时展示。

事件流转架构

pipeline.emit()
    ↓
AgentScopeEventPipeline.emit()
    ├─→ store.persist()  → 持久化到数据库
    └─→ bus.publish()    → 发布到 Redis Stream
            ↓
前端通过 GET /runs/{thread_id}/events 读取

事件统一格式

所有事件在 Redis 中传输时都包含以下字段:

{
  type: string,       // 事件类型
  threadId: string,   // 会话 ID
  runId: string,      // 运行 ID
  data: object        // 事件数据
}

1. Orchestrator 生命周期事件

run.started

Agent 开始运行时触发。

{
  type: "run.started",
  threadId: "xxx",
  runId: "yyy",
  data: {}
}

run.finished

Agent 成功完成时触发。

{
  type: "run.finished",
  threadId: "xxx",
  runId: "yyy",
  data: {}
}

run.error

Agent 运行出错时触发。

{
  type: "run.error",
  threadId: "xxx",
  runId: "yyy",
  data: {
    message: "runtime execution failed"
  }
}

2. Step 阶段事件

step.start

阶段开始时触发。

{
  type: "step.start",
  threadId: "xxx",
  runId: "yyy",
  data: {
    stepName: "router" | "worker"
  }
}

step.finish

阶段结束时触发。

{
  type: "step.finish",
  threadId: "xxx",
  runId: "yyy",
  data: {
    stepName: "router" | "worker"
  }
}

3. Worker 运行时事件

3.1 文本消息事件

text.start

文本消息开始时触发。

{
  type: "text.start",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    role: "assistant",
    stage: "worker"
  }
}

text.delta

文本内容增量更新时触发。

{
  type: "text.delta",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    delta: "这是新增的文本内容",
    stage: "worker"
  }
}

text.end

文本消息结束时触发,包含完整输出和使用统计。

{
  type: "text.end",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    role: "assistant",
    stage: "worker",
    workerAgentOutput: {
      status: "success" | "partial_success" | "failed",
      answer: "主回复文本",
      key_points: ["要点1", "要点2"],
      result_type: "execution_report" | "clarification" | "error_report" | "unknown",
      suggested_actions: ["建议操作1"],
      error: null | { code: string, message: string },
      ui_hints: { ... } | null  // 仅在 ui_mode 非空时存在
    },
    model: "gpt-4o",
    inputTokens: 1000,
    outputTokens: 500,
    cost: 0.025,
    latencyMs: 1500
  }
}

workerAgentOutput 详细结构:

// WorkerAgentOutputLite
{
  status: "success" | "partial_success" | "failed",
  answer: string,
  key_points: string[],
  result_type: "execution_report" | "clarification" | "error_report" | "unknown",
  suggested_actions: string[],
  error: { code: string, message: string } | null
}

// WorkerAgentOutputRich (当 ui.ui_mode 非空时)
{
  // ... WorkerAgentOutputLite 字段
  ui_hints: {
    ui_mode: string,
    ui_state: object,
    actions: UiHintAction[]
  }
}

3.2 工具调用事件

tool.start

工具调用开始时触发。

{
  type: "tool.start",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    toolCallId: "call-abc",
    toolName: "calendar_read",
    stage: "worker"
  }
}

tool.args

工具调用参数时触发。

{
  type: "tool.args",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    toolCallId: "call-abc",
    toolName: "calendar_read",
    args: { start_date: "2024-01-01", end_date: "2024-01-07" },
    stage: "worker"
  }
}

tool.end

工具调用结束时触发。

{
  type: "tool.end",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    toolCallId: "call-abc",
    toolName: "calendar_read",
    stage: "worker"
  }
}

tool.result

工具执行结果时触发。

{
  type: "tool.result",
  threadId: "xxx",
  runId: "yyy",
  data: {
    messageId: "msg-xxx",
    toolCallId: "call-abc",
    toolName: "calendar_read",
    stage: "worker",
    toolAgentOutput: {
      tool_name: "calendar_read",
      tool_call_id: "call-abc",
      tool_call_args: { start_date: "2024-01-01", end_date: "2024-01-07" },
      status: "success" | "failed",
      result_summary: "找到3个事件...",
      ui_hints: null,
      attachments: null
    }
  }
}

toolAgentOutput 详细结构:

{
  tool_name: string,
  tool_call_id: string,
  tool_call_args: object | null,
  status: "success" | "failed",
  result_summary: string,
  ui_hints: object | null,
  attachments: Array<{
    bucket: string,
    path: string,
    mime_type: string,
    url: string
  }> | null
}

使用统计字段

text.end 事件中包含使用统计:

字段 类型 说明
model string 使用的模型名称
inputTokens number 输入 token 数量
outputTokens number 输出 token 数量
cost number 花费(美元)
latencyMs number 延迟(毫秒)

前端接收示例

const eventSource = new EventSource(`/runs/${threadId}/events`);

eventSource.addEventListener('run.started', (e) => {
  console.log('Agent started:', JSON.parse(e.data));
});

eventSource.addEventListener('step.start', (e) => {
  console.log('Step started:', JSON.parse(e.data));
});

eventSource.addEventListener('text.delta', (e) => {
  const data = JSON.parse(e.data);
  console.log('Text delta:', data.data.delta);
});

eventSource.addEventListener('tool.start', (e) => {
  const data = JSON.parse(e.data);
  console.log('Tool called:', data.data.toolName);
});

eventSource.addEventListener('tool.result', (e) => {
  const data = JSON.parse(e.data);
  console.log('Tool result:', data.data.toolAgentOutput);
});

eventSource.addEventListener('text.end', (e) => {
  const data = JSON.parse(e.data);
  console.log('Worker output:', data.data.workerAgentOutput);
  console.log('Usage:', {
    inputTokens: data.data.inputTokens,
    outputTokens: data.data.outputTokens,
    cost: data.data.cost
  });
});

eventSource.addEventListener('run.finished', (e) => {
  console.log('Agent finished:', JSON.parse(e.data));
});

eventSource.addEventListener('run.error', (e) => {
  console.log('Agent error:', JSON.parse(e.data));
});