在实际项目中,我们很少只有一个 Agent 在战斗。代码审查需要静态分析 + LLM 推理,数据流水线需要调度器 + 多个处理节点,运维排障需要日志采集 + 根因分析 + 修复执行。当多个 AI Agent 或工具需要协同工作时,**拓扑架构的选择直接决定了系统的可维护性、扩展性和故障恢复能力。**

多工具集成架构设计:Hub-and-Spoke / Pipeline / P2P 三种拓扑全面对比

简介

在实际项目中,我们很少只有一个 Agent 在战斗。代码审查需要静态分析 + LLM 推理,数据流水线需要调度器 + 多个处理节点,运维排障需要日志采集 + 根因分析 + 修复执行。当多个 AI Agent 或工具需要协同工作时,拓扑架构的选择直接决定了系统的可维护性、扩展性和故障恢复能力。

本篇深入对比三种主流多工具集成拓扑:Hub-and-Spoke(星型)、Pipeline(流水线)和 P2P(对等网络),从适用场景、性能特征、代码示例三个维度给出可落地的选型指南。

2. Hub-and-Spoke(星型架构)

2.1 核心概念

所有 Agent 节点(Spoke)不直接通信,而是通过一个中心调度器(Hub)进行协调。Hub 负责任务分解、路由、状态追踪和结果聚合。

text
              ┌─────────┐
              │   Hub   │
              │ (调度器) │
              └────┬────┘
         ┌─────────┼─────────┐
         ▼         ▼         ▼
    ┌────────┐ ┌────────┐ ┌────────┐
    │Spoke A │ │Spoke B │ │Spoke C │
    │ 编码器  │ │ 测试器  │ │ 审查器  │
    └────────┘ └────────┘ └────────┘

2.2 适用场景

  • 任务可明确分解的场景:一个主任务能拆成多个独立子任务
  • 需要统一上下文的场景:所有子任务共享同一份代码库或需求文档
  • 需要集中管控的场景:审计、限流、预算控制

2.3 架构实现示例

python
class HubScheduler:
    """星型架构的中心调度器"""

    def __init__(self):
        self.agents = {
            "code_writer": Agent("claude-code", "code"),
            "tester": Agent("codex", "test"),
            "reviewer": Agent("opencode", "review"),
            "doc_writer": Agent("llm", "docs"),
        }
        self.task_queue = asyncio.Queue()
        self.results = {}

    async def dispatch(self, task: Task) -> dict:
        """将任务分解并分发到各 Spoke"""
        subtasks = self.decompose(task)
        futures = {}

        for subtask in subtasks:
            agent = self.agents[subtask.target_agent]
            futures[subtask.id] = agent.execute(subtask)

        # 等待所有子任务完成
        results = await asyncio.gather(*futures.values())
        return self.aggregate(dict(zip(futures.keys(), results)))

    async def handle_failure(self, subtask_id: str, error: Exception):
        """Spoke 失败时的补偿策略"""
        # 重试、降级或通知人工介入
        logger.warning(f"Spoke {subtask_id} failed: {error}")
        await self.retry_or_escalate(subtask_id, error)

    def decompose(self, task: Task) -> list[SubTask]:
        """任务分解策略 - 基于规则或 LLM"""
        if task.type == "feature":
            return [
                SubTask(id="code", target_agent="code_writer", input=task.spec),
                SubTask(id="test", target_agent="tester", input=task.spec),
                SubTask(id="review", target_agent="reviewer", depends_on=["code"]),
                SubTask(id="docs", target_agent="doc_writer", depends_on=["code"]),
            ]
        # 其他任务类型...

    def aggregate(self, results: dict) -> dict:
        """聚合结果 - 冲突检测、质量评分"""
        # 检查代码与测试的兼容性
        if results.get("code") and results.get("test"):
            compat = self.check_compatibility(
                results["code"].output,
                results["test"].output
            )
            results["compatibility"] = compat
        return results

2.4 优缺点分析

维度 优势 劣势
可维护性 集中管理,调试简单 Hub 成为单点故障
扩展性 添加新 Spoke 容易 Hub 吞吐量受限
上下文管理 全局视图,避免信息孤岛 Hub 需要维护大量状态
延迟 可并行执行无依赖子任务 所有流量经过 Hub
复杂度 逻辑集中,编码简单 Hub 逻辑随 Spoke 数量增长

