别再把大模型当成“万能工具人“:Spring AI Multi-Agent 架构的工程化落地实战

别再把大模型当成"万能工具人":Spring AI Multi-Agent 架构的工程化落地实战

单 Agent 能跑通 Demo,Multi-Agent 才能承载生产。真正的分水岭不是 Prompt 写得多漂亮,而是能否把智能体能力拆成可治理、可扩展、可观测、可灰度的工程系统。

版本与适用范围

本文面向 Java/Spring 技术栈,重点讨论如何基于 Spring AI、Spring AI Alibaba、A2A、Nacos、Redis、Kafka 与 Kubernetes 构建生产级 Multi-Agent 系统。

示例代码以 Java 21、Spring Boot 3.x、Spring AI 1.x API 风格为主,A2A 与 Nacos 部分参考 Spring AI Alibaba 1.0.0.4+ 及 Spring AI A2A 社区实现。由于 Spring AI 生态迭代较快,生产落地时应通过 BOM 锁定依赖版本,并以官方文档中的当前 API 为准。

一、为什么单 Agent 到生产一定会遇到天花板

很多团队做 AI 应用的第一版,通常是这样的:

一个超级系统提示词 + 一堆工具 + 一个 ChatClient = 一个看起来什么都会的 Agent

这个方案在原型阶段很快,但一旦进入电商客服、金融投顾、企业知识库、售后工单、运维诊断这类真实场景,就会暴露出结构性问题。

1.1 单 Agent 的四个核心问题

第一,认知负载过高。
一个 Agent 同时负责意图识别、订单查询、库存判断、优惠计算、退款审核、物流追踪和人工升级,模型需要在大量工具和规则之间做选择。工具越多,选择越不稳定,Prompt 越长,推理噪声越大。

第二,上下文污染严重。
订单问题、商品问题、售后问题、闲聊内容混在同一个上下文窗口里,模型很容易把历史信息误用于当前任务。例如用户上一轮问过 A 商品库存,下一轮查询 B 商品退款,模型可能错误复用 A 商品上下文。

第三,工程扩展性差。
单 Agent 无法按能力独立扩容。大促期间订单查询暴涨,本应只扩容订单 Agent,却不得不扩容整个 AI 服务,导致商品咨询、售后问答、闲聊能力也被动扩容,成本不可控。

第四,治理边界不清。
在企业里,订单团队、库存团队、售后团队、风控团队通常是不同组织。单 Agent 模式会把所有业务规则、工具定义和 Prompt 堆在一起,既难以审计,也难以灰度发布。

1.2 Multi-Agent 的本质不是"多个机器人聊天"

生产级 Multi-Agent 不是让几个大模型互相对话,而是把智能能力拆成多个具备明确职责、工具权限、上下文边界和治理策略的执行单元。

一个典型智能客服系统可以拆成:

Agent 职责 可访问工具 扩容特征
Intent Agent 意图识别、置信度评估 意图分类模型、规则库 CPU 轻、低延迟
Order Agent 订单查询、取消、退款前置判断 订单服务、支付服务 大促高峰明显
Product Agent 商品咨询、库存、推荐 商品服务、库存服务、向量检索 搜索链路重
AfterSale Agent 物流、退换货、纠纷处理 物流服务、售后系统 长链路、强规则
Risk Agent 风控校验、敏感操作拦截 风控规则、黑名单、审计系统 强一致、低容错
Human Handoff Agent 人工升级、工单生成 CRM、工单系统 业务兜底

架构视图如下:

Multi-Agent 的工程价值在于:

  • 职责单一:每个 Agent 只处理一个业务域,Prompt 更短,工具更少,决策更稳定。
  • 独立扩容:订单 Agent、售后 Agent、商品 Agent 可以按流量特征独立伸缩。
  • 故障隔离:库存工具异常不应拖垮退款链路,推荐服务超时不应影响订单查询。
  • 独立治理:不同团队可以独立维护自己的 Agent、工具、Prompt 和评估集。
  • 安全可控:高风险能力可以挂接 Risk Agent 与人工确认,不把关键操作完全交给模型。

二、生产级 Multi-Agent 总体架构

2.1 分层架构

这套架构有一个重要原则:LLM 只负责需要推理的部分,不负责系统治理。

也就是说,权限、限流、熔断、幂等、审计、灰度、租户隔离、预算控制、结果校验,都应该由工程系统兜住,而不是写进 Prompt 后祈祷模型遵守。

2.2 核心组件职责

组件 职责 关键设计点
Orchestrator 接收请求、识别意图、路由 Agent、聚合结果 超时预算、并发执行、降级策略
Agent Registry 管理本地与远程 Agent 元数据 能力标签、版本、健康状态、灰度权重
Context Manager 管理会话、任务、链路上下文 Redis 持久化、上下文压缩、租户隔离
Tool Registry 管理工具定义与执行入口 动态工具发现、权限控制、审计
Guardrail 输入输出安全与业务风控 敏感词、PII、越权、人工确认
Event Bus 异步任务和领域事件 Kafka 解耦、削峰、最终一致
Observability 可观测与成本治理 traceId、token、latency、tool error

2.3 技术选型建议

场景 推荐方案
快速原型 Spring AI + ChatClient + 本地工具
中小规模生产 Spring AI + Redis ChatMemory/Context + Resilience4j + Micrometer
多团队协作 Spring AI Alibaba + Nacos A2A Registry + 独立 Agent 服务
高并发场景 Java 21 虚拟线程 + Reactor 流式输出 + Redis 限流 + K8s HPA
企业级治理 A2A + MCP + Kafka + OpenTelemetry + 评估集 + 灰度平台

