尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Spring AI Alibaba 项目源码学习(十一)-Hook

Spring AI Alibaba 项目源码学习(十一)-Hook
📅 发布时间:2026/6/19 3:23:35

Hook 机制分析

请关注微信公众号:阿呆-bot

概述

本文档分析 Spring AI Alibaba Agent Framework 中的 Hook(钩子)机制,包括 Hook 接口、AgentHook、ModelHook 的设计、实现原理、执行位置、跳转机制以及具体实现类。

入口类说明

Hook - 钩子接口

Hook 是所有钩子的基接口,定义了钩子的基本能力。

核心职责:

  • 定义钩子名称
  • 定义钩子类型
  • 定义执行位置
  • 定义跳转能力

关键代码:

public interface Hook {String getName();HookType getHookType();List<JumpTo> canJumpTo();/*** Get the positions where this hook should be executed.* By default, this method checks for the @HookPositions annotation on the implementing class.** @return array of HookPosition values*/default HookPosition[] getHookPositions() {HookPositions annotation = this.getClass().getAnnotation(HookPositions.class);if (annotation != null) {return annotation.value();}// Default fallback based on hook typeif (this instanceof AgentHook) {return new HookPosition[]{HookPosition.BEFORE_AGENT, HookPosition.AFTER_AGENT};} else if (this instanceof ModelHook) {return new HookPosition[]{HookPosition.BEFORE_MODEL, HookPosition.AFTER_MODEL};}return new HookPosition[0];}
}

HookPosition - 执行位置

HookPosition 枚举定义了钩子的执行位置。

关键代码:

public enum HookPosition {/*** Hook executes before the agent starts processing*/BEFORE_AGENT,/*** Hook executes after the agent completes processing*/AFTER_AGENT,/*** Hook executes before the model is called*/BEFORE_MODEL,/*** Hook executes after the model returns a response*/AFTER_MODEL
}

AgentHook - Agent 级别钩子

AgentHook 在 Agent 执行前后插入逻辑。

关键代码:

public interface AgentHook extends Hook {default CompletableFuture<Map<String, Object>> beforeAgent(OverAllState state, RunnableConfig config) {return CompletableFuture.completedFuture(Map.of());}default CompletableFuture<Map<String, Object>> afterAgent(OverAllState state, RunnableConfig config) {return CompletableFuture.completedFuture(Map.of());}}

ModelHook - 模型级别钩子

ModelHook 在模型调用前后插入逻辑。

关键代码:

public interface ModelHook extends Hook {default CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, RunnableConfig config) {return CompletableFuture.completedFuture(Map.of());}default CompletableFuture<Map<String, Object>> afterModel(OverAllState state, RunnableConfig config) {return CompletableFuture.completedFuture(Map.of());}@Overridedefault HookType getHookType() {return HookType.MODEL;}
}

JumpTo - 跳转目标

JumpTo 枚举定义了钩子可以跳转的目标。

关键代码:

public enum JumpTo {tool,model,end
}

Hook 集成机制

Graph 集成

Hook 被集成到 ReactAgent 的 Graph 中:

关键代码:

// Add hook nodesfor (Hook hook : hooks) {if (hook instanceof AgentHook agentHook) {graph.addNode(hook.getName() + ".before", agentHook::beforeAgent);graph.addNode(hook.getName() + ".after", agentHook::afterAgent);} else if (hook instanceof ModelHook modelHook) {graph.addNode(hook.getName() + ".beforeModel", modelHook::beforeModel);if (modelHook instanceof HumanInTheLoopHook humanInTheLoopHook) {graph.addNode(hook.getName() + ".afterModel", humanInTheLoopHook);} else {graph.addNode(hook.getName() + ".afterModel", modelHook::afterModel);}}else {throw new UnsupportedOperationException("Unsupported hook type: " + hook.getClass().getName());}}// Categorize hooks by positionList<Hook> beforeAgentHooks = filterHooksByPosition(hooks, HookPosition.BEFORE_AGENT);List<Hook> afterAgentHooks = filterHooksByPosition(hooks, HookPosition.AFTER_AGENT);List<Hook> beforeModelHooks = filterHooksByPosition(hooks, HookPosition.BEFORE_MODEL);List<Hook> afterModelHooks = filterHooksByPosition(hooks, HookPosition.AFTER_MODEL);// Determine node flowString entryNode = determineEntryNode(beforeAgentHooks, beforeModelHooks);String loopEntryNode = determineLoopEntryNode(beforeModelHooks);String loopExitNode = determineLoopExitNode(afterModelHooks);String exitNode = determineExitNode(afterAgentHooks);// Set up edgesgraph.addEdge(START, entryNode);setupHookEdges(graph, beforeAgentHooks, afterAgentHooks, beforeModelHooks, afterModelHooks,entryNode, loopEntryNode, loopExitNode, exitNode, true, this);return graph;

