Replies: 4 comments
更新:Qwen Code 调研补充对 Qwen Code 的核心设计:LLM 驱动的工具通信Qwen Code 的理念是 LLM 驱动编排 — 所有 agent 间通信都通过 LLM 可见的工具完成,而非程序级通道。
|
| 模式 | 机制 | 适用场景 |
|---|---|---|
| Foreground (阻塞) | LLM 调用 agent 工具, 等待结果 |
诊断中派发检索 agent |
| Background (火忘) | 注册到 BackgroundTaskRegistry, 结果异步通知 |
销售助手慢脑检索 |
| Teammate (持久) | agent 工具的 name 参数创建, 持久驻留, 可接收多次 send_message |
翻译的术语 agent |
文件持久化的 Team 状态
~/.qwen/teams/{team}/
├── config.json # TeamFile (members 数组)
├── inboxes/
│ ├── leader.json # Leader 收件箱 (500ms 轮询)
│ └── {agent}.json # 各 teammate 收件箱
~/.qwen/tasks/{team}/
├── {task_id}.json # 独立任务文件, 带依赖图
双层并发锁: in-process Mutex + 跨进程 proper-lockfile。原子写入 (tmp+rename)。
共享任务板 (带依赖图 + 自动认领)
interface SwarmTask {
id: string
prompt: string
status: "pending" | "in_progress" | "completed" | "failed"
owner: string | null // IDLE teammate 自动 claim
blocks: string[] // 阻塞其他任务
blockedBy: string[] // 被其他任务阻塞
}- 完成时自动解除下游阻塞
- IDLE teammate 自动扫描并认领可用任务 (减少 Lead 编排负担)
Team 协议注入 (Prompt Addendum)
每个 teammate 的 system prompt 被注入协议指令,让 LLM 自主遵循:
1. 检查任务板 (task_list)
2. 认领并执行任务 (task_update → in_progress)
3. 完成后通过 send_message(to:"leader") 上报
4. 标记任务完成 (task_update → completed)
5. 回到步骤 1
关键技术细节
- 身份传播:
AsyncLocalStorage<TeammateIdentity>— per-async-context 身份解析 - Leader 轮询: 文件 inbox 每 500ms 轮询, 消息在下个 turn 注入 Leader 对话
- Teammate 消息: 直接走进程内优先级队列 (不经文件, 更快)
- 权限桥接: Teammate 工具审批请求路由到 Leader UI via
leaderPermissionBridge单例 - Stall 检测: 600 秒无活动 → 自动中止
- 最大 teammates: 10 个 (可配置)
对我们架构提案的修正
基于 Qwen Code 的发现,建议对原提案做以下修正:
修正 1: send_message 应为 LLM 可见工具
原提案: TeamMessageChannel 是程序级通道, Agent 不直接感知通信机制。
修正: 将 send_message 暴露为 LLM 可见工具, 让 LLM 自己决定何时向其他 agent 发消息。Qwen Code 证明了这种方式可行且灵活。
# 作为 PydanticAI 工具暴露给 Lead 和 Workers
async def send_message(
to: str, # teammate 名称或 "*" 广播
message: str, # 消息内容
message_type: str = "info", # info | escalation | result | shutdown_request
) -> str:
"""Send a message to a teammate or broadcast to all."""修正 2: 加入共享任务板
原提案: 无任务板, Lead 通过 dispatch_to_worker 显式派发。
修正: 加入带依赖图的任务板, 支持自动认领:
team:
tasks:
- id: ch3_translation
prompt: "翻译第3章"
blocked_by: [glossary_init] # 等术语表初始化完成
- id: glossary_init
prompt: "初始化术语表"
assignee: terminology_checker
- id: consistency_check
prompt: "全文一致性检查"
blocked_by: [ch1_translation, ch2_translation, ch3_translation]IDLE worker 自动认领未阻塞的任务, 减少 Lead 编排负担。
修正 3: 文件持久化优于纯内存
原提案: Blackboard 为内存 dict。
修正: Team 状态 (inbox, tasks, blackboard) 默认文件持久化, 可选内存模式用于短生命周期 team:
.omo/teams/{team_name}/
├── config.json # 角色定义 + 通信权限
├── inboxes/
│ ├── lead.json
│ └── {role}.json
├── tasks/
│ └── {task_id}.json
└── blackboard/
├── glossary.json
└── manual_outline.json
双层锁 (in-process asyncio.Lock + filelock) + 原子写入。翻译场景运行数小时也不丢数据。
修正 4: Team 协议通过 prompt 注入
原提案: 通过程序强制 workflow (dispatch → execute → report)。
修正: 在 teammate 的 system prompt 中注入团队协议, 让 LLM 自主遵循:
你是翻译团队的成员。工作流程:
1. 调用 task_list 查看可用任务
2. 调用 task_update 认领一个未阻塞的任务
3. 执行任务, 可调用 read_blackboard 读取共享上下文
4. 遇到问题调用 send_message(to:"lead", type:"escalation") 请求仲裁
5. 完成后调用 send_message(to:"lead", type:"result") 上报结果
6. 调用 task_update 标记任务完成
7. 回到步骤 1
修正 5: 消息优先级对齐
原提案: 用户输入 > 仲裁请求 > 后台推送
修正 (参考 Qwen Code): SHUTDOWN > 用户输入 > LEADER 消息 > PEER 消息 > 后台推送
class MessagePriority(IntEnum):
SHUTDOWN = 0 # 关闭指令, 最高优先
USER = 10 # 用户输入
LEADER = 20 # Lead → Worker 的指令
ESCALATION = 30 # Worker → Lead 的仲裁请求
PEER = 40 # Worker ↔ Worker 横向通信
BACKGROUND = 50 # 后台结果推送修正后的架构总览
┌──────────────────────────────────────────────────────────────────┐
│ Team Layer │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ Role Config │ │ Task Board │ │ Blackboard (file-based) │ │
│ │ (YAML) │ │ (file-based) │ │ glossary, outline, ... │ │
│ │ mode, perms │ │ deps, claim │ │ read-any, write-auth │ │
│ └──────┬───────┘ └──────┬───────┘ └───────────┬─────────────┘ │
│ │ │ │ │
│ ┌──────▼───────────────────▼───────────────────────▼──────────┐ │
│ │ LLM-Visible Communication Tools │ │
│ │ │ │
│ │ send_message(to, message, type) → Direct + Broadcast │ │
│ │ task_list() / task_create() / task_update() → Task Board │ │
│ │ read_blackboard(key) / write_blackboard(key, value) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────────▼─────────────────────────────────┐ │
│ │ Message Router + Priority Queue │ │
│ │ SHUTDOWN > USER > LEADER > ESCALATION > PEER > BACKGROUND │ │
│ │ Permission check (can_message) + routing │ │
│ └───────────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────────▼─────────────────────────────────┐ │
│ │ Lead Loop (extends RunHandle) │ │
│ │ │ │
│ │ while not closing: │ │
│ │ if msg := poll(priority=SHUTDOWN): handle_shutdown() │ │
│ │ elif msg := poll(priority=USER): handle_user() │ │
│ │ elif msg := poll(priority=ESCALATION): arbitrate() │ │
│ │ elif msg := poll(priority=BACKGROUND): inject_result() │ │
│ │ else: wait_for_any() │ │
│ └───────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
与原提案的变更汇总
| 组件 | 原提案 | 修正后 | 来源 |
|---|---|---|---|
| 通信方式 | 程序级 TeamMessageChannel |
LLM 可见 send_message 工具 |
Qwen Code |
| 任务管理 | 无 | 文件持久化任务板 + 依赖图 + 自动认领 | Qwen Code |
| 状态持久化 | 内存 Blackboard | 文件持久化 (inbox/tasks/blackboard) | Qwen Code + oh-my-openagent |
| 协议执行 | 程序强制 workflow | Prompt 注入, LLM 自主遵循 | Qwen Code |
| 消息优先级 | 用户 > 仲裁 > 后台 | SHUTDOWN > 用户 > LEADER > ESCALATION > PEER > 后台 | Qwen Code |
| Worker 工具 | dispatch/broadcast/read/write | send_message + task_list/create/update + read/write_blackboard | Qwen Code |
RFC-0055: Dynamic Team Mode — Proposal Summary基于前期的架构调研(8 框架对比 + Qwen Code/OMO 深入分析 + Oracle 架构验证),已生成完整 RFC: 一句话总结在 AgentPool 中新增 核心设计决策
架构概览graph TB
subgraph Existing["AgentPool 现有基础设施 (零改动)"]
SC["SessionController"] --> CS["Child Session"]
SP["SessionPool"] --> RH["RunHandle"]
RH --> MD["steer / followup"]
AR["AgentRegistry"] --> AD["Agent Definition"]
HC["HostContext → session_pool (已存在)"]
end
subgraph New["新增组件 (5 文件, ~6 行改动)"]
TS["TeamService Protocol<br/>4 methods"]
TS --> RLTS["RunLoopTeamService"]
TCC["TeamCommCapability"] --> TS
TCC --> FTS["FileTeamState"]
FTS --> Inbox["inbox"]
FTS --> Tasks["tasks + deps"]
FTS --> BB["blackboard + locks"]
TMC["TeamModeConfig"]
end
Existing -->|"复用"| New
4 方案对比
推荐方案镜像现有 工具 API通用工具 (所有成员): Lead 专属: 文件持久化结构变更量
实现计划 (4 阶段)
与现有机制共存
6 个开放问题
RFC 全文: 欢迎 review 和反馈。 |
|
@Leoyzen 我把 discussion #160 和 RFC-0055 的架构上下文整理到了一个独立的文档分支 分支包含:
PR 已创建:#172 我的目标是:把"局部方案"背后的"全局问题、约束、取舍"显性化,这样后续 review 不需要再反推意图。如果你方便,可以重点看一下:
期待反馈。 |
|
@Leoyzen 继续跟进一下 discussion #160 里关于 Dynamic Team 的设计思路。我和团队里做了一些讨论,从"假设技术债务已经还清"的角度推演了设计空间,整理出来想听听你的看法。这些不是建议现在重构 PR #168,而是作为远期演进方向的探讨。 核心观察:Agent 的统一视角目前 这个统一视角不是说"现在就应该合并 API",而是说它们可以共享同一套底层生命周期机制,对外仍保留各自的概念和 API。 这个视角带来的启发
关键抽象:地址地址不是 agent,不是进程,不是状态。地址是可路由的身份标识符。 是否保留地址,决定了一个 Agent 是:
这个概念可以解释为什么 subagent "用完就扔、无法继续对话",而 team member 可以多次通信。当前 RFC-0055 的 生命周期管理可以替代"常驻""常驻"不是本质,而是"保留地址 + 持久化状态 + 进程一直在线"的组合。如果拆开: lifecycle:
retain_address: true/false # 是否可被再次联系
retain_state: true/false # 是否保留状态
recoverable: true/false # 是否可休眠/唤醒
warm: true/false # 是否常驻进程
ttl: 300s # 空闲多久后释放
这个模型可以让 相关文档这些内容已经整理到 docs 分支(#172):
想和你探讨的问题
以上都是设计层面的探讨,不影响 PR #168 的当前实现。期待你的看法。 |
Uh oh!
There was an error while loading. Please reload this page.
Team Agent 架构设计: Lead-Worker + Peer 通信 + 共享 Blackboard
背景
基于对 7 个相关项目(pydantic-ai-harness、Hermes-Agent、OpenCode、oh-my-openagent、Zed、claw-code、DeerFlow)的调研(详见
docs/survey/multi-agent-orchestration/),AgentPool 当前的 Team 机制(graph 编译 + sequential/parallel 执行)覆盖了批量并行场景,但在以下场景中存在缺口:DelegationService是单向的(spawn → result),Worker 无法在运行中向 Lead 上报问题或请求仲裁RunHandle只接受用户输入,不接受 Worker 消息目标场景
场景 1: 工业诊断
场景 2: 手册级翻译系统
场景 3: 销售助手
提案:三层架构
第一层:角色定义 (Role Definition)
在现有
AgentConfig基础上增加 team 角色元数据:关键属性:
mode: persistent | ephemeral— 控制生命周期can_message— 通信权限白名单, 减少 noisebroadcasts/subscribes— 发布订阅模式pool: true— 标记可批量实例化第二层:通信通道 (Communication Channels)
三种通道类型:
1. Direct Channel (点对点)
2. Broadcast Channel (发布订阅)
3. Blackboard (共享状态)
第三层:Lead Agent 运行循环
扩展
RunHandle为TeamLeadRunLoop, 增加多优先级输入:与 AgentPool 现状的映射
AgentConfig(YAML)RoleConfig(mode/pool/can_message/broadcasts)DelegationService.spawn_subagent()(单向)TeamMessageChannel(双向, 带优先级)BroadcastChannel(复用 EventBus)Blackboard(读写权限)RunHandle(用户输入 only)TeamLeadRunLoop(用户 + Worker 双输入)BaseTeam._execute_parallel()EscalationMessage+ Lead 仲裁处理steer()(用户消息)background_inject()(Worker 结果)可复用基础设施
EventBus→ Broadcast Channel 底层SessionPool→ 管理 Worker sessionsBaseTeam._execute_parallel()→ 批量 Worker 执行RunHandle.steer()→ 后台结果注入基础AbstractCapability→ Worker 工具/指令注入需要新建的组件
TeamMessageChannel— 类型化消息通道 (Direct + Escalation)Blackboard— 共享状态服务 (读写权限控制)TeamLeadRunLoop— 扩展 RunHandle 的多输入循环RoleConfig— 角色定义模型 (mode, pool, can_message, broadcasts)待讨论的设计决策
can_message白名单限制?graph:YAML 语法, 还是作为补充? 现有 graph 适合静态拓扑, 新机制适合动态通信dispatch_to_worker,broadcast_to_team,read_blackboard,write_blackboard,arbitrate)调研参考
详细调研文档在
docs/survey/multi-agent-orchestration/目录下, 包含:特别相关的借鉴:
All reactions