news 2026/10/21 11:24:41

聊聊 Agent 工程化:Demo 很好写,生产却处处是坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
聊聊 Agent 工程化:Demo 很好写,生产却处处是坑

前言

很多同学初学 Spring AI Alibaba 智能体时,都会觉得 Agent 开发非常简单:定义工具、注入模型、写一段提示词、调用agent.call()即可运行。

但这种只能跑通的 Demo Agent,绝对无法上线生产。

日常开发中,90% 的 Agent 线上问题(无限循环调用工具、模型幻觉、参数乱传、任务失控、无法排查),全部源于缺少生产级防护。

本文不讲传统编程、Workflow、Skill 基础概念,只讲Spring AI Alibaba 生产级 Agent 的核心落地标准,带完整可运行代码案例,区分「玩具 Agent」和「线上可用 Agent」的本质区别。

阅读提示:本文基于 Spring AI Alibaba 1.1.x 版本,部分 API 与早期版本存在差异,建议对照实际依赖版本确认方法签名。

一、为什么 Demo Agent 不能上生产?

1.1 Demo 版简易 Agent(反面案例,不要直接上生产)

特点:代码少,跑 Demo 很爽,上线会出各种问题
@Service
@RequiredArgsConstructor
public class SimpleDemoAgentService {

private final ChatModel chatModel;
private final DemoTool demoTool;

public ReactAgent buildDemoAgent() {
ToolCallbackProvider toolProvider = ToolCallbackProvider.of(demoTool);
return ReactAgent.builder()
.name("demo-agent")
.model(chatModel)
.tools(toolProvider.getToolCallbacks())
.instruction("你是订单故障排查专家,使用工具完成故障排查。")
// 没有最大迭代、没有超时、没有持久化、没有监听
.saver(new MemorySaver())
.build();
}

public String execute(String goal) {
ReactAgent agent = buildDemoAgent();
return agent.call(goal).getContent();
}
}

@Service
class DemoTool {
@Tool(description = "根据订单号查询错误日志")
public String queryErrorLog(@ToolParam(description = "订单号") String orderNo) {
throw new RuntimeException("数据库查询异常");
}
}

1.2 Demo Agent 线上必现的坑

  1. 没有最大迭代限制,模型可能无限循环调用同一个工具
  2. 工具抛出异常,直接打断整个 ReAct 推理循环,任务直接失败
  3. 使用MemorySaver,服务重启任务状态全部丢失
  4. 没有事件监听,工具调用、思考过程无记录,出问题无法排查
  5. 无超时控制,遇到大模型慢响应会持续占用业务线程
  6. 提示词只有角色,缺少失败策略、禁止行为约束

二、生产级 Agent 完整代码案例

2.1 生产工具层:Skill 改造

重点:工具只负责原子能力,异常由框架统一处理,无需在每个工具方法中重复 try-catch。

Spring AI Alibaba 内置了ToolExecutionExceptionProcessor机制。该接口是一个函数式接口,用于将工具抛出的ToolExecutionException转换为可发送回 AI 模型的字符串,或者抛出异常供调用者处理。这意味着我们可以在 Agent Builder 层面统一配置异常处理策略,工具类本身保持干净。

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class TroubleShootTool {

@Tool(description = "根据订单号查询订单错误日志,获取故障信息")
public String queryErrorLog(@ToolParam(description = "订单编号") String orderNo) {
// 入参校验,直接抛异常,由 ToolExecutionExceptionProcessor 统一处理
if (orderNo == null || orderNo.isBlank()) {
throw new IllegalArgumentException("orderNo不能为空");
}
// 模拟业务查询逻辑
// return db.selectLog(orderNo);
throw new RuntimeException("数据库连接异常");
}

@Tool(description = "查询订单基础信息")
public String queryOrderInfo(@ToolParam(description = "订单编号") String orderNo) {
if (orderNo == null || orderNo.isBlank()) {
throw new IllegalArgumentException("orderNo不能为空");
}
return "{\"orderNo\":\"" + orderNo + "\",\"userId\":10001,\"amount\":129.00}";
}
}