2.5 典型工具映射

Hub 实现 Spoke 类型
Hermes Agent 调度层 Claude Code, Codex, OpenCode
LangGraph Supervisor 各种 Tool Node
AutoGen GroupChatManager 对话 Agent
CrewAI ManagerAgent Crew 成员

3. Pipeline(流水线架构)

3.1 核心概念

Agent 节点按固定顺序串联,每个节点的输出作为下一个节点的输入。数据单向流动,像工厂流水线一样逐级处理。

text
┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│  Stage 1 │───▶│  Stage 2 │───▶│  Stage 3 │───▶│  Stage 4 │
│ 需求解析  │    │ 代码生成  │    │ 测试验证  │    │ 部署执行  │
└─────────┘    └─────────┘    └─────────┘    └─────────┘

3.2 适用场景

  • 处理流程固定的场景:步骤明确、顺序不可变
  • 需要严格质量控制的场景:每个阶段有独立的准入/准出标准
  • 数据转换流水线:原始数据 → 清洗 → 分析 → 报告

3.3 架构实现示例

python
class PipelineStage:
    """流水线阶段基类"""

    def __init__(self, name: str, agent: Agent,
                 validator: Callable = None,
                 retry_count: int = 2):
        self.name = name
        self.agent = agent
        self.validator = validator
        self.retry_count = retry_count

    async def execute(self, input_data: dict) -> PipelineResult:
        """执行阶段处理,含验证和重试"""
        last_error = None
        for attempt in range(self.retry_count + 1):
            try:
                result = await self.agent.process(input_data)

                # 质量门控检查
                if self.validator and not self.validator(result):
                    raise QualityGateError(
                        f"Stage {self.name} validation failed"
                    )

                return PipelineResult(
                    stage=self.name,
                    status="success",
                    output=result,
                    metrics=self.collect_metrics(result)
                )
            except Exception as e:
                last_error = e
                logger.warning(
                    f"Stage {self.name} attempt {attempt+1} failed: {e}"
                )

        return PipelineResult(
            stage=self.name,
            status="failed",
            error=last_error
        )


class AgentPipeline:
    """流水线编排器"""

    def __init__(self, stages: list[PipelineStage]):
        self.stages = stages
        self.pipeline_state = PipelineState()

    async def run(self, initial_input: dict) -> PipelineReport:
        """从头到尾执行流水线"""
        current_data = initial_input

        for stage in self.stages:
            # 可选:条件跳过
            if self.should_skip(stage, current_data):
                self.pipeline_state.record_skip(stage.name)
                continue

            result = await stage.execute(current_data)
            self.pipeline_state.record(result)

            if result.status == "failed":
                # 快速失败 或 降级继续
                if self.fail_fast:
                    raise PipelineException(
                        f"Pipeline halted at {stage.name}"
                    )
                self.pipeline_state.record_fallback(stage.name)
                current_data = self.get_fallback_data(stage.name)
            else:
                current_data = result.output

        return self.pipeline_state.generate_report()

    def should_skip(self, stage: PipelineStage, data: dict) -> bool:
        """动态跳过逻辑 - 基于条件判断"""
        if stage.name == "test" and data.get("skip_tests"):
            return True
        if stage.name == "deploy" and not data.get("tests_passed"):
            return True
        return False

3.4 实际 Pipeline 示例:代码修复流水线

python
# 定义一个完整的代码修复流水线
fix_pipeline = AgentPipeline(stages=[
    PipelineStage(
        name="analyze",
        agent=CodexAgent(),
        validator=lambda r: r.confidence > 0.7,
        retry_count=1,
    ),
    PipelineStage(
        name="generate_fix",
        agent=ClaudeCodeAgent(),
        validator=lambda r: r.patch.is_valid(),
        retry_count=2,
    ),
    PipelineStage(
        name="test_fix",
        agent=TestRunnerAgent(),
        validator=lambda r: r.pass_rate > 0.95,
        retry_count=3,
    ),
    PipelineStage(
        name="commit",
        agent=GitAgent(),
        validator=lambda r: r.push_successful,
        retry_count=1,
    ),
])

