Logo车 专
返回项目列表

智能体风险管控

Agent风险管控Checkpoint限流重试

搭建多层执行防护体系,整合调用频次限流、指数退避重试、异常优雅降级能力,规避 Agent 循环调用与服务失控问题;基于 Checkpoint 持久化推理状态,实现复杂任务断点恢复与状态回溯

智能体风险管控

搭建多层执行防护体系,整合调用频次限流、指数退避重试、异常优雅降级能力,规避 Agent 循环调用、服务失控问题;基于 Checkpoint 持久化推理状态,实现复杂任务断点恢复与状态回溯。


一、多层防护架构总览

┌─────────────────────────────────────────────────────────────┐
│  Layer 6: HTTP 请求守卫                                      │
│  AdminAuthInterceptor (JWT) + PreviewModeInterceptor (只读)  │
├─────────────────────────────────────────────────────────────┤
│  Layer 6: 幂等防护 (AOP)                                     │
│  RepeatExecuteLimit → Redisson 分布式锁 + Redis 成功标记      │
├─────────────────────────────────────────────────────────────┤
│  Layer 5: 集群会话锁 (Redis Lease)                           │
│  Lua 原子操作: ACQUIRE / RENEW / RELEASE                     │
├─────────────────────────────────────────────────────────────┤
│  Layer 4: JVM 任务注册                                       │
│  ChatRuntimeRegistry: ConcurrentHashMap.putIfAbsent()       │
├─────────────────────────────────────────────────────────────┤
│  Layer 3: Agent 循环限流 (Hooks)                             │
│  ModelCallLimitHook + ToolCallLimitHook                     │
├─────────────────────────────────────────────────────────────┤
│  Layer 2: 执行拦截器链 (Interceptors)                         │
│  兼容适配 → 输入降级 → 指数退避重试 → 异常兜底                   │
├─────────────────────────────────────────────────────────────┤
│  Layer 1: Checkpoint 持久化 + 断点恢复                        │
│  MysqlSaver → GRAPH_CHECKPOINT / GRAPH_THREAD               │
└─────────────────────────────────────────────────────────────┘

二、调用频次限流

2.1 Agent Hooks 限流(最内层)

ChatAgentConfiguration 中为 ReactAgent 注册两个限流 Hook:

Hook单次运行上限线程生命周期上限超限行为
ModelCallLimitHook8 次40 次END(优雅终止)
ToolCallLimitHook (tavily_search)6 次30 次END(优雅终止)

超限行为 ExitBehavior.END 意味着不会抛异常,而是让 Agent 在当前轮次正常结束并返回已有结果,避免用户看到报错。

2.2 配置参数

ChatAgentProperties 中可调:

参数默认值说明
maxModelCallsPerRun8单次 Agent 执行最大 LLM 调用数
maxModelCallsPerThread40单个会话线程最大 LLM 调用数
maxToolCallsPerRun6单次执行最大 Tavily 搜索次数
maxToolCallsPerThread30单个会话线程最大 Tavily 搜索次数
recommendationTimeoutMs3000推荐问题生成超时

2.3 分布式幂等限流

通过 @RepeatExecuteLimit 注解 + AOP 实现双层防重:

请求到达
  → Redis success flag 检查(已成功则直接返回)
  → JVM LocalLockCache 检查(本地已加锁则拒绝)
  → Redisson 公平锁获取(分布式锁)
  → 执行业务方法
  → 执行成功 → 设置 Redis success flag(durationTime TTL)

三层检查确保同一操作不会在集群中重复执行。


三、指数退避重试

3.1 ToolRetryInterceptor 配置

ChatAgentConfiguration 中配置:

ToolRetryInterceptor.builder()
    .toolName("tavily_search")
    .maxRetries(2)
    .initialDelay(200L)     // 初始延迟 200ms
    .maxDelay(1200L)        // 最大延迟 1200ms
    .jitter(true)           // 随机抖动,防止惊群效应
    .onFailure(OnFailureBehavior.RETURN_MESSAGE)
    .build()

3.2 退避策略

