Skip to content

Latest commit

 

History

History
2458 lines (1810 loc) · 84.8 KB

File metadata and controls

2458 lines (1810 loc) · 84.8 KB

Agent Team Platform — API 开发者手册

版本: 2.0.0 | 更新日期: 2026-07-12 基础URL: http://localhost:3001 | 所有 API 前缀: /api 默认端口: 3001 | 协议: HTTP + SSE 流式推送

本手册覆盖 Loop Studio(Loop Engineering Agent Team Platform)对外暴露的全部 REST API、MCP 协议端点与 A2A 协议端点,共计约 191 个端点。所有端点均来自源码 src/routes.jssrc/mcp-server.jssrc/a2a-protocol.js,无凭空编造。


目录


认证与鉴权

机制概述

平台采用 API Token + Bearer Header 鉴权,所有 /api/* 路径都会经过 authMiddleware。Token 通过 POST /api/tokens 创建,格式为 lps_<24位随机串>(明文只在创建时返回一次,数据库仅存 SHA-256 哈希)。

Bearer Token 使用方式

# 方式一:Authorization Header(推荐)
curl -H "Authorization: Bearer lps_xxxxxxxxxxxxxxxxxxxxxxxx" http://localhost:3001/api/teams

# 方式二:query 参数(仅用于无法设置 Header 的场景,如浏览器 EventSource)
curl http://localhost:3001/api/teams?key=lps_xxxxxxxxxxxxxxxxxxxxxxxx

生产环境 vs 开发环境差异

环境 触发条件 无 Token 行为
开发环境 NODE_ENV !== 'production'LOOP_REQUIRE_AUTH !== 'true' 放行(视为本地控制台)
生产环境 NODE_ENV === 'production'LOOP_REQUIRE_AUTH=true 返回 401 UNAUTHORIZED

公开路径(无需鉴权):

  • GET /api/events — SSE 事件流(EventSource 无法设置 Header)
  • POST /api/integrations/feishu/webhook — 飞书回调(使用 verificationToken 鉴权)
  • GET /health — K8s 探针
  • GET /metrics — Prometheus 抓取

Token 权限范围(scopes)

创建 Token 时可指定 scopes,默认为 ['tasks:read', 'tasks:write', 'agents:read']。常用 scope:

  • tasks:read / tasks:write — 任务读写
  • agents:read — Agent 读取
  • admin — 管理员(全权限)

速率限制

限制类型 范围 阈值
通用限制 /api/* 所有方法 每 IP 每分钟 600 次
写操作限制 /api/* POST/PUT/DELETE/PATCH 每 IP 每分钟 120 次

超限返回 429,body 为 { error: { code: 'RATE_LIMITED', message: '...' } }


通用约定

请求/响应格式

  • 请求体:除文件上传外,统一为 application/json,body 大小限制 5MB。
  • 响应体:统一为 JSON(application/json),SSE 端点为 text/event-stream
  • 字符编码:UTF-8。
  • 文件上传:multipart/form-data,单文件上限 100MB。

错误响应格式

{
  "error": "错误描述(中文)",
  "success": false
}

鉴权类错误为嵌套结构:

{ "error": { "code": "UNAUTHORIZED", "message": "生产环境必须携带 API Token" } }

错误码定义

HTTP 状态 含义 触发场景
200 成功 GET/PUT/POST(无资源创建)
201 创建成功 POST 创建资源(Agent/Task/Token/Webhook 等)
400 请求错误 参数缺失/格式错误/状态不允许操作
401 未授权 缺少或无效 Token(生产环境)
403 禁止访问 危险命令拦截/Origin 不允许
404 不存在 资源未找到
406 不可接受 MCP Accept header 不满足
413 实体过大 上传文件超 100MB
429 请求过多 触发速率限制
500 服务器错误 内部异常
503 服务降级 健康检查数据库不通

分页参数约定

容器列表端点 GET /api/containers 支持分页:

参数 类型 默认 说明
page int 1 页码,从 1 开始
limit int 50 每页数量
status string - 按状态过滤
backend string - 按后端过滤(docker/native)

其他列表端点(teams/agents/tasks 等)默认返回全量,如需限制可通过 limit query 参数(如 GET /api/teams/:id/logs?limit=500)。

SSE 实时流说明

平台提供三类 SSE 端点,统一遵循以下规范:

响应头:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

消息格式:

data: {"type":"task:log","taskId":"task-xxx",...}\n\n
  • 首行 retry: 3000\n\n 表示客户端断连后 3 秒重连。
  • 每 15 秒发送 : heartbeat\n\n 注释行保活(防止代理超时)。
  • 客户端断连时服务端自动清理订阅。

SSE 端点列表:

  • GET /api/events — 全局任务事件流(可加 ?taskId=xxx 聚焦单任务)
  • GET /api/teams/:id/stream — 团队级事件流
  • GET /api/containers/stream — 容器状态实时流
  • POST /api/workspaces/:id/terminal — 终端命令流式输出
  • GET /mcp — MCP server notifications(需 session)
  • POST /a2a (method=tasks/sendSubscribe) — A2A 流式任务

浏览器订阅示例(EventSource 无法设 Header,用 ?key= 传 token):

const es = new EventSource('http://localhost:3001/api/events?key=lps_xxx');
es.onmessage = (e) => console.log(JSON.parse(e.data));

1. 健康检查与统计

GET /api/health

轻量健康检查(无需鉴权,但走 /api 前缀)。

响应: 200

{ "status": "ok", "ts": "2026-07-12T08:00:00.000Z" }

示例:

curl http://localhost:3001/api/health

GET /health

K8s/容器探针端点(不带 /api 前缀,无需鉴权)。会探测数据库连通性。

响应: 200(健康) / 503(降级)

{
  "status": "ok",
  "uptime": 3600,
  "timestamp": "2026-07-12T08:00:00.000Z",
  "pid": 12345
}

GET /api/stats

平台全局统计(任务/审批/Agent 概览)。

响应: 200

{
  "tasksByStatus": [{ "status": "queued", "count": 3 }, { "status": "running", "count": 1 }],
  "pendingApprovals": 2,
  "busyAgents": 1,
  "totalAgents": 8,
  "totalTasks": 42
}

示例:

curl -H "Authorization: Bearer lps_xxx" http://localhost:3001/api/stats

GET /metrics

Prometheus 抓取端点(无需鉴权,供 Prometheus 抓取)。

响应: 200,Content-Type: text/plain; version=0.0.4,返回 Prometheus 文本格式指标。

curl http://localhost:3001/metrics

2. 平台部署

平台支持远程 SSH 部署 Loop Studio 本体(platform/*)和团队常驻服务(team-service/*)。

跨平台支持:自动检测远程 OS(detectPlatform),支持 Linux / Mac / Windows 三种平台:

  • Linux: apt-get/yum 安装 Node.js,mkdir -p + tar 解压,systemd 服务
  • Mac: Homebrew 安装 Node.js,与 Linux 兼容的命令路径
  • Windows: winget 安装 Node.js/Git/Docker,PowerShell 命令,%TEMP% 临时目录
  • deployPlatform(全量部署)支持 Linux/Mac;deployTeamService(轻量部署)三平台均支持

POST /api/platform/deploy

远程部署平台到 SSH 服务器。

请求体:

字段 类型 必填 说明
host string SSH 主机
user string SSH 用户(默认 root)
key string SSH 私钥路径(默认 ~/.ssh/id_rsa)
port int SSH 端口(默认 22)
path string 部署路径(默认 /opt/agent-team)
service_token string 服务 Token(未提供则自动生成)

响应: 200

{ "success": true, "serviceToken": "lps_xxx", "logs": ["...部署日志..."] }

示例:

curl -X POST http://localhost:3001/api/platform/deploy \
  -H "Content-Type: application/json" \
  -d '{"host":"192.168.1.10","user":"root","path":"/opt/agent-team"}'

POST /api/platform/check

检查远程部署状态。

请求体: 同 deploy 的 host/user/key/port/path。

响应: 200,返回部署状态对象。

POST /api/platform/undeploy

卸载远程平台。

请求体: 同 deploy 的连接参数。

响应: 200 { "success": true }

POST /api/team-service/deploy

部署团队常驻轻量 HTTP 服务(方向 B)。

请求体: 同 platform/deploy,path 默认 /opt/agent-team-service

响应: 200

{ "success": true, "serviceUrl": "http://192.168.1.10:3100", "serviceToken": "lps_xxx", "logs": [] }

POST /api/team-service/undeploy

卸载团队常驻服务。

请求体: { host, user, key, port, path },path 默认 /opt/agent-team-service

响应: 200 { "success": true, "logs": [] }

POST /api/team-service/check

健康检查远程团队服务(直接 curl 远程 /health)。

请求体:

字段 类型 必填 说明
serviceUrl string 远程服务 URL

响应: 200

{ "success": true, "statusCode": 200, "info": { "status": "ok" } }

3. Agent 管理

Agent 分为 定义层(is_definition=true,平台级模板)和 实例层(团队实例化产生,带 parent_agent_id)。

GET /api/agents

获取所有 Agent(定义 + 实例)。

Query 参数:

参数 说明
definitions_only true/1 时只返回平台定义,不含团队实例

响应: 200,Agent 数组。

curl http://localhost:3001/api/agents
curl "http://localhost:3001/api/agents?definitions_only=true"

GET /api/agents/definitions

快捷端点:只返回平台定义层 Agent。响应: 200,Agent 数组。

GET /api/agents/:id

获取单个 Agent 详情。

响应: 200 Agent 对象;404 { "error": "Agent not found" }

curl http://localhost:3001/api/agents/orchestrator

POST /api/agents

动态创建 Agent。

请求体(常见字段):

字段 类型 必填 说明
name string Agent 名称
role string 角色(orchestrator/implementer/reviewer/qa等)
system_prompt string 系统提示词
model string 使用的模型 ID
skills array 技能数组
is_external boolean 是否外部 agent
endpoint string 外部 agent 端点(A2A)

响应: 201 Agent 对象;400 { "error": "..." }

curl -X POST http://localhost:3001/api/agents \
  -H "Content-Type: application/json" \
  -d '{"name":"My Agent","role":"implementer","model":"deepseek-chat"}'

PUT /api/agents/:id

更新 Agent 配置。请求体:可更新字段的部分对象。响应: 200 更新后的 Agent。

DELETE /api/agents/:id

删除 Agent(定义层删除会级联处理实例)。响应: 200 { "deleted": true }

POST /api/agents/:id/clone

克隆 Agent 为新的定义层 Agent。

请求体: { name?, ...其他覆盖字段 }响应: 201 克隆出的新 Agent。

curl -X POST http://localhost:3001/api/agents/orchestrator/clone \
  -H "Content-Type: application/json" -d '{"name":"Orchestrator 副本"}'

POST /api/agents/:id/test-connection

测试外部 Agent 连通性(前端"测试连接"按钮调用)。仅 is_external=true 的 Agent 可用。发现 Agent Card 后会持久化到 DB。

响应: 200

{ "ok": true, "card": { /* A2A Agent Card */ }, "latency_ms": 120 }

