Agent 架构与框架面试通关 15 问:从 ReAct 到 LangGraph,面试官真正想考什么
面试官问"你用过 LangChain 吗",你说"用过"。
然后他问:“那你说说 LangChain 的 Agent 和 LangGraph 的 Agent 有什么本质区别?”
你停了三秒。
这三秒,就是 Agent 架构面试的分水岭。
用过框架和理解框架,是两件完全不同的事。这篇文章把 Agent 架构与框架面试的 15 道核心题全部拆开——从五大组件的串联逻辑,到 ReAct/Plan-and-Execute/Reflexion 三种推理模式的本质差异,从 LangGraph 的 State Graph 核心概念,到框架选型的决策树,再到"从零实现一个最小 Agent"的代码级考题。
读完之后,面试官问"然后呢",你能接住。
模块一:架构基础
Q1:Agent 的五大核心组件是什么?它们怎么串联起来工作?
这是 Agent 架构面试的第一道题,也是后续所有问题的基础。很多候选人能说出"感知、记忆、推理、行动",但说不清楚它们之间的数据流。
五大组件:
| 组件 | 英文 | 职责 | 类比 |
|---|---|---|---|
| 感知 | Perception | 接收外部输入(文本/图像/工具返回值) | 眼睛和耳朵 |
| 记忆 | Memory | 存储上下文、历史、知识 | 大脑的记忆区 |
| 推理 | Reasoning | 基于输入和记忆,决定下一步行动 | 大脑的决策区 |
| 行动 | Action | 执行工具调用、生成输出 | 手和嘴 |
| 反馈 | Feedback | 接收行动结果,更新状态 | 神经反射弧 |
串联逻辑(数据流):
外部输入 ↓ Perception(解析输入,转为 Agent 可理解的格式) ↓ Memory(检索相关历史和知识,注入上下文) ↓ Reasoning(LLM 推理:该做什么?调哪个工具?) ↓ Action(执行工具调用 / 生成回答) ↓ Feedback(工具返回结果 / 用户反馈) ↓ 回到 Memory(更新状态,写入新记忆) ↓ 回到 Reasoning(判断是否完成,还是继续循环)
面试追问:
“这五个组件,哪个是 Agent 和普通 LLM 调用的本质区别?”
是 Feedback 驱动的循环。普通 LLM 调用是单次的:输入 → 输出,结束。Agent 是循环的:输出的结果会作为新的输入,驱动下一轮推理,直到任务完成。这个"循环 + 工具调用"的组合,才是 Agent 的本质。
“五大组件里,哪个最容易出问题?”
Reasoning。感知、记忆、行动都是相对确定的工程问题,但推理依赖 LLM,而 LLM 是概率性的——它可能推理出错误的行动计划,可能陷入死循环,可能在工具调用失败后不知道怎么恢复。这也是为什么 Agent 可靠性是面试的重点考察方向。
Q2:Agent 和 Workflow 的本质区别是什么?什么时候该用 Agent,什么时候该用 Workflow?
这道题考的是你对 Agent 适用边界的理解。很多候选人把所有自动化任务都叫"Agent",面试官会追问。
核心区别:
| 维度 | Workflow | Agent |
|---|---|---|
| 控制流 | 预定义(DAG/状态机) | 动态(LLM 决策) |
| 分支逻辑 | 硬编码 | 运行时推理 |
| 工具调用 | 固定顺序 | 按需选择 |
| 适应性 | 低(输入变化就可能失败) | 高(能处理未预见的情况) |
| 可预测性 | 高 | 低 |
| 成本 | 低(无额外 LLM 推理) | 高(每步都要 LLM 决策) |
| 调试难度 | 低 | 高 |
选型原则:
用 Workflow 的场景:
- • 流程固定,输入输出格式明确(如:发票 OCR → 字段提取 → 写入数据库)
- • 对可靠性要求极高,不能有随机性
- • 成本敏感,不能每步都调 LLM
用 Agent 的场景:
- • 任务需要根据中间结果动态调整路径(如:研究助手,不知道要搜几次才够)
- • 工具的选择和顺序无法预先确定
- • 需要处理异常情况并自主恢复
一个判断标准:如果你能把任务的所有分支都画成流程图,用 Workflow。如果流程图画不完,用 Agent。
面试追问:
“LangGraph 是 Workflow 还是 Agent?”
两者都可以。LangGraph 本质上是一个图编排框架,你可以用它实现确定性的 Workflow(每条边都是固定的),也可以用它实现 Agent(加入 LLM 决策的条件边)。这也是 LangGraph 比早期 LangChain Agent 更受欢迎的原因——它给了开发者更精细的控制权。
Q3:ReAct、Plan-and-Execute、Reflexion——三种推理模式的本质差异是什么?
这是架构面试的核心题。能把三种模式说清楚,说明你不只是"用过",而是"理解了"。
ReAct(Reasoning + Acting)
核心思想:推理和行动交替进行,每一步都基于上一步的观察结果。
Thought: 我需要查一下今天的天气Action: search("北京今天天气")Observation: 晴,25°CThought: 天气不错,我可以告诉用户适合出行Action: finish("今天北京晴天,25°C,适合出行")
特点:
- • 优点:简单、透明、每步可追踪
- • 缺点:没有全局规划,容易在复杂任务中走弯路;每步都要 LLM 推理,成本高
适用场景:任务步骤不超过 5-7 步,工具调用结果能直接指导下一步的场景。
Plan-and-Execute(规划后执行)
核心思想:先用 LLM 生成完整的执行计划,再按计划逐步执行。
[规划阶段]Planner: 任务是"写一份竞品分析报告"Plan: Step 1: 搜索竞品 A 的最新功能 Step 2: 搜索竞品 B 的最新功能 Step 3: 对比两者的差异 Step 4: 生成报告[执行阶段]Executor: 按 Plan 逐步执行,每步调用对应工具
特点:
- • 优点:有全局视野,不容易走弯路;执行阶段可以用更小的模型降低成本
- • 缺点:规划阶段的计划可能不准确;中途遇到意外情况需要 re-plan,增加复杂度
适用场景:任务步骤多(>7步)、需要并行执行多个子任务的场景。
Reflexion(反思强化)
核心思想:Agent 执行任务后,生成自然语言反思,反思结果写入记忆,指导下次执行。
[第一次尝试]Action: 执行任务Result: 失败(测试用例不通过)[反思阶段]Reflection: "我在第 3 步没有处理边界情况,下次应该先检查输入是否为空"[第二次尝试]Memory: 检索到上次的反思Action: 执行任务(加入了边界检查)Result: 成功
特点:
- • 优点:能从失败中学习,随着迭代次数增加,成功率提升
- • 缺点:需要多次尝试,延迟高;反思质量依赖 LLM 能力
适用场景:代码生成、数学推理等有明确对错标准的任务;允许多次迭代的场景。
三种模式对比:
| 维度 | ReAct | Plan-and-Execute | Reflexion |
|---|---|---|---|
| 规划方式 | 逐步推理 | 先全局规划 | 迭代改进 |
| 适合任务长度 | 短(<7步) | 长(>7步) | 任意(需多次迭代) |
| 成本 | 中 | 低(执行阶段可用小模型) | 高(多次尝试) |
| 错误恢复 | 弱 | 需 re-plan | 强(从失败中学习) |
| 实现复杂度 | 低 | 中 | 高 |
Q4:LLM 是无状态的,Agent 的"状态"存在哪里?
这道题考的是你对 Agent 状态管理的理解,是很多候选人的盲区。
核心问题:LLM 每次调用都是全新的,不记得上一次说了什么。那 Agent 的"我现在执行到第几步了"、“上一个工具返回了什么”,存在哪里?
答案:状态存在 Agent 框架的 State 对象里,不在 LLM 里。
# LangGraph 的 State 示例from typing import TypedDict, Annotatedfrom langgraph.graph import add_messagesclass AgentState(TypedDict): messages: Annotated[list, add_messages] # 对话历史 current_step: int # 当前执行步骤 tool_results: dict # 工具调用结果 plan: list[str] # 执行计划(Plan-and-Execute 模式) is_complete: bool # 任务是否完成
状态的生命周期:
用户输入 → 初始化 State ↓每次 LLM 推理:把 State 序列化为 Prompt(消息历史 + 当前上下文) ↓LLM 输出 → 解析结果 → 更新 State ↓工具调用 → 工具结果写入 State ↓判断是否完成(读 State)→ 继续循环 or 结束
面试追问:
“State 存在内存里,Agent 崩溃了怎么办?”
这就是 Checkpoint 的作用。LangGraph 的 Checkpointer 会在每个节点执行后把 State 持久化到存储(SQLite/PostgreSQL/Redis),Agent 崩溃后可以从最近的 Checkpoint 恢复,不需要从头开始。这也是 LangGraph 相比早期 LangChain Agent 的重要工程改进。
模块二:推理模式深入
Q5:ReAct 的 Prompt 模板长什么样?不同模型的差异在哪?
这道题考的是你有没有真正写过 ReAct Prompt,而不只是调用了框架的封装。
标准 ReAct Prompt 模板:
你是一个 AI 助手,可以使用以下工具:{tools_description}使用以下格式:Thought: 你对当前情况的思考Action: 要使用的工具名称,必须是 [{tool_names}] 之一Action Input: 工具的输入参数(JSON 格式)Observation: 工具返回的结果...(可以重复 Thought/Action/Observation 多次)Thought: 我现在知道最终答案了Final Answer: 对用户问题的最终回答开始!Question: {input}{agent_scratchpad}
关键设计点:
-
agent_scratchpad:这是 ReAct 的核心——把之前所有的 Thought/Action/Observation 都放在这里,让 LLM 看到完整的推理历史,才能做出正确的下一步决策。
-
- 工具描述的质量:工具描述写得好不好,直接影响 LLM 选工具的准确率。好的工具描述要说清楚:做什么、输入格式、输出格式、什么时候用。
不同模型的差异:
| 模型 | ReAct 表现特点 | 注意事项 |
|---|---|---|
| GPT-4o | 格式遵循好,工具选择准确 | 成本高,适合复杂任务 |
| Claude 3.5 Sonnet | 推理链质量高,不容易陷入死循环 | 对 Prompt 格式要求稍宽松 |
| Llama 3.1 70B | 需要更明确的格式约束 | 建议用 Function Calling 而非纯文本 ReAct |
| GPT-4o-mini | 简单任务够用,复杂任务容易出错 | 适合作为 Plan-and-Execute 的执行模型 |
面试追问:
“ReAct 和 Function Calling 有什么关系?”
ReAct 是一种推理模式(Thought → Action → Observation 的循环),Function Calling 是 LLM 的一种能力(结构化输出工具调用参数)。现代 Agent 框架通常用 Function Calling 来实现 ReAct 的 Action 步骤——用 Function Calling 替代纯文本的 Action: tool_name\nAction Input: {...},格式更可靠,解析更稳定。
Q6:Plan-and-Execute 的规划失败了怎么办?Re-plan 策略怎么设计?
这是 Plan-and-Execute 模式的核心工程挑战,能答出来说明你真正用过这个模式。
规划失败的三种场景:
场景一:计划步骤不可执行
- • 例如:Planner 生成了"Step 3: 调用 X 工具",但 X 工具不存在
- • 解决:执行前做计划验证(检查每个步骤引用的工具是否存在)
场景二:中途遇到意外情况
- • 例如:Step 2 的工具返回了"数据不存在",后续步骤依赖这个数据
- • 解决:Executor 检测到异常后,触发 Re-planner
场景三:计划完成但结果不符合预期
- • 例如:报告生成了,但用户说"这不是我要的格式"
- • 解决:Human-in-the-loop,让用户确认后 re-plan
Re-plan 策略设计:
from langgraph.graph import StateGraphdefshould_replan(state: AgentState) -> str: """判断是否需要 re-plan""" last_result = state["tool_results"].get("last_result") # 工具调用失败 if last_result and last_result.get("error"): return"replan" # 执行了 3 步还没有进展 if state["current_step"] > 3andnot state["has_progress"]: return"replan" # 正常继续 return"continue"# 在 LangGraph 中加入条件边graph.add_conditional_edges( "executor", should_replan, { "replan": "planner", # 回到规划节点 "continue": "executor"# 继续执行 })
Re-plan 的上下文注入:Re-plan 时,要把失败原因和已完成的步骤告诉 Planner,避免重复犯同样的错误:
replan_prompt = f"""原始任务:{original_task}原始计划:{original_plan}已完成步骤:{completed_steps}失败原因:{failure_reason}请基于以上信息,生成一个修正后的执行计划:"""
面试加分点:提到 Re-plan 的次数限制——如果允许无限 re-plan,Agent 可能陷入死循环。生产环境通常设置最大 re-plan 次数(如 3 次),超过后降级为人工处理。
Q7:Reflexion 和 Few-shot 的本质区别是什么?
这道题很多候选人答不清楚,因为两者表面上都是"给 LLM 一些例子"。
Few-shot:静态的,你手动写几个示例放在 Prompt 里,每次调用都用同样的示例。
few_shot_prompt = """示例 1:输入:计算 2+2输出:4示例 2:输入:计算 3×5输出:15现在:输入:{user_input}输出:"""
Reflexion:动态的,Agent 从自己的失败中自动生成新的示例,写入记忆,下次自动检索使用。
# Reflexion 的核心循环defreflexion_loop(task: str, max_attempts: int = 3): memories = [] for attempt inrange(max_attempts): # 检索历史反思 relevant_reflections = retrieve_reflections(task, memories) # 执行任务(注入历史反思) result = execute_with_reflections(task, relevant_reflections) # 评估结果 if is_success(result): return result # 生成反思(失败时) reflection = generate_reflection(task, result) memories.append(reflection) return result # 返回最后一次尝试的结果
核心差异:
| 维度 | Few-shot | Reflexion |
|---|---|---|
| 示例来源 | 人工编写 | Agent 自动生成 |
| 更新方式 | 静态(不会变) | 动态(每次失败后更新) |
| 适应性 | 低(只适应预见的情况) | 高(能适应新的失败模式) |
| 成本 | 低 | 高(需要多次尝试) |
| 适用场景 | 格式固定的任务 | 有明确对错标准的复杂任务 |
面试追问:
“Reflexion 的反思质量怎么保证?”
反思质量取决于两点:一是评估函数的准确性(能不能正确判断成功/失败),二是 LLM 的反思能力(能不能从失败中提炼出有用的经验)。如果评估函数不准,Reflexion 可能强化错误的行为。所以 Reflexion 最适合有明确评估标准的任务(如代码测试通过/不通过、数学答案对/错)。
模块三:主流框架拆解
Q8:LangGraph 的核心概念是什么?State/Node/Edge/Checkpoint 怎么理解?
LangGraph 是 2025-2026 年 Agent 面试的最高频框架,必须给代码级的理解。
四大核心概念:
① State(状态):Agent 的"大脑",存储所有中间状态。
from typing import TypedDict, Annotatedfrom langgraph.graph import add_messagesclass AgentState(TypedDict): messages: Annotated[list, add_messages] # add_messages 是 reducer,自动追加而非覆盖 next_action: str iteration_count: int
② Node(节点):执行具体逻辑的函数,接收 State,返回更新后的 State。
def call_llm(state: AgentState) -> AgentState: """调用 LLM 推理节点""" response = llm.invoke(state["messages"]) return {"messages": [response]} # 只返回需要更新的字段def call_tool(state: AgentState) -> AgentState: """工具调用节点""" last_message = state["messages"][-1] tool_result = execute_tool(last_message.tool_calls[0]) return {"messages": [ToolMessage(content=tool_result)]}
③ Edge(边):定义节点之间的流转关系。
from langgraph.graph import StateGraph, ENDgraph = StateGraph(AgentState)# 添加节点graph.add_node("llm", call_llm)graph.add_node("tool", call_tool)# 固定边graph.add_edge("tool", "llm") # 工具执行完,回到 LLM# 条件边(动态路由)defshould_continue(state: AgentState) -> str: last_message = state["messages"][-1] if last_message.tool_calls: return"tool" # 有工具调用,去执行工具 return END # 没有工具调用,结束graph.add_conditional_edges("llm", should_continue)graph.set_entry_point("llm")
④ Checkpoint(检查点):持久化 State,支持暂停/恢复/Human-in-the-loop。
from langgraph.checkpoint.memory import MemorySaverfrom langgraph.checkpoint.postgres import PostgresSaver# 开发环境:内存 Checkpointercheckpointer = MemorySaver()# 生产环境:PostgreSQL Checkpointercheckpointer = PostgresSaver.from_conn_string("postgresql://...")# 编译时注入 Checkpointerapp = graph.compile(checkpointer=checkpointer)# 运行时指定 thread_id(同一 thread_id 的对话共享状态)config = {"configurable": {"thread_id": "user_123_session_456"}}result = app.invoke({"messages": [HumanMessage("帮我分析这份报告")]}, config=config)
Human-in-the-loop 的实现:
# 在需要人工确认的节点前设置 interruptapp = graph.compile( checkpointer=checkpointer, interrupt_before=["execute_action"] # 执行前暂停,等待人工确认)# 运行到 interrupt 点后暂停result = app.invoke(input, config)# 此时 Agent 暂停,等待人工确认# 人工确认后继续app.invoke(None, config) # 传 None 表示继续执行
面试追问:
“LangGraph 和早期 LangChain Agent 的本质区别是什么?”
早期 LangChain Agent 是黑盒的——你告诉它工具列表和目标,它自己决定怎么做,你很难控制中间步骤。LangGraph 是白盒的——你明确定义每个节点做什么、每条边怎么流转,Agent 的行为完全可预测、可调试。这是从"魔法盒子"到"可控工程"的转变。
Q9:CrewAI 的四层架构是什么?Task/Agent/Crew/Process 怎么理解?
CrewAI 是基于角色的多 Agent 框架,面试中经常被拿来和 LangGraph 对比。
四层架构:
Crew(团队) └── Process(执行流程:Sequential / Hierarchical) └── Agent(角色:有名字、目标、背景故事、工具) └── Task(任务:有描述、期望输出、负责人)
代码示例:
from crewai import Agent, Task, Crew, Processfrom crewai_tools import SerperDevTool, WebsiteSearchTool# 定义工具search_tool = SerperDevTool()# 定义 Agent(角色)researcher = Agent( role="AI 研究员", goal="收集关于 {topic} 的最新信息", backstory="你是一名专注于 AI 领域的资深研究员,擅长从海量信息中提炼关键洞察", tools=[search_tool], verbose=True, llm="gpt-4o")writer = Agent( role="技术写作专家", goal="将研究结果整理成清晰易读的报告", backstory="你是一名技术写作专家,擅长将复杂的技术内容转化为通俗易懂的文章", verbose=True, llm="gpt-4o-mini"# 写作任务用更便宜的模型)# 定义 Task(任务)research_task = Task( description="搜索关于 {topic} 的最新进展,整理出 5 个核心要点", expected_output="包含 5 个核心要点的结构化研究报告", agent=researcher)writing_task = Task( description="基于研究结果,撰写一篇 800 字的技术文章", expected_output="一篇结构清晰、语言流畅的 800 字技术文章", agent=writer, context=[research_task] # 依赖 research_task 的输出)# 组建 Crewcrew = Crew( agents=[researcher, writer], tasks=[research_task, writing_task], process=Process.sequential, # 顺序执行 verbose=True)# 执行result = crew.kickoff(inputs={"topic": "LangGraph 最新特性"})
Sequential vs Hierarchical Process:
| Process | 说明 | 适用场景 |
|---|---|---|
| Sequential | 任务按顺序执行,前一个任务的输出是后一个的输入 | 流程固定的任务(研究→写作→审核) |
| Hierarchical | 有一个 Manager Agent 负责分配任务和协调 | 任务分配需要动态决策的场景 |
面试追问:
“CrewAI 和 LangGraph 怎么选?”
这是框架选型的核心问题,下一题会详细讲。简短版:CrewAI 适合"角色分工明确、流程相对固定"的场景,上手快;LangGraph 适合"需要精细控制流程、有复杂条件分支、需要 Human-in-the-loop"的场景,灵活性更高但学习成本也更高。
Q10:LangChain vs LangGraph vs LlamaIndex vs CrewAI——框架选型决策树
这是面试中最常见的开放题,考的是你的工程判断力。
先理解各框架的定位:
| 框架 | 核心定位 | 最擅长 |
|---|---|---|
| LangChain | LLM 应用开发工具箱 | 快速原型、Chain 组合、工具集成 |
| LangGraph | Agent 编排框架 | 复杂 Agent 流程、状态管理、Human-in-the-loop |
| LlamaIndex | 数据框架 | RAG、知识库、文档处理 |
| CrewAI | 多 Agent 协作框架 | 角色分工、任务委托、团队协作 |
选型决策树:
你的任务是什么?│├── 主要是 RAG / 知识库 / 文档处理?│ └── → LlamaIndex(数据处理能力最强)│├── 单个 Agent,需要精细控制流程?│ ├── 流程简单,快速原型?→ LangChain(上手最快)│ └── 流程复杂,需要 Checkpoint/Human-in-the-loop?→ LangGraph│├── 多个 Agent 协作?│ ├── 角色分工明确,流程相对固定?→ CrewAI(上手快)│ └── 需要动态路由、复杂协调逻辑?→ LangGraph(灵活性最高)│└── 生产级系统,需要可观测性和可靠性? └── → LangGraph + LangSmith(最完整的工程化支持)
一个真实的选型案例:
场景:构建一个"智能研究助手",用户输入研究主题,Agent 自动搜索、阅读、总结,生成报告。
- • 如果是 MVP 阶段:用 CrewAI,3 个 Agent(搜索员/阅读员/写作员),Sequential Process,一天内跑通
- • 如果是生产阶段:用 LangGraph,精细控制每个步骤,加 Checkpoint 支持断点续传,加 Human-in-the-loop 让用户确认搜索方向
面试追问:
“你们团队用的是哪个框架?为什么选它?”
这是考你实战经验的题。如果你真的用过,说出具体的选型理由和踩过的坑。如果没用过,可以说"我在项目中用过 X,选它的原因是 Y,遇到的最大问题是 Z,解决方案是 W"——有具体细节比泛泛而谈更有说服力。
Q11:LangChain 为什么被社区诟病?它的核心问题在哪?
这道题考的是你对框架的批判性思考,能答出来说明你不是"框架粉"。
LangChain 的三大核心问题:
① 过度抽象,调试困难
LangChain 的 Chain 和 Agent 封装了太多细节,当出问题时很难定位是哪一层出了错。一个简单的工具调用失败,可能需要翻好几层源码才能找到原因。
② 版本迭代快,API 不稳定
LangChain 的 API 在早期版本中变化频繁,很多教程代码在新版本里直接跑不通。这对生产环境是个噩梦。
③ 依赖过重
安装 LangChain 会带来大量依赖,很多是用不到的。对于只需要某个功能的项目,这是不必要的负担。
LangChain 的反驳:
- • 对于快速原型,LangChain 的封装确实能节省大量时间
- • LangChain 的生态最完整,支持的 LLM 和工具最多
- • LangGraph 是 LangChain 团队推出的,两者可以配合使用
面试加分点:能说出"我在什么场景下会用 LangChain,在什么场景下会绕过它直接用 LangGraph 或原生 API"——这说明你有实际的工程判断,不是非此即彼。
模块四:工程实践
Q12:从零实现一个最小 Agent——不用框架,需要哪些模块?
这是高级面试题,考的是你对 Agent 底层机制的理解。能从零实现,说明你不依赖框架。
最小 Agent 的五个核心模块:
import jsonfrom openai import OpenAIfrom typing importCallableclient = OpenAI()# ① 工具注册表classToolRegistry: def__init__(self): self.tools: dict[str, Callable] = {} self.schemas: list[dict] = [] defregister(self, name: str, func: Callable, description: str, parameters: dict): self.tools[name] = func self.schemas.append({ "type": "function", "function": { "name": name, "description": description, "parameters": parameters } }) defexecute(self, name: str, arguments: dict) -> str: if name notinself.tools: returnf"Error: Tool '{name}' not found" try: returnstr(self.tools[name](**arguments)) except Exception as e: returnf"Error: {str(e)}"# ② 状态管理classAgentState: def__init__(self): self.messages: list[dict] = [] self.iteration: int = 0 self.max_iterations: int = 10 defadd_message(self, role: str, content: str, **kwargs): msg = {"role": role, "content": content} msg.update(kwargs) self.messages.append(msg)# ③ LLM 推理defcall_llm(state: AgentState, tools: list[dict]) -> dict: response = client.chat.completions.create( model="gpt-4o", messages=state.messages, tools=tools, tool_choice="auto" ) return response.choices[0].message# ④ 工具执行defexecute_tools(message, registry: ToolRegistry) -> list[dict]: results = [] ifnot message.tool_calls: return results for tool_call in message.tool_calls: name = tool_call.function.name args = json.loads(tool_call.function.arguments) result = registry.execute(name, args) results.append({ "role": "tool", "tool_call_id": tool_call.id, "content": result }) return results# ⑤ Agent 主循环defrun_agent(user_input: str, registry: ToolRegistry) -> str: state = AgentState() state.add_message("system", "你是一个有用的 AI 助手,可以使用工具来回答问题。") state.add_message("user", user_input) while state.iteration < state.max_iterations: state.iteration += 1 # LLM 推理 message = call_llm(state, registry.schemas) # 把 LLM 输出加入消息历史 state.messages.append(message) # 没有工具调用 → 任务完成 ifnot message.tool_calls: return message.content # 执行工具 tool_results = execute_tools(message, registry) state.messages.extend(tool_results) return"达到最大迭代次数,任务未完成"# 使用示例registry = ToolRegistry()registry.register( name="get_weather", func=lambda city: f"{city}今天晴天,25°C", description="获取指定城市的天气", parameters={ "type": "object", "properties": {"city": {"type": "string", "description": "城市名称"}}, "required": ["city"] })result = run_agent("北京今天天气怎么样?", registry)print(result)
这个最小实现展示了 Agent 的核心机制:工具注册 → 状态管理 → LLM 推理 → 工具执行 → 循环判断。框架(LangChain/LangGraph)做的事情,本质上就是把这些模块封装得更好用、更可靠。
Q13:Agent 的流式输出怎么实现?异步工具调用怎么编排?
这是工程实践题,考的是你有没有处理过 Agent 的性能问题。
流式输出(Streaming):
用户等待 Agent 响应时,如果要等所有工具调用完成才输出,体验很差。流式输出让用户能实时看到 Agent 的推理过程。
# LangGraph 的流式输出from langgraph.graph import StateGraphapp = graph.compile()# stream() 方法逐步返回每个节点的输出for chunk in app.stream( {"messages": [HumanMessage("帮我分析这份报告")]}, config={"configurable": {"thread_id": "123"}}): for node_name, node_output in chunk.items(): print(f"[{node_name}]: {node_output}")
异步工具调用:
当 Agent 需要并行调用多个工具时,串行执行会浪费时间。
import asynciofrom langchain_core.tools import tool@toolasyncdefsearch_web(query: str) -> str: """搜索网络""" # 异步 HTTP 请求 asyncwith aiohttp.ClientSession() as session: result = await session.get(f"https://api.search.com?q={query}") returnawait result.text()@toolasyncdefsearch_database(query: str) -> str: """搜索数据库""" # 异步数据库查询 result = await db.execute(f"SELECT * FROM docs WHERE content LIKE '%{query}%'") returnstr(result)# 并行执行多个工具asyncdefparallel_tool_execution(tool_calls: list) -> list: tasks = [ execute_tool_async(tc.function.name, tc.function.arguments) for tc in tool_calls ] results = await asyncio.gather(*tasks, return_exceptions=True) return results
面试追问:
“并行工具调用有什么风险?”
主要有两个:一是工具之间有依赖关系时不能并行(Tool B 的输入依赖 Tool A 的输出);二是并发请求可能触发 API 限流。解决方案:在工具 Schema 里标注依赖关系,框架自动判断哪些可以并行;对外部 API 调用加限流控制(Semaphore)。
Q14:State Machine vs Graph——什么时候该用哪种 Agent 架构?
这道题考的是你对不同 Agent 架构范式的理解。
状态机 Agent(State Machine):
状态:[等待输入] → [分析意图] → [调用工具] → [生成回答] → [等待输入]转换:由明确的条件触发(如"意图是查询天气"→ 转到"调用天气工具")
特点:
- • 状态和转换完全预定义
- • 可预测、可测试
- • 适合流程固定的场景(如客服机器人的标准流程)
图 Agent(Graph-based,如 LangGraph):
节点:每个节点是一个处理函数边:固定边 + 条件边(由 LLM 或规则动态决定)
特点:
- • 流程可以动态变化
- • 支持循环、分支、并行
- • 适合复杂的 Agent 任务
选型原则:
| 场景 | 推荐架构 | 理由 |
|---|---|---|
| 客服标准流程(问候→意图识别→处理→结束) | 状态机 | 流程固定,可预测性高 |
| 研究助手(搜索次数不确定) | 图 Agent | 需要动态决定搜索几次 |
| 代码生成(写→测试→修复→测试) | 图 Agent + Reflexion | 需要循环迭代 |
| 表单填写引导 | 状态机 | 每个字段是一个状态,转换明确 |
面试加分点:提到"混合架构"——外层用状态机定义大的业务流程,内层用图 Agent 处理需要动态决策的子任务。这是生产环境中最常见的模式。
模块五:真题实战
Q15:白板题——画一个"智能客服 Agent"的架构图,并说明每个组件的设计决策
这是 Senior 级别面试的标配白板题。考的不只是你能不能画出来,而是你能不能说清楚每个设计决策背后的 trade-off。
需求分析:
- • 用户通过文字/语音提问
- • Agent 能回答产品问题、处理退款申请、查询订单状态
- • 需要支持多轮对话
- • 复杂问题需要转人工
- • 支持 10 万日活用户
架构图:
用户输入(文字/语音) ↓[输入处理层] - 语音转文字(ASR) - 意图识别(分类:产品咨询/退款/订单查询/其他) - 敏感词过滤 ↓[路由层] - 简单问题 → FAQ 检索(RAG) - 复杂问题 → Agent 处理 - 超出能力范围 → 转人工 ↓[Agent 核心(LangGraph)] ┌─────────────────────────────────┐ │ State: {messages, user_id, │ │ intent, order_info} │ │ │ │ Node: LLM 推理 │ │ Node: 工具调用 │ │ - query_order_db() │ │ - process_refund() │ │ - search_faq() │ │ Node: 人工转接判断 │ └─────────────────────────────────┘ ↓[记忆层] - 短期:Redis(当前会话) - 长期:PostgreSQL + pgvector(用户历史) ↓[输出层] - 回答生成 - 满意度收集 - 对话日志(LangSmith)
关键设计决策(面试官最想听的部分):
① 为什么在 Agent 前加路由层?
不是所有问题都需要 Agent。FAQ 类问题用 RAG 直接回答,成本是 Agent 的 1/10,延迟也更低。路由层把简单问题过滤掉,让 Agent 只处理真正需要推理的复杂问题。
② 为什么用 LangGraph 而不是 CrewAI?
客服场景需要精细控制:什么时候转人工(置信度低于阈值)、什么时候需要用户确认(退款金额超过 500 元)。LangGraph 的 interrupt_before 机制能精确控制这些节点,CrewAI 做不到这种粒度。
③ 记忆层为什么要冷热分离?
10 万日活用户,如果所有记忆都放向量数据库,成本很高。7 天内活跃用户的记忆放 Redis(热数据,快),历史记忆放 PostgreSQL + pgvector(温数据,便宜)。90 天以上不活跃的用户记忆归档到 S3(冷数据,极便宜)。
④ 转人工的触发条件怎么设计?
三种触发条件:
-
- 置信度低于阈值(LLM 输出的 confidence score < 0.7)
-
- 用户明确要求(“我要找人工”)
-
- 敏感操作(退款金额 > 1000 元,需要人工审核)
面试追问:
“这个架构的最大风险是什么?”
最大风险是 Agent 的不可预测性——LLM 可能在某些边缘情况下给出错误的回答或执行错误的操作(如错误地触发退款)。缓解方案:对所有写操作(退款、修改订单)加 Human-in-the-loop 确认;对 Agent 的输出做后处理验证;建立完善的监控和告警(LangSmith + 自定义指标)。
总结:面试官真正在考什么
Agent 架构面试,表面上考框架,实际上考三件事:
① 你有没有系统性认知:能不能把 ReAct/Plan-and-Execute/Reflexion 的差异说清楚,能不能给出框架选型的决策树,而不是"我用过 LangChain,挺好用的"。
② 你有没有工程判断力:LangGraph vs CrewAI 怎么选,状态机 vs 图 Agent 怎么选,流式输出 vs 批量输出怎么选——每个选择背后都有 trade-off,能说出 trade-off 才是真正的工程判断。
③ 你有没有踩过坑:Re-plan 的次数限制、并行工具调用的限流问题、LangChain 的调试困难——这些坑只有真正用过的人才知道。
这 15 道题,覆盖了 Agent 架构面试的完整知识图谱。建议重点练 Q3(三种推理模式对比)、Q8(LangGraph 核心概念)、Q10(框架选型决策树)、Q15(白板题)这四道高频题——这四道题能答好,Agent 架构面试基本稳了。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)