工具注入机制

Hook 可以通过 ToolInjection 接口注入工具:

关键代码:

private void setupToolsForHooks(List<Hook> hooks, AgentToolNode toolNode) {if (hooks == null || hooks.isEmpty() || toolNode == null) {return;}List<ToolCallback> availableTools = toolNode.getToolCallbacks();if (availableTools == null || availableTools.isEmpty()) {return;}for (Hook hook : hooks) {if (hook instanceof ToolInjection) {ToolInjection toolInjection = (ToolInjection) hook;ToolCallback toolToInject = findToolForHook(toolInjection, availableTools);if (toolToInject != null) {toolInjection.injectTool(toolToInject);}}}}

具体实现

ModelCallLimitHook - 模型调用限制钩子

ModelCallLimitHook 限制模型调用次数,防止过度调用。

关键代码:

@HookPositions({HookPosition.BEFORE_MODEL, HookPosition.AFTER_MODEL})
public class ModelCallLimitHook implements ModelHook {private static final String THREAD_COUNT_KEY = "__model_call_limit_thread_count__";private static final String RUN_COUNT_KEY = "__model_call_limit_run_count__";private final Integer threadLimit;private final Integer runLimit;private final ExitBehavior exitBehavior;@Overridepublic CompletableFuture<Map<String, Object>> beforeModel(OverAllState state, RunnableConfig config) {// Read current counts from stateint threadModelCallCount = state.value(THREAD_COUNT_KEY, Integer.class).orElse(0);int runModelCallCount = state.value(RUN_COUNT_KEY, Integer.class).orElse(0);// Check if limits are already exceeded (before making the call)boolean threadLimitExceeded = threadLimit != null && threadModelCallCount >= threadLimit;boolean runLimitExceeded = runLimit != null && runModelCallCount >= runLimit;if (threadLimitExceeded || runLimitExceeded) {if (exitBehavior == ExitBehavior.ERROR) {throw new ModelCallLimitExceededException(...);}else if (exitBehavior == ExitBehavior.END) {// Add message indicating limit was exceeded and jump to endString message = buildLimitExceededMessage(...);List<Message> messages = new ArrayList<>((List<Message>) state.value("messages").orElse(new ArrayList<>()));messages.add(new AssistantMessage(message));Map<String, Object> updates = new HashMap<>();updates.put("messages", messages);return CompletableFuture.completedFuture(updates);}}return CompletableFuture.completedFuture(Map.of());}@Overridepublic CompletableFuture<Map<String, Object>> afterModel(OverAllState state, RunnableConfig config) {// Read current counts from stateint threadModelCallCount = state.value(THREAD_COUNT_KEY, Integer.class).orElse(0);int runModelCallCount = state.value(RUN_COUNT_KEY, Integer.class).orElse(0);// Increment counters after the model callMap<String, Object> updates = new HashMap<>();updates.put(THREAD_COUNT_KEY, threadModelCallCount + 1);updates.put(RUN_COUNT_KEY, runModelCallCount + 1);return CompletableFuture.completedFuture(updates);}

功能:

  • 跟踪线程级别和运行级别的模型调用次数
  • 达到限制时终止 Agent 或抛出异常
  • 支持跳转到 END

HumanInTheLoopHook

HumanInTheLoopHook 实现交互机制,允许人工干预 Agent 执行。

功能:

  • 在模型调用后暂停执行
  • 等待人工输入或确认
  • 根据人工反馈决定继续或终止

PIIDetectionHook - PII 检测钩子

PIIDetectionHook 检测和处理个人身份信息(PII)。

功能:

  • 检测消息中的 PII
  • 标记或过滤敏感信息
  • 保护用户隐私

关键类关系

以下 PlantUML 类图展示了 Hook 系统的类关系:

image.png

关键流程

以下 PlantUML 时序图展示了 Hook 的执行流程:

dd.png

实现关键点说明

1. Graph 节点集成

Hook 被转换为 Graph 节点:

  • 每个 Hook 方法对应一个节点
  • 节点名称格式:{hookName}.{methodName}
  • 通过边连接形成执行链

2. 位置分类

Hook 按位置分类:

  • BEFORE_AGENT:Agent 执行前
  • AFTER_AGENT:Agent 执行后
  • BEFORE_MODEL:模型调用前
  • AFTER_MODEL:模型调用后

3. 链式执行

Hook 按顺序链式执行:

  • beforeAgent hooks 按顺序执行
  • beforeModel hooks 按顺序执行
  • afterModel hooks 按逆序执行
  • afterAgent hooks 按逆序执行

4. 跳转机制

Hook 可以通过 canJumpTo() 定义跳转能力:

  • JumpTo.tool:跳转到工具节点
  • JumpTo.model:跳转到模型节点
  • JumpTo.end:跳转到结束节点

跳转通过状态中的 jump_to 键控制。

5. 工具注入

Hook 可以通过 ToolInjection 接口注入工具:

  • 在 Graph 初始化时自动注入
  • 支持按名称或类型匹配
  • 用于 Hook 内部功能实现

6. 状态更新

Hook 通过返回 Map<String, Object> 更新状态:

  • 返回的 Map 会合并到当前状态
  • 支持键策略控制更新方式
  • 可以修改消息、添加元数据等

总结说明

核心设计理念

  1. 生命周期钩子:在 Agent 和 Model 的关键生命周期点插入逻辑
  2. Graph 集成:Hook 作为 Graph 节点集成到执行流程
  3. 跳转控制:支持灵活的流程控制,可以跳转到不同节点
  4. 工具注入:支持 Hook 使用工具实现复杂功能

关键优势

  • 灵活性:可以在多个位置插入自定义逻辑
  • 可扩展性:易于添加新的 Hook 实现
  • 流程控制:支持跳转机制实现复杂流程
  • 解耦设计:Hook 与核心逻辑解耦

解决的问题

  • 监控和限制:通过 ModelCallLimitHook 限制调用次数
  • 人工干预:通过 HumanInTheLoopHook 实现人工干预
  • 安全检测:通过 PIIDetectionHook 检测敏感信息
  • 工具集成:通过 ToolInjection 支持 Hook 使用工具

使用场景

  • ModelCallLimitHook:需要限制模型调用次数的场景
  • HumanInTheLoopHook:需要人工审核或确认的场景
  • PIIDetectionHook:需要保护用户隐私的场景
  • 自定义 Hook:需要扩展 Agent 功能的场景

Hook 机制为 Agent Framework 提供了强大的扩展能力,使开发者能够在 Agent 生命周期的关键点插入自定义逻辑,实现复杂的业务需求。

相关新闻

  • ftp,sftp,scp,tftp几种简单对比,以及python实现ftp功能
  • 实用指南:深入解析音频编解码器(Audio CODEC):硬件、接口与驱动开发
  • linux burpsuite

最新新闻

  • 跨境零售库存与定价人工调控滞销囤货问题很难提前预判?2026智能体自动化方案实战
  • 打破语言壁垒:Translumo如何让游戏、视频和软件界面瞬间变得可读?
  • 智能锡膏柜选购经验分享,亲测效果好
  • 高速ADC实战指南:从MCP37220/MCP37D20-200参数解读到系统设计避坑
  • 终极指南:霞鹜文楷屏幕阅读版字体如何解决数字阅读疲劳问题
  • i.MX异构多核VirtIO网络共享:原理、部署与性能调优实战

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号