PUT /api/agents/:id/instance-config

更新 Agent 实例配置(可改 workspace/mcp/skills/env/goal_focus)。

请求体: 实例配置对象,如 { extra_skills: [...], mcp_servers: [...] }响应: 200 更新后的 Agent。

curl -X PUT http://localhost:3001/api/agents/inst-xxx/instance-config \
  -H "Content-Type: application/json" \
  -d '{"goal_focus":"专注后端 API 实现"}'

4. Agent 配置文件(.md)

每个 Agent 拥有 6 个核心 .md 配置文件(OpenClaw 架构):SOUL.mdAGENTS.mdIDENTITY.mdTOOLS.mdMEMORY.mdSKILL.md

GET /api/agents/:id/files

列出 Agent 的所有 .md 文件(自动初始化文件结构)。

响应: 200,文件元信息数组:

[{ "filename": "SOUL.md", "size": 1024, "is_core": true }, ...]

GET /api/agent-files/core-defs

获取核心文件定义(前端展示用,无需 agent id)。

响应: 200,核心文件定义数组。

GET /api/agents/:id/files/:filename

读取单个 .md 文件内容。

响应: 200

{ "filename": "SOUL.md", "content": "...", "size": 1024 }
curl http://localhost:3001/api/agents/orchestrator/files/SOUL.md

PUT /api/agents/:id/files/:filename

写入/更新 .md 文件。

请求体:

字段 类型 必填 说明
content string 文件内容

响应: 200 写入结果对象。

curl -X PUT http://localhost:3001/api/agents/orchestrator/files/SOUL.md \
  -H "Content-Type: application/json" \
  -d '{"content":"# SOUL\n你是协调者..."}'

POST /api/agents/:id/files/:filename/reset

重置核心文件为默认内容(自定义文件不可重置)。响应: 200 重置结果。

DELETE /api/agents/:id/files/:filename

删除自定义 .md 文件(核心文件不可删)。响应: 200 { "deleted": true }


5. Agent Skills

Skills 采用文件夹结构:skills/<name>/SKILL.md。提供两套接口:文件夹管理 + 实例动态增删。

GET /api/agents/:id/skills

列出 Agent 的所有 skills(自动初始化)。响应: 200,skill 列表:

[{ "name": "code-review", "description": "...", "size": 512 }]

GET /api/agents/:id/skills/:name

读取单个 skill 的 SKILL.md

响应: 200 { "name": "...", "content": "...", "size": 512 };404 不存在。

PUT /api/agents/:id/skills/:name

写入/创建 skill 的 SKILL.md

请求体: { "content": "..." }(content 必填)。响应: 200 写入结果。

curl -X PUT http://localhost:3001/api/agents/orchestrator/skills/code-review \
  -H "Content-Type: application/json" \
  -d '{"content":"# Code Review\n审查代码质量..."}'

POST /api/agents/:id/skills/:name/reset

重置 skill 为默认内容(需 Agent 存在)。响应: 200 重置结果。

DELETE /api/agents/:id/skills/:name

删除整个 skill 文件夹。响应: 200 { "deleted": true }

POST /api/agents/:id/skills/add

为 Agent 实例动态添加 Skill(不影响 Agent 定义,只修改实例的 skills + 写入 SKILL.md)。定义层 Agent 也可用此接口(直接 append 到 skills 数组)。

请求体:

字段 类型 必填 说明
name string skill 名称(会 slugify)
description string 描述
when_to_use string 调用时机
content string SKILL.md 内容(空则生成模板)

响应: 200

{ "success": true, "skill": { "name": "..." }, "total_skills": 3 }
curl -X POST http://localhost:3001/api/agents/inst-xxx/skills/add \
  -H "Content-Type: application/json" \
  -d '{"name":"api-design","description":"REST API 设计","when_to_use":"设计接口时","content":"# API Design\n..."}'

DELETE /api/agents/:id/skills/:name/remove

从 Agent 实例移除动态添加的 Skill(只能移除 extra_skills,定义层 skills 不可移除)。定义层 Agent 调用会返回 400。

响应: 200

{ "success": true, "removed": "api-design", "remaining_skills": 2 }

6. 模型 Provider 管理

GET /api/model-providers

获取所有 Provider(含 API Key 脱敏)。响应: 200,Provider 数组。

GET /api/models

获取所有可用模型(扁平化,带 provider 信息)。响应: 200,模型数组:

[{ "id": "deepseek-chat", "provider": "deepseek", "name": "DeepSeek Chat" }]

POST /api/model-providers

创建 Provider(创建后自动同步到 OpenClaw)。

请求体(常见字段):

字段 类型 必填 说明
id string Provider ID
name string 显示名称
base_url string API base URL
api_key string API Key
models array 模型列表

响应: 201 Provider 对象。

curl -X POST http://localhost:3001/api/model-providers \
  -H "Content-Type: application/json" \
  -d '{"id":"deepseek","name":"DeepSeek","base_url":"https://api.deepseek.com","api_key":"sk-xxx","models":[{"id":"deepseek-chat"}]}'

PUT /api/model-providers/:id

更新 Provider(含 API Key 设置)。请求体:可更新字段。响应: 200 Provider。

DELETE /api/model-providers/:id

删除 Provider。响应: 200 { "deleted": true }

POST /api/model-providers/sync

手动同步所有 Provider 到 OpenClaw。响应: 200 { "synced": true }

POST /api/model-providers/:id/test

测试 Provider 的 API Key 连通性(向 Provider 发送最小请求验证 API Key 是否有效)。前端"设置 → 模型 Provider"页面的"测试连接"按钮调用此端点。

响应: 200

{ "ok": true, "provider": "deepseek", "latency_ms": 320, "model": "deepseek-chat" }

失败响应: 200(业务级失败,非 4xx)

{ "ok": false, "provider": "deepseek", "error": "Invalid API key", "status": 401 }

行为:后端 testProviderConnection(db, providerId) 取出 Provider 配置(含解密后的 API Key),向其 base_url 发送一个最小 chat completions 请求(如 "Hi"),根据响应判断连通性。请求超时或 HTTP 非 2xx 均视为失败,返回 ok: false 及错误信息。

curl -X POST http://localhost:3001/api/model-providers/deepseek/test \
  -H "Authorization: Bearer lps_xxx"

7. 任务管理

任务是平台的核心执行单元,可分配给团队(team_id)或单个 Agent(assigned_agent_id)。

GET /api/tasks

任务列表(支持过滤)。

Query 参数:

参数 说明
status 按状态过滤(queued/running/completed/failed/needs_attention)
parent_id 按父任务过滤
team_id 按团队过滤

响应: 200,任务数组。

curl "http://localhost:3001/api/tasks?status=running&team_id=team-xxx"

GET /api/tasks/:id

任务详情。响应: 200 Task;404 { "error": "Task not found" }

GET /api/tasks/:id/tree

任务树(含子任务)。响应: 200 { task, children: [...] };404 不存在。

POST /api/tasks

创建任务。

请求体:

字段 类型 必填 说明
title string 任务标题
goal string 任务目标
stop_condition string 停止条件
mode string 模式:turn(默认)/goal
priority int 优先级 1-5(默认 2)
assigned_agent_id string 分配给单个 agent
team_id string 分配给团队
max_retries int 最大重试次数
source string 来源(默认 web)

响应: 201 Task 对象;400 { "error": "title, goal, stop_condition 必填" }

curl -X POST http://localhost:3001/api/tasks \
  -H "Content-Type: application/json" \
  -d '{"title":"实现登录API","goal":"完成用户登录接口","stop_condition":"接口可通过测试","team_id":"team-xxx"}'

POST /api/tasks/:id/dispatch

派发任务。team_id 走团队执行(把任务转为 mission 分配给团队并启动);否则走单 agent 快速模式

  • 任务状态必须为 queuedneeds_attention,否则 400。
  • 团队非待命状态时先重新部署,再 assignMission → startTeam → runTeamMission(阻塞等待完成)。
  • 单 agent 模式:mode=goalexecuteGoal,否则 executeTurn

请求体(可选):{ "agent_id": "..." }(单 agent 模式覆盖)。

响应: 200(立即返回,执行异步进行)

{ "dispatched": true, "taskId": "task-xxx", "mode": "team", "teamId": "team-xxx" }
curl -X POST http://localhost:3001/api/tasks/task-xxx/dispatch

GET /api/tasks/:id/logs

任务日志(默认最近 500 条)。响应: 200,日志数组。

GET /api/tasks/:id/runs

任务的运行记录列表。响应: 200,run 数组(含 steps JSON 解析)。

DELETE /api/tasks/:id

删除任务(运行中的任务需先停止)。

响应: 200 { "deleted": true };400 { "error": "运行中..." };404 { "error": "Task not found" }


8. 审批管理

GET /api/approvals

审批列表。

Query 参数: status(默认 pending,可选 approved/rejected)。

响应: 200,审批数组:

[{ "id": "appr-xxx", "task_id": "...", "type": "...", "status": "pending", "payload": {...} }]

