Agent执行链路分析
一、介绍
通过现有的动态构建方式,我们可以实现 Ai API、Model、Client、Tool(MCP)、Advisor(包括记忆与RAG)和Prompt的组合,从而完成 Ai Agent 服务的处理。
最初,当 OpenAI 刚发布时,我们主要是与 AI 进行单向询问(包括上下文记忆),并从中获得问题的答案。随着技术的发展,RAG 知识库的出现使得我们每次提问时可以结合知识库来获取更全面的内容。接着,MCP 服务协议的引入,使 AI 拥有了调用外部服务的能力。
再往后,AI Agent 的概念逐渐形成。这意味着,AI 不再只是被动地提供答案,而是具备了环境感知、自主决策和执行行动的能力,从而完成最终结果。
如今,当我们使用一些 AI Agent 时,它们在处理问题时不仅能感知环境状态(即询问内容),还会根据当前状态制定行动计划,调用各种工具和 API 执行任务,并在多轮交互中维持上下文状态,最终输出结果。这也是我们目前正在进行的工作。
鉴于 Ai Agent 的复杂性,我们不能一开始就直接进入编码阶段,否则可能会让一些团队成员感到困惑。因此,我们决定先从 Agent 的单元测试入手,结合动态实例化的各项服务,逐步处理 Agent 的循环机制,制定行动计划并执行多轮对话。
二、功能流程
如图,不同方案实现的 Agent 流程;

Ai Agent 的处理过程可以根据不同的应用场景划分为几种类型:
- 固定步骤执行:这种方式适用于配置固定工作流,以提高任务执行的准确性。例如,检索资料、发布帖子、处理通知等任务通常采用这种方法。
- 顺序循环调用:在这种模式下,Agent 会按预设顺序执行多个 Client 端任务。这适用于一些简单且已经分配好动作的任务关系,执行方式与固定步骤类似,但可根据需要进行顺序调整。
- 智能动态决策:这是目前市面上最常见的 Ai Agent 实现方式。该方式通过动态规划执行步骤,实时观察执行结果,评估任务状态,并根据判断决定后续行动。最终,Agent 会给出完成任务的结果。
三、工程实现
本节主要以 AutoAgent 单测的方式学习 Agent 执行过程;

