Spring AI Alibaba 项目源码学习(七)-Agent、BaseAgent、ReactAgent 分析

Agent、BaseAgent、ReactAgent 分析

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

概述

本文档分析 Spring AI Alibaba Agent Framework 中的核心 Agent 类层次结构,包括 Agent 基类、BaseAgent 抽象类和 ReactAgent 具体实现,重点分析其关键方法、功能职责和类间关系。

入口类说明

Agent - 所有 Agent 的基类

Agent 是所有 Agent 实现的抽象基类,提供了 Agent 的通用能力和 Graph 管理功能。

核心职责

  • 管理 Agent 的名称和描述
  • 提供 Graph 的初始化和编译
  • 提供统一的调用接口(invoke、stream)
  • 支持调度执行

关键代码

public abstract class Agent {  	/** The agent's name. Must be a unique identifier within the graph. */ 	protected String name;  	/** 	 * One line description about the agent's capability. The system can use this for 	 * decision-making when delegating control to different agents. 	 */ 	protected String description;  	protected CompileConfig compileConfig;  	protected volatile CompiledGraph compiledGraph;  	protected volatile StateGraph graph;  	/** 	 * Protected constructor for initializing all base agent properties. 	 * @param name the unique name of the agent 	 * @param description the description of the agent's capability 	 */ 	protected Agent(String name, String description) throws GraphStateException { 		this.name = name; 		this.description = description; 	}  	/** 	 * Default protected constructor for subclasses that need to initialize properties 	 * differently. 	 */ 	protected Agent() { 		// Allow subclasses to initialize properties through other means 	}  	/** 	 * Gets the agent's unique name. 	 * @return the unique name of the agent. 	 */ 	public String name() { 		return name; 	}  	/** 	 * Gets the one-line description of the agent's capability. 	 * @return the description of the agent. 	 */ 	public String description() { 		return description; 	}  	public StateGraph getGraph() { 		if (this.graph == null) { 			try { 				this.graph = initGraph(); 			} 			catch (GraphStateException e) { 				throw new RuntimeException(e); 			} 		} 		return this.graph; 	}  	public synchronized CompiledGraph getAndCompileGraph() { 		if (compiledGraph != null) { 			return compiledGraph; 		}  		StateGraph graph = getGraph(); 		try { 			if (this.compileConfig == null) { 				this.compiledGraph = graph.compile(); 			} 			else { 				this.compiledGraph = graph.compile(this.compileConfig); 			} 		} catch (GraphStateException e) { 			throw new RuntimeException(e); 		} 		return this.compiledGraph; 	} 

关键方法

  • initGraph():抽象方法,子类实现以创建状态图
  • getAndCompileGraph():获取并编译 Graph(线程安全)
  • invoke():同步调用 Agent
  • stream():流式调用 Agent

BaseAgent - Agent 的抽象扩展

BaseAgent 继承自 Agent,提供了输入输出管理和节点转换能力。

核心职责

  • 管理输入输出 Schema 和类型
  • 管理输出键和键策略
  • 提供 asNode() 方法将 Agent 转换为 Graph 节点

关键代码

public abstract class BaseAgent extends Agent {  	protected String inputSchema; 	protected Type inputType;  	protected String outputSchema; 	protected Class<?> outputType;  	/** The output key for the agent's result */ 	protected String outputKey;  	protected KeyStrategy outputKeyStrategy;  	protected boolean includeContents;  	protected boolean returnReasoningContents;  	public BaseAgent(String name, String description, boolean includeContents, boolean returnReasoningContents, String outputKey, 			KeyStrategy outputKeyStrategy) throws GraphStateException { 		super(name, description); 		this.includeContents = includeContents; 		this.returnReasoningContents = returnReasoningContents; 		this.outputKey = outputKey; 		this.outputKeyStrategy = outputKeyStrategy; 	}  	public abstract Node asNode(boolean includeContents, boolean returnReasoningContents, String outputKeyToParent);  	public boolean isIncludeContents() { 		return includeContents; 	}  	public String getOutputKey() { 		return outputKey; 	}  	public void setOutputKey(String outputKey) { 		this.outputKey = outputKey; 	}  	public KeyStrategy getOutputKeyStrategy() { 		return outputKeyStrategy; 	}  	public void setOutputKeyStrategy(KeyStrategy outputKeyStrategy) { 		this.outputKeyStrategy = outputKeyStrategy; 	}  	String getInputSchema() { 		return inputSchema; 	}  	void setInputSchema(String inputSchema) { 		this.inputSchema = inputSchema; 	}  	Type getInputType() { 		return inputType; 	}  	void setInputType(Type inputType) { 		this.inputType = inputType; 	}  	String getOutputSchema() { 		return outputSchema; 	}  	void setOutputSchema(String outputSchema) { 		this.outputSchema = outputSchema; 	}  	void setIncludeContents(boolean includeContents) { 		this.includeContents = includeContents; 	}  	public boolean isReturnReasoningContents() { 		return returnReasoningContents; 	}  	public void setReturnReasoningContents(boolean returnReasoningContents) { 		this.returnReasoningContents = returnReasoningContents; 	} } 

关键方法

