Kanban 多 Agent 协作:Hermes Kanban 板 + 多个 Profile Agent 并行处理
任务分解 → 智能分配 → 并行执行 → 自动完成 = 敏捷级多 Agent 协作系统
简介
在软件开发团队中,Kanban 看板是一种被广泛验证的任务管理方法。它通过可视化的卡片流转,让团队清晰地看到每个任务的状态、瓶颈和进度。
如果我们将这套方法应用到多 Agent 系统中呢?
答案是:Hermes Kanban 多 Agent 协作系统——Hermes 作为 Scrum Master,维护一个 Kanban 看板,将复杂任务分解为子任务卡片,分配给不同专业角色的 Profile Agent,并行处理,自动流转,最终汇聚成果。
本文将详细讲解如何实现这套系统,让多个 Agent 像一支高效的敏捷开发团队一样协作。
一、Kanban 多 Agent 协作理念
1.1 从人类团队到 Agent 团队
┌─────────────────────────────────────────────────────────────┐
│ 人类敏捷团队 vs Agent 团队 │
│ │
│ 人类团队: │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ PM │ │ 前端 │ │ 后端 │ │ 测试 │ │
│ │ 拆解任务│ │ 写UI │ │ 写API │ │ 写用例 │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │
│ Agent 团队: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Hermes (Scrum Master) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────┐ │ │
│ │ │ Kanban板 │ │ 任务分配器│ │ 进度监控器│ │汇总器│ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └─────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ┌────┴────┐ ┌─────┴─────┐ ┌────┴────┐ ┌────┴────┐ │
│ │PM Agent │ │Frontend │ │Backend │ │Test │ │
│ │分析需求 │ │Agent │ │Agent │ │Agent │ │
│ └─────────┘ └───────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────┘1.2 Agent Profile 角色定义
| 角色 | Profile Agent | 职责 | 工具集 |
|---|---|---|---|
| PM Agent | pm-analyst |
需求分析、任务拆解、优先级排序 | 思维导图、Jira API |
| 架构 Agent | architect |
技术方案设计、接口定义 | UML、架构图生成 |
| 前端 Agent | frontend-dev |
UI/UX 实现、组件开发 | 代码生成、浏览器预览 |
| 后端 Agent | backend-dev |
API 开发、数据库设计 | 代码生成、数据库工具 |
| 测试 Agent | qa-engineer |
测试用例编写、自动化测试 | 测试框架、覆盖率工具 |
| 运维 Agent | devops-engineer |
部署配置、CI/CD 设置 | Docker、K8s 工具 |
| 文档 Agent | tech-writer |
API 文档、用户手册 | Markdown、文档生成 |
二、Hermes Kanban 板实现
2.1 Kanban 数据结构
# hermes/kanban/models.py
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional
from datetime import datetime
import uuid
class TaskStatus(str, Enum):
BACKLOG = "backlog" # 待办
TODO = "todo" # 待处理
IN_PROGRESS = "in_progress" # 进行中
REVIEW = "review" # 审查中
DONE = "done" # 已完成
BLOCKED = "blocked" # 阻塞
class TaskPriority(str, Enum):
CRITICAL = "P0"
HIGH = "P1"
MEDIUM = "P2"
LOW = "P3"
class AgentProfile(str, Enum):
PM = "pm-analyst"
ARCHITECT = "architect"
FRONTEND = "frontend-dev"
BACKEND = "backend-dev"
QA = "qa-engineer"
DEVOPS = "devops-engineer"
WRITER = "tech-writer"
@dataclass
class KanbanCard:
"""看板卡片"""
card_id: str = field(default_factory=lambda: f"CARD-{uuid.uuid4().hex[:8]}")
title: str = ""
description: str = ""
status: TaskStatus = TaskStatus.BACKLOG
priority: TaskPriority = TaskPriority.MEDIUM
assigned_to: Optional[AgentProfile] = None
parent_card: Optional[str] = None
sub_cards: list[str] = field(default_factory=list)
dependencies: list[str] = field(default_factory=list)
created_at: datetime = field(default_factory=datetime.utcnow)
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
output: str = ""
output_artifacts: list[str] = field(default_factory=list)
effort_estimate: int = 0 # 故事点
actual_effort: int = 0
retry_count: int = 0
max_retries: int = 3
tags: list[str] = field(default_factory=list)
metadata: dict = field(default_factory=dict)
def to_dict(self) -> dict:
return {
"card_id": self.card_id,
"title": self.title,
"description": self.description,
"status": self.status.value,
"priority": self.priority.value,
"assigned_to": self.assigned_to.value if self.assigned_to else None,
"parent_card": self.parent_card,
"sub_cards": self.sub_cards,
"dependencies": self.dependencies,
"created_at": self.created_at.isoformat(),
"started_at": self.started_at.isoformat() if self.started_at else None,
"completed_at": self.completed_at.isoformat() if self.completed_at else None,
"output": self.output[:500] if self.output else "",
"output_artifacts": self.output_artifacts,
"effort_estimate": self.effort_estimate,
"actual_effort": self.actual_effort,
"retry_count": self.retry_count,
"tags": self.tags,
}
@dataclass
class KanbanBoard:
"""看板"""
board_id: str = field(default_factory=lambda: f"BOARD-{uuid.uuid4().hex[:6]}")
name: str = ""
description: str = ""
cards: dict[str, KanbanCard] = field(default_factory=dict)
wip_limits: dict[TaskStatus, int] = field(default_factory=lambda: {
TaskStatus.IN_PROGRESS: 5,
TaskStatus.REVIEW: 3,
})
created_at: datetime = field(default_factory=datetime.utcnow)
@property
def columns(self) -> dict[TaskStatus, list[KanbanCard]]:
"""按状态分列"""
cols = {status: [] for status in TaskStatus}
for card in self.cards.values():
cols[card.status].append(card)
# 每列按优先级排序
for status in cols:
cols[status].sort(key=lambda c: TaskPriority[c.priority])
return cols
@property
def is_complete(self) -> bool:
"""所有任务是否完成"""
return all(
c.status == TaskStatus.DONE
for c in self.cards.values()
)
@property
def progress(self) -> float:
"""完成进度"""
if not self.cards:
return 0.0
done = sum(1 for c in self.cards.values() if c.status == TaskStatus.DONE)
return done / len(self.cards) * 1002.2 Kanban 看板管理器
# hermes/kanban/manager.py
import asyncio
import json
from typing import Optional, Callable
class KanbanManager:
"""Hermes Kanban 看板管理器"""
def __init__(self, name: str = "Agent Sprint"):
self.board = KanbanBoard(name=name)
self.agent_handlers: dict[AgentProfile, Callable] = {}
self.event_log: list[dict] = []
self._subscribers: list[Callable] = []
def register_agent(self, profile: AgentProfile, handler: Callable):
"""注册 Agent 处理器"""
self.agent_handlers[profile] = handler
self._log_event("agent_registered", {
"profile": profile.value,
"handler": handler.__name__,
})
def add_card(self, card: KanbanCard) -> str:
"""添加卡片到看板"""
self.board.cards[card.card_id] = card
self._log_event("card_added", card.to_dict())
return card.card_id
def move_card(self, card_id: str, new_status: TaskStatus):
"""移动卡片到新状态"""
if card_id not in self.board.cards:
raise ValueError(f"卡片 {card_id} 不存在")
card = self.board.cards[card_id]
# 检查 WIP 限制
if new_status in self.board.wip_limits:
current_count = sum(
1 for c in self.board.cards.values()
if c.status == new_status
)
if current_count >= self.board.wip_limits[new_status]:
self._log_event("wip_limit_reached", {
"status": new_status.value,
"limit": self.board.wip_limits[new_status],
})
return False
old_status = card.status
card.status = new_status
if new_status == TaskStatus.IN_PROGRESS:
card.started_at = datetime.utcnow()
elif new_status == TaskStatus.DONE:
card.completed_at = datetime.utcnow()
self._log_event("card_moved", {
"card_id": card_id,
"from": old_status.value,
"to": new_status.value,
})
# 通知订阅者
self._notify_subscribers("card_moved", card)
return True
def get_ready_tasks(self, profile: AgentProfile) -> list[KanbanCard]:
"""获取某个 Agent 可以处理的任务"""
ready = []
for card in self.board.cards.values():
# 状态为 TODO 且分配给该 Agent
if card.status == TaskStatus.TODO and card.assigned_to == profile:
# 检查依赖
deps_met = all(
self.board.cards[dep_id].status == TaskStatus.DONE
for dep_id in card.dependencies
if dep_id in self.board.cards
)
if deps_met:
ready.append(card)
return ready
async def execute_card(self, card: KanbanCard) -> KanbanCard:
"""执行卡片任务"""
if card.assigned_to not in self.agent_handlers:
raise ValueError(f"Agent {card.assigned_to} 未注册")
handler = self.agent_handlers[card.assigned_to]
self.move_card(card.card_id, TaskStatus.IN_PROGRESS)
try:
# 调用 Agent 处理器
result = await handler(card)
card.output = result.get("output", "")
card.output_artifacts = result.get("artifacts", [])
card.actual_effort = result.get("effort", 0)
# 移动到审查
self.move_card(card.card_id, TaskStatus.REVIEW)
self._log_event("card_executed", card.to_dict())
return card
except Exception as e:
card.retry_count += 1
if card.retry_count >= card.max_retries:
self.move_card(card.card_id, TaskStatus.BLOCKED)
self._log_event("card_blocked", {
"card_id": card.card_id,
"error": str(e),
"retries": card.retry_count,
})
else:
self.move_card(card.card_id, TaskStatus.TODO)
raise
def display_board(self) -> str:
"""生成看板文本视图"""
lines = [
f"╔══════════════════════════════════════════════════════╗",
f"║ {self.board.name:^52} ║",
f"║ 进度: {self.board.progress:.0f}% "
f"卡片: {len(self.board.cards)} ║",
f"╠══════════════════════════════════════════════════════╣",
]
status_names = {
TaskStatus.BACKLOG: "📋 待办",
TaskStatus.TODO: "📝 待处理",
TaskStatus.IN_PROGRESS: "🔄 进行中",
TaskStatus.REVIEW: "🔍 审查中",
TaskStatus.DONE: "✅ 已完成",
TaskStatus.BLOCKED: "🚫 阻塞",
}
columns = self.board.columns
max_cards = max(len(cards) for cards in columns.values()) or 1
for row in range(max_cards + 2):
line = "║"
for status in TaskStatus:
cards = columns[status]
width = 14
if row == 0:
line += f" {status_names[status]:^{width}} │"
elif row == 1:
limit = self.board.wip_limits.get(status, "∞")
line += f" {'─' * width} │"
elif row - 2 < len(cards):
card = cards[row - 2]
priority_icon = {"P0": "🔴", "P1": "🟠", "P2": "🟡", "P3": "🟢"}
icon = priority_icon.get(card.priority, "⚪")
label = f"{icon} {card.title[:10]}"
line += f" {label:<{width}} │"
else:
line += f" {' ' * width} │"
lines.append(line)
lines.append("╚══════════════════════════════════════════════════════╝")
return "\n".join(lines)
def _log_event(self, event_type: str, details: dict):
"""记录事件"""
self.event_log.append({
"timestamp": datetime.utcnow().isoformat(),
"event": event_type,
"details": details,
})
def _notify_subscribers(self, event: str, card: KanbanCard):
"""通知订阅者"""
for sub in self._subscribers:
try:
sub(event, card)
except Exception:
pass
def subscribe(self, callback: Callable):
"""订阅看板事件"""
self._subscribers.append(callback)
def export_board(self) -> dict:
"""导出看板数据"""
return {
"board_id": self.board.board_id,
"name": self.board.name,
"created_at": self.board.created_at.isoformat(),
"progress": self.board.progress,
"cards": {cid: c.to_dict() for cid, c in self.board.cards.items()},
"event_log": self.event_log[-50:], # 最近 50 条
}三、Profile Agent 实现
3.1 基础 Agent Profile
# hermes/kanban/profiles/base.py
from abc import ABC, abstractmethod
from typing import Any
class AgentProfile(ABC):
"""Agent Profile 基类"""
def __init__(self, name: str, tools: list[str] = None):
self.name = name
self.tools = tools or []
self.system_prompt = self._build_system_prompt()
@abstractmethod
def _build_system_prompt(self) -> str:
"""构建系统提示词"""
pass
@abstractmethod
async def handle_task(self, card: KanbanCard) -> dict:
"""处理看板任务"""
pass
class PMAgent(AgentProfile):
"""产品经理 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深产品经理,擅长需求分析和任务拆解。
你的职责:
1. 理解用户需求,明确功能边界
2. 将大需求拆解为可执行的子任务
3. 评估每个任务的优先级和复杂度
4. 定义验收标准
输出格式:JSON,包含 tasks 列表,每个任务有 title、description、priority、effort、assignee。"""
async def handle_task(self, card: KanbanCard) -> dict:
# 模拟需求分析
tasks = self._breakdown_requirement(card.description)
return {
"output": json.dumps(tasks, ensure_ascii=False, indent=2),
"artifacts": ["requirements.md", "task_breakdown.json"],
"effort": len(tasks),
"sub_tasks": tasks,
}
def _breakdown_requirement(self, requirement: str) -> list[dict]:
"""拆解需求为子任务"""
# 实际实现中会调用 LLM
return [
{"title": "需求文档", "desc": "编写详细需求文档",
"priority": "P0", "effort": 3, "assignee": "pm-analyst"},
{"title": "技术方案", "desc": "设计系统架构和接口",
"priority": "P0", "effort": 5, "assignee": "architect"},
{"title": "数据库设计", "desc": "设计数据库 Schema",
"priority": "P1", "effort": 3, "assignee": "backend-dev"},
{"title": "前端页面", "desc": "实现用户界面",
"priority": "P1", "effort": 8, "assignee": "frontend-dev"},
{"title": "后端 API", "desc": "实现业务逻辑接口",
"priority": "P1", "effort": 8, "assignee": "backend-dev"},
{"title": "测试用例", "desc": "编写测试用例并执行",
"priority": "P2", "effort": 5, "assignee": "qa-engineer"},
{"title": "部署配置", "desc": "配置 CI/CD 和部署环境",
"priority": "P2", "effort": 3, "assignee": "devops-engineer"},
{"title": "文档编写", "desc": "编写 API 文档和用户手册",
"priority": "P3", "effort": 3, "assignee": "tech-writer"},
]
class ArchitectAgent(AgentProfile):
"""架构师 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深系统架构师,擅长技术方案设计。
你的职责:
1. 根据需求设计系统架构
2. 定义 API 接口和数据结构
3. 选择合适的技术栈
4. 输出架构图和技术文档"""
async def handle_task(self, card: KanbanCard) -> dict:
return {
"output": "架构设计完成:微服务架构,3 个核心服务",
"artifacts": ["architecture.md", "api_spec.yaml", "db_schema.sql"],
"effort": 5,
}
class FrontendAgent(AgentProfile):
"""前端开发 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深前端开发工程师,擅长 React/Vue 开发。
你的职责:
1. 根据设计稿实现页面
2. 编写可复用的组件
3. 确保响应式设计和可访问性
4. 编写单元测试"""
async def handle_task(self, card: KanbanCard) -> dict:
return {
"output": "前端页面开发完成:登录页、仪表盘、设置页",
"artifacts": ["src/App.tsx", "src/components/", "src/pages/"],
"effort": 8,
}
class BackendAgent(AgentProfile):
"""后端开发 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深后端开发工程师,擅长 Python/FastAPI 开发。
你的职责:
1. 根据 API 规范实现接口
2. 编写数据库模型和迁移
3. 实现业务逻辑和权限控制
4. 编写集成测试"""
async def handle_task(self, card: KanbanCard) -> dict:
return {
"output": "后端 API 开发完成:12 个端点,数据库迁移",
"artifacts": ["app/api/", "app/models/", "migrations/"],
"effort": 8,
}
class QAAgent(AgentProfile):
"""测试工程师 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深 QA 工程师,擅长自动化测试。
你的职责:
1. 编写测试用例
2. 执行单元测试、集成测试、E2E 测试
3. 生成测试报告
4. 发现并记录 Bug"""
async def handle_task(self, card: KanbanCard) -> dict:
return {
"output": "测试完成:通过 45/48 用例,3 个 Bug 已修复",
"artifacts": ["tests/", "coverage_report.html"],
"effort": 5,
}
class DevOpsAgent(AgentProfile):
"""运维工程师 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深 DevOps 工程师,擅长容器化和 CI/CD。
你的职责:
1. 编写 Dockerfile 和 docker-compose
2. 配置 CI/CD 流水线
3. 设置监控和告警
4. 编写部署文档"""
async def handle_task(self, card: KanbanCard) -> dict:
return {
"output": "部署配置完成:Docker + K8s + CI/CD",
"artifacts": ["Dockerfile", "docker-compose.yml", ".github/workflows/"],
"effort": 3,
}
class TechWriterAgent(AgentProfile):
"""技术文档工程师 Agent"""
def _build_system_prompt(self) -> str:
return """你是一位资深技术文档工程师。
你的职责:
1. 编写 API 文档
2. 编写用户使用手册
3. 编写部署指南
4. 维护 Changelog"""
async def handle_task(self, card: KanbanCard) -> dict:
return {
"output": "文档编写完成:API 文档、用户手册、部署指南",
"artifacts": ["docs/api.md", "docs/user-guide.md", "CHANGELOG.md"],
"effort": 3,
}四、Kanban 协作引擎
4.1 协作引擎实现
# hermes/kanban/engine.py
import asyncio
from datetime import datetime
class KanbanEngine:
"""Kanban 协作引擎"""
def __init__(self, manager: KanbanManager):
self.manager = manager
self.agents: dict[AgentProfile, AgentProfile] = {}
def register_agent(self, profile: AgentProfile, handler):
"""注册 Agent"""
self.agents[profile] = handler
self.manager.register_agent(profile, handler)
async def run_sprint(self) -> dict:
"""运行一个 Sprint"""
print(f"\n{'='*60}")
print(f"🚀 Sprint 开始: {self.manager.board.name}")
print(f"{'='*60}\n")
iteration = 0
max_iterations = 50 # 防止无限循环
while not self.manager.board.is_complete and iteration < max_iterations:
iteration += 1
print(f"\n--- 迭代 {iteration} ---")
print(self.manager.display_board())
# 获取所有可执行的任务
tasks_to_run = []
for profile in AgentProfile:
if profile in self.agents:
ready = self.manager.get_ready_tasks(profile)
tasks_to_run.extend(ready)
if not tasks_to_run:
# 检查是否全部完成
if self.manager.board.is_complete:
break
# 检查是否有阻塞
blocked = [
c for c in self.manager.board.cards.values()
if c.status == TaskStatus.BLOCKED
]
if blocked:
print(f"\n⚠️ 阻塞任务: {[c.card_id for c in blocked]}")
# 尝试解除阻塞
for card in blocked:
self.manager.move_card(card.card_id, TaskStatus.TODO)
card.retry_count = 0
continue
# 还有未完成但不在 TODO 状态的任务
pending = [
c for c in self.manager.board.cards.values()
if c.status not in (TaskStatus.DONE, TaskStatus.TODO)
]
if pending:
await asyncio.sleep(0.5) # 等待进行中的任务完成
continue
break
# 并行执行任务
coroutines = []
for card in tasks_to_run:
handler = self.agents[card.assigned_to]
coroutines.append(self.manager.execute_card(card))
if coroutines:
results = await asyncio.gather(*coroutines, return_exceptions=True)
# 处理审查 -> 自动通过
for card, result in zip(tasks_to_run, results):
if isinstance(result, KanbanCard):
self.manager.move_card(card.card_id, TaskStatus.DONE)
print(f" ✅ {card.title} 已完成")
elif isinstance(result, Exception):
print(f" ❌ {card.title} 执行失败: {result}")
# 生成 Sprint 报告
report = self._generate_sprint_report()
print(f"\n{'='*60}")
print("📊 Sprint 完成!")
print(f"{'='*60}")
print(report)
return self.manager.export_board()
def _generate_sprint_report(self) -> str:
"""生成 Sprint 报告"""
board = self.manager.board
lines = [
f"📋 Sprint 报告: {board.name}",
f"总任务数: {len(board.cards)}",
f"完成进度: {board.progress:.0f}%",
f"",
f"按状态分布:",
]
for status, cards in board.columns.items():
if cards:
lines.append(f" {status.value}: {len(cards)} 个任务")
total_effort = sum(c.actual_effort for c in board.cards.values())
lines.append(f"\n总工作量: {total_effort} 故事点")
lines.append(f"\n产出物:")
for card in board.cards.values():
if card.output_artifacts:
lines.append(f" {card.title}: {', '.join(card.output_artifacts)}")
return "\n".join(lines)4.2 实战演示:完整 Sprint
# hermes/examples/kanban_sprint_demo.py
async def run_sprint_demo():
"""运行完整的 Sprint 演示"""
# 创建看板
manager = KanbanManager(name="SaaS 平台开发 Sprint #1")
# 注册 Agent
profiles = {
AgentProfile.PM: PMAgent("pm-analyst"),
AgentProfile.ARCHITECT: ArchitectAgent("architect"),
AgentProfile.FRONTEND: FrontendAgent("frontend-dev"),
AgentProfile.BACKEND: BackendAgent("backend-dev"),
AgentProfile.QA: QAAgent("qa-engineer"),
AgentProfile.DEVOPS: DevOpsAgent("devops-engineer"),
AgentProfile.WRITER: TechWriterAgent("tech-writer"),
}
# PM 拆解需求
pm_card = KanbanCard(
title="需求分析:用户管理系统",
description="开发一个包含注册、登录、权限管理的用户管理系统",
assigned_to=AgentProfile.PM,
priority=TaskPriority.CRITICAL,
effort_estimate=5,
)
manager.add_card(pm_card)
# 引擎
engine = KanbanEngine(manager)
for profile, agent in profiles.items():
engine.register_agent(profile, agent.handle_task)
# 运行 Sprint
result = await engine.run_sprint()
# 最终看板
print("\n📋 最终看板状态:")
print(manager.display_board())
return result
# 运行
asyncio.run(run_sprint_demo())五、Kanban 看板可视化
5.1 实时看板视图
╔══════════════════════════════════════════════════════╗
║ SaaS 平台开发 Sprint #1 ║
║ 进度: 87% 卡片: 8 ║
╠══════════════════════════════════════════════════════╣
║ 📋 待办 │ 📝 待处理 │ 🔄 进行中 │ 🔍 审查中 │
║ ──────────────┼──────────────┼─────────────┼───────────┤
║ 🔴 数据库设 │ │ 🟡 前端页 │ 🔴 需求文档│
║ 🔴 后端 API │ │ │ │
║ 🟡 测试用例 │ │ │ │
║ │ │ │ │
║ 🟡 部署配置 │ │ │ │
║ 🟢 文档编写 │ │ │ │
║ │ │ │ │
║ 🟢 技术方 │ │ │ │
╚══════════════════════════════════════════════════════╝5.2 事件日志
[18:30:00] Sprint 开始
[18:30:01] 任务入队: CARD-a1b2c3d4 (需求分析:用户管理系统)
[18:30:02] pm-analyst 开始处理 CARD-a1b2c3d4
[18:30:05] CARD-a1b2c3d4 完成,拆解出 8 个子任务
[18:30:05] 子任务加入看板
[18:30:06] architect 开始处理 CARD-e5f6g7h8 (技术方案)
[18:30:06] backend-dev 开始处理 CARD-i9j0k1l2 (数据库设计)
[18:30:08] CARD-e5f6g7h8 完成 → 审查
[18:30:09] CARD-e5f6g7h8 通过审查 → 已完成
[18:30:10] CARD-i9j0k1l2 完成 → 审查 → 已完成
[18:30:11] frontend-dev 开始处理 CARD-m3n4o5p6 (前端页面)
[18:30:11] backend-dev 开始处理 CARD-q7r8s9t0 (后端 API)
...
[18:35:00] Sprint 完成! 8/8 任务已完成六、高级特性
6.1 任务依赖管理
def create_dependency_chain(manager: KanbanManager) -> list[str]:
"""创建任务依赖链"""
# 需求分析 → 技术方案 → 前后端开发 → 测试 → 部署
cards = []
pm = KanbanCard(
title="需求分析",
assigned_to=AgentProfile.PM,
priority=TaskPriority.CRITICAL,
effort_estimate=3,
)
pm.status = TaskStatus.TODO
manager.add_card(pm)
cards.append(pm.card_id)
arch = KanbanCard(
title="技术方案",
assigned_to=AgentProfile.ARCHITECT,
priority=TaskPriority.CRITICAL,
effort_estimate=5,
dependencies=[pm.card_id],
)
manager.add_card(arch)
cards.append(arch.card_id)
backend = KanbanCard(
title="后端开发",
assigned_to=AgentProfile.BACKEND,
priority=TaskPriority.HIGH,
effort_estimate=8,
dependencies=[arch.card_id],
)
manager.add_card(backend)
cards.append(backend.card_id)
frontend = KanbanCard(
title="前端开发",
assigned_to=AgentProfile.FRONTEND,
priority=TaskPriority.HIGH,
effort_estimate=8,
dependencies=[arch.card_id],
)
manager.add_card(frontend)
cards.append(frontend.card_id)
# 前后端完成后才能测试
qa = KanbanCard(
title="测试",
assigned_to=AgentProfile.QA,
priority=TaskPriority.MEDIUM,
effort_estimate=5,
dependencies=[backend.card_id, frontend.card_id],
)
manager.add_card(qa)
return cards6.2 WIP 限制与流量控制
class WIPController:
"""WIP 限制控制器"""
def __init__(self, limits: dict[TaskStatus, int]):
self.limits = limits
def can_move(self, board: KanbanBoard, card_id: str, to_status: TaskStatus) -> bool:
"""检查是否可以移动"""
if to_status not in self.limits:
return True
current = sum(
1 for c in board.cards.values()
if c.status == to_status and c.card_id != card_id
)
return current < self.limits[to_status]
def suggest_next(self, board: KanbanBoard) -> Optional[KanbanCard]:
"""建议下一个应该处理的任务"""
# 优先处理阻塞的任务
blocked = [c for c in board.cards.values() if c.status == TaskStatus.BLOCKED]
if blocked:
return min(blocked, key=lambda c: TaskPriority[c.priority])
# 其次处理审查中的任务(减少 WIP)
review = board.columns[TaskStatus.REVIEW]
if review:
return review[0]
# 然后是进行中的
in_progress = board.columns[TaskStatus.IN_PROGRESS]
if in_progress:
return in_progress[0]
# 最后是新任务
todo = board.columns[TaskStatus.TODO]
if todo:
return todo[0]
return None七、总结
Hermes Kanban 多 Agent 协作系统将经典的看板方法应用到 AI Agent 协作中,实现了:
- 可视化任务管理:Kanban 看板让每个 Agent 的任务状态一目了然
- 智能任务分配:根据 Agent Profile 自动分配最合适的任务
- 依赖管理:任务之间的依赖关系自动追踪和解析
- 并行执行:无依赖的任务自动并行处理,最大化效率
- WIP 限制:防止系统过载,保持流畅的工作节奏
- 自动流转:任务完成后自动流转到下一状态
- Sprint 报告:自动生成完整的 Sprint 总结报告
这种模式特别适合复杂项目的多 Agent 协作场景,让多个专业 Agent 像一支高效团队一样工作。
下一篇文章将是本系列的实战巅峰——全栈 10 Agent 协作构建 SaaS 系统,从需求分析到部署运维的全链路实现。
下篇预告
86 | 全栈实战 10 Agent 协作 SaaS:需求分析 → 架构 → 前端 → 后端 → 测试 → 部署 → 运维全链路,10 个 Agent 协同构建一个完整的 SaaS 平台。这是多 Agent 协作的终极实战!