用 Solon TeamAgent 落地供应链异常管理与自动补货

某制造企业供应链团队每天要处理大量供应商、库存、物流异常。核心问题:

痛点 具体表现 业务损失
异常发现滞后 库存低于安全水位时发现偏晚 断供停工风险高
补货决策不一致 相同水位,不同采购员处理不同 资金占用波动大
供应商管理靠人盯 交期、质检靠人工跟踪 采购大量时间耗在查进度
多系统切换 ERP / WMS / SRM 来回切 一个异常要查多个系统

一、业务方案

1.1 目标

  • 异常发现从"天级"变为"巡检级"
  • 常规补货由 Agent 生成建议,小额可自动执行
  • 采购人效提升:一人可覆盖更多 SKU
  • 异常处理全流程可追踪

1.2 核心流程

text 复制代码
数据层
  ├─ ERP → 库存水位、在途订单、历史消耗
  ├─ SRM → 供应商交期、质检合格率、评级
  └─ WMS → 入库数据、库龄、呆滞料

Agent 巡检层
  ├─ 检测库存异常(低于安全水位 / 呆滞超期)
  ├─ 检测交期异常(预计延迟)
  ├─ 检测质检异常(批次合格率偏低)
  └─ 自动生成异常报告

自动化处理层
  ├─ 常规补货 → 生成采购建议 / 小额自动下单
  ├─ 延迟预警 → 通知供应商并要求回复
  ├─ 呆滞处理 → 提出降价/退货/报废建议
  └─ 严重异常 → 升级到供应链总监

二、技术落地(TeamAgent 实现)

说明 :供应链场景天然是多职责协作,更适合 TeamAgent + 多个 ReActAgent 成员

2.1 系统架构

text 复制代码
                 ┌──────────────────┐
                 │    TeamAgent     │
                 │  (供应链主管)      │
                 └────────┬─────────┘
                          │
          ┌───────────────┼───────────────┐
          │               │               │
   ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
   │ 库存监控 Agent│ │ 补货执行 Agent│ │ 异常处理 Agent│
   │ (ReActAgent) │ │ (ReActAgent) │ │ (ReActAgent) │
   └─────────────┘ └─────────────┘ └─────────────┘
          │               │               │
   ┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
   │ ERP API     │ │ 采购/OA API  │ │ SRM/通知 API │
   └─────────────┘ └─────────────┘ └─────────────┘

2.2 领域工具(真实 API)

java 复制代码
import org.noear.solon.ai.annotation.ToolMapping;
import org.noear.solon.ai.chat.tool.AbsToolProvider;
import org.noear.solon.annotation.Param;

/** 库存监控工具 */
public class InventoryTools extends AbsToolProvider {
    @ToolMapping(description = "查询指定 SKU 当前库存、安全水位、在途数量、日均消耗")
    public String check_inventory(@Param(description = "SKU 编码") String sku) {
        // 生产环境改为 ERP 查询
        return """
            {
              "sku":"%s",
              "quantity":850,
              "safeLevel":2000,
              "inTransit":0,
              "dailyConsumption":380.0,
              "alert":"below_safe_level"
            }
            """.formatted(sku);
    }

    @ToolMapping(description = "查询 SKU 补货提前期(天)")
    public String get_lead_time(@Param(description = "SKU 编码") String sku) {
        return "{\"sku\":\"" + sku + "\", \"leadTimeDays\": 12}";
    }
}

/** 补货执行工具 */
public class ReplenishmentTools extends AbsToolProvider {
    @ToolMapping(description = "根据当前库存、日均消耗、提前期计算建议补货量")
    public String calc_reorder_qty(
            @Param(description = "当前库存") int currentStock,
            @Param(description = "安全水位") int safeLevel,
            @Param(description = "日均消耗") double dailyConsumption,
            @Param(description = "提前期天数") int leadTimeDays) {
        int shortage = safeLevel - currentStock
                + (int) (dailyConsumption * leadTimeDays);
        int reorderQty = Math.max(shortage, 0);
        return "{\"reorderQty\": " + reorderQty + "}";
    }

    @ToolMapping(description = "创建采购单。小额可直接提交,大额返回待审批")
    public String create_po(
            @Param(description = "SKU") String sku,
            @Param(description = "采购数量") int qty,
            @Param(description = "供应商编码") String supplier,
            @Param(description = "预估金额") double amount) {
        if (amount >= 50_000) {
            return "{\"status\":\"pending_approval\", \"sku\":\"" + sku
                    + "\", \"qty\":" + qty + ", \"amount\":" + amount + "}";
        }
        return "{\"status\":\"submitted\", \"poNumber\":\"PO-"
                + System.currentTimeMillis() + "\", \"sku\":\"" + sku
                + "\", \"qty\":" + qty + ", \"supplier\":\"" + supplier + "\"}";
    }
}

/** 异常处理工具 */
public class ExceptionTools extends AbsToolProvider {
    @ToolMapping(description = "查询供应商交期与历史表现")
    public String check_supplier(
            @Param(description = "供应商编码") String supplierCode,
            @Param(description = "SKU") String sku) {
        return """
            {
              "supplier":"%s",
              "sku":"%s",
              "delayRate6m":0.12,
              "passRate":0.983,
              "preferred":true
            }
            """.formatted(supplierCode, sku);
    }

    @ToolMapping(description = "向主管发送异常升级通知")
    public String notify_manager(
            @Param(description = "异常摘要") String summary) {
        return "已通知供应链主管:" + summary;
    }
}

2.3 构建子代理与 TeamAgent

java 复制代码
import org.noear.solon.ai.agent.AgentSession;
import org.noear.solon.ai.agent.react.ReActAgent;
import org.noear.solon.ai.agent.session.InMemoryAgentSession;
import org.noear.solon.ai.agent.team.TeamAgent;
import org.noear.solon.ai.agent.team.TeamProtocols;
import org.noear.solon.ai.chat.ChatModel;

