API.md 14 KB

Agent Execution API - 前端对接文档

版本:v2.0 更新日期:2026-02-03


📋 概览

本 API 提供 Agent 执行过程的实时可视化能力,包括:

  • REST API - 查询历史数据、获取完整 Step 树
  • WebSocket - 实时推送 Step 更新(支持断线续传)

核心概念

  • Trace - 一次完整的任务执行(如一次 Agent 运行)
  • Step - 执行过程中的一个原子操作,形成树结构
  • Event - Step 的变更事件(用于 WebSocket 推送和断线续传)

可以运行 python3 examples/feature_extract/run.py 来生成数据。

🌐 REST API

基础信息

  • Base URL: http://localhost:8000
  • Content-Type: application/json

1. 列出 Traces

获取 Trace 列表(支持过滤)

GET /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_steps": 15,
      "total_tokens": 5000,
      "total_cost": 0.05,
      "created_at": "2026-02-03T15:30:00"
    }
  ],
  "total": 1
}

2. 获取 Trace 元数据

GET /api/traces/{trace_id}

响应示例

{
  "trace_id": "abc123",
  "mode": "agent",
  "task": "分析代码库结构",
  "status": "running",
  "total_steps": 15,
  "total_tokens": 5000,
  "total_cost": 0.05,
  "total_duration_ms": 12345,
  "last_sequence": 15,
  "last_event_id": 15,
  "created_at": "2026-02-03T15:30:00",
  "completed_at": null
}

3. 获取完整 Step 树 ⭐ 重要

获取 Trace 的完整 Step 树(适合小型 Trace,<100 个 Step)

GET /api/traces/{trace_id}/tree?view=compact&max_depth=10

查询参数: | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | view | string | compact | compact - 精简视图 / full - 完整视图 | | max_depth | int | 无限 | 最大树深度 |

响应示例

{
  "trace_id": "abc123",
  "root_steps": [
    {
      "step_id": "step-001",
      "step_type": "thought",
      "status": "completed",
      "sequence": 1,
      "parent_id": null,
      "description": "分析项目结构...",
      "has_children": true,
      "children_count": 2,
      "duration_ms": 1234,
      "tokens": 500,
      "cost": 0.005,
      "created_at": "2026-02-03T15:30:01",
      "data": {
        "content": "让我先看看项目的目录结构...",
        "model": "claude-sonnet-4.5"
      },
      "children": [
        {
          "step_id": "step-002",
          "step_type": "action",
          "status": "completed",
          "parent_id": "step-001",
          "description": "glob_files(**/*.py)",
          "data": {
            "tool_name": "glob_files",
            "arguments": {"pattern": "**/*.py"}
          },
          "children": [
            {
              "step_id": "step-003",
              "step_type": "result",
              "status": "completed",
              "parent_id": "step-002",
              "data": {
                "tool_name": "glob_files",
                "output": ["src/main.py", "src/utils.py"]
              }
            }
          ]
        }
      ]
    }
  ]
}

注意

  • children 字段包含嵌套的子节点(递归结构)
  • compact 视图:data 中的大字段(如 messages)会被省略
  • full 视图:返回所有字段(数据量可能很大)

4. 懒加载单个节点

适用于大型 Trace(>100 Step),按需加载子树

GET /api/traces/{trace_id}/node/{step_id}?expand=true&max_depth=2

查询参数: | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | expand | bool | false | 是否展开子节点 | | max_depth | int | 1 | 展开深度 | | view | string | compact | 视图类型 |

响应:与 /tree 格式相同,但只返回指定节点及其子树。


⚡ WebSocket API

连接

const ws = new WebSocket(
  'ws://localhost:8000/api/traces/{trace_id}/watch?since_event_id=0'
)

查询参数: | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | since_event_id | int | 0 | 从哪个事件 ID 开始
0 = 补发所有历史
>0 = 只补发指定 ID 之后的 |


事件类型

1. connected(连接成功)

{
  "event": "connected",
  "trace_id": "abc123",
  "current_event_id": 15
}

说明:连接建立后的第一条消息,包含当前最新的 event_id

前端处理

if (data.event === 'connected') {
  // 保存 event_id 用于断线重连
  localStorage.setItem('last_event_id', data.current_event_id)
}