# 执行
report = await fix_pipeline.run({
    "bug_report": "Memory leak in connection pool",
    "repo_path": "/opt/data/my-project",
    "skip_tests": False,
})

3.5 优缺点分析

维度 优势 劣势
可维护性 每阶段职责单一,易测试 阶段间耦合度高
扩展性 可插入新阶段 重排阶段顺序代价大
质量控制 天然的质量门控点 早期阶段错误会级联
延迟 可流式输出中间结果 总体延迟为各阶段之和
复杂度 线性复杂度,易理解 分支和回退逻辑复杂

4. P2P(对等网络架构)

4.1 核心概念

所有 Agent 节点地位平等,可以直接通信和协商任务。没有中心节点,通过共识机制或投票决定下一步行动。

text
    ┌──────┐         ┌──────┐
    │Agent A├────────▶│Agent B│
    └───┬──┘         └───┬──┘
        │                │
        ▼                ▼
    ┌──────┐         ┌──────┐
    │Agent D├◀────────│Agent C│
    └──────┘         └──────┘
    (网状互连,自由协商)

4.2 适用场景

  • 任务边界模糊的场景:无法预先定义明确的分工
  • 需要动态协作的场景:Agent 根据实时情况自主决定谁处理什么
  • 容错性要求极高的场景:任何节点失效都不影响整体

4.3 架构实现示例

python
class P2PAgent:
    """对等网络中的 Agent 节点"""

    def __init__(self, name: str, capabilities: list[str]):
        self.name = name
        self.capabilities = set(capabilities)
        self.peers: dict[str, "P2PAgent"] = {}
        self.message_bus = MessageBus()
        self.state = AgentState.IDLE

    def register_peer(self, peer: "P2PAgent"):
        """注册对等节点"""
        self.peers[peer.name] = peer
        peer.peers[self.name] = self  # 双向注册

    async def handle_task_proposal(self, proposal: TaskProposal):
        """收到任务提案后的响应策略"""
        # 评估自身能力匹配度
        match_score = self.evaluate_match(proposal)

        if match_score > self.ACCEPT_THRESHOLD:
            # 接受任务
            self.state = AgentState.WORKING
            await self.message_bus.broadcast(
                TaskAcceptance(
                    proposer=proposal.sender,
                    accepter=self.name,
                    task=proposal.task,
                )
            )
            result = await self.execute(proposal.task)
            await self.message_bus.broadcast(TaskResult(
                agent=self.name, result=result
            ))
        else:
            # 拒绝或转发给更合适的节点
            best_peer = self.find_best_peer(proposal)
            if best_peer:
                await self.message_bus.send(
                    best_peer.name,
                    TaskForward(original=proposal, suggested_by=self.name)
                )
            else:
                await self.message_bus.broadcast(
                    TaskRejection(task=proposal.task, reason="no_match")
                )

    def find_best_peer(self, proposal: TaskProposal) -> str:
        """寻找最合适的对等节点"""
        candidates = []
        for peer_name, peer in self.peers.items():
            if peer.state != AgentState.WORKING:
                score = peer.evaluate_match(proposal)
                candidates.append((peer_name, score))

        if candidates:
            return max(candidates, key=lambda x: x[1])[0]
        return None


class P2PNetwork:
    """P2P 网络协调层"""

    def __init__(self):
        self.agents: dict[str, P2PAgent] = {}
        self.message_bus = MessageBus()

    def add_agent(self, agent: P2PAgent):
        """添加 Agent 并自动建立对等连接"""
        self.agents[agent.name] = agent
        # 与所有已有 Agent 建立连接
        for existing in self.agents.values():
            if existing.name != agent.name:
                agent.register_peer(existing)

    async def submit_task(self, task: Task) -> TaskReport:
        """提交任务到网络,由网络自主协商处理"""
        proposal = TaskProposal(
            sender="orchestrator",
            task=task,
            deadline=task.deadline,
            priority=task.priority,
        )

        # 广播任务提案
        await self.message_bus.broadcast(proposal)

        # 等待网络自发形成协作
        return await self.collect_results(task)

4.4 优缺点分析

