多 Agent 协同的异常隔离与容错设计:基于 Supervisor 模式的子任务重启
在企业级多智能体(Multi-Agent)长程复杂工作流(如全自动多模态研报生成、代码重构测试套件生成)中,系统由主控 Agent(Supervisor)与多个垂直子 Agent(如爬虫 Agent、计算 Agent、绘图 Agent、审核 Agent)协同组成。
由于各个子 Agent 在运行时需要频繁调用外部不可信的网络 API、执行动态代码沙箱或依赖大模型的意图推理,局部子任务的突发异常是不可避免的常态:
- 爬虫 Agent 在抓取某个网页时遇到了反爬封禁(HTTP 403);
- 绘图 Agent 由于显存不足生成失败抛出异常;
- 如果系统采用传统的“全局单体错误抛出”,一个边缘子任务的崩溃就会直接导致耗时已达 2 分钟的整个长任务全盘覆没(Cascading Failure)!
在分布式容错理论中,源自 Erlang/OTP 架构的Supervisor(监督者模式)是解决局部崩溃与自愈恢复的工业级标杆。
今天我们拆解如何在多 Agent 调度内核中构建Supervisor 容错监督树,实现基于One-For-One(单点重启)、One-For-All(全量回滚)与指数退避自愈的生产级容错架构。
一、Supervisor 监督树容错与异常隔离模型
flowchart TD Main[用户提交长程复合任务] --> Sup[Supervisor 主控监督者] subgraph Worker_Pool [子 Agent 独立隔离沙箱] Sup --> WorkerA[Sub-Agent A (数据清洗 - 正常运行)] Sup --> WorkerB[Sub-Agent B (网页爬取 - 突发异常崩溃!)] Sup --> WorkerC[Sub-Agent C (图表渲染 - 待命)] end WorkerB -- 抛出 WebScrapeTimeoutError --> Sup subgraph Healing_Strategy [Supervisor 容错决策与自愈管道] Sup --> CheckStrategy{判定容错策略} CheckStrategy -- One-For-One 策略 --> IsRetryable{重试次数 <= 3?} IsRetryable -- 是 --> RestartB[1. 仅隔离并重启 Worker B (带动态代理与指数退避)] IsRetryable -- 否 (重试耗尽) --> FallbackB[2. 降级: 为 Worker B 注入空数据/本地快照, 保证主干继续推进!] end RestartB --> Sup FallbackB --> Sup Sup --> Deliver[3. 交付最终完整成果 (主干流程 0 崩溃!)]二、生产级 Python Supervisor 容错引擎核心代码实现
import time import logging from typing import Dict, Any, Callable, List, Optional from pydantic import BaseModel logger = logging.getLogger(__name__) class AgentExecutionError(Exception): """可恢复的子 Agent 执行异常""" pass class TaskResult(BaseModel): agent_name: str status: str # "SUCCESS", "RESTARTED_AND_HEALED", "DEGRADED_FALLBACK", "FATAL_FAILED" result: Any retry_count: int class AgentSupervisorEngine: def __init__(self, max_retries: int = 3, backoff_base_sec: float = 1.0): self.max_retries = max_retries self.backoff_base = backoff_base_sec def supervise_execute_single_agent( self, agent_name: str, agent_func: Callable[[dict], dict], payload: dict, fallback_func: Optional[Callable[[dict], dict]] = None ) -> TaskResult: """ 核心监督逻辑:遵循 One-For-One 隔离重启与自愈策略 """ retries = 0 while retries <= self.max_retries: try: print(f"[*] [Supervisor] 正在调度执行子 Agent: [{agent_name}] (尝试第 {retries + 1} 次)...") # 在独立沙箱上下文中执行子任务 out = agent_func(payload) status = "SUCCESS" if retries == 0 else "RESTARTED_AND_HEALED" return TaskResult(agent_name=agent_name, status=status, result=out, retry_count=retries) except Exception as e: retries += 1 logger.warning(f"[Supervisor Alert] ⚠️ 子 Agent [{agent_name}] 发生异常: {str(e)}") if retries <= self.max_retries: # 指数退避休眠自愈 sleep_time = self.backoff_base * (2 ** (retries - 1)) print(f"[!] 触发 One-For-One 隔离重启机制,休眠 {sleep_time:.1f}s 后拉起新实例...") time.sleep(sleep_time) else: # 重试次数耗尽,进入优雅降级(Graceful Degradation) if fallback_func: print(f"[Fallback] 子 Agent [{agent_name}] 重试耗尽,触发本地兜底降级方案...") fallback_data = fallback_func(payload) return TaskResult( agent_name=agent_name, status="DEGRADED_FALLBACK", result=fallback_data, retry_count=retries ) else: print(f"[FATAL] 子 Agent [{agent_name}] 彻底失败且无降级方案!") return TaskResult( agent_name=agent_name, status="FATAL_FAILED", result=None, retry_count=retries )三、真实多 Agent 协同容错实战演示
def test_supervisor_resilience(): supervisor = AgentSupervisorEngine(max_retries=2, backoff_base_sec=0.2) # 1. 模拟一个偶发性报错的外部抓取 Agent (前 2 次失败,第 3 次成功) scrape_attempts = 0 def unstable_scraper_agent(ctx: dict) -> dict: nonlocal scrape_attempts scrape_attempts += 1 if scrape_attempts < 2: raise AgentExecutionError("外部目标网站反爬拦截 (HTTP 429 Too Many Requests)") return {"scraped_data": "【行业最新大盘数据】2026年新能源渗透率达 52%"} # 2. 模拟一个彻底宕机的边缘画图 Agent (带本地静态图表降级兜底) def broken_chart_agent(ctx: dict) -> dict: raise RuntimeError("GPU 显存爆仓,绘图引擎崩溃!") def chart_fallback(ctx: dict) -> dict: return {"chart_url": "https://cdn.internal.com/static/default_pie_chart.png", "is_fallback": True} print("=" * 60) # 监督执行 Agent A (自愈成功) res_a = supervisor.supervise_execute_single_agent("ScraperAgent", unstable_scraper_agent, {}) print(f"[✓] 任务 A 交付状态: {res_a.status} (重试 {res_a.retry_count} 次), 数据: {res_a.result}") # 监督执行 Agent B (优雅降级成功) res_b = supervisor.supervise_execute_single_agent("ChartAgent", broken_chart_agent, {}, fallback_func=chart_fallback) print(f"[✓] 任务 B 交付状态: {res_b.status} (降级兜底成功), 数据: {res_b.result}") print("=" * 60)四、生产治理三大黄金法则
- 子任务强物理隔离(Process / Goroutine Isolation):各个子 Agent 严禁共用可变的全局内存变量,防止一个 Agent 发生内存污染影响整个进程;
- 设置单子任务硬超时上限(Context Timeout):为每个子 Agent 分配独立的执行超时(如 10 秒),防止死循环把 Supervisor 拖死;
- 关键任务与非关键任务分级(Tiered Task Classification):对于核心交易/支付 Agent,重试耗尽必须抛出全局回滚;对于边缘的配图、格式美化 Agent,一律允许静默降级放行。
把 Supervisor 监督者模式做进多 Agent 系统的调度底层,智能体在面对充满不可控外部环境时,才能真正展现出如磐石般的稳定与高可用。