跳转至

Team Protocols: Agent 间通信标准

概述

Team Protocols 定义了团队成员之间的通信、同步和协调规则。它们确保即使 agent 在不同进程中并行运行时也能可靠协作。

核心协议

1. 权限同步协议

确保所有队友遵守团队负责人设置的一致权限规则。

流程: 权限请求

队友查询:
  1. 调用 Tool: Edit("/forbidden-file.ts")
  2. 检查: 本地权限规则
  3. 本地规则: 拒绝
  4. 检查: 团队规则 (team.json)
  5. 团队规则: 中立 (未指定)
  6. 操作: 向负责人发送权限请求

发送给负责人的消息:
  {
    id: "perm-req-123",
    from: "frontend-agent",
    type: "permission_request",
    tool: "Edit",
    path: "/forbidden-file.ts",
    timestamp: 1712000000000
  }

负责人处理:
  1. 接收邮箱消息
  2. 评估: 这个路径可以安全编辑吗?
  3. 决策: allow | deny | ask_user
  4. 响应:
     {
       id: "perm-req-123",
       type: "permission_response",
       decision: "allow",
       reason: "集成所需"
     }

队友恢复:
  1. 轮询邮箱获取响应
  2. 接收 permission_response
  3. 决策: allow → 继续执行 Edit
  4. Tool 执行继续

权限规则继承

负责人授予权限:
  teamAllowedPaths: [
    {
      path: "src/**",
      toolName: "Edit",
      addedBy: "lead-agent"
    }
  ]

队友继承:
  "我可以根据团队规则编辑 src/**"

队友检查权限:
  1. Edit("/src/main.ts")
  2. "src/main.ts" 匹配 "src/**"? 是
  3. 权限: 允许 (无需请求)

队友检查:
  1. Edit("/config/secrets.json")
  2. "config/secrets.json" 匹配 "src/**"? 否
  3. 权限: 询问负责人

2. Task 通知协议

所有团队成员在 task 变更时接收通知。

流程: Task 状态变更

队友更新:
  TaskUpdate({
    taskId: "1",
    status: "in_progress",
    owner: "frontend-agent"
  })

系统广播:
  通知所有队友:
  {
    type: "task_notification",
    taskId: "1",
    change: {
      status: { old: "pending", new: "in_progress" },
      owner: { old: null, new: "frontend-agent" }
    },
    timestamp: 1712000000000
  }

队友处理:
  1. 接收通知
  2. 更新本地 task 缓存
  3. 检查我的任何 task 是否现在解除阻塞
  4. 如果解除阻塞: 记录消息 "Task 2 现在可以开始"
  5. 可以立即认领: TaskUpdate(taskId: 2, in_progress)

示例级联:
  Task 1 完成
    → Task 2 解除阻塞 (被 1 阻塞)
    → Task 3 解除阻塞 (被 1 和 2 阻塞)
    → 多个队友现在可以开始工作

3. Session 重连协议

允许队友从断开连接中恢复。

流程: Session 恢复

队友 Session 活跃:
  Agent 在 tmux pane 中运行
  Session: "session-456"

连接丢失:
  (网络问题、终端关闭等)

负责人检测:
  1. 轮询团队 session 状态
  2. 检测: session-456 不再活跃
  3. 标记: 队友 "inactive"
  4. 日志: "frontend 在 2024-04-01 15:32 离线"

重连:
  1. 用户重连到 tmux pane
  2. 系统检测: 相同 session 恢复
  3. 进程: 仍在运行还是崩溃?
     → 如果崩溃: 重启
     → 如果运行: 恢复正常操作
  4. 标记: 队友 "active"
  5. 重放: 任何错过的消息 (权限更新、task 变更)

4. 邮箱消息协议

负责人和队友之间的通用消息传递系统。

消息结构

interface TeamMessage {
  id: string                 // 唯一消息 ID
  from: AgentId             // 发送者 agent ID
  to: AgentId               // 接收者 agent ID
  type: MessageType
  content: unknown          // 消息特定内容
  timestamp: number         // Unix ms
  acknowledged?: boolean    // 接收者已处理?
}

type MessageType =
  | "permission_request"    // 队友: 询问负责人
  | "permission_response"   // 负责人: 响应请求
  | "task_notification"     // 任何: task 变更
  | "status_update"         // 队友: 报告进度
  | "error_report"          // 队友: 报告失败
  | "instruction"           // 负责人: 指导队友
  | "question"              // 队友: 寻求指导
  | "acknowledgment"        // 任何: 确认收到

邮箱存储

~/.claude/teams/my-team/mailbox/