POST /api/approvals/:id/decide

决策审批。

请求体:

字段 类型 必填 说明
decision string approved/rejected(会归一化处理)
approver string 决策者标识(默认 human)

响应:

  • 200 { "decided": true, "decision": "approved", "status": "approved" }
  • 404 { "error": "Approval not found" }(id 不存在)
  • 400 { "error": "已决策" }(重复决策)

行为:approved 时触发 executeApproval 执行被审批阻塞的操作,并通知飞书。

curl -X POST http://localhost:3001/api/approvals/appr-xxx/decide \
  -H "Content-Type: application/json" \
  -d '{"decision":"approved","approver":"alice"}'

9. API Token 管理

GET /api/tokens

列出所有 Token(脱敏显示)。响应: 200,Token 数组(token 字段不返回明文)。

POST /api/tokens

创建 API Token。

请求体:

字段 类型 必填 说明
name string Token 名称
scopes array 权限范围(默认 ['tasks:read','tasks:write','agents:read'])

响应: 201,明文 token 仅此一次返回:

{ "id": "tok-xxx", "name": "CI Token", "token": "lps_xxxxxxxxxxxxxxxxxxxxxxxx", "scopes": ["tasks:read","tasks:write"] }
curl -X POST http://localhost:3001/api/tokens \
  -H "Content-Type: application/json" \
  -d '{"name":"CI Token","scopes":["tasks:read","tasks:write"]}'

DELETE /api/tokens/:token

删除 Token。由于前端脱敏显示无法传回完整 token,用 token 前缀匹配删除(/api/tokens/lps_abc 会匹配所有以 lps_abc 开头的记录)。

响应: 200 { "deleted": true };404 { "error": "Token not found" }


10. Webhook 管理

Webhook 是出站通知:任务完成/失败时平台 POST 到用户注册的 URL。

GET /api/webhooks

列出所有 Webhook。响应: 200,Webhook 数组。

POST /api/webhooks

创建 Webhook。

请求体(常见字段):

字段 类型 必填 说明
url string 回调 URL
events array 订阅事件类型
secret string 签名密钥(用于 X-LoopStudio-Signature)

响应: 201 Webhook 对象。

curl -X POST http://localhost:3001/api/webhooks \
  -H "Content-Type: application/json" \
  -d '{"url":"https://my-app.com/webhook","events":["task.completed","task.failed"]}'

Webhook 事件类型

Webhook 支持的事件类型分为两层:任务级事件(粗粒度)和 Agent/Subtask 级事件(细粒度,由 team-orchestrator.js 在团队编排过程中触发)。

任务级事件(粗粒度)

事件 触发时机
task.completed 任务状态变为 completed
task.failed 任务状态变为 failed

Agent/Subtask 级事件(细粒度)

以下 5 个事件由 team-orchestrator 在团队执行过程中实时触发,便于外部系统监视团队级执行细节:

事件 触发时机 Payload 字段
agent.started 某个 agent 实例开始执行子任务 teamIdagentIdagentNameroletaskIdsubtaskGoalts
agent.completed 某个 agent 实例完成子任务(成功) teamIdagentIdagentNameroletaskIdsubtaskGoalduration_msts
agent.failed 某个 agent 实例子任务执行失败 teamIdagentIdagentNameroletaskIdsubtaskGoalerrorts
subtask.started 子任务状态变为 started(进入执行) teamIdsubtaskIdsubtaskGoalroleparallelGroupts
subtask.completed 子任务状态变为 completed(执行完成) teamIdsubtaskIdsubtaskGoalrolestatusts

订阅示例(订阅全部细粒度事件以实时监视团队执行):

curl -X POST http://localhost:3001/api/webhooks \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://my-app.com/webhook",
    "events":["agent.started","agent.completed","agent.failed","subtask.started","subtask.completed"],
    "secret":"my-signing-secret"
  }'

签名校验:若创建时提供了 secret,平台 POST 通知时会带 X-LoopStudio-Signature header(HMAC-SHA256),接收方应校验签名以防伪造。

DELETE /api/webhooks/:id

删除 Webhook。响应: 200 { "deleted": true }


11. 飞书集成

POST /api/integrations/feishu/webhook

飞书入站回调端点(飞书群消息回调此 URL,自动创建任务)。无需平台 Token,靠飞书 verificationToken 鉴权。

配置方式:在飞书开放平台 → 事件订阅 → 请求地址填入此 URL。

响应: 200(由飞书 handler 处理);400 { "error": "飞书集成未配置..." }(未配置 FEISHU_APP_ID)。

GET /api/integrations/feishu/status

获取飞书配置状态 + 入站回调 URL。

响应: 200

{
  "configured": true,
  "hasVerificationToken": true,
  "inboundUrl": "http://your-host:3001/api/integrations/feishu/webhook",
  "inboundUrlDesc": "将此 URL 填入飞书开放平台 → 事件订阅 → 请求地址。飞书群消息会回调此 URL,自动创建任务。",
  "outboundNote": "出站 Webhook 在「集成中心 → Webhook」配置,任务完成/失败时我们会 POST 通知你的服务。"
}

12. 容器管理

容器是 Agent 执行任务的隔离环境(支持 docker/native 后端)。

GET /api/containers

容器列表(分页)。

Query 参数: statusbackendpage(默认 1)、limit(默认 50)。

响应: 200

{ "items": [{ "id": "c-xxx", "status": "running", "backend": "docker" }], "page": 1, "limit": 50, "total": 12 }

GET /api/containers/:id

容器详情。响应: 200 容器对象;404 { "error": "Container not found" }

GET /api/containers/:id/logs

容器日志(可按关键字过滤)。

Query 参数: keyword(过滤包含关键字的日志行)。

响应: 200,日志数组。

GET /api/containers/:id/evidence

容器的证据文件(测试产物等)。响应: 200 evidence 对象;404 无证据。

POST /api/containers/:id/stop

强制停止容器。响应: 200 { "stopped": true };404 不存在。

POST /api/containers/:id/preserve

保留容器(供排查,不被自动回收)。

请求体: { "reason": "manual" }(reason 默认 manual)。响应: 200 { "preserved": true }

POST /api/containers/:id/reclaim

回收容器。响应: 200 { "reclaimed": true }

GET /api/containers/:id/timeline

容器时间线(生命周期事件)。响应: 200 时间线数组;404 不存在。

POST /api/containers/:id/event

容器事件接收(agent-runner 上报)。请求体: 任意事件数据。响应: 200 { "received": true }

GET /api/metrics/overview

集群总览指标。响应: 200

{ "total": 12, "running": 3, "byBackend": { "docker": 10, "native": 2 } }

GET /api/metrics/alerts

异常告警列表。响应: 200,告警数组。

GET /api/containers/stream

容器状态 SSE 实时推送。

行为:连接时先推一次全量 overview,之后每 500ms 推送增量事件。

事件格式:

data: {"type":"overview","data":{...}}\n\n
data: {"type":"container:state","containerId":"c-xxx",...}\n\n
const es = new EventSource('http://localhost:3001/api/containers/stream?key=lps_xxx');
es.onmessage = e => console.log(JSON.parse(e.data));

GET /api/containers/backend/detect

检测可用容器后端。响应: 200 { "backend": "docker" | "native" }


13. 工作区管理

工作区是 Agent 操作代码的目录,支持 zip 上传、本地路径注册、git clone 三种创建方式。

GET /api/workspaces

工作区列表。响应: 200,工作区数组。

POST /api/workspaces/upload

上传 zip 创建工作区(单文件上限 100MB)。

请求体: multipart/form-data

字段 类型 必填 说明
file file zip 文件
description string 描述

响应: 200 工作区对象;413 { "error": "文件过大,限制 100MB" }

curl -X POST http://localhost:3001/api/workspaces/upload \
  -F "file=@project.zip" -F "description=我的项目"

POST /api/workspaces/local

从本地路径注册工作区。

请求体:

字段 类型 必填 说明
path string 本地绝对路径
name string 工作区名称
description string 描述

响应: 200 工作区对象。

POST /api/workspaces/url

从 URL 创建工作区(git clone 远程仓库,支持部署到外网服务器)。

请求体:

字段 类型 必填 说明
url string git 仓库 URL
name string 工作区名称
description string 描述
branch string 分支

响应: 200 工作区对象。

curl -X POST http://localhost:3001/api/workspaces/url \
  -H "Content-Type: application/json" \
  -d '{"url":"https://github.com/user/repo.git","branch":"main"}'

GET /api/workspaces/:id

工作区详情。响应: 200 工作区;404 { "error": "工作区不存在" }

GET /api/workspaces/:id/tree

工作区文件树。响应: 200 文件树结构。

GET /api/workspaces/:id/file

读取工作区内文件。

Query 参数: path(文件相对路径)。响应: 200 { path, content, ... }

PUT /api/workspaces/:id/file

写入/创建工作区内文件。

请求体: { "path": "src/index.js", "content": "..." }(path、content 必填)。

响应: 200 写入结果。

DELETE /api/workspaces/:id/file

删除工作区内文件。Query 参数: path(必填)。响应: 200 删除结果。

POST /api/workspaces/:id/terminal

命令行终端:在工作区执行命令,SSE 流式返回实时输出。

请求体: { "command": "npm test" }(command 必填)。

安全:通过 detectDangerousCommand 拦截危险命令(返回 403)。

行为:Windows 用 cmd.exe /c,Linux/Mac 用 /bin/sh -c,2 分钟超时。

SSE 事件:

data: {"type":"start","data":{"command":"npm test","cwd":"/path"}}\n\n
data: {"type":"stdout","data":"..."}\n\n
data: {"type":"stderr","data":"..."}\n\n
data: {"type":"exit","data":{"code":0,"stdout":"...","stderr":"..."}}\n\n
curl -N -X POST http://localhost:3001/api/workspaces/ws-xxx/terminal \
  -H "Content-Type: application/json" \
  -d '{"command":"npm test"}'

DELETE /api/workspaces/:id

删除工作区。响应: 200 删除结果。

GET /api/workspaces/:id/commits