2.2 全链路可观测:基于 Hook 机制采集运行轨迹

重点:框架提供Hook机制,可在模型调用前后、工具执行前后插入自定义逻辑。Hook 逻辑要轻,不能阻塞主链路。

Spring AI Alibaba 内置了多种 Hook,包括ModelCallLimitHook(限制 LLM 调用次数)、ToolCallLimitHook(限制工具执行次数)、HumanInTheLoopHook(人工审批)、PIIDetectionHook(敏感信息检测)等。

以下自定义 Hook 用于采集 Agent 全链路运行轨迹:

import com.alibaba.cloud.ai.graph.agent.hook.Hook;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;

@Slf4j
@Component
public class TraceHook implements Hook {

private long taskStartTime;

@Override
public int getOrder() {
return 0;
}

@Override
public Map<String, Object> beforeModelCall(Map<String, Object> context) {
if (taskStartTime == 0) {
taskStartTime = System.currentTimeMillis();
log.info("[AgentTrace]任务开始");
}
log.info("[AgentTrace]模型调用前,上下文键:{}", context.keySet());
return context;
}

@Override
public Map<String, Object> afterModelCall(Map<String, Object> context) {
log.info("[AgentTrace]模型调用完成");
return context;
}

public long getCostMs() {
return System.currentTimeMillis() - taskStartTime;
}
}

Hook 接口提供了getTools()默认方法,允许 Hook 向 Agent 动态注册工具。耗时统计需业务代码自行完成并落库,框架不会自动持久化。

2.3 构建生产级 ReactAgent 服务

核心点:工具级超时、模型调用限制、生产提示词、注入 Hook、持久化 Saver、异常兜底。
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.checkpoint.BaseCheckpointSaver;
import com.alibaba.cloud.ai.graph.agent.hook.modelcalllimit.ModelCallLimitHook;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;

import java.time.Duration;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProductionAgentService {

private final ChatModel chatModel;
private final TroubleShootTool troubleShootTool;
private final TraceHook traceHook;
// 生产替换 MemorySaver,使用 RedisSaver / JDBCSaver 等持久化实现
private final BaseCheckpointSaver checkpointSaver;

/**
* 构建生产可用 Agent 实例
*/
public ReactAgent buildProductionAgent() {
// 生产提示词:不只是角色,增加强制约束、失败策略
String productionInstruct = """
你是订单故障排查专家。
1. 可以调用工具查询订单信息、查询错误日志。
2. 如果工具返回以【工具调用异常/工具业务错误】开头内容,不要无限重试同一个工具。
3. 证据收集充分后,直接输出排查结论,主动结束任务,禁止无意义调用工具。
4. 禁止编造工具,禁止编造业务数据,全部信息来源于工具返回。
""";

return ReactAgent.builder()
.name("production-trouble-agent")
.model(chatModel)
.methodTools(troubleShootTool) // 直接传入工具对象
.instruction(productionInstruct)
.checkpointSaver(checkpointSaver) // 持久化状态存储
.toolExecutionTimeout(Duration.ofSeconds(30)) // 工具级超时(默认5分钟)
.toolExecutionExceptionProcessor((ex, toolName, toolInput) -> {
// 统一异常处理:将异常转为可发送给模型的错误文本
log.error("工具[{}]执行异常,入参:{}", toolName, toolInput, ex);
return "【工具调用异常】" + toolName + "执行失败:" + ex.getMessage();
})
.hooks(
ModelCallLimitHook.builder().runLimit(5).build(), // 限制模型调用次数
traceHook // 全链路轨迹采集
)
.build();
}

/**
* 对外执行 Agent 任务,统一异常兜底
*/
public String runAgentTask(String userGoal) {
ReactAgent agent = buildProductionAgent();
try {
String result = agent.call(userGoal).getContent();
log.info("[Agent]任务完成,总耗时{}ms", traceHook.getCostMs());
return result;
} catch (Exception e) {
log.error("[Agent]执行发生系统异常,耗时{}ms", traceHook.getCostMs(), e);
if (e.getClass().getSimpleName().contains("MaxIterations")
|| e.getMessage() != null && e.getMessage().contains("limit")) {
return "任务终止:已达到最大工具调用轮次,无法继续执行,请精简问题重试。";
}
return "AI任务执行系统异常,请稍后重试。";
}
}
}