  • asNode():抽象方法,将 Agent 转换为 Graph 节点,用于嵌套 Agent

ReactAgent - ReAct 模式实现

ReactAgentBaseAgent 的具体实现,实现了经典的 ReAct(Reasoning + Acting)模式。

核心职责

  • 实现 ReAct 循环:推理 → 行动 → 观察
  • 管理 LLM 节点和工具节点
  • 支持 Hook 和 Interceptor 扩展
  • 控制最大迭代次数

关键代码

public class ReactAgent extends BaseAgent { 	private static final int DEFAULT_MAX_ITERATIONS = 10;  	private final AgentLlmNode llmNode;  	private final AgentToolNode toolNode;  	private CompiledGraph compiledGraph;  	private List<Hook> hooks;  	private List<ModelInterceptor> modelInterceptors;  	private List<ToolInterceptor> toolInterceptors;  	private int maxIterations;  	private int iterations = 0;  	private String instruction;  	private Function<OverAllState, Boolean> shouldContinueFunc;  	public ReactAgent(AgentLlmNode llmNode, AgentToolNode toolNode, CompileConfig compileConfig, Builder builder) throws GraphStateException { 		super(builder.name, builder.description, builder.includeContents, builder.returnReasoningContents, builder.outputKey, builder.outputKeyStrategy); 		this.instruction = builder.instruction; 		this.llmNode = llmNode; 		this.toolNode = toolNode; 		this.compileConfig = compileConfig; 		this.shouldContinueFunc = builder.shouldContinueFunc; 		this.hooks = builder.hooks; 		this.modelInterceptors = builder.modelInterceptors; 		this.toolInterceptors = builder.toolInterceptors; 		this.includeContents = builder.includeContents; 		this.inputSchema = builder.inputSchema; 		this.inputType = builder.inputType; 		this.outputSchema = builder.outputSchema; 		this.outputType = builder.outputType; 		this.maxIterations = builder.maxIterations <= 0 ? DEFAULT_MAX_ITERATIONS : builder.maxIterations;  		// Set interceptors to nodes 		if (this.modelInterceptors != null && !this.modelInterceptors.isEmpty()) { 			this.llmNode.setModelInterceptors(this.modelInterceptors); 		} 		if (this.toolInterceptors != null && !this.toolInterceptors.isEmpty()) { 			this.toolNode.setToolInterceptors(this.toolInterceptors); 		} 	} 

Graph 初始化

@Override 	protected StateGraph initGraph() throws GraphStateException { 		KeyStrategyFactory keyStrategyFactory = buildMessagesKeyStrategyFactory();  		if (hooks == null) { 			hooks = new ArrayList<>(); 		}  		// Validate hook uniqueness 		Set<String> hookNames = new HashSet<>(); 		for (Hook hook : hooks) { 			if (!hookNames.add(hook.getName())) { 				throw new IllegalArgumentException("Duplicate hook instances found"); 			} 		}  		// Create graph 		StateGraph graph = new StateGraph(name, keyStrategyFactory);  		graph.addNode("model", node_async(this.llmNode)); 		graph.addNode("tool", node_async(this.toolNode));  		// some hooks may need tools so they can do some initialization/cleanup on start/end of agent loop 		setupToolsForHooks(hooks, toolNode);  		// Add hook nodes 		for (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 position 		List<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 flow 		String entryNode = determineEntryNode(beforeAgentHooks, beforeModelHooks); 		String loopEntryNode = determineLoopEntryNode(beforeModelHooks); 		String loopExitNode = determineLoopExitNode(afterModelHooks); 		String exitNode = determineExitNode(afterAgentHooks);  		// Set up edges 		graph.addEdge(START, entryNode); 		setupHookEdges(graph, beforeAgentHooks, afterAgentHooks, beforeModelHooks, afterModelHooks, 				entryNode, loopEntryNode, loopExitNode, exitNode, true, this); 		return graph; 	} 

关键类关系

以下 PlantUML 类图展示了 Agent 类层次结构:
Spring AI Alibaba 项目源码学习(七)-Agent、BaseAgent、ReactAgent 分析

关键流程

以下 PlantUML 时序图展示了 ReactAgent 的执行流程:
Spring AI Alibaba 项目源码学习(七)-Agent、BaseAgent、ReactAgent 分析

实现关键点说明

1. 模板方法模式

Agent 使用模板方法模式:

  • initGraph() 是抽象方法,子类实现具体的图构建逻辑
  • getAndCompileGraph() 是模板方法,定义了 Graph 的获取和编译流程

2. Builder 模式

ReactAgent 使用 Builder 模式构建:

  • Builder 类提供流畅的 API
  • 支持链式调用配置各种参数
  • build() 时创建 ReactAgent 实例

3. ReAct 循环实现

ReactAgent 通过 Graph 实现 ReAct 循环:

  • model 节点:LLM 推理,决定下一步行动
  • tool 节点:执行工具调用
  • 条件边:根据 LLM 输出决定是否继续循环

4. Hook 集成机制

Hook 被集成到 Graph 中:

  • AgentHook:在 Agent 执行前后插入节点
  • ModelHook:在模型调用前后插入节点
  • 通过 HookPosition 控制执行时机

5. Interceptor 链式调用

Interceptor 通过链式调用实现:

  • ModelInterceptor:拦截模型调用请求和响应
  • ToolInterceptor:拦截工具调用请求和响应
  • 支持请求修改和响应处理

6. 状态管理

使用 OverAllState 管理状态:

  • messages 键存储对话历史
  • input 键存储用户输入
  • 支持键策略控制状态更新方式

总结说明

核心设计理念

  1. 分层抽象:Agent → BaseAgent → ReactAgent 三层设计,职责清晰
  2. ReAct 模式:通过 Graph 实现推理-行动循环
  3. 可扩展性:通过 Hook 和 Interceptor 机制支持扩展
  4. 状态驱动:基于状态图的状态驱动执行

关键优势

  • 灵活性:支持多种调用方式(同步、异步、流式)
  • 可扩展性:Hook 和 Interceptor 机制支持功能扩展
  • 可组合性:通过 asNode() 方法支持 Agent 嵌套
  • 类型安全:支持输入输出 Schema 和类型定义

使用场景

  • 单 Agent 应用:直接使用 ReactAgent 构建单 Agent 应用
  • 多 Agent 编排:通过 asNode() 方法将 ReactAgent 转换为节点,用于 FlowAgent 编排
  • 嵌套 Agent:支持 Agent 嵌套,实现复杂的 Agent 层次结构

关键方法说明

Agent 基类方法

  • initGraph():抽象方法,子类必须实现,用于创建状态图
  • getAndCompileGraph():获取并编译 Graph,使用双重检查锁定确保线程安全
  • invoke():同步调用 Agent,返回 Optional<OverAllState>
  • stream():流式调用 Agent,返回 Flux<NodeOutput>

BaseAgent 方法

  • asNode():抽象方法,将 Agent 转换为 Graph 节点,用于嵌套场景
  • getOutputKey():获取输出键,用于从状态中提取结果
  • getOutputKeyStrategy():获取输出键策略,控制状态更新方式

ReactAgent 方法

  • call():同步调用,返回 AssistantMessage
  • initGraph():创建 ReAct 循环的状态图
  • setupToolsForHooks():为 Hook 注入工具
  • filterHooksByPosition():根据位置过滤 Hook

Agent Framework 通过这种层次化的设计,实现了灵活、可扩展的 Agent 开发框架,为构建智能应用提供了坚实的基础。

发表评论

评论已关闭。

相关文章