ChatModel chatModel = LlmUtil.getChatModel();

// 1) 库存监控专家
ReActAgent inventoryAgent = ReActAgent.of(chatModel)
        .name("inventory_monitor")
        .role("你是库存监控专家。负责检查库存水位,识别低于安全水位的 SKU。")
        .defaultToolAdd(new InventoryTools())
        .build();

// 2) 补货执行专家
ReActAgent replenishAgent = ReActAgent.of(chatModel)
        .name("replenishment")
        .role("你是补货执行专家。根据缺货信息计算补货量并创建采购单。")
        .defaultToolAdd(new ReplenishmentTools())
        .build();

// 3) 异常处理专家
ReActAgent exceptionAgent = ReActAgent.of(chatModel)
        .name("exception_handler")
        .role("你是异常处理专家。分析供应商风险,必要时升级通知主管。")
        .defaultToolAdd(new ExceptionTools())
        .build();

// 4) 组建团队(顺序协作)
TeamAgent supplyChainTeam = TeamAgent.of(chatModel)
        .name("supply_chain_group")
        .agentAdd(inventoryAgent)
        .agentAdd(replenishAgent)
        .agentAdd(exceptionAgent)
        .protocol(TeamProtocols.SEQUENTIAL)
        .build();

AgentSession session = InMemoryAgentSession.of("supply_chain_round_001");

String task = """
    巡检 SKU A-1002:
    1. 检查库存是否低于安全水位
    2. 若缺货,计算补货量并创建采购单(供应商 SUP-01,单价 0.12)
    3. 若金额或供应商风险偏高,升级通知主管
    """;

String result = supplyChainTeam.prompt(task)
        .session(session)
        .call()
        .getContent();

2.4 大额补货加 HITL

补货涉及资金,建议对 create_po 做人工审批:

java 复制代码
import org.noear.solon.ai.agent.react.intercept.HITLInterceptor;

HITLInterceptor hitl = new HITLInterceptor()
        .onTool("create_po", (trace, args) -> {
            double amount = Double.parseDouble(args.get("amount").toString());
            return amount >= 50_000 ? "大额补货需主管审批" : null;
        });

ReActAgent replenishAgent = ReActAgent.of(chatModel)
        .name("replenishment")
        .role("你是补货执行专家。")
        .defaultToolAdd(new ReplenishmentTools())
        .defaultInterceptorAdd(hitl)
        .build();

2.5 定时巡检怎么做?

TeamAgent / ReActAgent 本身不内置 cron。用业务调度触发即可:

java 复制代码
// 伪代码:每 15 分钟触发一次
@Scheduled(cron = "0 */15 * * * ?")
public void patrol() throws Throwable {
    String skuList = String.join(",", erpService.getAllActiveSku());
    supplyChainTeam.prompt("检查这些 SKU 的库存异常并给出处理建议:" + skuList)
            .session(InMemoryAgentSession.of("patrol-" + System.currentTimeMillis()))
            .call();
}

三、业务效果(定性)

  • 异常发现从"人工发现"变为"定时巡检"
  • 常规补货从手工填单变为 Agent 生成建议 / 小额自动提交
  • 采购可把时间集中在战略物料与异常供应商
  • 每条决策可留 session / 审批日志,便于审计

真实处理示例

巡检发现:SKU A-1002 库存 850,安全水位 2,000,日均消耗 380,在途 0

Agent 链路

  1. check_inventory → below_safe_level
  2. get_lead_time → 12 天
  3. calc_reorder_qty → 建议补 6,850
  4. 金额 = 6,850 × 0.12 = 822(低于 5 万)→ create_po 直接提交
  5. 金额若 ≥ 5 万,则 HITL 挂起,等主管批准

四、同类场景扩展

业务场景 数据源 巡检逻辑 自动动作
零售门店补货 POS、门店库存 销量接近安全库存 生成调拨单
医疗耗材 消耗记录、效期 近效期优先消耗 标记并通知临床
备件库 设备台账、故障率 备件低于历史消耗 生成采购需求
大宗原料 期货价、库存、产能 低价 + 低库存 生成采购方案
跨境 FBA 平台库存、销量预测 可售天数不足 生成货件计划

五、落地建议

  1. 先巡检、后执行:前两周只发现异常并通知,不自动下单
  2. 分阶段放开金额阈值:1 万 → 5 万 → 常规 SKU 全自动
  3. 每条自动执行留审计日志:时间、SKU、数量、审批人
相关推荐
潇凝子潇1 小时前
UnsupportedOperationException
java·前端·数据库
慧都小项1 小时前
C/C++ 静态分析为什么要前移?Parasoft C/C++test 在 IDE 与 CI/CD 中的应用
c语言·c++·ide·功能测试·ai
qq_33776320192 小时前
国际期货资管系统开发方案|内外盘交易平台源码授权与二次开发支持
java·c语言·开发语言·c++·c#
不定积分要+C_yyy2 小时前
Java关键字final三种用法、核心特性与高频易错点
java·开发语言
xexpertS3 小时前
队列积压治理:如何避免异步系统出现难以恢复的消息积压
java·开发语言
阿木实验室9 小时前
AI无人机来了,飞手会被取代吗?
ai·无人机
深海鱼肝油ya11 小时前
小说自动生成系统(二)
人工智能·大模型·agent·智能体·自动化编程·小说生成系统
小林ixn11 小时前
会议纪要自动化:用 Claude Skill 把重复工作“卷”成一行命令
agent·自动化运维
ZhengEnCi11 小时前
LLM02-Context Priming:利用强模型上下文提升弱模型能力的策略
llm