- AiSearchMCPTest, 搜索 MCP 服务。
- AutoAgentTest,学习 Agent 执行过程。
1. 前置处理
这里我们先来增加一个百度搜索的 MCP 服务,便于 Ai Agent 过程测试,动态检索资料。
- 百度搜索MCP服务(url);https://sai.baidu.com/zh/detail/e014c6ffd555697deabf00d058baf388
- 百度搜索MCP服务(key);https://console.bce.baidu.com/iam/?_=1753597622044#/iam/apikey/list
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class AiSearchMCPTest {
@Test
public void test() {
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.openAiApi(OpenAiApi.builder()
.baseUrl("https://linjinpeng-veloera.hf.space/")
.apiKey("sk-dybTpF7pSuqF9hv0JALaKY2vmoppIW2rWT5pnZcFPPBtKq8u")
.completionsPath("v1/chat/completions")
.embeddingsPath("v1/embeddings")
.build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-5")
.toolCallbacks(new SyncMcpToolCallbackProvider(sseMcpClient()).getToolCallbacks())
.build())
.build();
ChatResponse call = chatModel.call(Prompt.builder().messages(new UserMessage("搜索今天北京天气状况。")).build());
log.info("测试结果:{}", JSON.toJSONString(call.getResult()));
}
public McpSyncClient sseMcpClient() {
HttpClientSseClientTransport sseClientTransport = HttpClientSseClientTransport.builder("http://appbuilder.baidu.com/v2/ai_search/mcp/")
.sseEndpoint("sse?api_key=Bearer+xxx-xxx/ALTAK-6SyOtHHftyPsWLoIpz3WL/e7a0d8c2e39e9596b0f1e183cd985da1c32a0d67")
.build();
McpSyncClient mcpSyncClient = McpClient.sync(sseClientTransport).requestTimeout(Duration.ofMinutes(360)).build();
var init_sse = mcpSyncClient.initialize();
log.info("Tool SSE MCP Initialized {}", init_sse);
return mcpSyncClient;
}
}25-09-15.11:13:23.975 [main ] INFO AiSearchMCPTest - 测试结果:{"metadata":{"contentFilters":[],"empty":true,"finishReason":"STOP"},"output":{"media":[],"messageType":"ASSISTANT","metadata":{"role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","refusal":"","index":0,"annotations":[{}],"id":"2819a261-f8cb-496d-ad14-58cc339f2a12"},"text":"今天北京的天气预报显示有阵雨或雷阵雨,最高气温是22°C。预计白天气温会下降,请注意防雨和增添衣物。晚上将由阴转多云,最低气温为19°C。\n\n您可以查看完整的天气预报和相关信息 [这里](https://baijiahao.baidu.com/s?id=1843285516386446252&wfr=spider&for=pc)。","toolCalls":[]}}- 运行测试后,可以看到 MCP 服务,并且能够检索到网络上的实时信息。
- 谷歌和必应也提供类似的搜索服务,可以申请使用。
2. 初始服务 - ChatClient
**测试类:**cn.cactusli.ai.test.spring.ai.AutoAgentTest
@Before
public void init() {
// 初始化 OpenAI API 配置
OpenAiApi openAiApi = OpenAiApi.builder()
.baseUrl("https://linjinpeng-veloera.hf.space/")
.apiKey("sk-dybTpF7pSuqF9hv0JALaKY2vmoppIW2rWT5pnZcFPPBtKq8u")
.completionsPath("v1/chat/completions")
.embeddingsPath("v1/embeddings")
.build();
// 初始化 ChatModel
chatModel = OpenAiChatModel.builder()
.openAiApi(openAiApi)
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.toolCallbacks(new SyncMcpToolCallbackProvider(stdioMcpClient(), sseMcpClient()).getToolCallbacks())
.build())
.build();
// 初始化 Planning Agent ChatClient - 负责任务规划
planningChatClient = ChatClient.builder(chatModel)
.defaultSystem("""
# 角色
你是一个智能任务规划助手,名叫 AutoAgent Planning。
# 说明
你是任务规划助手,根据用户需求,拆解任务列表,制定执行计划。每次执行前,必须先输出本轮思考过程,再生成具体的任务列表。
# 技能
- 擅长将用户任务拆解为具体、独立的任务列表
- 对简单任务,避免过度拆解
- 对复杂任务,合理拆解为多个有逻辑关联的子任务
# 处理需求
## 拆解任务
- 深度推理分析用户输入,识别核心需求及潜在挑战
- 将复杂问题分解为可管理、可执行、独立且清晰的子任务
- 任务按顺序或因果逻辑组织,上下任务逻辑连贯
- 拆解最多不超过5个任务
## 输出格式
请按以下格式输出任务计划:
**任务规划:**
1. [任务1描述]
2. [任务2描述]
3. [任务3描述]
...
**执行策略:**
[整体执行策略说明]
今天是 {current_date}。
""")
.defaultAdvisors(
PromptChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(50)
.build()
).build(),
SimpleLoggerAdvisor.builder().build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.maxTokens(2000)
.build())
.build();
// 初始化 Executor Agent ChatClient - 负责任务执行
executorChatClient = ChatClient.builder(chatModel)
.defaultSystem("""
# 角色
你是一个智能任务执行助手,名叫 AutoAgent Executor。
# 说明
你负责执行具体的任务,根据规划的任务列表逐步完成每个子任务。
# 执行流程
请使用交替进行的"思考、行动、观察"三个步骤来系统地解决任务:
**思考:** 基于当前上下文,分析当前任务需求,明确下一步行动目标
**行动:** 调用相应的工具或执行具体操作
**观察:** 记录执行结果,分析是否达到预期目标
# 技能
- 擅长使用各种工具完成具体任务
- 能够处理文件操作、搜索、分析等多种类型的任务
- 具备错误处理和重试机制
# 约束
- 严格按照任务列表执行,不偏离目标
- 每个任务完成后需要确认结果
- 遇到错误时要分析原因并尝试解决
今天是 {current_date}。
""")
.defaultAdvisors(
PromptChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(100)
.build()
).build(),
new RagAnswerAdvisor(vectorStore, SearchRequest.builder()
.topK(5)
.filterExpression("knowledge == 'article-prompt-words'")
.build()),
SimpleLoggerAdvisor.builder().build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.maxTokens(4000)
.build())
.build();
// 初始化 React Agent ChatClient - 负责响应式处理
reactChatClient = ChatClient.builder(chatModel)
.defaultSystem("""
# 角色
你是一个智能响应助手,名叫 AutoAgent React。
# 说明
你负责对用户的即时问题进行快速响应和处理,适用于简单的查询和交互。
# 处理方式
- 对于简单问题,直接给出答案
- 对于需要工具的问题,调用相应工具获取信息
- 保持响应的及时性和准确性
今天是 {current_date}。
""")
.defaultAdvisors(
PromptChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(20)
.build()
).build(),
SimpleLoggerAdvisor.builder().build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.maxTokens(1500)
.build())
.build();
}创建服务:采用硬编码方式创建 API 和 Model 服务,随后分别创建三种不同类型的客户端。
客户端类型:
- planningChatClient:负责任务规划。
- executorChatClient:负责任务执行。
- reactChatClient:负责响应式处理。
关键点:其中,每一步骤的提示词尤为关键,许多伙伴进入公司从事 AI Agent 开发工作时,即需专注于此类提示词的完善。
3. 固定步骤 - Agent
/**
* 测试完整的 AutoAgent 工作流程
*/
@Test
public void test_complete_auto_agent_workflow() {
String userRequest = "帮我创建一个关于Spring AI框架的技术文档,包括核心概念、使用示例和最佳实践";
log.info("=== 完整 AutoAgent 工作流程测试开始 ===");
log.info("用户请求: {}", userRequest);
// 第一步:任务规划 (Planning)
log.info("--- 步骤1: 任务规划 ---");
String planningResult = planningChatClient
.prompt("请为以下用户需求制定详细的执行计划:" + userRequest)
.system(s -> s.param("current_date", LocalDate.now().toString()))
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "workflow-planning-001")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 50))
.call().content();
log.info("规划结果: {}", planningResult);
// 第二步:任务执行 (Execution)
log.info("--- 步骤2: 任务执行 ---");
String executionContext = String.format("""
根据以下任务规划,请逐步执行每个任务:
任务规划:
%s
原始用户需求:%s
请开始执行第一个任务。
""", planningResult, userRequest);
String executionResult = executorChatClient
.prompt(executionContext)
.system(s -> s.param("current_date", LocalDate.now().toString()))
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "workflow-execution-001")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
.call().content();
log.info("执行结果: {}", executionResult);
// 第三步:结果总结和验证
log.info("--- 步骤3: 结果总结 ---");
String summaryContext = String.format("""
请对以下执行结果进行总结,并验证是否满足用户的原始需求:
原始需求:%s
执行结果:%s
请提供最终的总结报告。
""", userRequest, executionResult);
String summaryResult = reactChatClient
.prompt(summaryContext)
.system(s -> s.param("current_date", LocalDate.now().toString()))
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, "workflow-summary-001")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 50))
.call().content();
log.info("总结报告: {}", summaryResult);
log.info("=== 完整 AutoAgent 工作流程测试结束 ===");
}- 流程概述:这是一种固定步骤的 AI Agent 执行过程,适用于简单或明确固定的场景,可采用此类方式高效处理。
- 执行步骤:
- AI Agent 首先根据提示词,对用户的提问进行任务规划。
- 随后,开始任务执行。
- 最终,进行结果总结和验证。
4. 自主分析 - Agent
/**
* 动态多轮执行测试 - 模拟 PlanningAgent 和 ExecutorAgent 的完整动态执行流程
*
* 执行特点:
* 1. 动态分析用户输入,自主决定执行策略
* 2. 根据每轮执行结果,智能判断下一步行动
* 3. 支持可配置的最大执行步数
* 4. 具备任务完成判断和提前终止机制
* 5. 模拟真实的 Agent 思考-行动-观察循环
*/
@Test
public void test_dynamic_multi_step_execution() {
// 配置参数
int maxSteps = 4; // 最大执行步数
String userInput = "搜索小傅哥,技术项目列表。编写成一份文档,说明不同项目的学习目标,以及不同阶段的伙伴应该学习哪个项目。";
userInput = "搜索 springboot 相关知识,生成4个主要内容章节。每个章节要包括课程内容和配套示例代码。并发对应章节创建对md文档,方便小白伙伴学习。";
String sessionId = "dynamic-execution-" + System.currentTimeMillis();
log.info("=== 动态多轮执行测试开始 ====");
log.info("用户输入: {}", userInput);
log.info("最大执行步数: {}", maxSteps);
log.info("会话ID: {}", sessionId);
// 初始化执行上下文
StringBuilder executionHistory = new StringBuilder();
String currentTask = userInput;
boolean isCompleted = false;
// 初始化任务分析器 ChatClient - 负责任务分析和状态判断
ChatClient taskAnalyzerClient = ChatClient.builder(chatModel)
.defaultSystem("""
# 角色
你是一个专业的任务分析师,名叫 AutoAgent Task Analyzer。
# 核心职责
你负责分析任务的当前状态、执行历史和下一步行动计划:
1. **状态分析**: 深度分析当前任务完成情况和执行历史
2. **进度评估**: 评估任务完成进度和质量
3. **策略制定**: 制定下一步最优执行策略
4. **完成判断**: 准确判断任务是否已完成
# 分析原则
- **全面性**: 综合考虑所有执行历史和当前状态
- **准确性**: 准确评估任务完成度和质量
- **前瞻性**: 预测可能的问题和最优路径
- **效率性**: 优化执行路径,避免重复工作
# 输出格式
**任务状态分析:**
[当前任务完成情况的详细分析]
**执行历史评估:**
[对已完成工作的质量和效果评估]
**下一步策略:**
[具体的下一步执行计划和策略]
**完成度评估:** [0-100]%
**任务状态:** [CONTINUE/COMPLETED]
""")
.defaultAdvisors(
PromptChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(100)
.build()
).build(),
SimpleLoggerAdvisor.builder().build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.maxTokens(2000)
.temperature(0.3)
.build())
.build();
// 初始化精准执行器 ChatClient - 负责具体任务执行
ChatClient precisionExecutorClient = ChatClient.builder(chatModel)
.defaultSystem("""
# 角色
你是一个精准任务执行器,名叫 AutoAgent Precision Executor。
# 核心能力
你专注于精准执行具体的任务步骤:
1. **精准执行**: 严格按照分析师的策略执行任务
2. **工具使用**: 熟练使用各种工具完成复杂操作
3. **质量控制**: 确保每一步执行的准确性和完整性
4. **结果记录**: 详细记录执行过程和结果
# 执行原则
- **专注性**: 专注于当前分配的具体任务
- **精准性**: 确保执行结果的准确性和质量
- **完整性**: 完整执行所有必要的步骤
- **可追溯性**: 详细记录执行过程便于后续分析
# 输出格式
**执行目标:**
[本轮要执行的具体目标]
**执行过程:**
[详细的执行步骤和使用的工具]
**执行结果:**
[执行的具体结果和获得的信息]
**质量检查:**
[对执行结果的质量评估]
""")
.defaultToolCallbacks(new SyncMcpToolCallbackProvider(stdioMcpClient(), sseMcpClient()).getToolCallbacks())
.defaultAdvisors(
PromptChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(150)
.build()
).build(),
new RagAnswerAdvisor(vectorStore, SearchRequest.builder()
.topK(8)
.filterExpression("knowledge == 'article-prompt-words'")
.build()),
SimpleLoggerAdvisor.builder().build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.maxTokens(4000)
.temperature(0.5)
.build())
.build();
// 初始化质量监督器 ChatClient - 负责质量检查和优化
ChatClient qualitySupervisorClient = ChatClient.builder(chatModel)
.defaultSystem("""
# 角色
你是一个专业的质量监督员,名叫 AutoAgent Quality Supervisor。
# 核心职责
你负责监督和评估执行质量:
1. **质量评估**: 评估执行结果的准确性和完整性
2. **问题识别**: 识别执行过程中的问题和不足
3. **改进建议**: 提供具体的改进建议和优化方案
4. **标准制定**: 制定质量标准和评估指标
# 评估标准
- **准确性**: 结果是否准确无误
- **完整性**: 是否遗漏重要信息
- **相关性**: 是否符合用户需求
- **可用性**: 结果是否实用有效
# 输出格式
**质量评估:**
[对执行结果的详细质量评估]
**问题识别:**
[发现的问题和不足之处]
**改进建议:**
[具体的改进建议和优化方案]
**质量评分:** [0-100]分
**是否通过:** [PASS/FAIL/OPTIMIZE]
""")
.defaultAdvisors(
PromptChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(80)
.build()
).build(),
SimpleLoggerAdvisor.builder().build())
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-4.1")
.maxTokens(2500)
.temperature(0.2)
.build())
.build();
// 开始精准多轮执行
for (int step = 1; step <= maxSteps && !isCompleted; step++) {
log.info("\n🎯 === 执行第 {} 步 ===", step);
try {
// 第一阶段:任务分析
log.info("\n📊 阶段1: 任务状态分析");
String analysisPrompt = String.format("""
**原始用户需求:** %s
**当前执行步骤:** 第 %d 步 (最大 %d 步)
**历史执行记录:**
%s
**当前任务:** %s
请分析当前任务状态,评估执行进度,并制定下一步策略。
""",
userInput,
step,
maxSteps,
executionHistory.length() > 0 ? executionHistory.toString() : "[首次执行]",
currentTask
);
String analysisResult = taskAnalyzerClient
.prompt(analysisPrompt)
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId + "-analyzer")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
.call().content();
parseAnalysisResult(step, analysisResult);
// 检查是否已完成
if (analysisResult.contains("任务状态: COMPLETED") ||
analysisResult.contains("完成度评估: 100%")) {
isCompleted = true;
log.info("✅ 任务分析显示已完成!");
break;
}
// 第二阶段:精准执行
log.info("\n⚡ 阶段2: 精准任务执行");
String executionPrompt = String.format("""
**分析师策略:** %s
**执行指令:** 根据上述分析师的策略,执行具体的任务步骤。
**执行要求:**
1. 严格按照策略执行
2. 使用必要的工具
3. 确保执行质量
4. 详细记录过程
""", analysisResult);
String executionResult = precisionExecutorClient
.prompt(executionPrompt)
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId + "-executor")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 120))
.call().content();
parseExecutionResult(step, executionResult);
// 第三阶段:质量监督
log.info("\n🔍 阶段3: 质量监督检查");
String supervisionPrompt = String.format("""
**用户原始需求:** %s
**执行结果:** %s
**监督要求:** 请评估执行结果的质量,识别问题,并提供改进建议。
""", userInput, executionResult);
String supervisionResult = qualitySupervisorClient
.prompt(supervisionPrompt)
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId + "-supervisor")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 80))
.call().content();
parseSupervisionResult(step, supervisionResult);
// 根据监督结果决定是否需要重新执行
if (supervisionResult.contains("是否通过: FAIL")) {
log.info("❌ 质量检查未通过,需要重新执行");
currentTask = "根据质量监督的建议重新执行任务";
} else if (supervisionResult.contains("是否通过: OPTIMIZE")) {
log.info("🔧 质量检查建议优化,继续改进");
currentTask = "根据质量监督的建议优化执行结果";
} else {
log.info("✅ 质量检查通过");
}
// 更新执行历史
String stepSummary = String.format("""
=== 第 %d 步完整记录 ===
【分析阶段】%s
【执行阶段】%s
【监督阶段】%s
""", step, analysisResult, executionResult, supervisionResult);
executionHistory.append(stepSummary);
// 提取下一步任务
currentTask = extractNextTask(analysisResult, executionResult, currentTask);
// 添加步骤间的延迟
Thread.sleep(1500);
} catch (Exception e) {
log.error("❌ 第 {} 步执行出现异常: {}", step, e.getMessage(), e);
executionHistory.append(String.format("\n=== 第 %d 步执行异常 ===\n错误: %s\n", step, e.getMessage()));
currentTask = "处理上一步的执行异常,继续完成原始任务";
}
}
// 执行结果总结
// 输出执行总结
logExecutionSummary(maxSteps, executionHistory, isCompleted);
// 生成最终总结报告
if (!isCompleted) {
log.info("\n--- 生成未完成任务的总结报告 ---");
String summaryPrompt = String.format("""
请对以下未完成的任务执行过程进行总结分析:
**原始用户需求:** %s
**执行历史:**
%s
**分析要求:**
1. 总结已完成的工作内容
2. 分析未完成的原因
3. 提出完成剩余任务的建议
4. 评估整体执行效果
""", userInput, executionHistory.toString());
String summaryResult = reactChatClient
.prompt(summaryPrompt)
.advisors(a -> a
.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId + "-summary")
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 50))
.call().content();
logFinalReport(summaryResult);
}
log.info("\n🏁 === 动态多轮执行测试结束 ====");
}核心重点:此案例的重点在于将固定步骤转化为循环步骤。注意,在 for (int step = 1; step <= maxSteps && !isCompleted; step++) 循环中,会不断判断任务是否执行完成。如果未完成,则进行分析、自主规划,随后执行。该部分内容,最好执行结果验证,以确保准确性。
注意事项:此过程非常耗费 Token,并高度依赖于 LLM 的质量。如果使用较差的模型,则最终结果可能不太理想。