重试次数退避延迟(约)说明
第 1 次~200msinitialDelay
第 2 次~400msinitialDelay × 2
第 3 次~800msinitialDelay × 4(上限 maxDelay 1200ms)

加上 jitter=true 随机抖动,实际延迟会在计算值上下波动,避免大量请求同时重试。

3.3 失败兜底

OnFailureBehavior.RETURN_MESSAGE —— 全部重试失败后,返回一段用户可读的消息而非抛出异常,保证对话不中断。


四、异常优雅降级

4.1 TavilyToolInputFallbackInterceptor(输入降级)

拦截所有 tavily_search 调用,处理 LLM 生成异常参数:

异常情况降级策略
参数为空RunnableConfig 中取原始用户问题作为查询词
JSON 缺少 query 字段注入兜底查询词
参数为纯文本非 JSON自动包装为 {"query": "..."}
无任何可用兜底值返回 ToolCallResponse.error("tavily_search 工具缺少可用的 query 参数")

4.2 DashScopeCompatibilityInterceptor(兼容适配)

处理 DashScope(阿里云)模型与非标准输出的兼容问题:

兼容问题处理方式
不支持并行工具调用强制 parallelToolCalls = false
不支持 stream options移除流式选项
工具调用片段拆分按 ID 合并碎片化的 tool call(id/name/arguments 跨段补全)

同时记录完整的请求/响应日志(INFO 级别),用于问题排查。

4.3 ToolErrorInterceptor(异常兜底)

作为拦截器链的最后一环,捕获所有前面未处理的工具调用异常,将其转换为工具响应消息而非让 Agent 崩溃。

4.4 对话级优雅失败

BusinessChatService 的三种结束路径均使用 AtomicBoolean finalized 保证清理只执行一次:

路径触发场景行为
finishSuccessfully正常完成发送引用/推荐、归档到 MySQL、释放锁
finishWithFailure异常失败解析异常链提取 HTTP 错误详情、SSE 推送错误事件
stopTask用户主动停止中断 ReactAgent、SSE 推送停止状态

三种路径均保证:释放 Redis Lease + 移出运行时注册表 + 释放 Reactive 订阅。

4.5 无证据短路线(防幻觉)

在 RAG 检索链路中,若检索不到任何证据,系统返回"当前文档中没有检索到足够证据"而非让模型自由生成,避免幻觉。由 ChatPreparationOrchestrator 管控。


五、Agent 循环调用与失控防护

5.1 多层限流矩阵

层级机制限制
HooksModelCallLimitHook8 次/run,40 次/thread
HooksToolCallLimitHook6 次/run,30 次/thread
重试ToolRetryInterceptor最多 2 次,指数退避
超时Tavily HTTP 客户端连接 3s,读取 6s
租约Redis Lease每 10s 续期,30s TTL
注册JVM 任务注册putIfAbsent 防同会话并发

所有 Hook 超限行为均为 END(非 THROW),Agent 在当前轮次正常结束,不会扩散异常。

5.2 集群会话锁

RedisLeaseManager 基于 Lua 原子脚本 操作 Redis:

操作Lua 脚本逻辑
ACQUIRESET NX PX —— 仅当 key 不存在时设置,带毫秒 TTL
RENEW仅当 value 等于当前持有者 token 时才续期(防窃取)
RELEASE仅当 value 等于当前持有者 token 时才删除(防误释放)

租约 Key 格式:chat:running:{conversationId},TTL 30 秒,每 10 秒续期一次。

5.3 用户主动中断

businessChatReactAgent.interrupt(taskInfo.runnableConfig());

通过 Checkpoint 系统中断 Agent 执行,释放资源。


六、Checkpoint 持久化推理状态

6.1 数据库表结构

GRAPH_CHECKPOINT

字段类型说明
checkpoint_idVARCHAR(36)检查点唯一 ID(主键)
thread_idVARCHAR(36)会话线程 ID(外键关联 GRAPH_THREAD)
node_idVARCHAR(255)当前 Agent 图节点
next_node_idVARCHAR(255)下一个节点
state_dataJSON完整推理状态(含 messages 数组)
saved_atTIMESTAMP保存时间

