# Phase 10:高级编排(Advanced Orchestration) 日期:2026-04-04 状态:待开始 前置依赖:Phase 6-9(工具系统、Hook、插件、Skills) Demo参考:claw-code-main — assistant/, cli/, structuredIO.ts, remoteIO.ts --- ## 1. 阶段目标 实现**高级 Agent 编排能力**,包括: - Team 多 Agent 协作 - 远程/结构化传输 - 高级会话管理 - 后台任务系统 这是 claw-code 与 Jarvis 架构差距最大的地方,也是最复杂的功能。 --- ## 2. Team 多 Agent 协作 ### 2.1 TeamLeader ```python # backend/app/agents/team/leader.py @dataclass class TeamMember: """团队成员""" agent_id: str role: str capabilities: list[str] status: AgentStatus current_task: str | None = None @dataclass class TeamTask: """团队任务""" task_id: str description: str parent_id: str | None = None assignee: str | None = None status: TaskStatus dependencies: list[str] = field(default_factory=list) result: Any = None class TeamLeader: """ 团队领导者 负责协调多个 Agent 的协作 """ def __init__( self, team_id: str, tool_registry: ToolRegistry, hook_manager: HookManager ): self.team_id = team_id self.tool_registry = tool_registry self.hook_manager = hook_manager self.members: dict[str, TeamMember] = {} self.tasks: dict[str, TeamTask] = {} self.task_queue: asyncio.Queue = asyncio.Queue() async def create_team( self, config: TeamConfig ) -> str: """创建团队""" self.team_id = config.team_id # 创建团队成员 for member_config in config.members: member = TeamMember( agent_id=member_config.agent_id, role=member_config.role, capabilities=member_config.capabilities, status=AgentStatus.IDLE ) self.members[member.agent_id] = member return self.team_id async def assign_task( self, task: TeamTask ) -> str: """分配任务""" self.tasks[task.task_id] = task # 找到最合适的成员 assignee = await self._find_assignee(task) if assignee: task.assignee = assignee.agent_id assignee.current_task = task.task_id assignee.status = AgentStatus.WORKING return task.task_id async def _find_assignee( self, task: TeamTask ) -> TeamMember | None: """找到最适合执行任务的成员""" # 过滤掉忙碌的成员 available = [ m for m in self.members.values() if m.status == AgentStatus.IDLE ] if not available: return None # 按能力匹配 for cap in task.required_capabilities: matches = [m for m in available if cap in m.capabilities] if matches: return matches[0] return available[0] if available else None async def broadcast_task( self, description: str, required_capabilities: list[str] ) -> list[str]: """广播任务给所有符合条件的成员""" task_ids = [] for member in self.members.values(): if member.status != AgentStatus.IDLE: continue # 检查能力匹配 if not any(cap in member.capabilities for cap in required_capabilities): continue # 创建任务 task = TeamTask( task_id=generate_id(), description=description, assignee=member.agent_id, status=TaskStatus.PENDING ) await self.assign_task(task) task_ids.append(task.task_id) return task_ids async def collect_results( self, task_ids: list[str], timeout: float = 300 ) -> dict[str, Any]: """收集任务结果""" results = {} start_time = time.time() while len(results) < len(task_ids): if time.time() - start_time > timeout: break for task_id in task_ids: if task_id in results: continue task = self.tasks.get(task_id) if task and task.status == TaskStatus.COMPLETED: results[task_id] = task.result await asyncio.sleep(0.1) return results async def get_team_status(self) -> TeamStatus: """获取团队状态""" return TeamStatus( team_id=self.team_id, members={ agent_id: { "role": m.role, "status": m.status.value, "current_task": m.current_task } for agent_id, m in self.members.items() }, active_tasks=sum(1 for t in self.tasks.values() if t.status == TaskStatus.PENDING), completed_tasks=sum(1 for t in self.tasks.values() if t.status == TaskStatus.COMPLETED) ) ``` --- ## 3. 远程传输层 ### 3.1 StructuredIO ```python # backend/app/agents/transport/structured_io.py class StructuredIO: """ 结构化 IO 支持结构化的输入输出格式 """ async def send_response( self, channel: str, data: dict ): """发送结构化响应""" message = { "channel": channel, "type": "structured", "data": data, "timestamp": datetime.now().isoformat() } await self.transport.send(message) async def send_event( self, event_type: str, payload: dict ): """发送事件""" message = { "type": "event", "event": event_type, "payload": payload, "timestamp": datetime.now().isoformat() } await self.transport.send(message) async def send_tool_call( self, tool_name: str, arguments: dict, call_id: str ): """发送工具调用""" message = { "type": "tool_call", "tool": tool_name, "args": arguments, "call_id": call_id, "timestamp": datetime.now().isoformat() } await self.transport.send(message) async def receive(self) -> dict: """接收消息""" raw = await self.transport.receive() return self._parse(raw) def _parse(self, raw: bytes) -> dict: """解析消息""" # 支持 JSON 和流式格式 pass ``` ### 3.2 RemoteTransport ```python # backend/app/agents/transport/remote.py class RemoteTransport: """ 远程传输 支持远程 Agent 通信 """ def __init__( self, endpoint: str, auth_token: str ): self.endpoint = endpoint self.auth_token = auth_token self.websocket: WebSocket | None = None async def connect(self): """建立连接""" self.websocket = await websockets.connect( self.endpoint, extra_headers={"Authorization": f"Bearer {self.auth_token}"} ) async def send(self, message: dict): """发送消息""" if not self.websocket: await self.connect() await self.websocket.send(json.dumps(message)) async def receive(self) -> dict: """接收消息""" if not self.websocket: await self.connect() raw = await self.websocket.recv() return json.loads(raw) async def close(self): """关闭连接""" if self.websocket: await self.websocket.close() ``` --- ## 4. 高级会话管理 ### 4.1 AgentSession ```python # backend/app/agents/session/manager.py @dataclass class SessionConfig: """会话配置""" session_id: str user_id: str parent_session_id: str | None = None max_rounds: int = 50 max_tokens: int = 100000 timeout: float = 3600 isolation_mode: IsolationMode = IsolationMode.NONE capabilities: list[str] = field(default_factory=list) permissions: list[str] = field(default_factory=list) class AgentSession: """ Agent 会话 管理会话的生命周期和状态 """ def __init__( self, config: SessionConfig, agent_runtime: AgentRuntime ): self.config = config self.agent_runtime = agent_runtime self.state: SessionState = SessionState.INITIALIZING self.round_count: int = 0 self.token_count: int = 0 self.messages: list[Message] = [] self.tool_calls: list[ToolCall] = [] self.events: list[SessionEvent] = [] async def initialize(self) -> str: """初始化会话""" # 创建会话记录 await self._create_session_record() # 初始化隔离环境 if self.config.isolation_mode != IsolationMode.NONE: await self._initialize_isolation() self.state = SessionState.ACTIVE return self.config.session_id async def process_message( self, message: str ) -> Response: """处理消息""" if self.state != SessionState.ACTIVE: raise SessionStateError(f"Session not active: {self.state}") # 检查轮次限制 self.round_count += 1 if self.round_count > self.config.max_rounds: raise SessionLimitError("Max rounds exceeded") # 处理消息 response = await self.agent_runtime.process( message, context=self._get_context() ) # 记录 self.messages.append(Message(role="user", content=message)) self.messages.append(Message(role="assistant", content=response.content)) # 更新 token 计数 self.token_count += response.usage.total_tokens return response async def spawn_child_session( self, config: SessionConfig ) -> "AgentSession": """创建子会话""" child_config = SessionConfig( **{ **asdict(config), "parent_session_id": self.config.session_id } ) child_session = AgentSession( config=child_config, agent_runtime=self.agent_runtime ) await child_session.initialize() return child_session async def get_session_summary(self) -> SessionSummary: """获取会话摘要""" return SessionSummary( session_id=self.config.session_id, user_id=self.config.user_id, round_count=self.round_count, token_count=self.token_count, message_count=len(self.messages), tool_call_count=len(self.tool_calls), duration_seconds=(datetime.now() - self.start_time).total_seconds(), state=self.state.value ) async def persist(self): """持久化会话""" await self.session_service.save(SessionRecord( session_id=self.config.session_id, user_id=self.config.user_id, state=self.state.value, round_count=self.round_count, token_count=self.token_count, messages=self.messages, tool_calls=self.tool_calls, events=self.events )) ``` --- ## 5. 后台任务系统 ### 5.1 BackgroundTaskManager ```python # backend/app/agents/background/manager.py @dataclass class BackgroundTask: """后台任务""" task_id: str description: str agent_config: dict schedule: str | None = None # cron expression status: BackgroundTaskStatus created_at: datetime started_at: datetime | None = None completed_at: datetime | None = None result: Any = None error: str | None = None class BackgroundTaskManager: """ 后台任务管理器 管理长期运行的 Agent 任务 """ def __init__( self, task_store: TaskStore, agent_factory: AgentFactory ): self.task_store = task_store self.agent_factory = agent_factory self._running_tasks: dict[str, asyncio.Task] = {} self._scheduler = AsyncIOScheduler() async def submit_task( self, task: BackgroundTask ) -> str: """提交后台任务""" # 保存任务记录 await self.task_store.save(task) # 如果有定时计划,调度任务 if task.schedule: self._scheduler.add_job( self._execute_task, CronTrigger.from_crontab(task.schedule), args=[task.task_id] ) else: # 立即执行 asyncio.create_task(self._execute_task(task.task_id)) return task.task_id async def _execute_task(self, task_id: str): """执行任务""" task = await self.task_store.get(task_id) if not task: return self._running_tasks[task_id] = asyncio.current_task() task.status = BackgroundTaskStatus.RUNNING task.started_at = datetime.now() await self.task_store.save(task) try: # 创建 Agent agent = await self.agent_factory.create(task.agent_config) # 执行 result = await agent.run() task.status = BackgroundTaskStatus.COMPLETED task.result = result except Exception as e: task.status = BackgroundTaskStatus.FAILED task.error = str(e) finally: task.completed_at = datetime.now() await self.task_store.save(task) if task_id in self._running_tasks: del self._running_tasks[task_id] async def cancel_task(self, task_id: str) -> bool: """取消任务""" if task_id in self._running_tasks: self._running_tasks[task_id].cancel() del self._running_tasks[task_id] task = await self.task_store.get(task_id) if task: task.status = BackgroundTaskStatus.CANCELLED await self.task_store.save(task) return True async def get_task_status(self, task_id: str) -> BackgroundTask | None: """获取任务状态""" return await self.task_store.get(task_id) async def list_tasks( self, user_id: str, status: BackgroundTaskStatus | None = None ) -> list[BackgroundTask]: """列出任务""" return await self.task_store.list(user_id, status) ``` --- ## 6. 文件结构 ``` backend/app/agents/ ├── team/ # Team 协作 │ ├── __init__.py │ ├── leader.py # 团队领导 │ ├── member.py # 团队成员 │ └── task.py # 团队任务 │ ├── transport/ # 传输层 │ ├── __init__.py │ ├── structured_io.py # 结构化 IO │ ├── remote.py # 远程传输 │ └── websocket.py # WebSocket 传输 │ ├── session/ # 会话管理 │ ├── __init__.py │ ├── manager.py # 会话管理器 │ ├── context.py # 会话上下文 │ └── persistence.py # 会话持久化 │ ├── background/ # 后台任务 │ ├── __init__.py │ ├── manager.py # 后台任务管理器 │ ├── scheduler.py # 任务调度 │ └── executor.py # 任务执行器 │ └── coordinator.py # 协调整合(现有) ``` --- ## 7. 验收标准 | 检查点 | 标准 | |--------|------| | Team 创建 | 可以创建和管理 Agent 团队 | | Team 任务分配 | 任务能正确分配给合适的成员 | | Team 结果收集 | 能收集和聚合多成员的结果 | | 结构化 IO | 支持结构化的输入输出格式 | | 远程传输 | 支持远程 Agent 通信 | | 会话管理 | 支持复杂的会话层级和状态管理 | | 后台任务 | 支持定时和异步后台任务 | | 子会话 | 支持从父会话创建子会话 | --- ## 8. Demo 借鉴 | claw-code | Jarvis 对应 | |-----------|------------| | `src/assistant/sessionHistory.ts` | `session/manager.py` | | `src/cli/structuredIO.ts` | `transport/structured_io.py` | | `src/cli/remoteIO.ts` | `transport/remote.py` | | `src/cli/transports/*` | `transport/` | | Team/* tools | `team/leader.py` | | Background tasks | `background/manager.py` |