工作区 commit 历史(agent 改动版本管理)。

Query 参数: limit(默认 20)。响应: 200,commit 数组。

POST /api/workspaces/:id/rollback

回滚工作区到指定 commit(回滚前自动创建备份 commit)。

请求体: { "commitHash": "abc123" }(必填)。

响应: 200 { "success": true, ... };400 { "error": "回滚失败" }

POST /api/workspaces/:id/snapshot/:teamId

创建 OCI 镜像级工作区快照(团队隔离)。响应: 200 快照信息。

DELETE /api/workspaces/:id/snapshot/:teamId

删除指定团队的快照。响应: 200 { "removed": true }

POST /api/workspaces/:id/snapshot/:teamId/commit

提交快照更改。响应: 200 提交结果。

GET /api/workspaces/:id/snapshot/:teamId

获取快照信息。响应: 200 快照对象。

GET /api/workspaces/:id/snapshots

列出工作区所有快照。响应: 200,快照数组。

GET /api/workspace/teams

查询工作区上的共享团队。

Query 参数: workspace(必填,工作区路径)。

响应: 200

{ "workspace": "/path", "teamCount": 2, "teams": [{ "id": "team-xxx", "name": "..." }] }

14. MCP 协议与管理

平台既是 MCP Server(对外暴露工具),也管理 外部 MCP Server 的接入。

14.1 MCP Server 协议端点(JSON-RPC 2.0 over HTTP)

POST /mcp

MCP 协议主端点,接收 JSON-RPC 2.0 请求,响应可能是单条 JSON 或 SSE 流。

请求头要求:

  • Origin:必须允许(防 DNS rebinding)
  • Accept:必须同时包含 application/jsontext/event-stream
  • Mcp-Session-Id:非 initialize 请求必须携带(initialize 时由 server 生成返回)
  • Mcp-Protocol-Version(可选):支持的版本 2025-06-18 / 2025-03-26 / 2024-11-05

支持的方法:

方法 说明 响应
initialize 初始化会话,返回协议版本+能力,生成 sessionId application/json,header 带 Mcp-Session-Id
tools/list 列出所有工具 application/json
tools/call 调用工具(可能长时间运行) SSE 流,最后一条是 JSON-RPC response
resources/list 列出工作区资源 application/json
resources/read 读取资源(uri: loop-studio://workspace/<id>) application/json

initialize 请求示例:

curl -X POST http://localhost:3001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"demo","version":"1.0"}}}'

响应(header 含 Mcp-Session-Id: <uuid>):

{
  "jsonrpc": "2.0", "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": { "tools": { "listChanged": false }, "resources": { "list": true, "read": true } }
  }
}

tools/call 示例(需带 sessionId header):

curl -X POST http://localhost:3001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: <sessionId>" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"create_task","arguments":{"title":"demo","goal":"test","stop_condition":"done"}}}'

批量请求:body 为数组时,返回数组结果。通知(无 id 字段)返回 202

GET /mcp

打开 SSE stream 接收 server notifications(需 sessionId)。

请求头: Accept: text/event-stream(必须),Mcp-Session-Id(必须)。

特性:

  • 支持 Last-Event-ID header 重放断连后的事件(resumability)。
  • 每 30 秒发送心跳。

DELETE /mcp

终止 session(需 Mcp-Session-Id header)。响应: 200 { "jsonrpc":"2.0","result":{"ok":true} };404 session 不存在。

GET /.well-known/mcp-agent-card

MCP Agent Card 发现端点(便于发现元信息)。

响应: 200

{ "name": "loop-studio-mcp", "version": "1.0.0", "capabilities": { "tools": { "listChanged": false }, "resources": { "list": true, "read": true } } }

14.2 外部 MCP Server 管理

GET /api/mcp/servers

列出所有已注册的 MCP server(token 脱敏为 ***)。响应: 200,server 数组。

POST /api/mcp/servers

创建(注册)外部 MCP server。

请求体(常见字段):

字段 类型 必填 说明
name string server 名称
url string server URL
token string 访问 token

响应: 200 注册结果。

DELETE /api/mcp/servers/:id

删除 MCP server。响应: 200 { "deleted": true }

POST /api/mcp/servers/:id/sync

同步 MCP server(刷新可用工具列表)。响应: 200 { tools: [...] }

GET /api/mcp/external-tools

获取所有外部 MCP server 聚合的工具列表。响应: 200,工具数组。

GET /api/mcp/presets

获取 MCP 预设服务器列表。响应: 200,预设数组。

POST /api/mcp/presets/:name/apply

一键应用预设:从预设创建 mcp_servers 记录 + 注册 + 刷新工具。

路径参数: name 预设名称。

响应: 200 应用结果;404 预设不存在;400 预设为 local 类型不可应用。


15. A2A 协议与管理

A2A(Agent-to-Agent)协议支持跨平台 Agent 发现与任务委派。

15.1 A2A 协议端点

GET /.well-known/agent.json

A2A Agent Card 发现端点(标准路径,无需鉴权)。

响应: 200

{
  "name": "Agent Team",
  "description": "可部署的 Loop Engineering 团队 — 接收使命后自主拆解、协作、验证、迭代",
  "protocolVersion": "0.3.0",
  "version": "1.0.0",
  "url": "http://your-host:3001/a2a",
  "authentication": { "schemes": ["Bearer"], "credentials": "Bearer token via Authorization header" },
  "capabilities": { "streaming": true, "pushNotifications": true, "stateTransition": true },
  "defaultInputModes": ["text/plain", "application/json"],
  "defaultOutputModes": ["text/plain", "application/json"],
  "skills": [{ "id": "tpl-xxx", "name": "...", "description": "...", "tags": ["general"] }]
}

GET /.well-known/agent-card.json

旧路径,301 重定向到 /.well-known/agent.json

pushNotifications 能力说明:Agent Card 中 capabilities.pushNotificationstrue,表示平台支持主动推送任务状态变更通知。外部 agent 在 tasks/send 请求中可通过 pushNotification 参数提供 callbackUrl(及可选 sessionToken),平台在轮询发现任务状态变更(working → completed/failed 等)时会主动 POST 通知到该 URL,无需外部 agent 反复调用 tasks/get 轮询。通知 payload 与 tasks/get 返回的 task 对象结构一致。

POST /a2a

A2A JSON-RPC 端点(需鉴权,生产环境必须带 Bearer token)。

支持的方法:

方法 说明
tasks/send 发送任务给团队(同步返回 submitted/working 状态)
tasks/sendSubscribe 发送任务并订阅状态更新(SSE 流式响应)
tasks/get 查询任务状态
tasks/cancel 取消任务
tasks/list 列出所有 A2A 任务
tasks/questions (扩展) 查询团队待回答的 LEAD 提问,外部大脑替代人类用户
tasks/answer (扩展) 回答 LEAD 的指定提问
tasks/confirm (扩展) 审批 Plan(confirmed/replan)
tasks/message (扩展) 注入补充消息到运行中团队

扩展方法说明:后 4 个 tasks/questions|answer|confirm|message 是平台对 A2A 协议的非标准扩展,目的是让外部大脑(飞书机器人/Claude/ChatGPT)仅通过 A2A 一种协议即可完成与团队 LEAD 的全流程对话,无需混用 REST/MCP 双协议栈。Agent Card 的 extensions.dialogueMethods 字段会声明这些方法。功能等价的 REST 端点见 第 26 节

tasks/send 请求示例:

curl -X POST http://localhost:3001/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer lps_xxx" \
  -d '{
    "jsonrpc":"2.0","id":"req-1","method":"tasks/send",
    "params":{"message":{"role":"user","parts":[{"type":"text","text":"开发一个 REST API"}]},"sessionId":"sess-1"}
  }'

响应:平台自动找一个 deployed 状态的团队接收任务并启动执行:

{
  "jsonrpc":"2.0","id":"req-1",
  "result": {
    "id":"a2a-task-xxx",
    "status":{"state":"working","timestamp":"...","message":"已分配给团队 X,开始自主运转"},
    "artifacts":[]
  }
}

tasks/sendSubscribe(SSE 流式,任务状态变化时推送,5 分钟超时):

curl -N -X POST http://localhost:3001/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer lps_xxx" \
  -d '{"jsonrpc":"2.0","id":"req-2","method":"tasks/sendSubscribe","params":{"message":{...}}}'

SSE 事件:

event: task
data: {"jsonrpc":"2.0","id":"req-2","result":{"id":"...","status":{"state":"working"}}}

event: task
data: {"jsonrpc":"2.0","id":"req-2","result":{"id":"...","status":{"state":"completed"}}}

批量请求:body 为数组时返回数组结果(过滤 null)。通知(无 id)返回 202

扩展方法(外部大脑与 LEAD 对话):

tasks/questions — 查询团队待回答的 LEAD 提问:

curl -X POST http://localhost:3001/a2a \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"jsonrpc":"2.0","id":"q1","method":"tasks/questions","params":{"teamId":"team-xxx"}}'

响应:{ "teamId":"team-xxx", "pendingQuestions":[{...}], "count":N }

tasks/answer — 回答 LEAD 的提问(替代人类用户):

curl -X POST http://localhost:3001/a2a \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"jsonrpc":"2.0","id":"a1","method":"tasks/answer","params":{"questionId":"conv-xxx","answer":"使用 PostgreSQL 15"}}'

响应:{ "questionId":"conv-xxx", "answered":true, "teamId":"team-xxx", "source":"a2a_external_brain" }

tasks/confirm — 审批 Plan(confirmed/replan):

curl -X POST http://localhost:3001/a2a \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"jsonrpc":"2.0","id":"c1","method":"tasks/confirm","params":{"teamId":"team-xxx","decision":"confirmed"}}'

响应:{ "teamId":"team-xxx", "decision":"confirmed", "confirmed":true, "source":"a2a_external_brain" } 行为:写入 team.progress.plan_confirmed,orchestrator 轮询循环检测到后继续推进;同时通过 SSE 推送 team:plan_decision 事件(含 source:"a2a_external_brain")。若团队状态非 running,自动恢复执行。