维度 优势 劣势
可维护性 无单点故障,弹性极强 调试困难,行为不可预测
扩展性 动态加入/退出节点 节点数增加导致通信爆炸
决策质量 集思广益,减少偏见 可能出现死锁或循环
延迟 最短路径自动选择 协商过程引入额外延迟
复杂度 节点实现简单 网络层面复杂度高

4.5 P2P 协作示例:多 Agent 代码审查

python
# 场景:5 个审查 Agent 对同一段代码进行多维度审查
network = P2PNetwork()

# 添加各具专长的 Agent
agents = [
    P2PAgent("security", ["security_audit", "vuln_scan"]),
    P2PAgent("performance", ["perf_analysis", "bottleneck_detect"]),
    P2PAgent("style", ["lint_check", "format_check"]),
    P2PAgent("logic", ["logic_review", "edge_case_detect"]),
    P2PAgent("docs", ["doc_check", "api_compatibility"]),
]

for a in agents:
    network.add_agent(a)

# 提交审查任务
report = await network.submit_task(Task(
    type="code_review",
    input={
        "code_path": "src/auth/module.py",
        "diff": "...",
        "context": "OAuth2 认证模块重构",
    },
))
# 网络自动协商:security 处理安全、performance 处理性能...
# 最终聚合为一份综合审查报告

5. 三种拓扑综合对比矩阵

对比维度 Hub-and-Spoke Pipeline P2P
架构复杂度
调试难度
单点故障 Hub 是瓶颈 任一级可阻断
扩展方式 加 Spoke 加 Stage 加 Peer
通信开销 O(n) O(1) O(n²)
并行能力 强(无依赖时) 弱(顺序执行) 强(自主并行)
状态管理 集中式 分布式(阶段间) 全分布式
适合团队规模 小~中 中~大 大(复杂场景)
典型延迟 高(串行) 可变
容错策略 Hub 重试/降级 Stage 重试/跳过 Peer 自动接管

6. 选型决策树

text
需要多工具集成?
│
├─ 任务能否清晰分解为独立子任务?
│  ├─ 是 → 子任务间有依赖吗?
│  │       ├─ 有 → Pipeline(有固定顺序的流水线)
│  │       └─ 无 → Hub-and-Spoke(并行分发)
│  │
│  └─ 否 → 任务边界是否模糊/需要动态协商?
│           ├─ 是 → P2P(自主协作网络)
│           └─ 否 → Hub-and-Spoke(集中管控)
│
└─ 容错性是否是第一优先级?
    └─ 是 → P2P(无单点故障)

实战经验法则

  1. 从 Hub-and-Spoke 开始:80% 的场景用星型架构就够了,简单可靠
  2. 有严格流程用 Pipeline:CI/CD、数据处理、合规审查等流程固定的场景
  3. P2P 留给高级场景:多 Agent 辩论、复杂排障、创意协作等需要涌现能力的场景
  4. 混合架构最常见:实际项目中往往是 Hub-and-Spoke 的 Hub 内部用了 Pipeline,或者 P2P 网络中的每个 Peer 本身是一个微 Pipeline

7. 总结

三种拓扑没有绝对的优劣,只有适不适合:

  • Hub-and-Spoke 是默认选项,集中管控、易于调试,适合绝大多数企业场景
  • Pipeline 是流程专家,顺序明确、质量可控,适合有严格 SOP 的处理链路
  • P2P 是灵活王者,弹性极强、自动协商,适合复杂多变的协作场景

在实际架构中,混合使用往往能发挥各自优势。比如用 Hub-and-Spoke 做全局编排,每个 Spoke 内部用 Pipeline 处理专业子流程,关键节点间用 P2P 做异常协商。

理解这三种拓扑的本质差异,是构建可靠多 Agent 系统的第一步。

下篇预告

Agent 选型矩阵:什么任务配什么工具?

有了架构蓝图,接下来要解决的核心问题是:具体任务该分配给哪个 Agent? 代码生成该用 Claude Code 还是 Codex?批量 Bug 修复哪个效率更高?文档生成、测试编写、代码审查各有什么最优选择?下一篇将给出一份实战验证过的选型矩阵,帮你做出最优决策。


本文属于「AI Agent 工具集成实战」系列。系列完整目录见系列索引。