2. step_added(新增 Step)⭐ 最常用

{
  "event": "step_added",
  "event_id": 16,
  "ts": "2026-02-03T15:30:10.123456",
  "step": {
    "step_id": "step-016",
    "step_type": "action",
    "status": "completed",
    "sequence": 16,
    "parent_id": "step-001",
    "description": "read_file(config.yaml)",
    "has_children": false,
    "children_count": 0,
    "duration_ms": 50,
    "data": {
      "tool_name": "read_file",
      "arguments": {"file_path": "config.yaml"}
    }
  }
}

前端处理

if (data.event === 'step_added') {
  // 添加到树结构
  addStepToTree(data.step)

  // 更新 event_id
  localStorage.setItem('last_event_id', data.event_id)
}

3. step_updated(Step 更新)

{
  "event": "step_updated",
  "event_id": 17,
  "ts": "2026-02-03T15:30:15.123456",
  "step_id": "step-016",
  "patch": {
    "status": "completed",
    "duration_ms": 1234
  }
}

说明patch 是增量更新(只包含变化的字段)

前端处理

if (data.event === 'step_updated') {
  const step = findStepById(data.step_id)
  Object.assign(step, data.patch)
  updateUI()
}

4. trace_completed(任务完成)

{
  "event": "trace_completed",
  "event_id": 18,
  "ts": "2026-02-03T15:35:00.123456",
  "trace_id": "abc123",
  "total_steps": 18
}

前端处理

if (data.event === 'trace_completed') {
  console.log('Task completed!')
  ws.close()
}

5. error(错误)

{
  "event": "error",
  "message": "Too many missed events (150), please reload full tree via REST API"
}

说明

  • 如果断线期间产生超过 100 条事件,会收到此错误
  • 此时应该用 REST API 重新加载完整树

断线续传

场景:网络断开后重新连接,不丢失中间的更新

实现方式

let lastEventId = 0

// 初次连接
const ws = new WebSocket(
  `ws://localhost:8000/api/traces/abc123/watch?since_event_id=0`
)

ws.onmessage = (event) => {
  const data = JSON.parse(event.data)

  // 保存最新 event_id
  if (data.event_id) {
    lastEventId = data.event_id
    localStorage.setItem('trace_abc123_event_id', lastEventId)
  }
}

ws.onclose = () => {
  // 3 秒后重连
  setTimeout(() => {
    // 从上次的 event_id 继续
    const ws2 = new WebSocket(
      `ws://localhost:8000/api/traces/abc123/watch?since_event_id=${lastEventId}`
    )
    // 服务器会补发 lastEventId 之后的所有事件
  }, 3000)
}

注意

  • 每条消息都有 event_idts 字段
  • 重连时传入 since_event_id,服务器自动补发缺失的事件(最多 100 条)
  • 超过 100 条会返回错误,需要用 REST API 重新加载

心跳检测

保持连接活跃,检测僵尸连接

// 每 30 秒发送心跳
const heartbeat = setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send('ping')
  }
}, 30000)

ws.onmessage = (event) => {
  const data = JSON.parse(event.data)
  if (data.event === 'pong') {
    console.log('Connection alive')
  }
}

📊 数据模型

Trace

字段 类型 说明
trace_id string 唯一 ID
mode string call - 单次调用 / agent - Agent 模式
task string 任务描述(Agent 模式)
status string running / completed / failed
total_steps int Step 总数
total_tokens int Token 总消耗
total_cost float 成本总和
total_duration_ms int 总耗时(毫秒)
last_sequence int 最新 Step 的 sequence
last_event_id int 最新事件 ID
created_at string 创建时间(ISO 8601)
completed_at string | null 完成时间

Step

顶层字段(所有 Step 共有)

字段 类型 说明
step_id string 唯一 ID
trace_id string 所属 Trace ID
step_type string 步骤类型(见下表)
status string 状态(见下表)
sequence int 在 Trace 中的顺序(递增)
parent_id string | null 父节点 ID
description string 简短描述
summary string | null 总结(仅 evaluation 类型)
has_children bool 是否有子节点
children_count int 子节点数量
duration_ms int | null 耗时(毫秒)
tokens int | null Token 消耗
cost float | null 成本
created_at string 创建时间
data object 类型相关的详细数据