tasks/message — 注入补充消息(外部大脑主动给 LEAD 发指令/上下文):

curl -X POST http://localhost:3001/a2a \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"jsonrpc":"2.0","id":"m1","method":"tasks/message","params":{"teamId":"team-xxx","message":"请同时支持 OAuth2 登录"}}'

响应:{ "teamId":"team-xxx", "convId":"conv-xxx", "received":true, "source":"a2a_external_brain" }

15.2 外部 A2A Agent 管理

GET /api/a2a/agents

列出所有外部 A2A Agent(token 脱敏,agent_card JSON 解析)。响应: 200,agent 数组。

POST /api/a2a/agents

创建外部 A2A Agent。

请求体(常见字段):

字段 类型 必填 说明
name string Agent 名称
endpoint string Agent Card URL
token string 访问 token

响应: 200 创建结果。

DELETE /api/a2a/agents/:id

删除外部 Agent。响应: 200 { "deleted": true }

POST /api/a2a/agents/:id/discover

发现外部 Agent 的 Agent Card(拉取并更新)。

响应: 200 { ok: true, card: {...} };404 Agent 不存在。

POST /api/a2a/agents/:id/send

向外部 Agent 发送任务(泛化兼容,不限于特定平台)。通过 Agent 名称查找并调用 sendTaskToExternalAgent

请求体:

字段 类型 必填 说明
message string 任务消息内容
callbackUrl string 回调 URL。提供后,平台在任务状态变更(working → completed/failed 等)时主动 POST 通知到该 URL,无需客户端反复 poll
sessionToken string 回调会话 Token。平台 POST 通知到 callbackUrl 时,会以 Authorization: Bearer <sessionToken> header 携带,用于接收方校验请求来源

响应: 200 任务结果 { taskId, status, ... };400 缺少 message;404 Agent 不存在。

回调通知:若提供了 callbackUrl,平台内部轮询外部 agent 任务状态发现变更时,会通过 notifyCallbackUrl 主动 POST 到该 URL,payload 包含 { taskId, status, artifacts, ... }(与 poll 返回结构一致),并携带 Authorization: Bearer <sessionToken> header(若提供了 sessionToken)。

curl -X POST http://localhost:3001/api/a2a/agents/agt_xxx/send \
  -H "Content-Type: application/json" \
  -d '{
    "message":"分析这段代码的安全风险",
    "callbackUrl":"https://my-app.com/a2a-callback",
    "sessionToken":"cb-token-xxx"
  }'

POST /api/a2a/agents/:id/poll

轮询外部 Agent 的任务执行结果。通过 Agent 名称查找并调用 pollExternalTask

请求体:

字段 类型 必填 说明
taskId string send 返回的任务 ID

响应: 200 轮询结果 { status, result, ... };400 缺少 taskId;404 Agent 不存在。

curl -X POST http://localhost:3001/api/a2a/agents/agt_xxx/poll \
  -H "Content-Type: application/json" \
  -d '{"taskId":"task-xxx"}'

16. Secrets 与安全

GET /api/secrets

列出所有 Secret(value 不返回明文)。响应: 200,secret 数组。

POST /api/secrets

创建 Secret。

请求体:

字段 类型 必填 说明
name string Secret 名称
value string Secret 值
description string 描述

响应: 200 secret 对象;400 { "error": "缺少 name 或 value" }

curl -X POST http://localhost:3001/api/secrets \
  -H "Content-Type: application/json" \
  -d '{"name":"DB_PASSWORD","value":"s3cret","description":"数据库密码"}'

DELETE /api/secrets/:id

删除 Secret。响应: 200 { "deleted": true }

GET /api/security/policy/:deployTarget

获取指定部署目标的安全沙箱策略。

路径参数: deployTarget(如 local/docker/remote-ssh)。

响应: 200,策略对象。

POST /api/security/validate

验证生产环境就绪状态。

请求体:

字段 类型 必填 说明
deployTarget string 部署目标
forceProduction boolean 是否强制生产模式

响应: 200,验证报告。


17. 团队管理(核心)

团队是平台的核心执行单元:由多个 Agent 组成,接收使命后自主拆解、协作、验证、迭代。这是文档的重点章节

GET /api/teams

团队列表。响应: 200,团队数组。

GET /api/teams/stats

团队统计。响应: 200,统计对象。

POST /api/teams

创建团队。

请求体:

字段 类型 必填 说明
name string 团队名称
mission string 使命描述
stop_condition string 停止条件
template_id string 模板 ID(基于模板创建)
workspace_path string 工作区路径
workspace_id string 工作区 ID(自动解析为 workspace_path)
members array 成员定义数组
config object 团队配置(见下表)

config 常用字段:

字段 类型 默认 说明
max_rounds int 3 最大工作轮次(拆解-执行-验证-迭代)
max_retries int 2 每子任务最大重试次数
parallel_coders bool false 开启并行编码(需有多个同角色实例才真正并行)
max_parallel int 4 并行度上限(防止过多 OpenClaw 进程同时启动)
plan_mode string manual Plan 确认模式:manual(需确认)/auto(自动执行)
max_tokens_per_mission int - 使命级 Token 预算,超出自动停止
model_assignment object - 按角色分配模型(智能路由自动填充)

响应: 200 团队对象(状态默认 draft);400 { "error": "..." }

curl -X POST http://localhost:3001/api/teams \
  -H "Content-Type: application/json" \
  -d '{"name":"我的团队","mission":"开发REST API","stop_condition":"接口测试通过","workspace_id":"ws-xxx"}'

GET /api/teams/:id

团队详情。响应: 200 团队对象;404 { "error": "团队不存在" }

PUT /api/teams/:id

更新团队配置(目前仅支持 config 字段浅合并,如 max_rounds / max_retries)。

请求体: { "config": { "max_rounds": 20 } }响应: 200 更新后的团队。

POST /api/teams/:id/deploy

部署团队(实例化成员 agent、准备 worktree)。

请求体: 部署选项,常用 { "target": "local" | "remote-ssh" | "docker" }

响应: 200 部署后的团队;400 { "error": "..." }

curl -X POST http://localhost:3001/api/teams/team-xxx/deploy \
  -H "Content-Type: application/json" -d '{"target":"local"}'

POST /api/teams/:id/mission

下发/更新使命。

请求体:

字段 类型 必填 说明
title string 使命标题
goal string 使命目标
stop_condition string 停止条件

响应: 200 结果对象。

POST /api/teams/:id/start

启动团队(开始自主运转)。优先用团队绑定的 workspace,没有才回退全局默认。

行为:同步 startTeam(设置状态 + 准备 worktree),然后异步启动 runTeamMission(不阻塞响应)。

响应: 200 { "started": true, "workspace": "/path" }

curl -X POST http://localhost:3001/api/teams/team-xxx/start

POST /api/teams/:id/stop

停止团队。请求体: { "reason": "..." }(可选)。响应: 200 团队对象。

POST /api/teams/:id/pause

暂停团队。响应: 200 团队对象。

POST /api/teams/:id/resume

恢复团队。响应: 200 团队对象。

PUT /api/teams/:id/workspace

更换团队工作区(不删团队,保留 team_id,经验自然累积)。

请求体: { "workspace_path": "/new/path" }(必填)。响应: 200 更新后的团队。

POST /api/teams/:id/redeploy

重新部署团队到新工作区(一步到位:换工作区 + 重新部署 + 可选直接执行新使命)。

请求体:

字段 类型 必填 说明
workspace_path string 新工作区路径
mission string 新使命(提供则下发)
stop_condition string 停止条件
deploy_config object 部署配置
auto_start boolean 是否自动启动(默认 true)

响应: 200

{ "redeployed": true, "workspace": "/path", "mission_assigned": true, "started": true }

POST /api/teams/:id/archive

归档团队。响应: 200 团队对象。

DELETE /api/teams/:id

删除团队(不可撤销,连带删除关联数据和实例化 agent)。响应: 200 { "deleted": true }

级联清理的表(共 12 张):team_members / runs / team_missions / team_integrations / team_deployments / pm_conversations / team_file_requests / team_materials / knowledge / pitfall_cards / tasks(含 approvals)/ logs。运行中的团队不允许删除(返回 400)。

GET /api/teams/:id/export

导出团队(支持 ?format=yaml)。

Query 参数: format(json 默认 / yaml)。

响应: format=yamlContent-Type: text/yaml;否则 JSON。

POST /api/teams/import

导入团队(JSON)。

请求体: 团队定义对象 + 可选 workspace_path响应: 200 导入的团队。

GET /api/teams/:id/export-package

导出团队为 tar 包(含 Skills + MCP 引用 + Secret 引用)→ 下载 tar.gz。

响应: 文件下载(res.download),文件名 <teamName>.tar.gz

POST /api/teams/import-package

从 tar 包导入团队(上传 tar.gz,还原 Skills + MCP + 检查 Secret)。

请求体: multipart/form-data,字段 file(tar.gz)+ 可选 workspace_path

响应: 200 导入报告。

GET /api/teams/:id/members

团队成员列表。响应: 200,成员数组。

POST /api/teams/:id/members

添加团队成员。

请求体:

字段 类型 必填 说明
agent_id string Agent ID
role_in_team string 团队内角色
is_lead boolean 是否 lead

响应: 200 { "id": "mid-xxx" }

DELETE /api/teams/:id/members/:mid

移除团队成员。响应: 200 { "deleted": true }

GET /api/teams/:id/instances

团队的 agent 实例列表(每个成员的实例化配置)。响应: 200,实例数组。

GET /api/teams/:id/tasks

团队关联的任务列表(任务-团队统一模型:任务归属团队)。响应: 200,任务数组(按 created_at DESC)。

POST /api/teams/:id/tasks

为团队创建任务(同时分配给团队,mode 自动为 team)。

请求体:

字段 类型 必填 说明
title string 任务标题
goal string 目标
stop_condition string 停止条件
priority int 优先级(默认 2)
source string 来源(默认 web)

响应: 201 Task 对象。

GET /api/teams/:id/missions