Frontend 邮箱:
  [
    {
      id: "msg-1",
      from: "lead",
      type: "task_notification",
      content: { taskId: "2", status: "unblocked" }
    },
    {
      id: "msg-2",
      from: "lead",
      type: "permission_response",
      content: { decision: "allow", reason: "..." }
    }
  ]

Backend 邮箱:
  [ ... ]

负责人没有个人邮箱,
而是通过轮询接收消息。

消息生命周期

1. 创建
   消息创建并写入接收者邮箱

2. 传递
   接收者轮询并读取邮箱
   → 消息加载到内存
   → 根据类型处理

3. 确认
   接收者标记为已处理
   → 从邮箱文件中删除
   → 释放磁盘空间

4. 归档 (可选)
   已处理的消息可以归档以保留历史

5. 执行同步协议

协调并行工作并防止冲突。

顺序约束: 阻塞的 Task

Task DAG:
  数据库 Schema → API 实现 → UI 集成

执行:
  时间 0:
    Frontend: TaskList() → 看到 Task 3 (被 2 阻塞)
    Backend: TaskList() → 看到 Task 2 (被 1 阻塞)
    Database: 认领 Task 1 → in_progress

  时间 5 分钟:
    Database: Task 1 完成
    → 发送通知: Task 1 已完成
    → Task 2 解除阻塞

    Backend: 接收通知
    → 更新本地 TaskList
    → Task 2 不再阻塞
    → 认领 Task 2 → in_progress

    Frontend: Task 3 仍被阻塞 (等待 Task 2)

  时间 15 分钟:
    Backend: Task 2 完成
    → 发送通知: Task 2 已完成
    → Task 3 解除阻塞

    Frontend: 接收通知
    → Task 3 现在可运行
    → 认领 Task 3 → in_progress

冲突预防: 文件锁定

场景: 两个队友尝试编辑同一文件

Frontend 尝试:
  Edit("/src/api.ts")
  1. 检查: 文件被锁定?
  2. 被锁定者: Backend
  3. 操作: 询问负责人
     "Backend 正在编辑 /src/api.ts, 我应该等待吗?"
  4. 负责人响应: "等待 backend 完成"
  5. Frontend: 等待或处理不同文件

Backend 完成:
  1. 释放锁
  2. 通知: "/src/api.ts 现在可用"

Frontend 恢复:
  1. 获取锁
  2. Edit 继续

通信渠道

1. 邮箱 (异步)

用于权限、task 变更、状态更新: - 非阻塞 - 持久化 (在断开连接后存活) - 由队友轮询 - 适用于: 决策、通知

2. WebSocket (同步, 可选)

用于实时协调: - 即时传递 - 需要连接 - 如果可用则使用 - 如果不可用则回退到邮箱

3. 共享 Task 列表 (最终一致性)

所有 agent 看到相同的 task 状态 (有轻微延迟): - 文件系统作为真实来源 - 锁定以保持一致性 - 写入者: TaskUpdateTool - 读取者: TaskListTool

协议示例

示例 1: Frontend 和 Backend 竞争

场景: Frontend 和 backend 都想编辑相同的 API 响应格式

时间 0:
  Frontend: "我将修改 API 响应以包含用户配置文件"
  Backend: "我将修改 API 响应以添加分页"

流程:
  1. Frontend 尝试: Edit("/src/api.ts")
     → 检查文件锁: 未锁定
     → 获取锁
     → Edit 继续

  2. Backend 尝试: Edit("/src/api.ts")
     → 检查文件锁: 被 Frontend 锁定
     → 发送权限请求: "我可以编辑吗?"
     → 负责人响应: "等待, frontend 正在编辑"
     → Backend: 暂时处理不同文件

  3. Frontend 完成编辑, 释放锁
     → 发送通知: "文件已释放"

  4. Backend 重试: Edit("/src/api.ts")
     → 检查文件锁: 未锁定
     → 获取锁
     → Edit 继续
     → 但现在与 frontend 的更改冲突!

  5. Backend 检测到冲突
     → 发送给负责人: "/src/api.ts 中的合并冲突"
     → 负责人: 审查两个更改, 决定合并策略
     → 负责人: 指导两个队友解决

示例 2: 权限边界跨越

场景: Backend 想编辑 frontend 文件 (通常不应该发生)

