Bonus-5 · Agent 开发原理与面试准备手册
🎯 目标:把"Agent 开发"从概念到代码、从单 Agent 到多 Agent、从框架对比到工业架构,讲深讲透,作为学习路径 + 面试系统化复习材料。 📅 整理日期:2026-05-27 🎓 配套阅读:Bonus-2(RAG/Agent 实战)、Bonus-3(推理优化)、Bonus-4(Context Length)。
0. 三句话先讲清
Agent = LLM(大脑) + Tools(手) + Memory(记忆) + Loop(感知-决策-行动循环)。
所有 Agent 框架的"底层算法"都是 ReAct:
Thought → Action → Observation → Thought → ...。框架之间的差异是调度、状态管理、协作方式,不是算法本身。工业级 Agent 的难点不在于"让 LLM 调用工具",而在于幻觉控制 + 错误恢复 + 成本 + 可观测性 + 安全沙箱。会用 LangChain 不等于会做 Agent。
1. Agent 的定义与边界
1.1 什么算 Agent,什么不算?
| 形态 | 是否 Agent | 为什么 |
|---|---|---|
llm.complete(prompt) 单次调用 | ❌ | 没有循环,没有决策 |
| Prompt chain (固定 N 步流水线) | ❌ (是 Workflow) | 步骤固定,无动态决策 |
| LLM + RAG retriever (1 retrieve + 1 generate) | ❌ (是 RAG) | 没有"是否继续 retrieve"的判断 |
| LLM + 工具,循环到自己说停 | ✅ Agent | 满足 Loop + Decision + Action |
| LLM + 工具,最多调用 1 次,然后必停 | 🟡 弱 Agent (Single-step tool use) | 介于 chain 和 agent 之间 |
核心判别:模型自己决定什么时候停(Final Answer / 没有 Action / 达到 max_steps)。
1.2 Workflow vs Agent —— Anthropic 经典分类
Anthropic 的 "Building Effective Agents" 把 LLM 系统分两类:
| Workflow (流水线) | Agent (自主体) |
|---|---|
| 代码主导,LLM 是 step 之一 | LLM 主导,代码是 tool 集合 |
| 流程可预测、可绘 DAG | 流程动态、长尾难绘 |
| 例:翻译流水线、SQL 生成 + 校验 + 执行 | 例:Cursor agent、Claude Code、Devin |
| 成本可控、可测试 | 成本不可控、难 deterministic |
面试金句:"绝大多数生产场景需要的是 Workflow 不是 Agent。先用 Workflow 解决,只有当步骤无法预先确定时再升级到 Agent。"
2. ReAct — Agent 的"汇编语言"
2.1 原始论文与核心思想
ReAct: Synergizing Reasoning and Acting in Language Models (Yao et al., 2022)
核心洞察:让模型显式输出 reasoning trace(Thought),再输出 Action,比让它隐式推理后直接 Action 准确率显著提升。
Thought_t: 思考当前应该做什么
Action_t: tool_name(args) ← 解析执行
Observation_t: <tool result> ← 喂回 prompt
Thought_t+1: 综合观察,决定下一步
...
Final Answer: <最终答案>
2.2 ReAct 在数学上的形式化
把对话历史定义为:
h_t = [s_0, a_0, o_0, s_1, a_1, o_1, ..., s_t]
其中 s_i 是 Thought,a_i 是 Action,o_i 是 Observation。
每一步 LLM 是一个条件分布:
p(s_{t+1}, a_{t+1} | h_t) = LLM(h_t)
执行 action 得到环境的 deterministic 函数:
o_{t+1} = ENV(a_{t+1})
→ 整个 Agent 是一个 POMDP(Partially Observable Markov Decision Process)的 policy,LLM 充当 policy network,只是没有显式训练 policy gradient —— 行为靠预训练 + 少量 finetune(GRPO/ORPO 等可以专门训 agent policy)。
2.3 为什么 ReAct 有效?三个机制
- Verbalization grounding:Thought 是显式输出的自然语言,模型把推理"摊到台面上",降低 hallucination
- Tool 作为外部 oracle:tool result 是确定性的(calculator/datetime/search),给模型提供 ground truth
- Self-correction:观察到 Action 失败后,Thought 可以重新规划
2.4 ReAct 在生产中的两种实现
实现 A:Prompt 驱动(模型直接输出文本)
SYSTEM = """你是 ReAct agent. 可用工具: ...
输出格式:
Thought: <思考>
Action: tool_name(<args>)
Observation: <由工具填充>
...
Final Answer: <最终答案>"""
while step < max_steps:
resp = llm.chat.completions.create(..., stop=["Observation:"])
out = resp.choices[0].message.content
if "Final Answer:" in out: return parse_final(out)
action = parse_action(out)
obs = execute_tool(action)
messages.append({"role": "user", "content": f"Observation: {obs}"})
适用:任意模型,但解析脆弱(正则 / 括号配对)。Bonus-2 的 agent_demo.py 就是这套。
实现 B:Function Calling 驱动(模型直出 JSON)
tools = [
{"type": "function", "function": {"name": "calculator", "parameters": {...}}},
{"type": "function", "function": {"name": "search", "parameters": {...}}},
]
while step < max_steps:
resp = llm.chat.completions.create(messages=messages, tools=tools, tool_choice="auto")
msg = resp.choices[0].message
if not msg.tool_calls: # 模型不再调用工具
return msg.content
for tc in msg.tool_calls:
result = execute_tool(tc.function.name, json.loads(tc.function.arguments))
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
适用:OpenAI / Anthropic / Qwen2.5+ / Mistral 等支持 function calling 的模型。强结构化、解析零成本、生产首选。
3. Tool Use 三种范式
| 范式 | 工具表达 | 优势 | 劣势 | 代表 |
|---|---|---|---|---|
| A. ReAct prompting | Free-form text + 正则 | 任意模型 | 解析脆弱 | 早期 LangChain |
| B. Function Calling | JSON Schema | 结构化、稳定 | 依赖模型微调 + 推理框架支持 | OpenAI / Claude / Qwen2.5 |
| C. Code-as-Action | 模型直接写 Python | 表达力最强(组合工具) | 沙箱安全风险 | smolagents、Devin |
3.1 Function Calling 的内部机制
模型层:
- 在 SFT 阶段用大量
<tool_call>{...}</tool_call>样本训练 - 推理时根据 tools schema 引导生成符合 schema 的 JSON
推理框架层(vLLM 例):
vllm serve Qwen/Qwen2.5-7B-Instruct \
--enable-auto-tool-choice \
--tool-call-parser hermes # 不同模型用不同 parser: hermes / llama3_json / mistral
--tool-call-parser 决定怎么把模型输出文本解析回 OpenAI ChatCompletion 格式的 tool_calls 字段。
3.2 Code-as-Action 的崛起
smolagents (HuggingFace) 把 Action 定义为"写一段 Python 代码":
Thought: 我需要先查时间,再计算两个数。
Code:
```python
now = datetime.now()
result = calculator("3 * 4 + 5")
print(f"Time: {now}, Result: {result}")
**优势**:
- 组合工具(一段代码里调多个 tool)
- 控制流(if/for/try)由代码处理,不需要 agent loop
- 错误恢复(try/except)交给沙箱
**劣势**:
- **必须在沙箱里执行**(否则任意代码执行 = RCE)
- 调试难度高(代码生成错误时 stack trace 复杂)
工业级 Code-as-Action 沙箱:**E2B、Daytona、Modal、Pyodide**。
### 3.3 三种范式的选择
模型支持 function calling (OpenAI/Claude/Qwen2.5+) → B 模型不支持但有强 instruction following → A 任务需要复杂组合 / 数据处理 / 控制流 → C (Code-as-Action)
---
## 4. Memory / State 管理
### 4.1 五种 Memory 类型(认知科学借用)
| 类型 | 描述 | LLM Agent 中的对应 |
| --- | --- | --- |
| **Working memory** | 当前对话上下文 | LLM context window |
| **Short-term episodic** | 最近几次交互 | conversation history (slide window) |
| **Long-term episodic** | 历史交互记录 | vector DB(query 时检索) |
| **Semantic memory** | 事实/知识 | RAG knowledge base |
| **Procedural memory** | "怎么做"的技能 | Tool library + skill prompts |
### 4.2 Conversation Memory 的工程实现
#### A. Buffer Memory(简单)
```python
messages.append(new_message)
if total_tokens(messages) > max_tokens:
messages = messages[-N:] # 保留最近 N 条
B. Summary Memory(中等)
if total_tokens(messages) > threshold:
summary = llm.summarize(messages[:-K])
messages = [{"role": "system", "content": summary}, *messages[-K:]]
C. Vector Memory(高级)
def get_relevant_history(query, k=5):
return vector_db.search(query, k=k)
messages = system_prompt + get_relevant_history(query) + [user_msg]
D. Hierarchical Memory(MemGPT 风格)
- L1: Working context (in prompt)
- L2: Recall storage (recent, in DB)
- L3: Archive (vector DB, by similarity)
- L4: External (function call to retrieve)
LLM 自己决定从 L2/L3/L4 拉什么进 L1。
4.3 State 持久化
Agent 不应该把所有状态写进 prompt,关键状态应该外部化:
# 不推荐:state 全在 prompt 里
messages.append({"role": "system", "content": f"Current todo list: {json.dumps(todos)}"})
# 推荐:state 在外部,工具读写
@tool
def get_todos() -> list: return db.get_todos()
@tool
def add_todo(item: str): db.add(item)
面试金句:"Agent 的 state 应该用'外部可读写'的方式管理,而不是塞进 prompt。否则 context 爆炸 + 状态不一致。"
5. Planning 范式
5.1 五种 Planning 方法对比
| 方法 | 思想 | 适用 | 代价 |
|---|---|---|---|
| Chain-of-Thought (CoT) | 单次输出全部 reasoning steps | 简单任务 | 1× LLM call |
| ReAct | Step-by-step,每步可调工具 | 需要工具的任务 | N× LLM call |
| Plan-and-Execute | 先生成全计划,再逐步执行 | 任务步骤清晰 | 1 plan + N exec |
| ReWOO | Plan 输出含 dependency 的 DAG,可并行执行 | 多步任务可并行 | 1 plan + 并行 exec |
| Tree-of-Thought (ToT) | 同时探索多个推理分支,backtrack | 搜索类(数学/编程) | M × N call (昂贵) |
| Reflexion | 失败后让模型反思,记录到 memory,下次避免 | 长程任务 | 多 episode 学习 |
5.2 Plan-and-Execute 详解
User: 帮我订下周三北京到上海的机票,优先东方航空,价格 < 1500
Plan (LLM 一次性生成):
1. search_flights(from="北京", to="上海", date="2026-06-04", airline="东方航空")
2. filter price < 1500
3. book_flight(flight_id)
4. notify_user(booking_info)
Execute (逐步执行 + 中间结果代入):
step 1 → results = [...]
step 2 → filtered = [...]
step 3 → booking = {...}
step 4 → done
优势:Plan 阶段一次性 think hard,Execute 阶段 cheap;DAG 可并行。 劣势:Plan 错了整个 chain 都歪。
LangGraph 把这个模式做成 first-class:StateGraph 显式定义节点和边。
5.3 Reflexion — Self-improving Agent
Episode 1: Agent 失败 → 把 Trace 喂给 reflector LLM → 生成 "lesson learned"
Lesson: "下次遇到 X 不要用 Y 工具,应该先用 Z 工具确认"
Episode 2: 把 lesson 放进 system prompt → Agent 更聪明
面试常考:这跟 RLHF 的区别?
- RLHF 修改模型权重,需要梯度更新
- Reflexion 通过 prompt 注入"教训",zero gradient
6. Multi-Agent 协作模式
6.1 五种典型拓扑
| 模式 | 拓扑 | 适用 | 代表框架 |
|---|---|---|---|
| Sequential / Pipeline | A → B → C | 流水线任务 | LangGraph |
| Hierarchical | Orchestrator + Workers | 任务分解 | AutoGen, CrewAI |
| Parallel | Orchestrator → [A, B, C] → Merge | 独立子任务并行 | LangGraph |
| Debate / Multi-turn discussion | A ↔ B ↔ C 多轮 | 创意 / 决策 | AutoGen |
| Group Chat | 共享会话,Agent 自己决定何时说话 | 复杂协作 | AutoGen GroupChat |
6.2 何时用 Multi-Agent vs 单 Agent + 多工具?
| 信号 | Multi-Agent |
|---|---|
| 不同 Agent 需要不同的 system prompt / 角色 | ✅ |
| 不同 Agent 需要不同的工具集(隔离工具池) | ✅ |
| 任务需要专精能力(coder / reviewer / planner) | ✅ |
| 只是"调用更多工具" | ❌ 单 Agent + 多工具更简单 |
| 需要并行执行 | 🟡 单 Agent 也可以并行 tool calls |
Anthropic 经验之谈:大多数"multi-agent"场景其实可以用单 agent + 良好的 system prompt 实现,multi-agent 引入的复杂度和 latency 往往得不偿失。
6.3 Multi-Agent 的工程陷阱
- Context 爆炸:每个 sub-agent 都拷贝一份历史,token 用量 N 倍
- 协作幻觉:Agent A 告诉 Agent B 一个错误事实,B 信以为真
- 死循环:A 让 B 做,B 让 A 做
- 责任不清:出错时不知道是谁的锅(没 trace 几乎调不动)
防御性设计:
- 显式 Orchestrator(避免点对点通信)
- 共享 state 用结构化数据,不要纯自然语言
- 每个 sub-agent 独立 max_steps,总预算上限
- 必须有 trace ID 串起所有调用
7. Agent 框架横向对比
7.1 主流框架矩阵
| 框架 | 抽象层 | 范式 | 学习曲线 | 适用 |
|---|---|---|---|---|
| LangChain | 高,无所不包 | Chain + Agent + 一切 | 高(API 不稳) | 快速原型,Python 后端 |
| LangGraph | 中,StateGraph | 显式状态机 | 中 | 复杂多 agent / cyclic flow |
| LlamaIndex | 中,文档为中心 | RAG + Query Engine | 中 | 文档 QA / Knowledge Agent |
| AutoGen (MS) | 中,对话为中心 | Multi-agent conversation | 中 | 角色协作场景 |
| CrewAI | 低,任务为中心 | Sequential / Hierarchical Crews | 低 | 业务流程 |
| smolagents (HF) | 低,Code-as-Action | CodeAgent / ToolCallingAgent | 低 | "让模型直接写 Python" |
| OpenAI Agents SDK | 低,handoff 模型 | Sub-agent handoff | 低 | OpenAI/Anthropic API 直接用 |
| Pydantic-AI | 中,Type 强约束 | Schema-first agent | 中 | 生产 API,结构化输出 |
| Atomic Agents | 低,IO Schema | Strict input/output schema | 低 | 极简结构化 |
| MCP (Anthropic) | 协议层,跨进程 | Server-Client 工具协议 | 中 | 工具复用 / 跨产品 |
7.2 LangChain 的功过
优点:
- 生态最大,Document loader / Vector DB / LLM provider integration 都有
- prototype 最快
痛点:
- API 不稳(0.0 → 0.1 → 0.2 → 0.3 多次大重构)
- 抽象过度(LCEL / Runnable / Chain 太多概念)
- 生产环境调试困难(error trace 跨多层装饰器)
业内实情:prototype 用 LangChain,production 自己写或用 LangGraph。
7.3 LangGraph 的"对症下药"
LangGraph 解决了 LangChain 的 cyclic flow 问题:
from langgraph.graph import StateGraph, END
class AgentState(TypedDict):
messages: list
iteration: int
def llm_node(state):
resp = llm.invoke(state["messages"])
return {"messages": state["messages"] + [resp]}
def tool_node(state):
tool_result = execute_tool(state["messages"][-1])
return {"messages": state["messages"] + [tool_result]}
def should_continue(state):
if "Final Answer" in state["messages"][-1].content: return END
if state["iteration"] > 10: return END
return "tool"
g = StateGraph(AgentState)
g.add_node("llm", llm_node)
g.add_node("tool", tool_node)
g.add_edge("tool", "llm")
g.add_conditional_edges("llm", should_continue, {"tool": "tool", END: END})
g.set_entry_point("llm")
app = g.compile()
优势:
- 状态机显式,流程可视化
- 支持 streaming / checkpointing / human-in-the-loop
- LangSmith 集成,trace 强
7.4 MCP — 协议级标准化(Anthropic 2024 推出)
核心思想:把工具实现独立成"MCP Server",任何 Agent 客户端通过统一协议调用。
[Cursor Agent] ─┐
[Claude Code] ─┼─→ MCP Protocol ─→ [Filesystem MCP Server]
[Custom Agent] ─┘ → [GitHub MCP Server]
→ [Database MCP Server]
优势:
- 工具一次实现,N 个 Agent 复用
- 跨产品共享(Cursor 用的 Linear MCP 跟你 agent 用的可以同一份)
- 安全边界清晰(Server 独立进程)
面试常考:MCP 跟 function calling 的关系?
- function calling 是 模型与 Agent 之间 的协议(JSON Schema)
- MCP 是 Agent 与 Tool Provider 之间 的协议(JSON-RPC over stdio/SSE)
- 两者互补,不冲突
8. 工业界 Agent 系统拆解
8.1 Cursor / Claude Code(代码编辑 Agent)
User: "把这个函数改成异步的,加错误处理"
↓
[Agent Loop]
├─ Tool: read_file (查看上下文)
├─ Tool: codebase_search (找类似实现)
├─ Thought: 决定改法
├─ Tool: edit_file (写改动)
├─ Tool: run_tests (验证)
├─ Thought: 测试失败 → 修复
└─ Final: diff + 解释
关键设计:
- Read-only tools 默认放行,write-tools 需要 user approval
- 每次 edit 都有 diff preview
- Context 主要靠 codebase_search(RAG),不靠 long context
- max_steps 高(通常 50-100),但有 token 预算上限
8.2 Devin / OpenDevin(全自主编程 Agent)
User: "实现一个 Twitter 克隆"
↓
[Planner] → 拆解成 20 个 task
↓
[Worker Agent] 在沙箱(Docker)中:
├─ shell (apt-get install ...)
├─ editor (写代码)
├─ browser (查文档)
├─ git (commit / push)
└─ test runner
特点:
- 完整 sandbox 环境(VM / Docker),agent 有 root
- 长任务(几小时 - 几天)
- 失败率高,但可以无人值守
- 成本极高(Devin 一次任务可能消耗 $50+ token)
8.3 Manus / Replit Agent(任务自动化)
- 浏览器自动化 + shell + 代码生成
- 强调 "任务级"(订机票、自动报销、信息聚合)
- 用户给目标,Agent 自主探索
8.4 Claude Code(命令行 Agent,Anthropic 官方)
Toolset:
- Read / Edit / Write (file ops)
- Bash (shell)
- Grep / Glob (codebase search)
- WebFetch / WebSearch
- Agent (子 agent spawn)
- Task tools (todo)
设计哲学:
- Read-only 默认放行,destructive 必须确认
- 工具粒度细(Read vs Grep vs Glob 分开)
- 显式 Plan 模式(
ExitPlanMode工具) - Sub-agent 用于隔离 context(避免主 context 污染)
9. Agent 评估 — 比模型评估更难
9.1 为什么 Agent 难评估?
| 维度 | LLM benchmark (MMLU) | Agent benchmark |
|---|---|---|
| 输出 | 单个 token / 单 turn | 长 trace, multi-turn |
| 评判 | 字符串匹配 | 行为正确性 + 副作用 |
| 环境 | static dataset | 动态环境(浏览器、shell) |
| 评分自动化 | 简单 | 需要环境模拟 + LLM-as-Judge |
9.2 主流 Agent Benchmark
| Benchmark | 类型 | 测试什么 | SOTA 2025 |
|---|---|---|---|
| SWE-bench | 软件工程 | GitHub real bug 修复 | Claude 3.5 Sonnet ~50% |
| SWE-bench Verified | 人工筛选过的 SWE-bench 子集 | 同上但质量更高 | ~70% |
| WebArena | 浏览器操作 | 在网站上完成任务 | ~30-40% |
| GAIA | 通用助手 | 多步推理 + 工具 | GPT-4 + agent ~50% |
| AgentBench | 综合 | OS / DB / Web / Code 各任务 | 不同任务差异大 |
| τ-bench | 真实场景 | 客服 / 零售场景 | ~40-60% |
| OSWorld | 桌面操作 | 在 Linux/Mac 桌面操作 GUI | <20% |
重点:真实世界任务 SOTA 普遍 30-70%,跟 MMLU 等 90%+ 的"模型已经超越人类"是两个世界。
9.3 评估的工程实现
A. LLM-as-Judge
def judge_trace(task, trace, ground_truth):
return llm.complete(f"""
Task: {task}
Agent trace: {trace}
Ground truth: {ground_truth}
Score 1-10 on: correctness, efficiency, safety
""")
B. Functional Test
代码任务:跑测试套件,看 pass 多少。
C. Trajectory Comparison
跟人类 demo 比 trajectory similarity。
D. Side-effect Detection
Agent 跑完后检查:文件改对了吗?数据库状态对吗?
10. 失败模式与防御性设计
10.1 八种典型失败
| 失败 | 表现 | 缓解 |
|---|---|---|
| 死循环 | 反复调同一工具 | max_steps + 重复检测 |
| 工具幻觉 | 用不存在的工具 | strict tool validation + Reject early |
| 参数幻觉 | 给错误参数 | JSON Schema 校验 + retry with error |
| 过度自信 | 用错答案当 Final | Self-critique step before Final |
| Lost in middle | 长 trace 后忘记任务 | 定期 inject task reminder |
| Cascading error | 一步错全错 | 中间步骤 self-verify |
| Tool fabrication | 编造 tool 不存在的功能 | Tool docstring 严格,examples 完整 |
| Premature stop | 任务没做完就 Final | 明确的 success criteria in prompt |
10.2 七条生产规则
- Hard cap on steps:
max_steps=20,绝不让 agent 无限循环 - Token budget:单会话总 token 上限,超了就强制收尾
- Tool sandboxing:Code-as-action 必须沙箱;file/network 操作必须 whitelist
- Human-in-the-loop for destructive actions:发邮件、删数据、付款必须确认
- Trace everything:每次 tool call 全打,trace ID 串起来
- Graceful tool failures:工具 raise → 把 error 喂回 prompt,模型自己看
- Idempotency:重要操作(创建订单)要做去重,防止重试爆炸
10.3 安全防护清单
- [ ] Prompt injection 防御(用户输入不能修改 system prompt)
- [ ] Tool 调用 whitelist(允许范围内的 URL / file path)
- [ ] Rate limiting(单用户单时段调用上限)
- [ ] PII 脱敏(进 LLM 之前先 redact)
- [ ] Output filtering(出来的内容过敏感词)
- [ ] Audit log(所有 Action + Observation 持久化)
- [ ] Cost dashboard(token 用量 + 钱花了多少实时可见)
- [ ] Kill switch(异常情况一键停所有 agent)
11. 面试常考题型 + 答题框架
11.1 原理题
Q: ReAct 跟 CoT 的区别?
A:
- CoT 是 reasoning-only,单次输出完整 reasoning chain,无工具调用
- ReAct 是 reasoning + acting,每次 reasoning 后跟一个 action,action 结果反过来指导下一次 reasoning
- 数学上:CoT 是
p(answer|prompt),ReAct 是p(answer|prompt, tool_results)的多步序列决策
Q: Function calling 内部是怎么实现的?
A: 三层
- 模型层:SFT 用
<tool_call>{...}</tool_call>样本训练过 - 推理框架层:vLLM 的
--tool-call-parser把模型自然输出解析回 OpenAI tool_calls 格式 - 应用层:执行 tool,把结果以
role=tool消息追加,再次调 LLM
Q: 为什么 Agent 容易"Lost in the middle"?
A: 三个原因
- attention head 训练时倾向关注两端(开头任务说明,结尾当前生成)
- 长 trace 累积大量 tool observation,信号被噪音淹没
- 模型 RoPE 位置编码在 > train_len 后退化
缓解:RAG-style retrieval over trace、定期 summarize、inject task reminder
11.2 系统设计题
Q: 设计一个 "代码 review agent"
答题框架(STAR + Trade-off):
1. Requirement 分解
- 输入: PR diff + repo context
- 输出: 评论(行级)+ 总结
- 约束: 24h 内 review、cost < $0.5、不能误删代码
2. 架构
[GitHub Webhook]
↓
[Trigger Service] → 下载 PR diff
↓
[Context Builder] → RAG 召回相关文件
↓
[Review Agent (LangGraph)]
├─ Tool: read_file
├─ Tool: search_code (相似实现 / 历史 bug)
├─ Tool: run_lint
├─ Tool: post_comment (write, 需要审批)
└─ Final: 总结评论
↓
[Audit Log + Cost Tracker]
3. 关键设计决策
- Function calling > ReAct prompting:输出结构化、稳定
- LangGraph > LangChain:状态机清晰,checkpointing
- Read-only tools 自动放行,post_comment 走批准 queue
- max_steps=15, token budget=50K
- Trace 全打到 Datadog,失败可重放
4. Trade-off
- 用 RAG 而非 long-context:32K context vs 5K retrieval,准确率 + 成本 双优
- 单 agent 而非 multi-agent:任务清晰不需要分角色
- Claude 3.5 Sonnet (代码强) vs GPT-4o:选 Sonnet
Q: 设计一个 "自动报销 Agent"
要点:
- 必须 human-in-the-loop(涉及钱)
- OCR + 票据解析(独立 tool)
- 公司报销规则用 RAG / structured config
- 提交前 dry-run summary 给用户
- Audit log 强制(legal 要求)
Q: 多 agent 跑分布式爬虫
要点:
- Orchestrator 单一,Workers 无状态
- 共享 state 用 Redis / DB,不靠 message
- 每个 worker 独立 max_pages 配额
- Backoff + retry,robots.txt 遵守
- Trace ID 串起所有 page
11.3 工程题
Q: 一个 agent 跑了 30 步还没停,你怎么调?
1. 看 trace: 哪一步开始重复?
2. 看 tool result: 是否工具 always 返回同一结果?
3. 看 thought: 模型是否"看不懂"observation?
4. 看 prompt: success criteria 写清楚了吗?
5. 临时解:加 max_steps=10 兜底
6. 根本解: tool docstring 加 examples / explicit "When you have answer, output Final Answer"
Q: Agent 每个会话花 $10,怎么降?
1. 测量:trace 里 token 怎么分布?prefill 还是 decode?
2. Prefix caching:system prompt + tool def 走 prefix cache
3. 模型分级:简单子任务用 Haiku,复杂用 Sonnet
4. Tool 精简:不用的工具别给模型
5. Memory 压缩:Summarize old turns
6. Plan-and-Execute:Plan 用大模型,Execute 用小模型
7. Max_steps 收紧:从 30 → 15
Q: 怎么测试一个 Agent?
分四层:
1. Unit:每个 tool 独立测
2. Integration:agent + 单个 tool 的 mini scenario
3. End-to-end:完整任务 + LLM-as-Judge 打分
4. Regression:固定 N 个 golden trajectory,每次发布跑一遍
CI 要点:
- LLM 输出不稳,assert 不能太严格 (用 semantic similarity / LLM judge)
- 跑回归要 stable seed
- 关键路径要 deterministic tool mock
12. 学习路径推荐
12.1 三个月路径(从 0 到面试通过)
| 月 | 内容 | 产出 |
|---|---|---|
| 1 | LLM 基础(Transformer / Attention / RoPE / KV Cache),Prompt 工程,OpenAI / Claude API | 能用 API 实现 RAG demo |
| 2 | ReAct 原理 + LangGraph 实战 + Function Calling + MCP | 自己实现一个 multi-step agent |
| 3 | Multi-Agent + 工业架构(Cursor/Devin 拆解)+ benchmark + 面试题 | 完整 portfolio project + 面试 |
12.2 必读论文(按重要度)
- ReAct (2022) — 范式奠基
- Toolformer (2023) — Tool use 训练
- Reflexion (2023) — Self-improvement
- Voyager (2023) — Skill library
- MemGPT (2023) — 分层 memory
- Plan-and-Solve (2023) — Planning
- Tree of Thoughts (2023) — 搜索式推理
- Anthropic's Building Effective Agents (2024) — 工业经验
- MCP spec (2024) — 工具协议标准
12.3 必玩项目
- LangGraph 官方 tutorial(必做)
- 自己实现 ReAct loop(< 100 行,理解透)
- 用 MCP 写一个 Tool Server(理解协议)
- 拆解 Claude Code 源码(理解工业级实现)
- 跑通 SWE-bench Verified(感受真实难度)
12.4 面试硬通货
- 能现场白板 ReAct loop 代码(20 行)
- 能用一张图画清 Agent 系统(LLM / Tool / Memory / Loop)
- 能讲清楚 Workflow vs Agent 的边界
- 对 LangChain / LangGraph / AutoGen / MCP 都有手感
- 能拆解工业级 Agent(Cursor / Devin 至少一个深入讲清楚)
- 知道生产 Agent 的 8 种失败模式 + 7 条规则
13. 一句话总结
Agent = LLM + Tools + Memory + Loop;
底层算法全是 ReAct;框架差异在调度、状态、协作;
工业级 Agent 的难点是幻觉控制 + 错误恢复 + 成本 + 安全,不是"让模型调工具";
绝大多数生产场景用 Workflow 而不是 Agent,只有当步骤真的不能预先确定时,Agent 才是答案。
附录 A:Bonus-2 RAG/Agent 实战回看
实测代码已在 /opt/bonus2/:
rag_demo.py— ChromaDB + vLLM 端到端 RAGagent_demo.py— ReAct loop + 3 工具(calculator/datetime/kb_lookup)
测试 Q3 触发的真实问题: calculator(sqrt(144) + 3 * pow(2, 5)) regex [^)]*) 在第一个 ) 就停,args 错误 → 模型靠多步分解 work around,最终答对。这就是真实 Agent 现场:工具脆弱,模型韧性。
附录 B:面试模拟题库(20 道)
原理题
- 解释 ReAct 跟 CoT 的区别
- Function Calling 内部怎么实现的?
- MCP 跟 Function Calling 的关系是什么?
- 为什么 Agent 容易 Lost in the middle?
- Tool calling 用 ReAct prompting 还是 native function calling,选哪个?
选型题
- LangChain 和 LangGraph 选哪个?
- 什么时候上 Multi-Agent?
- ReAct vs Plan-and-Execute 怎么选?
- Code-as-Action 跟 Function Calling 各自适用场景?
系统设计题
- 设计一个代码 review agent
- 设计一个自动报销 agent
- 设计一个客服 agent(支持转人工)
- 设计一个搜索 agent(可以浏览网页)
- 设计一个研究助手 agent(读论文 + 总结)
工程题
- Agent 跑 30 步不停怎么调?
- Agent 花 $10/session 怎么降?
- Tool 偶尔失败怎么让 Agent 恢复?
- 多 agent 互相调用陷入死循环怎么破?
- 怎么测试 Agent?
- Production Agent 的可观测性怎么做?
附录 C:配套文档链接
- Bonus · 训练框架全景
- Bonus-2 · RAG/Agent 实战 — 实测代码
- Bonus-3 · 推理优化 — 影响 Agent latency
- Bonus-4 · Context Length 原理 — 影响 Agent memory
- Training v2 · 深度调参 — 训练 agent policy 时用