团队使命列表。响应: 200,使命数组。

GET /api/teams/:id/deployment

团队部署详情。响应: 200 部署记录(config/details 已 JSON 解析);404 { "error": "暂无部署记录" }

POST /api/teams/:id/check-remote-env

SSH 远程环境检测(检测 node/git/openclaw/rsync/docker 等)。

请求体:

字段 类型 必填 说明
ssh_host string SSH 主机
ssh_user string 用户(默认 agent)
ssh_key string 私钥路径(默认 ~/.ssh/id_rsa)
ssh_port int 端口(默认 22)

响应: 200

{
  "env": { "node": true, "git": true, "docker": false, "openclaw": true, "rsync": true },
  "mode": "docker | native | needs_bootstrap",
  "missing": ["docker"],
  "ready": true,
  "message": "远程环境就绪,将使用 Docker 容器模式(推荐)"
}

GET /api/teams/:id/stream

团队 SSE 事件流。

行为:

  • 回调式订阅:团队级事件 + 全局事件(匹配 teamId)。
  • 连接时先推一次当前团队状态 { "type": "team:state", "team": {...} }
  • 15 秒心跳保活。

事件类型:见附录 B(如 team:plan_decisionteam:plan_editedteam:materials_addedteam:statetask:log 等)。

const es = new EventSource('http://localhost:3001/api/teams/team-xxx/stream?key=lps_xxx');
es.onmessage = e => {
  const evt = JSON.parse(e.data);
  if (evt.type === 'team:plan_decision') console.log('Plan 决策:', evt.decision);
};

GET /api/teams/:id/logs

团队历史日志。Query 参数: limit(默认 500)。响应: 200,日志数组。

GET /api/teams/:id/runs

团队运行记录。响应: 200,run 数组(含 steps JSON 解析,按 created_at DESC)。

GET /api/teams/:id/skill-constraints