三、领域建模:先把 Agent 当成工程组件,而不是 Prompt

3.1 Agent 元数据模型

生产环境中,一个 Agent 至少要描述这些信息:

package com.example.agent.core;

import java.time.Duration;
import java.util.Set;

public record AgentDescriptor(
        String name,
        String version,
        String description,
        Set<String> capabilities,
        Set<String> allowedToolNames,
        Duration timeout,
        int maxConcurrency,
        boolean streamingSupported,
        AgentStatus status
) {
    public boolean canHandle(String capability) {
        return status == AgentStatus.UP && capabilities.contains(capability);
    }
}

enum AgentStatus {
    UP, DEGRADED, DOWN
}

这里的重点不是字段本身,而是架构思想:Agent 必须像微服务一样被描述、注册、发现、限流、熔断和观测。

3.2 统一执行接口

package com.example.agent.core;

import reactor.core.publisher.Flux;

public interface Agent {

    AgentDescriptor descriptor();

    AgentResult execute(AgentRequest request);

    default Flux<AgentStreamChunk> stream(AgentRequest request) {
        return Flux.just(AgentStreamChunk.done(execute(request).answer()));
    }
}
package com.example.agent.core;

import java.time.Instant;
import java.util.Map;

public record AgentRequest(
        String requestId,
        String tenantId,
        String userId,
        String sessionId,
        String input,
        AgentContext context,
        Map<String, Object> attributes,
        Instant deadline
) {
    public boolean expired() {
        return Instant.now().isAfter(deadline);
    }
}

public record AgentResult(
        String agentName,
        String answer,
        double confidence,
        boolean requiresHuman,
        Map<String, Object> facts
) {
    public static AgentResult humanRequired(String agentName, String reason) {
        return new AgentResult(agentName, reason, 0.0, true, Map.of("reason", reason));
    }
}

public record AgentStreamChunk(String content, boolean done) {
    public static AgentStreamChunk chunk(String content) {
        return new AgentStreamChunk(content, false);
    }

    public static AgentStreamChunk done(String content) {
        return new AgentStreamChunk(content, true);
    }
}

统一接口的好处是,Orchestrator 不需要关心底层是本地 Agent、远程 A2A Agent、Graph 工作流,还是一个普通 Java 服务。

四、Skills 与 Tool Calling:从"能调用"升级为"可治理"

Spring AI 的 Tool Calling 把 Java 方法或函数暴露给模型,让模型在需要时调用业务系统。官方抽象里,工具最终会被建模为 ToolCallback,可以通过 @Tool、函数式 Bean 或自定义 ToolCallback 提供。

但生产环境不能只停留在 @Tool。一个可上线的 Skill 至少要具备:

  • 元数据:名称、版本、负责人、风险等级、所属业务域。
  • 权限:哪些 Agent、租户、用户角色可以调用。
  • 治理:超时、重试、熔断、限流、降级。
  • 审计:谁在什么上下文里调用了什么工具,参数和结果是否脱敏。
  • 幂等:创建工单、取消订单、发起退款等写操作必须可重复提交。

4.1 Skill 元数据

package com.example.agent.skill;

import java.time.Duration;
import java.util.Set;

public record SkillMetadata(
        String name,
        String version,
        String owner,
        String domain,
        SkillRiskLevel riskLevel,
        Set<String> allowedAgents,
        Duration timeout,
        int requestsPerSecond,
        boolean returnDirect
) {
}

enum SkillRiskLevel {
    LOW, MEDIUM, HIGH
}

4.2 生产级库存查询 Skill

下面的代码展示一个更接近生产的工具实现:包含参数校验、限流、超时、指标、审计与异常转换。

package com.example.agent.skill.inventory;

import com.example.agent.skill.SkillMetadata;
import com.example.agent.skill.SkillRiskLevel;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import jakarta.validation.constraints.NotBlank;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Set;

@Component
public class InventorySkill {

    private static final Logger log = LoggerFactory.getLogger(InventorySkill.class);

    private final InventoryClient inventoryClient;
    private final MeterRegistry meterRegistry;

    public InventorySkill(InventoryClient inventoryClient, MeterRegistry meterRegistry) {
        this.inventoryClient = inventoryClient;
        this.meterRegistry = meterRegistry;
    }

    public SkillMetadata metadata() {
        return new SkillMetadata(
                "inventory_query",
                "1.0.0",
                "inventory-team",
                "product",
                SkillRiskLevel.LOW,
                Set.of("product-agent", "orchestrator-agent"),
                Duration.ofSeconds(2),
                300,
                false
        );
    }

    @Tool(name = "inventory_query", description = "查询指定 SKU 在指定仓库的可售库存。只用于库存咨询,不用于锁库存。")
    @CircuitBreaker(name = "inventoryClient", fallbackMethod = "fallback")
    @RateLimiter(name = "inventoryClient")
    public InventoryResponse queryInventory(
            @ToolParam(description = "商品 SKU 编码,例如 SKU-10086") @NotBlank String sku,
            @ToolParam(description = "仓库编码,可为空;为空时查询全国汇总库存") String warehouseCode
    ) {
        Timer.Sample sample = Timer.start(meterRegistry);
        try {
            InventoryResponse response = inventoryClient.query(sku, warehouseCode);
            meterRegistry.counter("agent.skill.success", "skill", "inventory_query").increment();
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值