索引:(thread_id, saved_at) 联合索引,支持按线程查询最新检查点。

GRAPH_THREAD

字段类型说明
thread_idVARCHAR(36)线程唯一 ID(主键)
thread_nameVARCHAR(255)线程名称(对应 conversationId)
is_releasedBOOLEAN是否已释放

唯一索引:(thread_name, is_released) 保证同一会话只有一个活跃线程。

6.2 MysqlSaver Bean

@Bean
public MysqlSaver mysqlCheckpointSaver(DataSource dataSource) {
    return MysqlSaver.builder()
        .dataSource(dataSource)
        .createOption(CreateOption.CREATE_IF_NOT_EXISTS)
        .build();
}

基于 com.alibaba.cloud.ai.graph.checkpoint.savers.mysql.MysqlSaver,自动建表,注入到 ReactAgent 的 .saver()

6.3 Checkpoint 管理服务

ChatCheckpointManager 封装三个操作:

操作方法行为
读取get(RunnableConfig)读取指定线程的最新检查点
列表list(RunnableConfig)列出线程的所有检查点
清空clearThread(String threadId)事务性删除检查点 + 线程记录

七、断点恢复与状态回溯

7.1 对话恢复

BusinessChatService 加载会话时:

RunnableConfig runnableConfig = RunnableConfig.builder()
    .threadId(archiveRecord.conversationId())
    .build();

Map<String, Object> state = checkpointManager.get(runnableConfig)
    .map(Checkpoint::getState)
    .orElseGet(Map::of);
Object messages = state.getOrDefault("messages", List.of());

从 MySQL 读取最新检查点,提取 messages 数组恢复到界面。即使应用重启,对话历史也不丢失。

7.2 会话视图暴露

ConversationSessionView 包含 checkpointCount 字段,显示该会话的检查点数量。

7.3 会话重置清理

int removedCheckpointCount = checkpointManager.clearThread(conversationId);

重置会话时清理所有检查点,返回删除数量。

7.4 执行恢复机制

ReactAgentExecutor 执行时传入相同的 threadId(即 conversationId):

reactAgent.stream(question, taskInfo.runnableConfig())

框架自动在每次模型交互/工具调用后保存检查点。使用相同 threadId 重新执行时,框架可从最后一个检查点恢复。


八、可观测性

8.1 全链路追踪

ConversationTraceRecorder 记录每个执行阶段的:

  • 阶段名称、开始/结束时间、执行状态(COMPLETED / FAILED)
  • 结构化快照数据

存储到 super_agent_chat_exchange_trace_stage 表。

8.2 用量与限流追踪

模型用途
ChatLimitStats限流统计:已用量 vs 上限、是否触发限流
ChatModelUsageTrace模型调用:token 消耗、provider、模型名、耗时、估算费用
ChatToolTrace工具调用:输入/输出、状态、错误信息、耗时
ChatDebugTrace调试全追踪(含限流统计)

通过 API /api/chat/exchange/detail 可查看完整的调试追踪信息。


九、HTTP 层守卫

9.1 AdminAuthInterceptor(JWT 认证)

拦截所有 /manage/**/admin/auth/me 请求:

  • 从请求头提取 JWT Token
  • 验证签名和有效期
  • 失败返回 401 + JSON 错误体

9.2 PreviewModeInterceptor(预览模式)

app.preview-mode.enabled=true 时,拦截 16 个写操作路径:

  • 对话流、文档上传/删除、索引重建等
  • 流式端点返回 SSE 错误事件
  • REST 端点返回 JSON 错误

9.3 配置

参数默认值说明
app.admin-auth.enabled管理后台认证开关
app.admin-auth.jwt.secretJWT 签名密钥
app.admin-auth.jwt.expiration-minutesJWT 过期时间
app.preview-mode.enabledfalse预览模式/只读模式开关

十、涉及扩展点(未启用)

作为参考实现的示例代码(ai-example 模块),展示 Hook 和 Interceptor 的扩展能力:

示例类型功能
LoggingHookAgentHook在 Agent 执行前后记录日志
SensitiveWordInterceptorModelInterceptor拦截敏感词(炸药/违法洗钱/攻击学校),注入安全提示