step_type(步骤类型)

类型 说明 来源
goal 目标/计划 LLM
thought 思考/分析 LLM
evaluation 评估总结 LLM
response 最终回复 LLM
action 工具调用 System
result 工具结果 System
memory_read 读取记忆 System
memory_write 写入记忆 System

status(步骤状态)

状态 说明
planned 计划中(未执行)
in_progress 执行中
awaiting_approval 等待用户确认
completed 已完成
failed 失败
skipped 跳过

data 字段(按 step_type)

thought / response:

{
  "model": "claude-sonnet-4.5",
  "content": "让我先分析...",
  "messages": [...],  // full 视图才有
  "tool_calls": [...]  // 如果有工具调用
}

action:

{
  "tool_name": "read_file",
  "arguments": {
    "file_path": "config.yaml"
  }
}

result:

{
  "tool_name": "read_file",
  "output": "file content...",
  "error": null
}

memory_read:

{
  "experiences_count": 5,
  "skills_count": 3
}

🎯 推荐的实现方案

方案 1:纯 WebSocket(简单场景)

适用于:实时监控进行中的任务,Step 数量 < 100

// 只用 WebSocket,自动获取历史
const ws = new WebSocket(
  'ws://localhost:8000/api/traces/abc123/watch?since_event_id=0'
)

ws.onmessage = (event) => {
  const data = JSON.parse(event.data)

  if (data.event === 'step_added') {
    // 历史 + 新增的 Step 都会收到
    addStepToTree(data.step)
  }
}

优点:代码简单 缺点:超过 100 个 Step 会失败


方案 2:REST + WebSocket(生产推荐)

适用于:查看历史任务,或 Step 数量 > 100

// 1. 先用 REST API 获取完整树
const response = await fetch(
  `/api/traces/${traceId}/tree?view=compact`
)
const treeData = await response.json()
renderTree(treeData.root_steps)

// 2. 连接 WebSocket 监听增量更新
const ws = new WebSocket(
  `ws://localhost:8000/api/traces/${traceId}/watch?since_event_id=0`
)

ws.onmessage = (event) => {
  const data = JSON.parse(event.data)
  if (data.event === 'step_added') {
    addStepToTree(data.step)  // 只处理新增的
  }
}

优点:可靠,支持大型 Trace 缺点:略复杂


🐛 错误处理

HTTP 错误码

状态码 说明
200 成功
404 Trace/Step 不存在
400 参数错误
500 服务器错误

WebSocket 错误

ws.onerror = (error) => {
  console.error('WebSocket error:', error)
  // 重连
}

ws.onclose = (event) => {
  console.log('Connection closed:', event.code, event.reason)
  // 自动重连
}

💡 最佳实践

1. 保存 event_id 用于断线重连

ws.onmessage = (event) => {
  const data = JSON.parse(event.data)
  if (data.event_id) {
    localStorage.setItem(
      `trace_${traceId}_event_id`,
      data.event_id
    )
  }
}

2. 实现自动重连

function connectWebSocket(traceId) {
  const lastEventId = localStorage.getItem(`trace_${traceId}_event_id`) || 0
  const ws = new WebSocket(
    `ws://localhost:8000/api/traces/${traceId}/watch?since_event_id=${lastEventId}`
  )

  ws.onclose = () => {
    setTimeout(() => connectWebSocket(traceId), 3000)
  }

  return ws
}

3. 使用 compact 视图减少流量

// ✅ 推荐
const response = await fetch(`/api/traces/${id}/tree?view=compact`)

// ❌ 避免(数据量可能很大)
const response = await fetch(`/api/traces/${id}/tree?view=full`)

4. 按需懒加载(大型 Trace)

// 初次只加载第一层
const tree = await fetch(
  `/api/traces/${id}/tree?max_depth=1`
).then(r => r.json())

// 用户点击展开时,懒加载子树
async function onExpand(stepId) {
  const node = await fetch(
    `/api/traces/${id}/node/${stepId}?expand=true&max_depth=1`
  ).then(r => r.json())

  appendChildren(stepId, node.children)
}

🔗 相关文档


📞 问题反馈

如有问题请提 Issue:https://github.com/anthropics/agent/issues