流程:
  1. Backend: "我需要修复 UI 组件"
     → Edit("/src/components/Header.tsx")

  2. 系统检查:
     → 本地规则: 拒绝 (backend 不能编辑 src/components)
     → 团队规则: 拒绝 (backend 不在路径允许列表中)

  3. 向负责人发送权限请求:
     {
       tool: "Edit",
       path: "/src/components/Header.tsx",
       reason: "需要更新 API 集成与 UI"
     }

  4. 负责人审查:
     → 需要 backend 专业知识? 是 (API 集成)
     → 为此文件授予临时权限

  5. 响应给 backend:
     {
       decision: "allow",
       reason: "API 集成更改需要 backend 知识",
       scope: "仅限 /src/components/Header.tsx"
     }

  6. Backend: Edit 继续
     → 进行必要的更改
     → 通知 frontend: "为 API 更新了 Header.tsx"

  7. Frontend 审查并批准
     → 集成成功

示例 3: 带依赖的并行工作

初始 Task 设置:
  Task A: "数据库 schema" (独立)
  Task B: "Backend API" (被 A 阻塞)
  Task C: "Frontend UI" (独立)
  Task D: "集成测试" (被 B, C 阻塞)

时间 0:
  Database: 认领 A → in_progress
  Frontend: 认领 C → in_progress
  Backend: Task B 被阻塞, 等待

时间 5:
  Database: Task A 完成 → 通知
  → Backend: 接收通知
  → Task B 解除阻塞!
  → Backend: 认领 B → in_progress

时间 10:
  Frontend: Task C 完成
  → Database 和 Backend 都在工作 (不需要)

时间 15:
  Backend: Task B 完成
  → Tester: 接收通知
  → Task D 解除阻塞 (A 和 C 都完成)
  → Tester: 认领 D → in_progress

时间 25:
  Tester: Task D 完成
  → 所有工作完成!

协议合规性

保证

保证: - 所有队友看到相同的 task 状态 (最终) - 权限决策一致 - 不会并发写入同一文件 - 消息按顺序传递

不保证: - 实时同步 (异步) - 即时消息传递 (依赖轮询) - 完美的冲突预防 (必须使用锁)

权衡

弹性优于一致性: - 队友可以离线工作 - 邮箱在断开连接后持久化 - 重连时赶上

简单性优于效率: - 基于文件的存储 (无数据库) - 轮询 (无复杂信号) - 人性化的冲突解决

实现细节

负责人-队友权限桥接

// leaderPermissionBridge.ts
function syncPermissionsToTeammate(lead, teammate) {
  // 1. 队友进行 tool 调用
  // 2. 检查: 这是否被允许?
  // 3. 本地规则: 首先应用
  // 4. 无匹配: 通过桥接查询负责人

  const leadDecision = await askLeadForPermission(tool, input)
  // 桥接查询负责人的权限状态
  // 返回: allow | deny | ask_user

  return leadDecision
}

Task 更新通知

// taskNotification.ts
function notifyTasksUpdated(taskId, changes) {
  // 1. Task 文件更新
  // 2. 系统检测: task 变更
  // 3. 广播给所有队友:
  //    - 每个邮箱中的消息
  //    - 本地 task 缓存失效
  //    - UI 刷新
}

邮箱轮询

// teammateMailbox.ts
async function pollMailbox(agentId) {
  // 每 5 秒:
  // 1. 检查此 agent 的邮箱文件
  // 2. 读取新消息
  // 3. 按类型处理:
  //    - task_notification → 更新 task 列表
  //    - permission_response → 解除阻塞等待的 tool
  //    - instruction → 执行负责人的指示
  // 4. 标记已处理的消息
  // 5. 从邮箱中删除
}

最佳实践

1. 清晰的责任边界

✅ 好:

{
  "frontend-agent": {
    "allowedPaths": ["src/components/**", "src/hooks/**"],
    "cannotEdit": ["src/api/**", "src/db/**"]
  }
}

❌ 坏:

{
  "all-agents": {
    "allowedPaths": ["**"],
    "cannotEdit": []
  }
}
// 无边界 = 冲突不可避免

2. 明确的 Task 依赖

✅ 好:

Task 1: "Schema 设计" (独立)
Task 2: "API 实现" (被 1 阻塞)
Task 3: "测试" (被 2 阻塞)

❌ 坏:

所有 task 独立
// 队友猜测顺序
// 返工风险

3. 定期同步检查

✅ 好:

团队负责人: 每次迭代轮询团队状态
→ 检查停滞的队友
→ 解决权限争议
→ 更新阻塞者

❌ 坏:

团队负责人: 设置后就忘记
// 队友卡住等待
// 问题累积

关键文件

文件 用途
src/utils/swarm/permissionSync.ts 权限协议
src/utils/swarm/teamHelpers.ts 团队工具
src/utils/swarm/leaderPermissionBridge.ts 负责人-队友桥接
src/utils/swarm/reconnection.ts 重连逻辑
src/utils/swarm/taskNotification.ts Task 通知
src/utils/teammateMailbox.ts 邮箱实现

另见