十一、完整文件清单

核心配置与拦截器

文件职责
chatagent/config/ChatAgentConfiguration.java集中装配 Hooks、Interceptors、Checkpoint Saver、ReactAgent
chatagent/config/ChatAgentProperties.java所有限流参数配置
chatagent/config/TavilySearchProperties.javaTavily HTTP 超时配置
chatagent/support/DashScopeCompatibilityInterceptor.javaDashScope 兼容适配
chatagent/support/TavilyToolInputFallbackInterceptor.javaTavily 输入降级
chatagent/support/ChatContextKeys.java上下文 Key 常量
chatagent/tool/TavilySearchTool.javaTavily 工具(含超时与追踪)

Checkpoint 系统

文件职责
chatagent/service/ChatCheckpointManager.javaCheckpoint 增删查 + 线程清理
chatagent/data/GraphCheckpoint.javaCheckpoint 实体
chatagent/data/GraphThread.javaGraph 线程实体
chatagent/mapper/GraphCheckpointMapper.javaMyBatis-Plus Mapper
chatagent/mapper/GraphThreadMapper.javaMyBatis-Plus Mapper

执行与调度

文件职责
chatagent/rag/executor/ReactAgentExecutor.java调用 ReactAgent + Checkpoint 支持
chatagent/service/BusinessChatService.java编排 Lease、Registry、执行、清理
chatagent/service/ChatRuntimeRegistry.javaJVM 级任务注册
chatagent/service/ConversationTraceRecorder.java全链路追踪记录

分布式安全框架

文件职责
service-lease-framework/.../RedisLeaseManager.javaRedis Lua 分布式租约
repeat-execute-limit-framework/.../RepeatExecuteLimit.java幂等注解
repeat-execute-limit-framework/.../RepeatExecuteLimitAspect.javaAOP 幂等切面

HTTP 守卫

文件职责
auth/support/AdminAuthInterceptor.javaJWT 认证拦截
auth/support/PreviewModeInterceptor.java预览模式拦截
auth/config/AdminWebMvcConfiguration.java拦截器注册
auth/config/PreviewModeProperties.java预览模式配置

调试/追踪模型

文件职责
chatagent/model/debug/ChatLimitStats.java限流统计
chatagent/model/debug/ChatModelUsageTrace.java模型用量追踪
chatagent/model/debug/ChatToolTrace.java工具追踪
chatagent/model/debug/ChatDebugTrace.java全量调试追踪
chatagent/model/ConversationSessionView.java会话视图(含 checkpointCount)
chatagent/vo/ConversationResetVo.java重置结果(含 removedCheckpointCount)

示例扩展(ai-example)

文件职责
ai-example/.../LoggingHook.javaAgentHook 示例
ai-example/.../SensitiveWordInterceptor.javaModelInterceptor 敏感词示例

数据库 DDL

文件职责
sql/Mysql/create_table_mysql.sqlGRAPH_CHECKPOINT、GRAPH_THREAD 建表语句

十二、设计亮点总结

  1. 纵深防御:六层防护从 HTTP → AOP → Redis → JVM → Agent Hooks → Checkpoint,每层独立,任一层失效不影响其他层
  2. 超限优雅终止ExitBehavior.END 而非 THROW,Agent 达到调用上限后正常返回已有结果,用户无感知
  3. 指数退避 + 抖动initialDelay=200ms → 400ms → 800ms,叠加随机抖动,避免重试风暴
  4. 降级链完整:输入降级(TavilyFallback)→ 重试(Retry)→ 异常兜底(ErrorInterceptor)→ 对话级兜底(finishWithFailure),问题不会穿透到用户
  5. Checkpoint 全自动:框架在每次模型/工具交互后自动保存状态到 MySQL,无需手动编码;相同 threadId 重启自动恢复
  6. 租约防窃取:Lua 原子脚本保证 Renew/Release 仅当 token 匹配时执行,防止集群中误释放他人租约
  7. 预览模式安全阀:一键开启只读模式,拦截所有写操作,适用于演示/线上只读场景
返回项目列表