团队生效的 Skill 约束汇总(从所有成员的 skills/*/SKILL.md 提取)。

响应: 200 { "constraints": "...", "sources": [...] }(无约束时 constraints 为 null)。

GET /api/teams/:id/timeline

团队运行历史(时间旅行,带步骤详情)。列表只返回 output_preview(前 2000 字符)避免响应过大。

响应: 200,run 数组:

[{
  "id":"run-xxx","agent_name":"Orchestrator","agent_role":"dispatcher",
  "phase":"plan","status":"completed","tokens_in":1000,"tokens_out":2000,
  "model":"deepseek-chat","created_at":"...","steps":[...],
  "verdict":"...","output_preview":"...(前2000字符)"
}]

GET /api/teams/:id/timeline/:runId

获取单个 run 的完整上下文(完整 output,非 preview)。

响应: 200 完整 run 对象;404 { "error": "运行记录不存在" }


18. 团队集成

团队级集成覆盖(feishu/webhook/mcp/a2a/secret),允许每个团队有独立的集成配置,覆盖全局默认。

GET /api/teams/:id/integrations

获取团队集成配置列表。

Query 参数: type(可选,过滤 feishu/webhook/mcp/a2a/secret)。

响应: 200,集成数组。

POST /api/teams/:id/integrations

创建团队级集成覆盖。

请求体: 集成定义对象(含 type、配置等)。响应: 201 集成对象。

PUT /api/team-integrations/:intId

更新团队级集成。请求体: 可更新字段。响应: 200 集成对象。

DELETE /api/team-integrations/:intId

删除团队级集成。响应: 200 { "deleted": true }


19. 知识沉淀

GET /api/knowledge

知识列表。

Query 参数:

参数 说明
team_id 按团队过滤
success true 只看成功,false 只看失败

响应: 200,知识数组。

POST /api/knowledge/search

检索相似经验(语义搜索)。

请求体:

字段 类型 必填 说明
mission string 使命文本
team_id string 限定团队

响应: 200,匹配的知识数组(limit 5,minScore 0.1)。

curl -X POST http://localhost:3001/api/knowledge/search \
  -H "Content-Type: application/json" \
  -d '{"mission":"开发一个登录API"}'

DELETE /api/knowledge/:id

删除知识。响应: 200 { "deleted": true }

POST /api/knowledge/scaffold

脚手架克隆:从历史经验克隆项目骨架。

请求体:

字段 类型 必填 说明
mission string 使命文本
template_id string 模板 ID
project_type string 项目类型

响应: 200 克隆结果。

GET /api/pitfall-cards

避坑卡片列表。响应: 200,卡片数组。

POST /api/pitfall-cards/search

搜索避坑卡片。请求体: { "mission": "..." }(mission 必填)。响应: 200,卡片数组。

DELETE /api/pitfall-cards/:id

删除避坑卡片。响应: 200 { "deleted": true }


20. 成本管理

POST /api/teams/:id/cost-estimate

使命级成本估算。

请求体(可选,默认用团队自身的 mission/stop_condition):

字段 类型 说明
mission string 使命文本
stop_condition string 停止条件

响应: 200,成本估算对象(基于成员数、lead 模型、team.config 的 max_rounds/max_retries)。

curl -X POST http://localhost:3001/api/teams/team-xxx/cost-estimate \
  -H "Content-Type: application/json" -d '{}'

POST /api/workspaces/:id/rollback-cost

回滚沉没成本报告:计算回滚到某 commit 会损失多少已投入成本。

请求体: { "commit_hash": "abc123" }(必填)。

响应: 200,成本报告。


21. 团队模板

GET /api/team-templates

模板列表。响应: 200,模板数组。

GET /api/team-templates/:id

模板详情。响应: 200 模板;404 { "error": "模板不存在" }

POST /api/team-templates

创建模板。

请求体: 模板定义对象,其中 member_config 为成员配置数组,每项支持以下字段:

字段 类型 必填 说明
agent_role string 角色(如 implementer/reviewer/orchestrator),用于 fallback 匹配
is_lead boolean 是否为 LEAD(默认 false)
agent_id string 绑定具体 agent 定义,精确指定 persona/model/tools;提供后 createTeam 优先按此匹配
persona_override string persona 覆盖(绑定 agent 时可附带)

兼容说明:members 字段可作为 member_config 的别名传入(后端自动兼容)。未提供 agent_id 时,createTeam 按 agent_role 匹配(模板可移植);提供 agent_id 时精确绑定(不可移植但 persona/model/tools 确定)。

响应: 200 模板对象。

curl -X POST http://localhost:3001/api/team-templates \
  -H "Content-Type: application/json" \
  -d '{
    "name":"我的模板",
    "description":"带 agent 绑定的工程团队",
    "member_config":[
      {"agent_role":"orchestrator","is_lead":true},
      {"agent_role":"implementer","is_lead":false,"agent_id":"agent-xxx","persona_override":"专注后端 API"}
    ]
  }'

DELETE /api/team-templates/:id

删除模板。响应: 200 { "deleted": true }

GET /api/team-templates/:id/export

导出模板。响应: 200 模板对象。

POST /api/team-templates/import

导入模板。请求体: 模板定义对象。响应: 200 模板对象。


22. 质量门禁

质量门禁提供 Go/No-Go 决策报告和各维度质量指标。

GET /api/quality-gate/report

生成 Go/No-Go 决策报告(综合)。

Query 参数:

参数 默认 说明
since 30 天前 起始时间(ISO)
workspace - 工作区路径过滤

响应: 200,决策报告对象。

GET /api/quality-gate/success-rate

使命成功率。Query 参数: since(默认 1970-01-01)。响应: 200,成功率统计。

GET /api/quality-gate/first-review-pass

首次审查通过率。Query 参数: since响应: 200,通过率统计。

GET /api/quality-gate/iterations

平均迭代次数。Query 参数: since响应: 200,迭代统计。

POST /api/quality-gate/hallucination-check

幻觉检测。

请求体: { "limit": 50 }(limit 默认 50)。响应: 200,检测结果。

GET /api/quality-gate/sse-stability

SSE 稳定性指标。响应: 200,稳定性统计。

GET /api/quality-gate/security-audit

运行安全审计。响应: 200,审计报告。

GET /api/quality-gate/path-traversal-test

路径穿越测试。响应: 200,测试结果。

GET /api/quality-gate/git-dirty

检查 git 工作区是否 dirty。

Query 参数: path(必填,工作区路径)。响应: 200,dirty 状态。

POST /api/quality-gate/crash-recovery

崩溃恢复:修复 dirty 工作区。

请求体: { "path": "/workspace/path" }(path 必填)。响应: 200

{ "recovered": true, "action": "committed", "commitHash": "abc123" }

POST /api/quality-gate/sse-stability/reset

重置 SSE 统计。响应: 200 { "reset": true }


23. Bridge Agent 对话(PM 提问/Plan 确认)

Bridge Agent 是团队与用户之间的对话桥梁,核心场景:PM 提问澄清需求 + Plan 确认/编辑。这是平台"人在回路"的关键机制。

GET /api/teams/:id/pm-questions

获取团队待回答的 Bridge Agent 提问。

响应: 200,问题数组:

[{
  "id":"conv-xxx","team_id":"team-xxx","question":"使用什么数据库?",
  "status":"pending","created_at":"..."
}]

POST /api/pm-conversations/:convId/answer

回答 Bridge Agent 提问。

请求体:

字段 类型 必填 说明
answer string 回答内容

响应:

  • 200 { "ok": true, ... }
  • 404 { "error": "对话不存在" }
  • 400 { "error": "该提问已处理" }

行为:回答后 Bridge Agent 会读取答案继续推进使命执行。

curl -X POST http://localhost:3001/api/pm-conversations/conv-xxx/answer \
  -H "Content-Type: application/json" \
  -d '{"answer":"使用 PostgreSQL 15"}'

POST /api/pm-conversations/:convId/skip

跳过 Bridge Agent 提问(让团队自行决策)。

响应: 200 结果对象;404 { "error": "对话不存在" }

POST /api/teams/:id/supplement

用户中途补充消息(非提问场景,用户主动给团队发信息)。

存入 pm_conversations 表(status=supplement),runTeamMission 每轮开头检查并注入。

实时待命特性:团队状态为 completed/failed/stopped 时,自动重启团队执行新使命(基于补充指令)。

请求体:

字段 类型 必填 说明
message string 补充消息内容

响应: 200

{ "ok": true, "restarted": true, "message": "补充指令已接收,团队已自动重启执行" }
curl -X POST http://localhost:3001/api/teams/team-xxx/supplement \
  -H "Content-Type: application/json" \
  -d '{"message":"请同时支持 OAuth2 登录"}'

POST /api/teams/:id/confirm-plan

Plan 用户确认 — 用户点击"确认执行"或"重新规划"后写入 team.progress.plan_confirmed

runTeamMissionawaiting_plan_confirmation 状态下轮询此字段。

请求体:

字段 类型 必填 说明
decision string confirmed(确认执行)/ replan(重新规划)

前置条件:团队 progress.status 必须为 awaiting_plan_confirmation,否则 400。

响应: 200 { "received": true, "decision": "confirmed" }

恢复机制:后端重启后 orchestrator 轮询循环可能已丢失,此接口会检查 team.status !== 'running' 并重新启动 runTeamMission

事件通知:会通过 SSE 推送 { "type": "team:plan_decision", "teamId": "...", "decision": "..." }

# 确认执行
curl -X POST http://localhost:3001/api/teams/team-xxx/confirm-plan \
  -H "Content-Type: application/json" -d '{"decision":"confirmed"}'

# 要求重新规划
curl -X POST http://localhost:3001/api/teams/team-xxx/confirm-plan \
  -H "Content-Type: application/json" -d '{"decision":"replan"}'

PUT /api/teams/:id/plan

Plan 用户编辑 — 允许用户修改 plan_subtasks(增删改子任务目标/角色/验收条件/并行组)。

修改后的 plan 存入 progress.plan_subtasks,orchestrator 在 confirmed 后优先使用。

前置条件:团队 progress.status 必须为 awaiting_plan_confirmation,否则 400。

请求体:

字段 类型 必填 说明
subtasks array 子任务数组(每个含 goal/role/stop_condition/parallel_group)
analysis string 分析说明(覆盖现有)
strategy string 策略说明(覆盖现有)

subtask 字段:

字段 类型 必填 说明
goal string 子任务目标
role string 执行角色(如 implementer)
stop_condition string 停止条件
parallel_group int 并行组(默认 0,同组并行执行)

校验:每个 subtask 必须有非空 goalrole,否则 400。

响应: 200 { "received": true, "subtaskCount": 5 }

行为:

  • 子任务会被 normalize(加 idx,trim goal,默认 role=implementer,默认 parallel_group=0)。
  • 标记 plan_edited: true
  • SSE 推送 { "type": "team:plan_edited", "teamId": "...", "subtaskCount": 5 }
curl -X PUT http://localhost:3001/api/teams/team-xxx/plan \
  -H "Content-Type: application/json" \
  -d '{
    "subtasks": [
      {"goal":"实现用户模型","role":"implementer","stop_condition":"模型可通过测试"},
      {"goal":"实现登录接口","role":"implementer","stop_condition":"接口可调用","parallel_group":1},
      {"goal":"实现注册接口","role":"implementer","stop_condition":"接口可调用","parallel_group":1}
    ],
    "strategy":"先模型后接口,登录注册并行"
  }'

PUT /api/teams/:id/plan-mode

设置团队的 Plan 模式。控制 Lead 生成拆解计划后是否需要用户手动确认才执行。

请求体:

字段 类型 必填 说明
plan_mode string manual(需用户确认,默认) 或 auto(自动确认直接执行)

响应: 200 { "received": true, "plan_mode": "auto", "team_id": "team-xxx" }

行为:

  • manual 模式:Lead 生成计划后团队暂停为 awaiting_plan_confirmation 状态,等待用户通过 POST /api/teams/:id/confirm-plan 确认。
  • auto 模式:Lead 生成计划后直接执行,不暂停。SSE 推送 { "type": "team:plan_auto_confirmed", ... } 事件(含 plan 详情)。
  • 也可通过 PUT /api/teams/:idconfig.plan_mode 字段设置。
  • SSE 推送 { "type": "team:plan_mode_changed", "teamId": "...", "plan_mode": "auto" }
curl -X PUT http://localhost:3001/api/teams/team-xxx/plan-mode \
  -H "Content-Type: application/json" -d '{"plan_mode":"auto"}'

典型 Plan 确认流程:

  1. 团队执行到规划阶段,progress.status 变为 awaiting_plan_confirmation
  2. SSE 推送 plan 给前端,用户查看 progress.plan_subtasks
  3. (可选)PUT /api/teams/:id/plan 编辑子任务。
  4. POST /api/teams/:id/confirm-plan 提交决策。
  5. orchestrator 读取决策,confirmed 开始执行,replan 重新规划。

24. 团队材料区

用户上传补充材料(文档/图片/数据文件)到团队工作区,agent 可直接通过文件系统访问。文件存储在 {workspace_path}/materials/ 下。

GET /api/teams/:id/materials

列出团队所有材料。响应: 200,材料数组:

[{
  "id":"mat-xxx","team_id":"team-xxx","filename":"spec.pdf",
  "stored_path":"/path/materials/mat-xxx_spec.pdf","size_bytes":102400,
  "mime_type":"application/pdf","description":"需求文档","uploaded_by":"user","created_at":"..."
}]

POST /api/teams/:id/materials

上传材料(支持多文件,最多 20 个)。

请求体: multipart/form-data

字段 类型 必填 说明
files file[] 多文件(最多 20)
description string 描述

行为:

  • 材料存储到 {team.workspace_path}/materials/,无 workspace 时用全局。
  • 防路径穿越:只用 basename,特殊字符替换为 _
  • SSE 通知团队:{ "type": "team:materials_added", "count": N, "files": [...] }

响应: 200

{ "success": true, "count": 2, "materials": [{ "id":"mat-xxx","filename":"...","size_bytes":1024,"mime_type":"...","stored_path":"..." }] }
curl -X POST http://localhost:3001/api/teams/team-xxx/materials \
  -F "files=@spec.pdf" -F "files=@api.yaml" -F "description=需求文档"

DELETE /api/teams/:id/materials/:materialId

删除材料(同时删除文件)。响应: 200 { "success": true };404 { "error": "材料不存在" }

GET /api/teams/:id/materials/:materialId/download

下载材料。响应: 文件下载(res.download);404 材料不存在或文件丢失。


25. 运行期文件请求

Agent team 运行过程中,若需要外部文件(如需求文档、数据集、配置模板等)才能继续执行,可通过"运行期文件请求"机制向外部请求文件。文件请求存储在 team_file_requests 表中,支持 REST(multipart 上传)、A2A(base64 上传)、MCP 工具三种接入方式。

使用场景:agent team 运行中发现缺少必要的输入文件(如"需要 schema.sql 才能实现数据库迁移"),由 agent 发起文件请求,外部系统(用户/外部大脑/CI)上传文件后 agent 继续执行。

文件存储路径:上传的文件存储在 {workspace_path}/materials/fulfilled/{requestId}_{filename},agent 可直接通过文件系统读取。

GET /api/teams/:id/file-requests

列出团队的 pending 文件请求(Agent 待 fulfill 的请求列表)。

响应: 200

[{
  "id": "freq-xxx", "team_id": "team-xxx", "agent_id": "inst-xxx",
  "description": "需要数据库 schema 文件", "expected_filename": "schema.sql",
  "status": "pending", "stored_path": null, "expires_at": "2026-07-13T09:00:00.000Z",
  "created_at": "..."
}]

POST /api/teams/:id/file-requests

Agent 发起文件请求(创建 pending 请求,默认 30 分钟后过期)。

请求体:

字段 类型 必填 说明
agent_id string 发起请求的 agent 实例 ID
description string 文件描述(需要什么文件、用途)
expected_filename string 期望的文件名

响应: 201

{ "id": "freq-xxx", "team_id": "team-xxx", "status": "pending", "expires_at": "2026-07-13T09:00:00.000Z" }
curl -X POST http://localhost:3001/api/teams/team-xxx/file-requests \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"agent_id":"inst-xxx","description":"需要数据库 schema 文件","expected_filename":"schema.sql"}'

事件通知:创建后触发 team:file_request webhook 事件。

GET /api/teams/:id/file-requests/:requestId

查询单个文件请求状态。

响应: 200 文件请求对象;404 { "error": "请求不存在" }

状态取值:pending(等待上传)/ fulfilled(已上传)/ rejected(已拒绝)/ expired(已过期)。

POST /api/teams/:id/file-requests/:requestId/fulfill

上传文件以满足请求(multipart 上传)。上传后状态变为 fulfilled,文件存储到 {workspace_path}/materials/fulfilled/{requestId}_{filename}

请求体: multipart/form-data

字段 类型 必填 说明
file file 上传的文件

响应: 200

{
  "success": true, "requestId": "freq-xxx", "status": "fulfilled",
  "stored_path": "/path/materials/fulfilled/freq-xxx_schema.sql",
  "filename": "schema.sql", "size_bytes": 2048
}
curl -X POST http://localhost:3001/api/teams/team-xxx/file-requests/freq-xxx/fulfill \
  -H "Authorization: Bearer lps_xxx" \
  -F "file=@schema.sql"

事件通知:上传后触发 team:file_fulfilled webhook 事件。

POST /api/teams/:id/file-requests/:requestId/reject

拒绝文件请求(用户/外部系统认为不需要提供该文件)。

请求体(可选): { "reason": "不需要此文件" }

响应: 200 { "success": true, "requestId": "freq-xxx", "status": "rejected" }

事件通知:拒绝后触发 team:file_rejected webhook 事件。

POST /api/file-requests/cleanup

清理过期的文件请求(将超过 expires_at 的 pending 请求标记为 expired)。可定期调用以回收资源。

响应: 200

{ "cleaned": 3, "remaining": 0 }

26. 外部大脑与 LEAD 对话(扩展 A2A + REST)

本节端点专门服务于外部大脑接入场景:用户已有一个现成的 agent 大脑(飞书机器人/Claude/ChatGPT/自研 LLM Agent),希望连接平台进行自动化编码,但大脑不作为 agent team 的成员,而是以"用户"角色与团队 LEAD 交流来完成任务。

26.1 设计理念

┌──────────────┐   REST/A2A    ┌──────────────────────────┐
│  外部大脑     │ ────────────► │  Loop Studio Platform    │
│ (Claude/GPT) │               │                          │
│  "用户"角色   │ ◄──SSE/Webhook│  ┌────────────────────┐  │
└──────────────┘               │  │  团队 LEAD          │  │
                                │  │  (dispatcher/PM)    │  │
                                │  └────────────────────┘  │
                                │         │ 拆解/调度       │
                                │  ┌──────▼───────┐        │
                                │  │ coder/tester │        │
                                │  │ reviewer ... │        │
                                │  └──────────────┘        │
                                └──────────────────────────┘

关键特征:

  • 外部大脑不进入 team_members 表,不占用 agent 实例
  • 外部大脑的所有交互都记录在 pm_conversations 表,审计字段 answered_by 区分 user(人类)/external_brain(REST)/a2a_external_brain(A2A)
  • 外部大脑可通过 REST(本节)或 A2A 扩展方法(第 15 节)任一方式接入,二者功能对等

26.2 REST 端点

GET /api/teams/:id/lead/questions

查询团队待回答的 LEAD 提问(仅返回 status=pending 的记录)。

响应: 200

{
  "teamId": "team-xxx",
  "pendingQuestions": [{
    "id": "conv-xxx", "team_id": "team-xxx", "round": 1,
    "question": "使用什么数据库?", "status": "pending",
    "created_at": "..."
  }],
  "count": 1
}
curl http://localhost:3001/api/teams/team-xxx/lead/questions \
  -H "Authorization: Bearer lps_xxx"

POST /api/teams/:id/lead/answer

回答 LEAD 的提问(外部大脑替代人类用户)。

请求体:

字段 类型 必填 说明
questionId string 提问 ID(pm_conversations.id)
answer string 回答内容

响应: 200 { "questionId":"...", "answered":true, "teamId":"...", "source":"external_brain" }

  • 400 缺少参数 / 提问不属于该团队
  • 404 提问不存在

审计:写入 pm_conversations.answered_by='external_brain'source='rest_api'

curl -X POST http://localhost:3001/api/teams/team-xxx/lead/answer \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"questionId":"conv-xxx","answer":"使用 PostgreSQL 15"}'

POST /api/teams/:id/lead/confirm-plan

审批 Plan(外部大脑确认/退回)。

请求体:

字段 类型 必填 说明
decision string confirmed(确认执行)/ replan(重新规划)

响应: 200 { "teamId":"...", "decision":"confirmed", "confirmed":true, "source":"external_brain" }

  • 400 decision 非法值
  • 404 团队不存在

行为:写入 team.progress.plan_confirmedplan_confirmed_by='external_brain'plan_confirmed_at,orchestrator 轮询 progress.plan_confirmed 检测到后继续推进。若团队状态非 running,自动恢复 orchestrator 执行循环(用于后端重启后恢复)。

curl -X POST http://localhost:3001/api/teams/team-xxx/lead/confirm-plan \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"decision":"confirmed"}'

POST /api/teams/:id/lead/message

注入补充消息到运行中团队(外部大脑主动给 LEAD 发指令/上下文)。

请求体:

字段 类型 必填 说明
message string 补充消息内容

响应: 200 { "teamId":"...", "convId":"conv-xxx", "received":true, "source":"external_brain" }

  • 400 缺少 message / 团队未运行

审计:写入 pm_conversations.answered_by='external_brain'source='rest_api'

curl -X POST http://localhost:3001/api/teams/team-xxx/lead/message \
  -H "Content-Type: application/json" -H "Authorization: Bearer lps_xxx" \
  -d '{"message":"请同时支持 OAuth2 登录"}'

26.3 典型接入流程

1. 外部大脑通过 tasks/send 下发使命(或人类在 Web 下发)
   ↓
2. 团队 LEAD 分析使命,产生提问 → 触发 team.pm_question webhook
   ↓
3. 外部大脑轮询 GET /lead/questions(或接收 webhook)获取提问
   ↓
4. 外部大脑根据自身知识 POST /lead/answer 回答
   ↓
5. LEAD 生成 Plan,等待确认 → 触发 team.plan_pending webhook
   ↓
6. 外部大脑 POST /lead/confirm-plan 确认执行
   ↓
7. 团队自主执行,外部大脑可通过 SSE / webhook 观察进度
   ↓
8. (可选)外部大脑 POST /lead/message 注入中途指令
   ↓
9. 团队完成,触发 team.completed webhook

26.4 webhook 事件

外部大脑接入场景下,建议订阅以下 webhook 事件(创建 webhook 时在 events 数组中指定):

事件 触发时机 关键字段
team.pm_question LEAD 向用户提问 teamId, convId, question, round
team.plan_pending Plan 生成等待确认 teamId, round, subtaskCount
team.completed 使命成功 teamId
team.failed 使命失败 teamId, error

附录 A:错误码速查

code 含义 触发端点
UNAUTHORIZED 生产环境无 Token 所有需鉴权端点
INVALID_TOKEN Token 无效 所有需鉴权端点
RATE_LIMITED 触发速率限制 所有 /api/*
MCP -32001 Origin 不允许 POST/GET /mcp
MCP -32002 Accept header 不满足 POST /mcp
MCP -32003 缺失/无效 Mcp-Session-Id POST/GET/DELETE /mcp(非 initialize)
MCP -32004 不支持的 MCP-Protocol-Version /mcp
MCP -32005 GET /mcp 需 Accept: text/event-stream GET /mcp
MCP -32006 session 不存在 DELETE /mcp

附录 B:SSE 事件类型

全局事件流(/api/events)与团队事件流(/api/teams/:id/stream)

type 说明 关键字段
task:log 任务日志 taskId, message, level
task:state 任务状态变更 taskId, status
team:state 团队状态变更 teamId, team
team:plan_decision Plan 用户决策 teamId, decision(confirmed/replan), source(user/external_brain/a2a_external_brain)
team:plan_edited Plan 用户编辑 teamId, subtaskCount
team:plan_auto_confirmed Plan 自动确认(auto模式) teamId, round, subtask_count
team:plan_mode_changed Plan 模式切换 teamId, plan_mode
team:parallel_downgrade 并行降级为串行 teamId, round, group, subtask_count, instance_count, reason, suggestion
team:model_auto_assigned 智能路由自动分配模型 teamId, assignment
team:materials_added 团队材料新增 teamId, count, files
team:pm_question LEAD 向用户/外部大脑提问 teamId, convId, question, round
team:plan_pending Plan 生成等待确认 teamId, round, subtaskCount

容器事件流(/api/containers/stream)

type 说明
overview 全量容器概览(连接时首推)
container:state 单容器状态变更

终端事件流(/api/workspaces/:id/terminal)

type 说明 data
start 命令开始 { command, cwd }
stdout 标准输出 文本
stderr 标准错误 文本
exit 命令结束 { code, stdout, stderr }
error 执行错误 错误消息

A2A 流式(/a2a method=tasks/sendSubscribe)

event 说明
task 任务状态变更
timeout 流超时(5 分钟)

附录 C:典型工作流

C1. 团队完整生命周期

# 1. 创建工作区
WS=$(curl -s -X POST http://localhost:3001/api/workspaces/url \
  -H "Content-Type: application/json" \
  -d '{"url":"https://github.com/user/repo.git"}' | jq -r .id)

# 2. 创建团队(绑定工作区)
TEAM=$(curl -s -X POST http://localhost:3001/api/teams \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"API团队\",\"mission\":\"开发REST API\",\"stop_condition\":\"测试通过\",\"workspace_id\":\"$WS\"}" | jq -r .id)

# 3. 部署 + 启动
curl -X POST http://localhost:3001/api/teams/$TEAM/deploy -H "Content-Type: application/json" -d '{"target":"local"}'
curl -X POST http://localhost:3001/api/teams/$TEAM/start

# 4. 订阅 SSE 等待 Plan 确认
# 5. 确认 Plan
curl -X POST http://localhost:3001/api/teams/$TEAM/confirm-plan \
  -H "Content-Type: application/json" -d '{"decision":"confirmed"}'

# 6. 查询结果
curl http://localhost:3001/api/teams/$TEAM
curl http://localhost:3001/api/teams/$TEAM/timeline

C2. 外部系统通过 A2A 委派任务

# 1. 发现 Agent Card
curl http://your-host:3001/.well-known/agent.json

# 2. 发送任务(需 Bearer token)
curl -X POST http://your-host:3001/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer lps_xxx" \
  -d '{"jsonrpc":"2.0","id":"1","method":"tasks/send","params":{"message":{"role":"user","parts":[{"type":"text","text":"开发一个待办应用"}]}}}'

C3. 外部 AI 客户端通过 MCP 调用平台

# 1. initialize(获取 sessionId)
SESSION=$(curl -s -X POST http://localhost:3001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"demo","version":"1.0"}}}' \
  -D - | grep -i mcp-session-id | awk '{print $2}' | tr -d '\r\n')

# 2. 列出工具
curl -X POST http://localhost:3001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# 3. 调用工具
curl -X POST http://localhost:3001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"create_task","arguments":{"title":"demo","goal":"test","stop_condition":"done"}}}'

# 4. 结束会话
curl -X DELETE http://localhost:3001/mcp -H "Mcp-Session-Id: $SESSION"

文档说明:本手册所有端点均来自 src/routes.js(主路由)、src/mcp-server.js(MCP 协议)、src/a2a-protocol.js(A2A 协议)、src/server.js(健康检查/Prometheus/工作区文件访问)源码,共覆盖约 191 个端点。如需了解各端点的具体业务逻辑,请查阅对应模块源码。完整测试覆盖见 TEST_REPORT_FINAL.md(196 用例 / 94.4% 通过率)。