2.4 持久化 Saver 的选择

MemorySaver仅适合开发测试,生产环境需选用持久化实现。Spring AI Alibaba 提供了多种开箱即用的 Saver:

Saver 实现存储后端适用场景
MemorySaverJVM 堆内存开发/测试/单机,进程重启丢失
RedisSaverRedis生产级分布式部署,支持过期策略
JDBCSaverMySQL/PostgreSQL/H2关系型数据库持久化
MongoDBSaverMongoDB文档型数据库持久化
FileSaver文件系统本地文件持久化
@Configuration
public class GraphSaverConfig {

@Bean
@ConditionalOnMissingBean
public BaseCheckpointSaver redisSaver(RedisConnectionFactory connectionFactory) {
return new RedisSaver(connectionFactory);
}
}

2.5 简单测试 Controller

@RestController
@RequiredArgsConstructor
public class AgentTestController {

private final ProductionAgentService productionAgentService;

@GetMapping("/agent/prod/execute")
public String execute(@RequestParam String goal) {
return productionAgentService.runAgentTask(goal);
}
}

访问示例:

http://localhost:8080/agent/prod/execute?goal=帮我排查订单O20260919001为什么提交失败

三、Demo Agent vs 生产 Agent 核心对比

维度Demo 玩具 Agent生产级 Agent
执行约束完全依赖模型自觉ModelCallLimitHook+toolExecutionTimeout双重硬护栏
工具异常处理直接抛异常,中断任务ToolExecutionExceptionProcessor统一处理,模型自主决策
提示词仅角色描述包含完整业务约束、禁止行为、容错策略
可观测性无轨迹、无日志、无法排查Hook 机制监听,模型调用、工具执行、耗时全记录
状态存储MemorySaver内存,重启丢失RedisSaver/JDBCSaver持久化,可回溯可恢复
上层编排直接对外暴露调用嵌入 Workflow,作为子任务执行

四、代码关键点解读

1. 工具异常统一处理 ——ToolExecutionExceptionProcessor

ToolExecutionExceptionProcessor是一个函数式接口,用于处理ToolExecutionException,将异常转换为可发送回 AI 模型的字符串。这意味着工具类只需抛出异常,无需在每个方法中重复 try-catch。模型收到错误文本后会自主决策是重试还是放弃,而不是被异常中断推理循环。

2. 硬护栏 ——ModelCallLimitHook+toolExecutionTimeout

ModelCallLimitHook是 Spring AI Alibaba 内置的 Hook,用于限制每个线程或每次运行的 LLM 调用次数。toolExecutionTimeout控制单个工具的执行超时,默认值为 5 分钟。两者配合形成双重保护:前者防止模型无限循环,后者防止单个工具挂起。

3. Hook 机制 —— 可观测性的核心

Spring AI Alibaba 的 Hook 机制允许在 Agent 执行流程的特定位置(BEFORE_MODEL、AFTER_MODEL 等)插入自定义逻辑。工具调用名称、参数、模型思考均可通过 Hook 捕获。耗时、迭代计数需要业务代码自行统计落库,框架不会自动持久化。Hook 逻辑要轻,不能阻塞主链路。

4. 状态存储 ——BaseCheckpointSaver

MemorySaver只适合单元测试、Demo;生产要实现BaseCheckpointSaver接口,把消息历史、中间状态存入数据库。Spring AI Alibaba Graph 具有内置的持久化层,通过检查点实现,检查点会在每个超级步骤保存图状态的检查点。

