AI Agent
AI Agent
Agent 是 AI 能力从"问答"跃升为"自动完成任务"的核心跨越,也是 2026 年 AI 工程师岗位最高频的考察方向之一。
写在前面
字节、阿里、美团的 AI 岗面试,Agent 相关问题出现频率极高。面试官问的不是"什么是 Agent",而是:你的 Agent 怎么防止无限循环?多 Agent 系统如何保证工具调用的幂等性?LangGraph4j 的状态机怎么设计? 本文系统梳理从 Tool Calling 到多 Agent 协作的核心知识点与实战代码。
Agent 核心概念
Agent vs 普通 LLM 调用
| 维度 | 普通 LLM 调用 | AI Agent |
|---|---|---|
| 交互模式 | 一问一答,单次调用 | 感知 → 规划 → 行动 → 观察的循环 |
| 工具使用 | 无 | 可调用外部工具(API/数据库/代码执行) |
| 自主性 | 被动响应 | 主动规划执行步骤 |
| 状态管理 | 无状态 | 维护任务状态和中间结果 |
| 典型延迟 | 1-3 秒 | 5-60 秒(多步执行) |
实际例子:用户说"分析我们公司上季度销售数据,生成报告并发邮件给管理层"。
Agent 执行流程:
- 调用
queryDatabase工具获取销售数据 - 调用
analyzeData工具进行数据分析 - 调用
generateReport工具生成报告 - 调用
sendEmail工具发送邮件 - 返回完成摘要
Tool Calling 机制
OpenAI 函数调用协议
工具定义(JSON Schema 格式):
{
"type": "function",
"function": {
"name": "queryDatabase",
"description": "查询 MySQL 数据库,执行 SELECT 语句返回结果",
"parameters": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "要执行的 SQL 查询语句,只允许 SELECT"
},
"limit": {
"type": "integer",
"description": "返回的最大行数,默认 100",
"default": 100
}
},
"required": ["sql"]
}
}
}模型如何决定调用工具:
- 接收用户消息 + 可用工具列表
- 分析任务是否需要工具
- 如果需要,输出结构化的
tool_calls响应(而非普通文本) - 客户端执行工具,将结果作为
tool角色消息返回 - 模型继续推理,直到认为任务完成
Spring AI @Tool 注解(最简实现)
@Component
@Slf4j
public class BusinessTools {
private final JdbcTemplate jdbcTemplate;
private final EmailService emailService;
/**
* 工具1:数据库查询(只读)
*/
@Tool(description = "查询业务数据库,仅支持 SELECT 语句,返回 JSON 格式结果")
public String queryBusinessData(
@ToolParam(description = "SQL SELECT 查询语句") String sql,
@ToolParam(description = "最大返回行数,默认 50,上限 200") int limit) {
if (!sql.trim().toLowerCase().startsWith("select")) {
return "错误:只允许执行 SELECT 查询";
}
try {
String limitedSql = sql + " LIMIT " + Math.min(limit, 200);
List<Map<String, Object>> results = jdbcTemplate.queryForList(limitedSql);
return new ObjectMapper().writeValueAsString(results);
} catch (Exception e) {
log.error("数据库查询失败: {}", sql, e);
return "查询失败:" + e.getMessage() + "\n请检查表名和字段是否正确";
}
}
/**
* 工具2:发送邮件(高风险操作,需幂等控制)
*/
@Tool(description = "发送邮件给指定收件人,支持 HTML 格式正文")
public String sendEmail(
@ToolParam(description = "收件人邮箱,多个用逗号分隔") String to,
@ToolParam(description = "邮件主题") String subject,
@ToolParam(description = "邮件正文,支持 HTML") String body,
@ToolParam(description = "幂等 ID,防止重复发送") String idempotencyKey) {
try {
if (emailService.alreadySent(idempotencyKey)) {
return "邮件已发送(幂等命中),跳过重复发送";
}
emailService.send(to.split(","), subject, body, idempotencyKey);
return "邮件已成功发送给:" + to;
} catch (Exception e) {
return "邮件发送失败:" + e.getMessage();
}
}
}
// Agent Service
@Service
public class TaskAgentService {
private final ChatClient chatClient;
public TaskAgentService(ChatClient.Builder builder, BusinessTools tools) {
this.chatClient = builder
.defaultSystem("""
你是一个业务自动化助手,能查询数据、分析结果、发送报告。
执行规范:
1. 先规划步骤,再逐步执行
2. 每次工具调用后检查结果,再决定下一步
3. 遇到错误时尝试修复,不能修复时告知用户
4. 最多执行 10 步工具调用,超出则报告当前进度
5. 任务完成后汇报执行摘要
""")
.defaultTools(tools)
.build();
}
public String executeTask(String taskDescription) {
return chatClient.prompt()
.user(taskDescription)
.call()
.content();
}
}ReAct 框架
ReAct = Reasoning(推理)+ Acting(行动),是目前最通用的 Agent 设计模式。
下图展示了 ReAct 框架中 Agent、LLM 与工具之间的完整交互时序:
工作循环:
Thought: 我需要先查询上季度的销售数据
Action: queryBusinessData(sql="SELECT SUM(amount) FROM orders WHERE quarter='Q1-2026'", limit=1)
Observation: [{"SUM(amount)": 3280450}]
Thought: 已获取数据,销售总额 328 万。现在需要与上季度对比
Action: queryBusinessData(sql="SELECT SUM(amount) FROM orders WHERE quarter='Q4-2025'", limit=1)
Observation: [{"SUM(amount)": 2927900}]
Thought: 环比增长 (328-292.79)/292.79 ≈ 12%。现在生成报告并发送邮件
Action: sendEmail(to="manager@company.com", subject="Q1 2026 销售报告", ...)
Observation: 邮件已成功发送
Final Answer: Q1 2026 销售总额 328 万,环比 Q4 2025 增长 12%,报告已发送至管理层。Plan-and-Execute 模式(复杂任务)
先让专门的"规划 LLM"制定执行计划,再让"执行 LLM"逐步执行——规划用强模型(GPT-4o/Claude 4),执行用小模型(DeepSeek-V3,降低成本)。
@Service
public class PlanAndExecuteAgent {
private final ChatClient plannerClient; // 强模型,负责规划
private final ChatClient executorClient; // 小模型,负责执行(降成本)
public String execute(String complexTask) {
// 1. 规划阶段(用强模型)
String plan = plannerClient.prompt()
.user("""
将以下任务分解为可执行步骤(JSON 格式):
任务:%s
返回格式:{"steps":[{"step":1,"action":"步骤描述","tool":"所需工具(可选)"}]}
""".formatted(complexTask))
.call()
.content();
ExecutionPlan executionPlan = parsePlan(plan);
StringBuilder results = new StringBuilder();
// 2. 执行阶段(用小模型,逐步执行)
for (Step step : executionPlan.steps()) {
String stepResult = executorClient.prompt()
.user("执行步骤:" + step.action() + "\n已完成步骤结果:\n" + results)
.call()
.content();
results.append("\n步骤").append(step.step()).append(":").append(stepResult);
}
// 3. 汇总(用强模型)
return plannerClient.prompt()
.user("根据以下执行结果,生成最终汇报:\n" + results)
.call()
.content();
}
}LangGraph4j 实战
LangGraph4j 将 Agent 建模为有向状态机,是 2025-2026 年构建复杂 Agent 工作流的主流 Java 方案。
核心概念
- Node(节点):处理逻辑单元(调用 LLM / 执行工具 / 条件判断)
- Edge(边):节点间的转移关系
- Conditional Edge(条件边):根据状态动态决定下一个节点
- State(状态):在节点间传递的数据对象
完整 ReAct Agent 实现
<dependency>
<groupId>org.bsc.langgraph4j</groupId>
<artifactId>langgraph4j-core</artifactId>
<version>1.5.0</version>
</dependency>// 1. 定义 Agent 状态
@Data
@Builder
public class AgentState {
private List<Message> messages;
private List<ToolCall> pendingToolCalls;
private String finalAnswer;
private int stepCount;
public static final int MAX_STEPS = 10;
}
// 2. 构建 ReAct Agent 图
@Configuration
public class ReactAgentConfig {
@Bean
public CompiledGraph<AgentState> reactAgentGraph(
ChatClient chatClient,
BusinessTools tools) throws GraphBuilderException {
// LLM 推理节点
NodeAction<AgentState> llmNode = state -> {
ChatResponse response = chatClient.prompt()
.messages(state.getMessages())
.call()
.chatResponse();
AssistantMessage msg = response.getResult().getOutput();
AgentState.AgentStateBuilder builder = state.toBuilder();
builder.messages(List.of(msg));
if (msg.getToolCalls() != null && !msg.getToolCalls().isEmpty()) {
builder.pendingToolCalls(msg.getToolCalls());
} else {
builder.finalAnswer(msg.getContent());
}
return Map.of("state", builder.build());
};
// 工具执行节点
NodeAction<AgentState> toolNode = state -> {
List<Message> toolResultMessages = new ArrayList<>();
for (ToolCall toolCall : state.getPendingToolCalls()) {
String result = executeToolByName(tools, toolCall.getName(), toolCall.getArguments());
toolResultMessages.add(new ToolResponseMessage(toolCall.getId(), toolCall.getName(), result));
}
return Map.of("state", state.toBuilder()
.messages(toolResultMessages)
.pendingToolCalls(null)
.build());
};
// 条件边:是否继续工具调用
EdgeAction<AgentState> shouldContinue = state -> {
if (state.getFinalAnswer() != null) return "end";
if (state.getStepCount() >= AgentState.MAX_STEPS) return "end"; // 防无限循环
if (state.getPendingToolCalls() != null && !state.getPendingToolCalls().isEmpty()) return "tool";
return "llm";
};
return StateGraph.builder(AgentState.class)
.addNode("llm", llmNode)
.addNode("tool", toolNode)
.addEdge(START, "llm")
.addConditionalEdges("llm", shouldContinue,
Map.of("tool", "tool", "end", END, "llm", "llm"))
.addEdge("tool", "llm")
.compile();
}
}多 Agent 协作
Orchestrator-Worker 模式
主 Agent(Orchestrator)接收任务,分配给专业子 Agent(Workers)执行,汇总结果。适合任务流程固定的场景。下图展示了 Orchestrator-Worker 的典型协作架构:
@Service
public class OrchestratorAgent {
private final ChatClient orchestratorClient;
private final DataAnalysisAgent dataAnalysisAgent;
private final ReportGenerationAgent reportAgent;
private final EmailAgent emailAgent;
public String executeComplexTask(String task) {
// 1. 规划:分解任务给子 Agent
String plan = orchestratorClient.prompt()
.system("""
你是任务协调者,可用 Agent:
- DataAnalysisAgent:数据查询和分析
- ReportGenerationAgent:报告生成和格式化
- EmailAgent:邮件发送
返回执行计划(JSON):
{"steps":[{"agent":"Agent名","task":"具体任务","input":"输入描述"}]}
""")
.user(task)
.call()
.content();
ExecutionPlan executionPlan = parsePlan(plan);
Map<String, String> results = new LinkedHashMap<>();
// 2. 按计划调用各子 Agent
for (Step step : executionPlan.steps()) {
String agentInput = resolveInputWithPreviousResults(step.input(), results);
String result = switch (step.agent()) {
case "DataAnalysisAgent" -> dataAnalysisAgent.analyze(agentInput);
case "ReportGenerationAgent" -> reportAgent.generate(agentInput);
case "EmailAgent" -> emailAgent.send(agentInput);
default -> "未知 Agent:" + step.agent();
};
results.put("step" + step.step(), result);
}
// 3. 汇总
return orchestratorClient.prompt()
.user("任务执行完成,汇总以下结果:\n" + results)
.call()
.content();
}
}Supervisor 模式(动态监督)
Supervisor 每轮观察所有 Agent 的输出,动态决定下一步由谁执行。更灵活,适合任务流程动态变化的场景。两种模式对比:
| 维度 | Orchestrator-Worker | Supervisor |
|---|---|---|
| 决策方式 | 预先规划,按序执行 | 动态决策,每轮判断 |
| 灵活性 | 低 | 高 |
| Token 消耗 | 低 | 高(每轮需要 Supervisor 决策) |
| 适合场景 | 流程固定的业务自动化 | 复杂探索性任务 |
生产级 Agent 注意事项
1. 防止无限循环(最重要)
三层保护:设置 MAX_STEPS 上限(10-20 步);系统提示词中明确步数限制;检测相同工具被重复调用超过 3 次自动终止。
2. 工具幂等性
发邮件、推送通知、支付等高风险操作必须加幂等 ID,防止 Agent 重试时重复执行。
3. 工具超时处理
@Component
public class TimeoutAwareToolExecutor {
private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
public String executeWithTimeout(Callable<String> toolCall, long timeoutMs, String toolName) {
Future<String> future = executor.submit(toolCall);
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
return String.format("工具 %s 执行超时(%dms),请简化查询或稍后重试", toolName, timeoutMs);
} catch (Exception e) {
return "工具执行失败:" + e.getMessage();
}
}
}4. 流式输出提升体验
Agent 多步执行可能需要 5-60 秒,必须用 SSE/WebSocket 流式展示中间步骤,否则用户会以为页面卡死。
高频面试题
Q: ReAct 模式的工作原理是什么?
ReAct = Reasoning + Acting。工作流程:模型先思考(Thought:我需要查询数据库)→ 决定行动(Action:调用工具)→ 获取观察结果(Observation:工具返回值)→ 再次思考 → ... → 直到得出最终答案。核心优势是将推理过程显式化,每步行动有依据,便于调试和可解释性。
Q: 如何防止 Agent 无限循环?
三层保护:1)代码层设置 MAX_STEPS 常量(通常 10-20),超过后强制停止并返回当前进度;2)系统提示词明确要求"最多 N 步内完成,无法完成时返回失败原因";3)检测重复调用模式(相同工具 + 相同参数超过 3 次),自动终止。
Q: 多 Agent 系统中 Orchestrator 和 Supervisor 有什么区别?
Orchestrator:中心化协调者,预先规划任务分解,按顺序分配给子 Agent,适合流程固定的场景,Token 消耗少。Supervisor:动态监督者,每轮观察所有 Agent 输出后再决定下一步,灵活但 Token 消耗更高,适合任务流程动态变化的探索性任务。
Q: 如何确保 Agent 工具调用的安全性?
四层安全策略:1)输入验证:只接受预定义类型参数;2)最小权限:数据库工具只允许 SELECT;3)沙箱隔离:代码执行工具在 Docker 容器中运行;4)人工审批:发邮件/支付/删除数据等高风险操作需二次确认。
Q: Agent 的 Token 消耗如何控制?
控制策略:1)Tool 返回结果压缩(数据库查询只返回关键字段,大文本截断);2)使用小模型执行简单步骤,大模型只做最终决策;3)设置 MAX_STEPS 上限避免无效循环;4)缓存工具调用结果(相同参数 10 分钟内命中缓存);5)选合适粒度的工具(粗粒度工具减少调用次数)。
Q: LangGraph4j 相比普通 ReAct 有什么优势?
LangGraph4j 将 Agent 建模为有向状态机,优势:1)状态可持久化,支持任务暂停/恢复(Checkpoint);2)支持并行执行多个节点;3)图结构清晰可视化,便于调试;4)支持人工介入节点(Human-in-the-Loop),敏感操作可暂停等待人工确认;5)状态机天然防止无限循环(循环检测是图算法的基本能力)。
知识星球深度内容
完整大厂面经(含详细答案、最新更新)、AI 项目源码、1v1 简历修改,扫码加入「AI 工程师加速社区」知识星球获取 👉 立即加入
