# Agent Teams 设计文档 (L1330) > 状态: **MVP 已交付** (2026-04-16, 5 commits) > TODO.md 对应条目: `L1330 engine/team.go + inbox/ - 接线 Agent Teams 模式` > Anthropic 对标: Claude Code Agent Teams v2.1.32 (2026-02-05 研究预览版) ## 目标 让 Flyto 引擎支持多 Agent 之间的 **peer-to-peer 通讯** 和 **共享任务清单** 协作, 实现 Anthropic Claude Code Agent Teams 研究预览中的核心能力, 但不 照搬其研究阶段保守决策, 坚持"领域无关 Agent 引擎"定位. ## 架构总览 ``` ┌────────────────────────┐ │ engine.Team (协调者) │ │ router / TaskList │ └────────────┬───────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ Leader Engine │ │ Worker A │ │ Worker B │ │ incomingInbox │ │ SubAgent │ │ SubAgent │ │ = "leader" │ │ inbox.ID=A │ │ inbox.ID=B │ └──────┬────────┘ └──────┬────────┘ └──────┬────────┘ │ │ │ └────── router ────┴──── messages ───┘ (inbox.Router) 共享任务清单: ┌─────────────────────────────────────────────────────┐ │ tasklist.TaskList (业务层: Add/Claim/Complete 状态机) │ │ ↓ │ │ tasklist.Store (存储层, 多实现) │ │ - MemoryStore (默认, 零外部依赖) │ │ - MarkdownStore (Anthropic Claude Code 互操作) │ │ - CustomStore (消费层: DB / Redis / WMS / HIPAA) │ └─────────────────────────────────────────────────────┘ ``` ## 决策对照表 (vs. Anthropic Claude Code v2.1.32) | Anthropic 特性 | Flyto 决策 | 原因 | |---------------|-----------|------| | Mailbox 消息格式 (from/to/type/content) | **保留** | 原生 `inbox.Message` 字段逐项对应 (`Router.Send ↔ SendMessage`), 通用模式, 跨行业中立 | | Teammates 独立 context window | **保留** | SubAgent 已有独立 context, 金融/医疗场景天然需要隔离 | | shared task list (markdown 文件) | **升华**: 抽象成 Store 接口, Markdown 是默认实现之一 | Markdown 本身通用 (Notion/Confluence/法律草稿也用); 但 file locking + 硬编码路径对医疗 HIPAA / 金融审计有害. 接口化后编程客户互操作 Anthropic, 合规行业换 Store 实现 | | TaskCreated / TaskCompleted / TeammateIdle hooks (shell) | **升华**: 复用 `flyto.EventObserver` 统一事件总线 | Observer 是 hook 的真超集 (可跑 shell 也可跑 Go 逻辑 / 审计 DB / Slack 通知); 新增 hook 系统等于架构回退 L1326 收敛 | | `send_message` mailbox 原语 | **升华**: 作为内置工具 (非"让模型学着写文件到 mailbox 目录") | 模型 tool calling 原生支持; Qwen / MiniMax / Gemini 都能直接用, 不依赖模型理解文件系统 | | 消息 ID (UUID) | **升华**: 纳秒时间戳 + 4 字节随机 hex | 时间戳前缀自带时序, 调试日志一眼排序; 金融审计场景天然需要时序 | | `FLYTO_EXPERIMENTAL_AGENT_TEAMS=1` env flag | **拒绝** | Anthropic 研究阶段保守; Flyto 不假设运维场景 (医院 IT / 银行运维不会 ssh 改 env) | | `no nested teams / lead fixed / no session resumption` 限制 | **拒绝** | 研究阶段保守决策; 供应链 "总装→子装→零件" / 大型组织 "部门→小组" 天然嵌套; 照抄等于主动砍掉企业场景 | | 三个独立 shell hook | **拒绝** | 和"升华 Observer"重复, 避免两套 hook 系统并存 | | File locking 作为唯一并发原语 | **拒绝 (作为唯一)** | Markdown 实现用 flock, 但 Store 接口允许 DB 事务 / Redis MULTI 等 | ## 核心 API ### Engine 级别 ```go type Config struct { // ... AgentName string // 此 Engine 的身份名 ("" = 不参与 Teams) IncomingInbox inbox.Inbox // peer 消息收件入口 ("" = 不参与) } type Engine struct { // 内部字段: agentName string incomingInbox inbox.Inbox } ``` `Engine.runLoop` 每轮开始 `Poll` `incomingInbox`, 收到的消息包装成 `` XML 注入对话流, 同时发 `TeammateMessageReceivedEvent` 给 Observer. ### Team 级别 ```go type TeamConfig struct { LeaderEngine *Engine PermissionHandler PermissionHandler SharedTaskList *tasklist.TaskList // 可选, 共享任务板 } func NewTeam(cfg TeamConfig) *Team { // 自动布线 Leader.incomingInbox = router.Inbox("leader") // 自动设置 Leader.agentName = "leader" (如未设置) } // 把发件身份注入 ctx, Leader Engine.Run(ctx, ...) 后可用 send_message 工具 func (t *Team) ContextForLeader(ctx context.Context) context.Context ``` ### 内置工具 | 工具 | 用途 | 权限默认 | |------|------|---------| | `send_message` | Worker/Leader 向同伴投递消息 | AutoApprove (Team 内信任) | | `add_shared_task` | 发布新任务到共享清单 | AutoApprove | | `list_shared_tasks` | 查看当前任务板 (可按 status 过滤) | ReadOnly | | `claim_shared_task` | 认领 Pending 任务 | AutoApprove | | `complete_shared_task` | 标记任务完成附结果 | AutoApprove | 非 Team 场景 (ctx 无 sender/provider) 调用这些工具返回错误, 对 SDK 零副作用. ## 使用示例 ### 最简场景: peer-to-peer 对话 ```go team := engine.NewTeam(engine.TeamConfig{ LeaderEngine: leaderEngine, }) ctx := team.ContextForLeader(context.Background()) ch := leaderEngine.Run(ctx, "和 reviewer-agent 讨论这段代码") ``` Leader 在对话中可调 `send_message(to="reviewer", content="...")`, 消息送达 `reviewer` 的 `incomingInbox`, reviewer 下一轮对话自然读到. ### 带共享任务清单 ```go store := tasklist.NewMarkdownStore("/tmp/team-tasks.md") list := tasklist.New(store) defer list.Close() team := engine.NewTeam(engine.TeamConfig{ LeaderEngine: leaderEngine, SharedTaskList: list, }) ctx := team.ContextForLeader(context.Background()) // Leader 可调 add_shared_task / list_shared_tasks / // claim_shared_task / complete_shared_task ``` ### 跨行业: 自定义 Store ```go // 金融合规场景 import "mycorp/storage/audit" auditStore := audit.NewPostgresTaskStore(db) list := tasklist.New(auditStore) team := engine.NewTeam(engine.TeamConfig{ LeaderEngine: leaderEngine, SharedTaskList: list, }) ``` 只要 `audit.NewPostgresTaskStore` 实现 `tasklist.Store` 接口四方法 (Get/CAS/List/Close), 引擎层零改动. ## 跨行业场景三例 ### 金融 (风控会审) ``` Leader: "评估 AAPL 买入 10000 股, 价 $180" ↓ send_message to=risk-analyst risk-analyst: "VaR=2.3%, 超过 2% 阈值, 建议拒绝" ↓ send_message to=compliance compliance: "合规合规, 仅反转风险; 建议降至 5000 股重测" ↓ 回报 Leader Leader: 调整建议, add_shared_task 记录决策供审计 ``` Store 选择: `CustomStore` 连 PostgreSQL `audit_trades` 表. ### 医疗 (会诊) ``` Primary-doctor: "患者 X 胸痛, 心电图 ST 段抬高" ↓ send_message to=cardiologist cardiologist: "急性心梗可能, 建议立即冠脉造影" ↓ send_message to=pharmacist pharmacist: "患者对阿司匹林过敏, 换氯吡格雷" ↓ add_shared_task "冠脉造影 + 氯吡格雷准备" ``` Store 选择: `CustomStore` 连 HIPAA 加密存储. ### 仓储 (波次调度) ``` Dispatcher: list_shared_tasks (status=pending) → 找到 "波次 W2026-01-001 待分配" claim_shared_task ↓ send_message to=picker-03 picker-03: 完成拣货, complete_shared_task (result=货物已集结) ↓ Dispatcher 看到, 启动下一波次 ``` Store 选择: `CustomStore` 连 WMS DB (波次表集成). ## 运行示例 ```bash cd core/ go run ./examples/agent_teams/debate # peer-to-peer 辩论 go run ./examples/agent_teams/tasklist_markdown # Anthropic 互操作 go run ./examples/agent_teams/tasklist_custom # 跨行业接入模板 ``` ## 竞品对比 (LangGraph / CrewAI / AutoGen / Anthropic 等) 详见配套文档 [agent_teams_competitive.md](agent_teams_competitive.md), 含: - 7 大主流方案核心维度对比表 - Flyto vs Anthropic 优缺点细节 - Flyto vs LangGraph / CrewAI 真正生态对手分析 - 跨行业通用性评分 (Flyto 综合 5 星) - 销售 / onboarding 话术参考 ## 测试覆盖 - `pkg/inbox/*_test.go`: 原 P0 覆盖 (message / router / memory / uds) - `pkg/tasklist/tasklist_test.go`: 业务层 + MemoryStore, 含并发 Claim 争抢 - `pkg/tasklist/markdown_store_test.go`: MarkdownStore, 含跨实例持久化 / round-trip / 并发 flock / 手写格式导入 所有测试 `go test ./...` 在 C5 交付时为绿. ## 迁移指南 (Anthropic Claude Code → Flyto) | Anthropic Claude Code | Flyto 对应 | |----------------------|----------| | `~/.claude/teams/{name}/tasks.md` | `tasklist.NewMarkdownStore(path)` | | `TeammateIdle` shell hook | `Observer.Event("teammate_idle", ...)` 订阅 | | `FLYTO_EXPERIMENTAL_AGENT_TEAMS=1` | 不需要 (默认启用) | | `claude code teams create` CLI | `engine.NewTeam(TeamConfig{...})` | ## 将来扩展 (等真实客户需求驱动, 不预先设计) - `fsnotify.Watcher` 实时监听 tasks.md 变化 (当前 Store 接口无 Watch 方法, 未阻塞 MVP) - Cross-machine Agent Teams (通过 Redis/NATS Inbox 实现, MemoryInbox 是接口之一) - Self-claim 重入策略 (失败任务如何允许别的 Worker 重试) - Task 嵌套 (parent/child 关系) - 优先级 / 截止时间字段 ## 历史背景 - 2026-02-05: Anthropic 发布 Claude Code Agent Teams research preview - 2026-04-14: Flyto session 发现 `engine.Team.router` 字段构造但未使用, 初判 dead code 建议删除; 后经核实是前一棒工程师的"前瞻性预留", 路径 订正后登记 P2 接线 TODO. - 2026-04-16: L1330 MVP 交付 (本文档涵盖的 5 个 commit): - C1 f7f75a3 耳朵+嘴巴 (Engine incoming inbox + send_message 工具) - C2 2928316 TaskList 业务层 + MemoryStore + 4 工具 - C3 b573019 MarkdownStore + Anthropic 兼容测试 - C4 1318b37 三个跨行业 example - C5 (本 commit) 文档 + TODO 对账