5. 异常统一捕获 —— 对外接口友好降级

对外接口不能把框架原始异常直接抛给前端,要做业务友好降级返回。同时,Agent 级的总超时建议通过 Spring 的@Async+CompletableFuture.get(timeout)在外层做兜底。

五、官方能力补充

5.1 结构化输出

生产级 Agent 往往需要结构化的输出而非自由文本。Spring AI Alibaba 的ReactAgent.Builder通过outputSchema和outputType方法处理结构化输出。推荐使用outputType(Class)—— 传入 Java 类,框架自动通过BeanOutputConverter转换为 JSON Schema,兼顾类型安全与代码可维护性。

public record DiagnosisResult(
String orderNo,
String rootCause,
String suggestion
) {}

ReactAgent agent = ReactAgent.builder()
.name("diagnosis-agent")
.model(chatModel)
.methodTools(troubleShootTool)
.outputType(DiagnosisResult.class) // 结构化输出
.build();

这样上层业务代码可以直接获得 Java POJO,无需解析自然语言。

5.2 Workflow 编排

Spring AI Alibaba Agent Framework 预置了多种多智能体工作流模式:SequentialAgent(顺序代理)、ParallelAgent(并行代理)、RoutingAgent(路由代理)和LoopAgent(循环代理)。

生产架构建议:Workflow 控边界,Agent 做动态子任务决策。

var workflow = SequentialAgent.builder()
.name("order-troubleshoot-workflow")
.agents(
routingAgent, // 路由:判断问题类型,分发到不同 Agent
reactAgent // 动态子任务:ReAct Agent 完成具体排查
)
.build();

六、核心总结

  1. 能调用工具、能跑通流程的只是 Demo,不是生产 Agent。生产 Agent 80% 代码都是护栏、容错、观测、兜底,而非核心推理逻辑。
  2. Hook 机制是生产排查核心,可以捕获每一轮模型调用、工具执行、运行状态,实现全链路可追溯。ModelCallLimitHook和ToolCallLimitHook是官方提供的开箱即用的调用限制手段。
  3. 生产 Agent 必须代码硬约束 + 模型软约束结合:提示词约束模型行为;ModelCallLimitHook+toolExecutionTimeout强制兜底,双向防失控。
  4. 工具定位是原子能力,只干活不决策。异常通过ToolExecutionExceptionProcessor在 Agent 层面统一消化,不打断推理循环。
  5. 线上理想架构:Workflow 控边界,Agent 做动态子任务决策。通过SequentialAgent、RoutingAgent等编排模式组合多个 Agent,规避 AI 不确定性带来的业务风险。
  6. 结构化输出通过outputType(Class)实现,让 Agent 返回可直接被业务代码消费的 Java POJO,是生产级 Agent 的重要能力。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 11:21:34

agent-framework-azure-ai-py - SKILL

name: agent-framework-azure-ai-py description: “Build persistent agents on Azure AI Foundry using the Microsoft Agent Framework Python SDK.” risk: critical source: community date_added: “2026-02-27” Azure 托管代理的 Agent Framework 使用 Microsoft Agent…

作者头像 李华
网站建设 2026/10/21 11:10:22

2012-2024年 上市公司-企业业务招待费数据 (xlsx+文献)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/21 10:58:53

RuoYi-Vue-Plus 多租户后台管理系统:完整搭建与避坑指南

RuoYi-Vue-Plus 多租户后台管理系统&#xff1a;完整搭建与避坑指南 【免费下载链接】RuoYi-Vue-Plus 多租户后台管理系统 重写RuoYi-Vue所有功能 集成 Sa-Token、Mybatis-Plus、WarmFlow、SpringDoc、Hutool、OSS 定期同步 项目地址: https://gitcode.com/GitHub_Trending/r…

作者头像 李华