版本:v4.0 更新日期:2026-02-04
本 API 提供 Agent 执行过程的实时可视化能力:
核心概念:
统一的 Trace 模型:
主 Trace 和 Sub-Trace 使用相同的数据结构:
- 每个 Trace 有独立的 GoalTree
- 每个 Trace 有独立的 Message List
- Sub-Trace 通过 parent_trace_id 和 parent_goal_id 关联父 Trace
- Trace ID 采用层级命名:
- 主 Trace: UUID (如 2f8d3a1c-4b6e-4f9a-8c2d-1e5b7a9f3c4d)
- Sub-Trace: {parent}@{mode}-{timestamp}-{seq} (如 2f8d3a1c...@explore-20260204220012-001)
数据结构:
后端存储:
1. 每个 Trace 独立存储(主 Trace 和 Sub-Traces)
2. GoalTree - 目标树结构 + 聚合统计
3. Messages - 执行记录,通过 goal_id 关联 Goal
关系:
- Goal.stats 从关联的 Messages 聚合计算
- Sub-Trace 通过 parent_trace_id 关联
- Goal 通过 sub_trace_ids 关联启动的 Sub-Traces
DAG 可视化(前端负责):
http://localhost:8000application/jsonGET /api/traces?status=running&limit=20
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| status | string | 否 | 过滤状态:running / completed / failed |
| mode | string | 否 | 过滤模式:call / agent |
| limit | int | 否 | 返回数量(默认 50,最大 100)|
响应示例:
{
"traces": [
{
"trace_id": "abc123",
"mode": "agent",
"task": "实现用户认证功能",
"status": "running",
"total_messages": 15,
"total_tokens": 5000,
"total_cost": 0.05,
"current_goal_id": "2.1",
"created_at": "2026-02-04T15:30:00"
}
],
"total": 1
}
GET /api/traces/{trace_id}
响应示例 1(主 Trace,explore 进行中):
{
"trace_id": "abc123",
"mode": "agent",
"task": "实现用户认证功能",
"status": "running",
"parent_trace_id": null,
"parent_goal_id": null,
"agent_type": "main",
"total_messages": 15,
"total_tokens": 5000,
"total_cost": 0.05,
"created_at": "2026-02-04T15:30:00",
"completed_at": null,
"goal_tree": {
"mission": "实现用户认证功能",
"current_id": "2",
"goals": [
{
"id": "1",
"parent_id": null,
"type": "normal",
"description": "分析代码",
"reason": "了解现有结构",
"status": "completed",
"summary": "用户模型在 models/user.py",
"self_stats": { "message_count": 5, "total_tokens": 2300, "total_cost": 0.03, "preview": "glob → read × 2" },
"cumulative_stats": { "message_count": 5, "total_tokens": 2300, "total_cost": 0.03, "preview": "glob → read × 2" }
},
{
"id": "2",
"parent_id": null,
"type": "agent_call",
"description": "并行探索认证方案",
"reason": "评估不同技术选型",
"status": "in_progress",
"agent_call_mode": "explore",
"sub_trace_ids": [
{"trace_id": "abc123.A", "mission": "JWT 方案"},
{"trace_id": "abc123.B", "mission": "Session 方案"}
],
"sub_trace_metadata": null,
"self_stats": { "message_count": 0, "total_tokens": 0, "total_cost": 0.0, "preview": null },
"cumulative_stats": { "message_count": 0, "total_tokens": 0, "total_cost": 0.0, "preview": null }
},
{
"id": "3",
"parent_id": null,
"type": "normal",
"description": "完善实现",
"reason": "基于选定方案完成实现",
"status": "pending"
}
]
},
"sub_traces": {
"abc123.A": {
"trace_id": "abc123.A",
"parent_trace_id": "abc123",
"parent_goal_id": "2",
"agent_type": "explore",
"task": "JWT 方案",
"status": "completed",
"total_messages": 8,
"total_tokens": 4000,
"total_cost": 0.05,
"created_at": "2026-02-04T15:31:00",
"completed_at": "2026-02-04T15:35:00"
},
"abc123.B": {
"trace_id": "abc123.B",
"parent_trace_id": "abc123",
"parent_goal_id": "2",
"agent_type": "explore",
"task": "Session 方案",
"status": "completed",
"total_messages": 10,
"total_tokens": 5000,
"total_cost": 0.06
}
}
}
响应示例 2(主 Trace,explore 已完成并合并):
{
"trace_id": "abc123",
"mode": "agent",
"task": "实现用户认证功能",
"status": "running",
"goal_tree": {
"mission": "实现用户认证功能",
"current_id": "3",
"goals": [
{
"id": "1",
"type": "normal",
"description": "分析代码",
"status": "completed",
"summary": "用户模型在 models/user.py"
},
{
"id": "2",
"type": "agent_call",
"description": "并行探索认证方案",
"status": "completed",
"agent_call_mode": "explore",
"sub_trace_ids": [
{
"trace_id": "abc123@explore-20260204220012-001",
"mission": "JWT 方案"
},
{
"trace_id": "abc123@explore-20260204220012-002",
"mission": "Session 方案"
}
],
"sub_trace_metadata": {
"abc123@explore-20260204220012-001": {
"task": "JWT 方案",
"status": "completed",
"summary": "实现完成,使用 JWT token,无状态但 token 较大",
"last_message": {
"role": "assistant",
"description": "生成 JWT token 并返回",
"content": "JWT 方案实现完成。使用 jsonwebtoken 库生成 token,包含 user_id 和过期时间。优点:无状态,易扩展。缺点:token 较大(约 200 字节),无法主动失效。",
"created_at": "2026-02-05T10:30:00"
},
"stats": {
"message_count": 8,
"total_tokens": 4000,
"total_cost": 0.05
}
},
"abc123@explore-20260204220012-002": {
"task": "Session 方案",
"status": "completed",
"summary": "实现完成,使用 Redis 存储 session,支持主动失效",
"last_message": {
"role": "assistant",
"description": "配置 Redis 并实现 session 管理",
"content": "Session 方案实现完成。使用 Redis 存储 session,支持过期自动清理和主动失效。优点:token 小(约 32 字节),可主动失效。缺点:需要 Redis,有网络开销。",
"created_at": "2026-02-05T10:32:00"
},
"stats": {
"message_count": 12,
"total_tokens": 4000,
"total_cost": 0.05
}
}
},
"summary": "探索了 2 个方案,JWT 和 Session 均可行",
"cumulative_stats": {
"message_count": 20,
"total_tokens": 8000,
"total_cost": 0.10
}
},
{
"id": "3",
"type": "normal",
"description": "完善实现",
"status": "in_progress"
}
]
},
"sub_traces": {
"abc123@explore-20260204220012-001": { /* ... */ },
"abc123@explore-20260204220012-002": { /* ... */ }
}
}
获取 Sub-Trace 的完整信息(包括 GoalTree)。
GET /api/traces/abc123.A
响应示例:
{
"trace_id": "abc123.A",
"parent_trace_id": "abc123",
"parent_goal_id": "2",
"agent_type": "explore",
"task": "JWT 方案",
"status": "completed",
"total_messages": 8,
"total_tokens": 4000,
"total_cost": 0.05,
"created_at": "2026-02-04T15:31:00",
"completed_at": "2026-02-04T15:35:00",
"goal_tree": {
"mission": "JWT 方案",
"current_id": null,
"goals": [
{
"id": "1",
"parent_id": null,
"type": "normal",
"description": "JWT 设计",
"status": "completed",
"summary": "设计完成",
"self_stats": { "message_count": 3, "total_tokens": 1500, "total_cost": 0.02, "preview": "read → edit" },
"cumulative_stats": { "message_count": 3, "total_tokens": 1500, "total_cost": 0.02, "preview": "read → edit" }
},
{
"id": "2",
"parent_id": null,
"type": "normal",
"description": "JWT 实现",
"status": "completed",
"summary": "实现完成",
"self_stats": { "message_count": 5, "total_tokens": 2500, "total_cost": 0.03, "preview": "edit × 3 → bash" },
"cumulative_stats": { "message_count": 5, "total_tokens": 2500, "total_cost": 0.03, "preview": "edit × 3 → bash" }
}
]
},
"sub_traces": {}
}
查询指定 Trace 的 Messages(用于查看边的详细执行内容)。
GET /api/traces/abc123/messages?goal_id=1
GET /api/traces/abc123.A/messages?goal_id=2
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| goal_id | string | 否 | 过滤指定 Goal 的 Messages(内部 ID,如 "1", "2")|
响应示例:
{
"trace_id": "abc123",
"messages": [
{
"message_id": "msg-001",
"trace_id": "abc123",
"role": "assistant",
"sequence": 1,
"goal_id": "1",
"content": {
"text": "让我先读取现有的 API 设计...",
"tool_calls": [
{
"id": "call_abc",
"name": "read_file",
"arguments": { "path": "api/routes.py" }
}
]
},
"description": "让我先读取现有的 API 设计...",
"tokens": 150,
"cost": 0.002,
"created_at": "2026-02-04T15:31:00"
},
{
"message_id": "msg-002",
"trace_id": "abc123",
"role": "tool",
"sequence": 2,
"goal_id": "1",
"tool_call_id": "call_abc",
"content": "# API Routes\n...",
"description": "read_file",
"tokens": null,
"cost": null,
"created_at": "2026-02-04T15:31:01"
}
],
"total": 2
}
const ws = new WebSocket(
'ws://localhost:8000/api/traces/{trace_id}/watch?since_event_id=0'
)
查询参数:
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| since_event_id | int | 0 | 从哪个事件 ID 开始。0 = 补发所有历史 |
连接后推送完整 Trace 信息,前端据此初始化 DAG。
{
"event": "connected",
"trace_id": "abc123",
"current_event_id": 15,
"trace": {
"trace_id": "abc123",
"status": "running",
"goal_tree": {
"mission": "实现用户认证功能",
"current_id": "2",
"goals": [...]
},
"sub_traces": {}
}
}
前端处理:
if (data.event === 'connected') {
initDAG(data.goal_tree)
localStorage.setItem('last_event_id', data.current_event_id)
}
{
"event": "goal_added",
"event_id": 16,
"goal": {
"id": "6",
"parent_id": "2",
"type": "normal",
"description": "编写测试",
"reason": "确保代码质量",
"status": "pending",
"summary": null,
"self_stats": { "message_count": 0, "total_tokens": 0, "total_cost": 0.0, "preview": null },
"cumulative_stats": { "message_count": 0, "total_tokens": 0, "total_cost": 0.0, "preview": null }
},
"parent_id": "2"
}
前端处理:
if (data.event === 'goal_added') {
insertGoal(data.goal, data.parent_id)
regenerateDAG()
}
包含级联完成场景:当所有子 Goal 完成时,父 Goal 自动 completed。
{
"event": "goal_updated",
"event_id": 17,
"goal_id": "3",
"updates": {
"status": "completed",
"summary": "接口设计完成"
},
"affected_goals": [
{
"goal_id": "3",
"cumulative_stats": { "message_count": 3, "total_tokens": 1500, "total_cost": 0.02, "preview": "read → edit" }
},
{
"goal_id": "2",
"status": "completed",
"summary": "功能实现完成",
"cumulative_stats": { "message_count": 8, "total_tokens": 4200, "total_cost": 0.05, "preview": "..." }
}
]
}
前端处理:
if (data.event === 'goal_updated') {
updateGoal(data.goal_id, data.updates)
for (const g of data.affected_goals) {
updateGoalStats(g.goal_id, g)
}
regenerateDAG()
}
后端更新统计后推送,包含受影响的所有 Goals。
{
"event": "message_added",
"event_id": 18,
"message": {
"message_id": "msg-018",
"role": "assistant",
"goal_id": "4",
"content": { "text": "...", "tool_calls": [...] },
"tokens": 500,
"cost": 0.005
},
"affected_goals": [
{
"goal_id": "4",
"self_stats": { "message_count": 6, "total_tokens": 3200, "total_cost": 0.035, "preview": "edit × 3 → bash × 2" },
"cumulative_stats": { "message_count": 6, "total_tokens": 3200, "total_cost": 0.035, "preview": "edit × 3 → bash × 2" }
},
{
"goal_id": "2",
"cumulative_stats": { "message_count": 9, "total_tokens": 4700, "total_cost": 0.055, "preview": "read → edit × 4 → bash × 2" }
}
]
}
说明:
affected_goals[0] 是直接关联的 Goal,更新 self_stats + cumulative_statscumulative_stats前端处理:
if (data.event === 'message_added') {
for (const g of data.affected_goals) {
updateGoalStats(g.goal_id, g)
}
// 根据当前展开状态更新对应边
rerenderEdge(data.message.goal_id)
}
{
"event": "trace_completed",
"event_id": 50,
"trace_id": "abc123",
"total_messages": 50,
"total_tokens": 25000,
"total_cost": 0.25
}
前端处理:
if (data.event === 'trace_completed') {
markTraceCompleted()
ws.close()
}
explore 或 delegate 工具启动 Sub-Trace 时触发。
{
"event": "sub_trace_started",
"event_id": 20,
"parent_trace_id": "abc123",
"parent_goal_id": "2",
"sub_trace": {
"trace_id": "abc123.A",
"parent_trace_id": "abc123",
"parent_goal_id": "2",
"agent_type": "explore",
"task": "JWT 方案",
"status": "running",
"total_messages": 0,
"total_tokens": 0,
"total_cost": 0.0
}
}
前端处理:
if (data.event === 'sub_trace_started') {
insertSubTrace(data.parent_trace_id, data.sub_trace)
regenerateDAG()
}
Sub-Trace 执行完成后触发。
{
"event": "sub_trace_completed",
"event_id": 35,
"trace_id": "abc123.A",
"parent_trace_id": "abc123",
"parent_goal_id": "2",
"summary": "JWT 方案实现完成,无状态但 token 较大",
"total_messages": 8,
"total_tokens": 4000,
"total_cost": 0.05
}
前端处理:
if (data.event === 'sub_trace_completed') {
updateSubTrace(data.trace_id, {
status: 'completed',
summary: data.summary,
total_messages: data.total_messages,
total_tokens: data.total_tokens,
total_cost: data.total_cost
})
regenerateDAG()
}
| 字段 | 类型 | 说明 |
|---|---|---|
trace_id |
string | 层级化 ID(如 "abc123", "abc123.A", "abc123.A.1") |
mode |
string | call - 单次调用 / agent - Agent 模式 |
task |
string | 任务描述 |
parent_trace_id |
string | null | 父 Trace ID(Sub-Trace 才有) |
parent_goal_id |
string | null | 哪个 Goal 启动的(Sub-Trace 才有) |
agent_type |
string | null | "main" / "explore" / "delegate" / "compaction" |
status |
string | running / completed / failed |
total_messages |
int | Message 总数 |
total_tokens |
int | Token 总消耗 |
total_cost |
float | 成本总和 |
created_at |
string | 创建时间(ISO 8601) |
completed_at |
string | null | 完成时间 |
Trace ID 规则:
2f8d3a1c-4b6e-4f9a-8c2d-1e5b7a9f3c"){parent_uuid}@{mode}-{timestamp}-{seq}
2f8d3a1c-4b6e-4f9a-8c2d-1e5b7a9f3c@explore-20260204220012-001"| 字段 | 类型 | 说明 |
|---|---|---|
mission |
string | 总任务描述(来自 Trace.task) |
current_id |
string | null | 当前焦点 Goal 的内部 ID |
goals |
Goal[] | 顶层目标列表 |
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 内部 ID,每个 Trace 独立编号("1", "2", "3"...) |
parent_id |
string | null | 父 Goal ID(层级关系) |
type |
string | normal / agent_call |
description |
string | 目标描述(做什么) |
reason |
string | 创建理由(为什么做) |
status |
string | pending / in_progress / completed / abandoned |
summary |
string | null | 完成/放弃时的总结 |
sub_trace_ids |
Array<{trace_id: string, mission: string}> | null | 启动的 Sub-Trace 信息(仅 agent_call) |
agent_call_mode |
string | null | "explore" / "delegate" / "sequential"(仅 agent_call) |
sub_trace_metadata |
object | null | Sub-Trace 元数据(仅 agent_call,包含最后消息等) |
self_stats |
GoalStats | 自身统计 |
cumulative_stats |
GoalStats | 累计统计 |
Goal 类型说明:
normal Goal:
parent_id 构建层级)agent_call Goal:
sub_trace_ids 关联启动的所有 Sub-Tracesagent_call_mode 标记执行模式:
"explore" - 并行探索:启动多个 Sub-Trace 并行执行,汇总结果后合并"delegate" - 单线委托:将大任务委托给单个 Sub-Trace 执行"sequential" - 顺序执行:按顺序启动多个 Sub-Trace分支探索与合并(explore 模式):
agent_call Goal 同时启动多个 Sub-Trace(如 2-5 个)last_message)summary)stats)agent_call Goal 完成时,表示所有分支已合并
sub_trace_metadata 保存详细元数据(给前端和后续决策使用)ID 设计:
parent_id 维护agent_call 类型的 Goal 会在完成时填充 sub_trace_metadata 字段,格式如下:
{
"sub_trace_metadata": {
"abc123@explore-20260204220012-001": {
"task": "JWT 方案",
"status": "completed",
"summary": "实现完成,使用 JWT token",
"last_message": {
"role": "assistant",
"description": "生成 JWT token 并返回",
"content": "JWT 方案实现完成。使用 jsonwebtoken 库生成 token...",
"created_at": "2026-02-05T10:30:00"
},
"stats": {
"message_count": 8,
"total_tokens": 4000,
"total_cost": 0.05
}
},
"abc123@explore-20260204220012-002": {
"task": "Session 方案",
"status": "completed",
"summary": "实现完成,使用 Redis 存储",
"last_message": {
"role": "assistant",
"description": "配置 Redis 并实现 session 管理",
"content": "Session 方案实现完成。使用 Redis 存储 session...",
"created_at": "2026-02-05T10:32:00"
},
"stats": {
"message_count": 12,
"total_tokens": 4000,
"total_cost": 0.05
}
}
}
}
字段说明:
task - Sub-Trace 的任务描述status - Sub-Trace 的最终状态(completed/failed)summary - Sub-Trace 的执行总结
run_agent() 返回的 summary 字段(如果有)last_message - 最后一条 assistant 消息(内容截断至 500 字符)
role - 固定为 "assistant"description - 消息的简短描述content - 消息内容(可能被截断)created_at - 消息创建时间stats - 统计信息(message_count, total_tokens, total_cost)用途:
| 字段 | 类型 | 说明 |
|---|---|---|
message_count |
int | 消息数量 |
total_tokens |
int | Token 总数 |
total_cost |
float | 总成本 |
preview |
string | null | 工具调用摘要(如 "read → edit × 2") |
| 字段 | 类型 | 说明 |
|---|---|---|
message_id |
string | 唯一 ID |
trace_id |
string | 所属 Trace ID(可能是主 Trace 或 Sub-Trace) |
role |
string | assistant / tool |
sequence |
int | 当前 Trace 内的顺序 |
goal_id |
string | null | 关联的 Goal 内部 ID(如 "1", "2")。可以为 null(初始阶段) |
tool_call_id |
string | null | tool 消息关联的 tool_call ID |
content |
any | 消息内容(和 LLM API 格式一致) |
description |
string | 消息描述(系统自动生成) |
tokens |
int | null | Token 消耗 |
cost |
float | null | 成本 |
created_at |
string | 创建时间 |
goal_id 说明:
null:在 Trace 开始时,Agent 还没有创建任何 Goal查询初始阶段 Messages:
GET /api/traces/{trace_id}/messages?goal_id=_init
_init 或 null 查询 goal_id 为 null 的 messages设计原则:诚实反映数据结构,不在后端创建额外节点。
在 Trace 开始阶段,Agent 还没有创建任何 Goal,这期间产生的 Messages 的 goal_id 为 null。前端应该创建一个虚拟的 START 节点来展示这些初始阶段的 messages。
[START] ────────→ [1:分析完成] ──→ [2:设计完成] ──→ [3:实现完成]
│
└─ goal_id=null 的 messages
(分析任务、创建计划等)
START 节点:
"START" 或 nullSTART → Goal 1 的边:
"START"// 1. 创建 START 节点
function buildDAG(goalTree, messages) {
const nodes = []
const edges = []
// 创建虚拟 START 节点
nodes.push({
id: 'START',
type: 'start',
data: {
label: 'START',
mission: goalTree.mission,
}
})
// 计算初始阶段的统计
const initMessages = messages.filter(m => m.goal_id === null)
const initStats = {
message_count: initMessages.length,
total_tokens: initMessages.reduce((sum, m) => sum + (m.tokens || 0), 0),
total_cost: initMessages.reduce((sum, m) => sum + (m.cost || 0), 0),
preview: generatePreview(initMessages)
}
// 创建 START 到第一个 Goal 的边
const firstGoal = goalTree.goals.find(g => g.parent_id === null)
if (firstGoal) {
edges.push({
source: 'START',
target: firstGoal.id,
data: {
messages: initMessages,
stats: initStats
}
})
}
// 创建其他 goals 的节点和边...
// ...
return { nodes, edges }
}
悬停 START 节点:
┌─────────────────────────────┐
│ START │
│ Mission: 实现用户认证系统 │
│ │
│ 初始阶段统计: │
│ • 2 messages │
│ • 500 tokens │
│ • $0.005 │
└─────────────────────────────┘
点击 START 节点:
点击 START → Goal 1 边:
内容示例:
[assistant] 我需要先分析这个任务...
[tool: goal] 创建了3个顶层目标
查询 API:
// 获取初始阶段的 messages
async function getInitMessages(traceId) {
const resp = await fetch(`/api/traces/${traceId}/messages?goal_id=_init`)
const data = await resp.json()
return data.messages // goal_id 全部为 null
}
情况 1:没有初始阶段 messages
情况 2:所有 messages 都是初始阶段
只显示 START 节点,没有其他节点
[START]
(分析中,3 msgs)
用户可以在 START → Goal 1 的边上编辑第一次 goal() 调用的参数:
这样用户就能方便地修改整体计划。
后端提供 Trace(包含 GoalTree 和 Sub-Traces),前端负责生成 DAG 视图。
普通 Goal(子目标):
agent_call Goal(Sub-Trace):
从 target 节点的 stats 获取:
target.cumulative_statstarget.self_stats// GoalTree(扁平列表,通过 parent_id 构建层级)
const goalTree = {
goals: [
{ id: "1", parent_id: null, description: "分析代码" },
{ id: "2", parent_id: null, description: "实现功能" },
{ id: "3", parent_id: "2", description: "设计接口" }, // 2 的子目标
{ id: "4", parent_id: "2", description: "实现代码" }, // 2 的子目标
{ id: "5", parent_id: null, description: "测试" }
]
}
// 构建层级视图
function buildHierarchy(goals) {
const map = new Map(goals.map(g => [g.id, { ...g, children: [] }]))
const roots = []
for (const goal of goals) {
const node = map.get(goal.id)
if (goal.parent_id) {
map.get(goal.parent_id)?.children.push(node)
} else {
roots.push(node)
}
}
return roots
}
// 展开状态
const expanded = new Set() // 空 = 全部折叠
// 生成可见节点序列
function getVisibleGoals(nodes, expanded) {
const result = []
for (const node of nodes) {
if (expanded.has(node.id) && node.children.length > 0) {
// 展开:递归处理子节点
result.push(...getVisibleGoals(node.children, expanded))
} else {
// 折叠:显示自己
result.push(node)
}
}
return result
}
// 折叠视图: [1] → [2] → [5]
// 展开 "2" 后: [1] → [3] → [4] → [5]
// 生成边
function generateEdges(visibleGoals) {
const edges = []
for (let i = 0; i < visibleGoals.length; i++) {
const source = i === 0 ? null : visibleGoals[i - 1]
const target = visibleGoals[i]
edges.push({
source: source?.id ?? null,
target: target.id,
// 边数据来自 target 的 stats
// 如果 target 有子节点且未展开,用 cumulative_stats
// 否则用 self_stats
stats: hasUnexpandedChildren(target, expanded)
? target.cumulative_stats
: target.self_stats
})
}
return edges
}
// 主 Trace 的 GoalTree
const mainTrace = {
trace_id: "abc123",
goal_tree: {
goals: [
{ id: "1", type: "normal", description: "分析问题" },
{ id: "2", type: "agent_call", agent_call_mode: "explore", sub_trace_ids: [
{"trace_id": "abc123.A", "mission": "JWT 方案"},
{"trace_id": "abc123.B", "mission": "Session 方案"}
] },
{ id: "3", type: "normal", description: "完善实现" }
]
},
sub_traces: {
"abc123.A": { trace_id: "abc123.A", task: "JWT 方案", status: "completed", total_tokens: 4000 },
"abc123.B": { trace_id: "abc123.B", task: "Session 方案", status: "completed", total_tokens: 5000 }
}
}
// 折叠视图:[1] → [2:并行探索] → [3]
// 展开 Sub-Traces 后的视图:
// ┌→ [abc123.A] ────┐
// [1] ──────┼ ├──→ [3]
// └→ [abc123.B] ────┘
// 继续展开 Sub-Trace abc123.A 内部
async function loadSubTrace(traceId) {
const resp = await fetch(`/api/traces/${traceId}`)
return await resp.json() // 返回完整 Trace,含 goal_tree
}
const subTraceA = await loadSubTrace("abc123.A")
// {
// trace_id: "abc123.A",
// goal_tree: {
// goals: [
// { id: "1", description: "JWT 设计" },
// { id: "2", description: "JWT 实现" }
// ]
// }
// }
// 展开后显示 Sub-Trace 内部 Goals:
// ┌→ [A.1:JWT设计] → [A.2:JWT实现] ──┐
// [1] ──────┼ ├──→ [3]
// └→ [abc123.B] ─────────────────────┘
// 注意:前端显示为 "A.1",实际查询是 GET /api/traces/abc123.A/messages?goal_id=1
| 边类型 | 说明 | 样式建议 |
|---|---|---|
| 普通边 | 顺序执行 | 实线 |
| 分叉边 | explore 分支开始 | 虚线或带标记 |
| 汇合边 | 分支合并到 merge 节点 | 虚线或带标记 |
| 废弃边 | abandoned 分支 | 灰色 |
let lastEventId = 0
function connect(traceId) {
const ws = new WebSocket(
`ws://localhost:8000/api/traces/${traceId}/watch?since_event_id=${lastEventId}`
)
ws.onmessage = (event) => {
const data = JSON.parse(event.data)
if (data.event_id) {
lastEventId = data.event_id
localStorage.setItem(`trace_${traceId}_event_id`, lastEventId)
}
// 处理事件...
}
ws.onclose = () => {
setTimeout(() => connect(traceId), 3000)
}
}
| 状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 404 | Trace 不存在 |
| 400 | 参数错误 |
| 500 | 服务器错误 |
{
"event": "error",
"message": "Too many missed events, please reload via REST API"
}