← 返回学习路线 ◆ 贯穿项目
应用工程与上线 · 阶段 14 · Agent 工程
Stage 14 / 17 · 应用工程与上线

Agent 工程 Agent Engineering

2026 年,Agent 已经从「玩具」进入「生产落地」阶段。协议收敛(MCP 做工具、A2A 做协作)、框架分化(生产编排与原型工具各归其位)、工程成熟(可观测、评估、安全从可选变成必须)是三个明确趋势。掌握 MCP Server 开发 + 生产级编排,是拿到 Agent 岗位的核心竞争力。

⏱ 5–6 周 🎯 核心 · 就业主力 ◆ 里程碑 M14 2026-09-29
AgentMCPA2ALangGraphLong-horizonComputer Use

阶段总览

✔
学完你能做到
  • 能说清 Agent 的本质循环,并正确选择 ReAct / Plan-and-Execute / 反思等模式
  • 掌握 Function Calling 与 MCP,能开发一个自己的 MCP Server 并接入 Agent
  • 理解 A2A 协议与多 Agent 协作的常见编排模式,能做框架选型
  • 能实现长程任务的状态管理、检查点、进度追踪与失败恢复
  • 了解 Computer Use / GUI Agent 的能力与风险,能做场景判断
  • 能建立 Agent 的可观测、评估与安全体系,使其可长期运行
  • 能回答面试中「为什么你的 Agent 可靠」这个终极问题
阶段知识结构总览 · 从智能体循环到生产可信任
阶段 14 · Agent 工程Agent Engineering · 7 大章 · 128 个知识点
1. Agent 的本质规划 / 记忆 / 工具 / 反馈ReAct 与 Plan-and-ExecuteReflexion 反思终止条件 max_steps / no-progress
2. 工具调用与 MCPJSON Schema 工具设计MCP Tools / ResourcesHost / Client / Servertool router 限 5–10
3. A2A 与多 AgentAgent Card 发现Task 状态机Supervisor / Handoff上下文隔离是主收益
4. 长程任务与 Computer Use状态外置 + 检查点幂等指纹 ledger熔断 + 补偿GUI 高危动作门禁
5. 生产化指标体系与故障排查纵深防御四层沙箱 + 最小权限prompt caching 降 10x
6. Agentic RLGRPO 不等长失真PPO + CriticARPO 分叉采样奖励黑客
7. Agent 评测轨迹级评估tau-bench / SWE-benchReplayEnv 回放进回归集
贯穿项目 · M14 MCP 工具生态与多 Agent 编排第 79–86 周至少 3 个自建 MCP server(检索、SQL 只读、沙箱代码执行)ReAct / Plan-Execute 循环,含工具选择、参数校验、步数上限、失败恢复多 Agent 分工(规划者 / 检索者 / 执行者 / 校验者)+ A2A 风格消…状态检查点、断点恢复、危险操作人工审批闸门
学习路径
★
一句话理解协议分工:MCP 连接你的 Agent 与工具,A2A 连接你的 Agent 与其他 Agent,Context Engineering 决定它到底有多聪明,Harness 决定它能不能跑一整天。』这四件事就是 2026 年 Agent 工程的全部骨架。
周次主题交付物
第 1 周Agent 循环与设计模式手写一个不依赖框架的最小 Agent
第 2 周Function Calling 与 MCP开发并接入一个自定义 MCP Server
第 3 周多 Agent 与 A2A用 LangGraph 实现多角色协作流程
第 4 周长程任务与状态管理带检查点与恢复的长任务 Agent
第 5 周Computer Use / GUI Agent一个浏览器自动化任务并分析风险
第 6 周生产化与综合项目带 tracing / evals / 审批的完整 Agent 系统

1. Agent 的本质:一个带记忆的循环

知识结构图 · Agent 的本质
Agent 的本质:一个带记忆的循环6 大知识域 · 24 个知识点
四大组件规划 Planning记忆 Memory工具 Tools反馈 Feedback错误回传而非抛出
学习路径
  1. 读 1.1:理解规划 / 记忆 / 工具 / 反馈四大组件与能力演进
  2. 跑内置代码:搭一个最小循环,让反馈以错误回传而非抛出形式处理
  3. 完成动手练习:给自己的 agent 补上四件套并自测
  4. 对接 M14:按四组件结构规划 MCP 工具 + 记忆 + 规划的编排骨架
✔ 能画出一个含四组件的 agent 循环并正确传递反馈
核心知识点详解
  • 规划 / 记忆 / 工具 / 反馈是四件套:单一循环里模型每轮会:依据记忆与目标规划下一步 → 调用工具拿到结果 → 把反馈回传成新的观察。任何框架(LangGraph / 手写循环)都是这四件的编排,区别只在显式程度:越显式越可控。
  • 反馈要「回传」而不是「抛出」:工具出错如果直接 raise,循环就断了;正确做法是把错误作为 observation 回传给模型,让它自主决策修错 / 换招 / 终止。实测里「错误回传而非抛出」能把多步任务成功率提升约 20–40%。
  • 记忆决定长程能力:工作记忆(当前状态)保持在上下文,长期记忆跨会话存取。上下文会随 token 增长撑爆,所以大任务要靠状态外置(见 4.1),别全指望模型「记住」。常见坑:记忆全堆在上下文里,步数一多就超长截断,模型「失忆」返工。
设计模式链式流水线ReAct 单 AgentPlan-and-ExecuteOrchestrator-Worker多 Agent 群聊慎用
学习路径
  1. 读 1.2:对比链式 / ReAct / Plan-Execute / Orchestrator-Worker 的适用
  2. 跑内置代码:把同一任务用流水线与单 Agent ReAct 各跑一遍
  3. 完成动手练习:判断当前任务该用哪种模式并说出理由
  4. 对接 M14:为多步工具任务选定 ReAct 或 Plan-Execute 骨架
✔ 能按任务特性选型设计模式并给出不用多 Agent 群聊的理由
核心知识点详解
  • 能否预停是「流水线 vs Agent」的分界:链式流水线适合步骤固定可枚举(>90% 调用路径不分支)的任务,快且可靠;一旦中途要依据中间结果动态决定下一步,就该上 Agent。判断口诀:分支多于 A·B 时,流水线的代码量会指数增长,Agent 反而更省。
  • ReAct / Plan-Execute 的选择:ReAct 边想边做,适合探索型少步骤;Plan-Execute 先一次性规划再逐步执行,适合 ≥5 步的稳定任务,规划多用强模型、执行多用小模型以省钱。Orchestrator-Worker 适合粒度明确的并行子任务。
  • 多 Agent 群聊是反模式,慎用:让多个 agent 自由互聊会出现协调开销与不可控性:token 翻 2–4 倍,还容易跑题。需要协作时优先用 Supervisor / Router 这类显式编排,而不是开放群聊。常见坑:为了「酷」上多 Agent,换来更高的失败率与成本,却说不清收益。
ReActThought / Action / ObsAction 标签解析no-progress 早停
学习路径
  1. 读 1.3:吃透 Thought / Action / Obs 交织与 Action 标签解析
  2. 跑内置代码:跑一个 ReAct 循环并观察三条 Thought-action-obs 记录
  3. 完成动手练习:加 no-progress 早停并在重复循环时终止
  4. 对接 M14:用 ReAct 驱动工具选择与参数校验的最小闭环
✔ 能解析 ReAct 轨迹并让 agent 在无进展时自动早停
核心知识点详解
  • ReAct = 思考 + 行动 + 观察的交织循环:每步模型输出一个 Thought(推理)→ Action(调用工具)+ 参数 → 把工具返回作为 Observation 喂回下一个 Thought。关键是把轨迹用 Action 标签解析出来:Tool[名称(参数)] 这类格式,用正则或 LLM 解析成可校验的结构化调用。
  • Action 标签解析是可靠性支点:模型的输出是自由文本,要从中稳定抽出动作就用限定的 JSON 或 XML Action 标签(如 name)+ json.loads 解析,解析失败就让模型重试。一次解析失败重试的损耗远小于后面带着脏参数执行工具。
  • no-progress 早停:防空转烧钱:模型常在原地打转。做法是维护一段滑动窗口(如最近 3–5 步),若 Thought 没有实质进展(没新信息 / 重复同样 action),就触发早停返回现状。实测能省掉 30%+ 的无效步数。常见坑:只设 max_steps 上限但不做无进展检测,模型慢吞吞烧满上限才停。
Plan-and-Execute强模型规划 + 小模型执行blocked 触发重规划≥5 步才划算
学习路径
  1. 读 1.4:掌握强模型规划 + 小模型执行与 blocked 重规划
  2. 跑内置代码:让执行卡住时触发重规划而不是死循环
  3. 完成动手练习:评估任务是否达到 ≥5 步再决定采用
  4. 对接 M14:实现 Plan-Execute 并用灵活模型规划、轻量模型执行
✔ 能演示任务被阻塞后自动重规划并恢复推进
核心知识点详解
  • 规划 / 执行分离:好钢用在刀刃上:用强模型一次性产出完整的步骤计划,再用轻量小模型逐条执行,成本可省 30–60%:思考发生一次,执行走便宜模型。适用门槛是任务≥5 步——步数太少时规划的收益覆盖不了它的开销。
  • blocked 触发重规划而非死循环:执行步骤失败 / 卡住时不能原地重试 N 次,而要带着失败信息重新规划剩余步骤(blocked: 原因 → 重新 plan)。关键命令是规划接口返回新计划而非执行接口再试,否则等于 ReAct 空转。
  • 规划要做成可校验的子目标:计划里每步要有可验证的完成判据(文件存在 / 断言通过),不满足就别标记为完成。常见坑:计划只列「要做的事」而无验收标准,执行 agent 对着模糊目标反复试错,重规划也救不回。
Reflexion 与边界语言化反思反思限 1–3 句Workflow 优先能用流水线不用 Agent
学习路径
  1. 读 1.5 与 1.6:掌握语言化反思限 1–3 句与 Router / Workflow 边界
  2. 跑内置代码:让失败后的反思进入下一次循环并观察修复
  3. 完成动手练习:判断该用流水线还是 Agent,避免过度设计
  4. 对接 M14:给工具调用失败加简短反思 + 修复重路的恢复回路
✔ 能控制反思成本并说清用流水线而非 Agent 的判断依据
核心知识点详解
  • Reflexion:失败后的一次性语言反思:任务失败后让模型写简短反思(限 1–3 句),指出根因并给出下次的改进,作为附加记忆进入下一轮循环。它比盲重试更有效:把「我错了」变成「错因 + 对策」,下次执行带上经验走。
  • 反思是成本控制的关键:反思本身也调模型,要限长度并只在失败时触发。长反思的收益衰减明显:1–3 句通常已足够,写一大段既费 token 又稀释重点。实测控制反思长度能让总体 token 稳定且成功率不降。
  • 能用 Workflow 就不用 Agent:Agent 的灵活换来自动 + 不可控 + 成本高。反过来,凡是步骤能写死的就用流水线(Router / Workflow):固定编排稳定、便宜、可测。判断标准:这步是不是真的需要「根据中间结果自主决策」。常见坑:什么任务都塞给 Agent,付出递归失控的代价却只得到流水线就能给的输出。
终止条件显式完成信号max_steps 硬上限token / deadline 预算无进展检测
学习路径
  1. 读 1.7:吃透显式完成信号、max_steps、token 预算、无进展检测
  2. 跑内置代码:给循环设硬上限并验证不会无限跑
  3. 完成动手练习:为任务配齐四类终止信号并测边界
  4. 对接 M14:把终止条件纳入 loop 并在多步任务上防止失控
✔ 能保证任何路径都在预算内终止且不会无限循环
核心知识点详解
  • 四类终止信号缺一不可:① 显式完成:模型输出 final 标记或满足目标判据;② max_steps 硬上限(如 12–60 步);③ 预算:token / 时长 / 金额上限;④ 无进展检测:连续几步无实质变化。四者叠加才保证「必停」——只靠完成信号会漏掉死循环。
  • 先设上限再上线:生产前必须验证最坏路径在最严预算内终止。做法:用一个只测「卡死」的对抗任务跑 max_steps 满额,确认系统优雅退出并返回当前进度,而不是挂死烧钱。
  • 早停判定要低误报:无进展检测的滑窗(如最近 3–5 步)要够短以免误停正常的长思考步。常见坑:max_steps 设得太大又没有 token 预算,模型能原地打转烧掉几千 token 才撞上限;应同时设步数与 token 双上限。
学习路径

1.1 四大组件与能力演进

① 规划 Planning
把目标拆成可执行步骤,并在执行中根据反馈调整。模式有 ReAct(边想边做)、Plan-and-Execute(先规划后执行)、树式搜索。
② 记忆 Memory
工作记忆(当前任务状态)、会话记忆、长期记忆(跨会话经验)。记忆设计是长程任务能否完成的关键。
③ 工具 Tools
检索、代码执行、数据库、API、浏览器。工具定义的质量直接决定 Agent 的可靠性——工具描述含糊,模型必然用错。
④ 反馈 Feedback
观察工具结果、判断是否成功、失败后换策略重试。没有反馈闭环的就不是 Agent,只是流水线。
python# 手写最小 Agent:理解一切框架底层就是这个循环
import json

TOOLS = {
    "calculator": lambda expr: str(eval(expr, {"__builtins__": {}}, {})),
    "search":     lambda q: vector_search(q),        # 你的检索函数
}

def run_agent(llm, task, max_steps=12):
    messages = [
        {"role": "system", "content":
            "你是任务执行助手。需要工具时输出 JSON: {\"tool\": 名称, \"args\": {...}},"
            "否则输出 {\"final\": 最终答案}。每次只能调用一个工具。"},
        {"role": "user", "content": task},
    ]
    for step in range(max_steps):
        reply = llm.chat(messages, temperature=0.1)
        try:
            action = json.loads(reply)
        except json.JSONDecodeError:
            messages.append({"role": "assistant", "content": reply})
            messages.append({"role": "user", "content": "格式错误,请只输出合法 JSON。"})
            continue

        if "final" in action:                          # 终止条件:给出最终答案
            return action["final"], step + 1

        name = action.get("tool")
        if name not in TOOLS:                          # 工具不存在:把错误交回模型
            obs = f"错误:工具 {name} 不存在。可用工具:{list(TOOLS)}"
        else:
            try:
                obs = TOOLS[name](**action.get("args", {}))
            except Exception as e:                     # 工具异常也要回传,而不是抛出
                obs = f"工具执行失败:{type(e).__name__}: {e}"

        messages.append({"role": "assistant", "content": reply})
        messages.append({"role": "user", "content": f"观察结果:{obs}"})
    return None, max_steps                            # 超过步数上限:明确失败,不要无限循环
⚠
为什么很多 Agent 会失控:① 没有步数上限:陷入循环烧钱;② 没有终止条件:模型不知道该何时停;③ 工具描述含糊:参数名不一致、说明不清,模型反复试错;④ 错误被抛出而不是回传:模型看不到失败就无法自我纠正;⑤ 状态没落盘:中途失败全部重来。这五点是生产 Agent 的必备检查项。
python# 上下文预算: 每步注入的内容都要计入, 超预算先摘要再继续
CTX_WINDOW = 128_000          # 2026 主流窗口 128k-1M token
RESERVE_OUT = 8_000           # 给输出留位
def ctx_tokens(msgs):
    return sum(len(m["content"]) // 4 for m in msgs)   # 粗略: 4 字符≈1 token
def trim(msgs, tools_schema, budget=100_000):
    used = ctx_tokens(msgs) + ctx_tokens([tools_schema])
    if used <= budget: return msgs                      # 预算内, 不动
    old = summarize(msgs[1:-1])                         # 旧历史压成一段
    return [msgs[0], {"role": "user", "content": f"历史摘要: {old}"}, msgs[-1]]
# 预期量级: 1 个工具 schema ≈ 120 token; 20 个工具 ≈ 2400 token(必须做 tool router);
#   50 步轨迹原文 ≈ 4 万 token, 摘要后 ≈ 1.5k, 单任务成本立降一个量级

1.2 设计模式:不要一上来就多 Agent

模式结构适用风险
单次调用一问一答分类、抽取、改写、翻译无(最可控)
链式流水线固定步骤串联步骤完全可预知的任务几乎没有;但无法应对意外
ReAct 单 Agent思考-行动-观察循环步骤需动态决定,中等复杂度易循环、成本不可控
Plan-and-Execute先出计划再逐步执行任务可分解、步骤较多计划错误会放大;需要中途重规划
Orchestrator-Worker主 Agent 派活给专职子 Agent可并行的多子任务通信开销与状态一致性
Debate / Critique生成 + 批判 + 修订高风险决策、内容评审成本翻倍,收益需验证
多 Agent 群聊多个角色自由对话探索性任务最容易失控,生产慎用
✔
一条被反复验证的经验:先用最简单的结构解决问题。只有在「单 Agent + 好工具 + 好上下文」确实做不到时,才引入多 Agent。多 Agent 带来的协调开销、状态不一致与调试难度,往往超过它带来的收益。能力不是靠 Agent 数量堆出来的。
python# 模式选择的成本模型: 先算净收益, 再决定要不要上多 Agent
def worth_parallel(n, t_serial, t_max, coord_overhead):
    return (n * t_serial - t_max) > coord_overhead      # 净省时延才并行
# 经验数字(实测量级):
#   多 Agent 至少多花 2-4 倍 token(每个子 Agent 各自 system + 工具 schema);
#   协调失败率随 Agent 数上升, 超过 4-5 个角色后收益通常转负;
#   fan-out 把 N*t 降到 max(t)+overhead, 但仅当子任务真正独立时成立

1.3 ReAct:思考-行动-观察的交织

ReAct 把「推理」与「行动」交替展开:模型先输出 Thought(对当前状态的推理),再输出 Action(调用某个工具),环境返回 Observation,模型据此再 Thought。它逼着模型在每步「先想再做」,比直接让模型一把梭更不容易跑偏;同时 Thought 对人类可读,是排查 Agent 行为的主要线索。

python# ReAct 用显式标签包裹 Action, 便于精确解析(比依赖松散 JSON 更稳定)
REACT_PROMPT = """可用工具: {tools}
每轮严格按以下格式输出:
Thought: 你现在的推理
Action: 工具名
Action Input: 工具参数(单行 JSON)
(环境会返回 Observation, 你继续)
能回答时输出:
Final Answer: 最终答案
"""
import re, json
ACT_RE = re.compile(r"Action:\s*(\w+)\s*Action Input:\s*(\{.*?\})", re.S)

def step(llm, messages, tools, max_steps=12, no_progress=3):
    recent = []
    for i in range(max_steps):
        out = llm(messages)
        if "Final Answer:" in out:                     # 终止①: 显式完成
            return out.split("Final Answer:")[1].strip(), i + 1
        m = ACT_RE.search(out)
        if not m:                                      # 格式不符 -> 让模型补
            messages.append({"role": "assistant", "content": out})
            messages.append({"role": "user", "content": "请严格按 Action/Action Input 格式输出。"})
            continue
        name, args = m.group(1), json.loads(m.group(2))
        obs = call_tool(name, args)                    # 环境返回 Observation
        messages.append({"role": "user", "content": f"Observation: {obs}"})
        recent.append(obs)
        # 终止③: 无进展检测——最近 no_progress 次 Observation 完全相同
        if len(recent) >= no_progress and len(set(recent[-no_progress:])) == 1:
            return None, i + 1
    return None, max_steps                              # 终止②: 步数硬上限
模式决策时机步数单步成本可控性易失控点
ReAct每步动态多中中行动-观察死循环
Plan-and-Execute先规划后执行中低(小模型执行)高计划错误放大
Reflexion失败后反思中-多中-高中反思本身变噪声
单步调用一次1低最高无(最可控)
⚠
ReAct 的头号风险:「Action → Observation」死循环:模型反复调用同一工具、或 Observation 不收敛却不自知。必须用 max_steps 与 no-progress 检测兜底,否则异常输入下会无限烧 token。
python# 一次真实 ReAct 轨迹: 可直接当回归断言用(附预期数字)
TRACE = [
  ("Thought", "需要先查订单",            "tok=48"),
  ("Action",  "search_orders(user_id=U1)", "tok=31"),
  ("Obs",     "count=2, orders=[...]",     "tok=210"),
  ("Action",  "refund_order(order_id=O9)", "tok=27"),
  ("Final",   "已为订单 O9 发起退款",       "tok=18"),
]
assert len(TRACE) == 5
assert sum(int(s.split("=")[1]) for _, _, s in TRACE) < 400   # 单任务 < 400 tok
# 判据: 步数 > max_steps(默认 12) 或 单任务 token > 4000 -> 记为异常轨迹进回归

1.4 Plan-and-Execute:先规划再执行

Plan-and-Execute 把任务先整体规划成有序步骤(plan),再逐项执行(execute)。它适合步骤可预见、长、且希望降低每步决策负担的任务:plan 可用强模型一次生成,execute 可用较小模型或纯工具完成,从而显著降本。当执行卡住时触发重规划(replan),而不是硬走。

python# Plan-and-Execute: 规划与执行解耦, 执行器可用更小/更便宜的模型
def plan(task, llm_strong):
    raw = llm_strong(f"把任务拆成有序步骤, 每行一个, 只输出步骤:\n{task}")
    return [s.strip("0123456789. ") for s in raw.splitlines() if s.strip()]

def execute(step, llm_small, tools):
    return llm_small(f"执行这一步: {step}\n可用工具: {tools}\n只输出 Action 或 Final Answer。")

def run(task, llm_strong, llm_small, tools, max_replan=2):
    steps = plan(task, llm_strong); results = []
    for _ in range(max_replan + 1):
        for step in steps:
            res = execute(step, llm_small, tools)
            results.append(res)
            if "blocked" in res.lower():               # 失败 -> 重规划剩余步骤
                steps = plan(f"原任务: {task}\n已完成: {results}\n失败在: {step}\n重规划剩余", llm_strong)
                break
        else:
            return results                            # 全部完成(无 blocked)
    return results                                     # 超重规划上限 -> 显式失败
失败模式成因缓解
计划错误强模型一次性规划也会错执行中校验 + 重规划
计划与状态脱节plan 不包含真实执行结果execute 后把结果回填 plan
过度细分步骤太碎, 往返过多合并相邻步骤, 粗粒度规划
不重规划卡住仍硬走检测 blocked 触发 replan
✔
什么时候上 Plan-and-Execute:任务 ≥ 约 5 步、子任务可独立验证、且失败代价高(如改生产数据、发对外消息)时,先规划能显著降低「走错一步就全废」的概率。纯闲聊或单步任务用它纯属 overhead。
python# Plan-and-Execute 成本拆分: 规划一次(强模型) + 执行 n 次(小模型)
def cost(steps, price_strong=20, price_small=1, plan_tok=800, step_tok=300):
    return plan_tok * price_strong + steps * step_tok * price_small
print(cost(3), cost(8))
# 预期输出: 16900 18400   (单位: 相对价格, 强:小 单价 20:1)
# 结论: 规划是一次性固定成本, 步骤越多摊薄越明显; <5 步时规划反而更贵

1.5 Reflexion:自我反思与重试

Reflexion 在失败后让模型「写一条反思」:把失败轨迹 + 一句语言化的自我批评存入记忆,下一轮把这个反思作为额外上下文,避免重蹈覆辙。它把「试错」变成可累积的经验,而不是每次从零乱撞——特别适合需要多次尝试才能学会的工具调用类任务。

python# Reflexion: 失败不是盲目重试, 而是带语言化反馈的重来
def run_with_reflexion(task, llm, tools, max_tries=3):
    memory = []                                        # 反思记忆, 跨轮累积
    for _ in range(max_tries):
        ctx = task + "\n".join(f"[过往反思 {i+1}] {m}" for i, m in enumerate(memory))
        traj, ok = agent_loop(ctx, llm, tools)
        if ok:
            return traj
        reflection = llm(f"以下尝试失败了:\n{traj}\n写一条不超过3句的反思, "
                         f"指出错在哪、下次如何避免:")
        memory.append(reflection)
        if len(memory) > 5:                            # 反思也要限长, 否则噪声累积
            memory = memory[-5:]
    return None
策略是否带反馈成本适用
普通重试否低瞬时错误(限流/超时)
Reflexion是(语言化)中-高需从失败中学的任务
微调是(参数化)高同一类失败反复出现
ℹ
反思的代价:每轮反思多一次模型调用;若不对反思做长度与质量约束,反思本身会变成上下文噪声,反而拖垮表现。经验值:反思限 1–3 句、最多保留最近 5 条。
python# 反思质量门: 过滤空话("要更小心"), 否则反思本身变噪声
VAGUE = ["小心", "注意", "再试一次", "更仔细"]
def keep_reflection(t):
    if len(t) > 300: return False                  # 太长 -> 噪声
    if any(v in t for v in VAGUE): return False    # 空话 -> 丢弃
    return ("因为" in t or "应该" in t)             # 需含因果
# 自查指标: 有效反思率(keep 为真 / 总反思) 应 > 60%;
#   低于 60% 说明失败模式没被识别, 应改工具/上下文, 而不是加反思轮数

1.6 Router / Workflow 与真 Agent 的边界

很多被称为「Agent」的系统其实不需要是 Agent。如果决策路径在部署时就完全确定(固定流程、固定分支),用 Workflow / 链式流水线即可——它更可控、更便宜、更易测试。Agent 的真正价值在于「运行期根据中间结果动态决定下一步」,以及「根据 Observation 自我纠正」——只有当这种不确定性真实存在时才值得为它付出 Agent 的协调与不可控成本。

特征推荐形态理由
输入固定、步骤固定Workflow / 链式可控、可测、便宜
输入多样但步骤可枚举Router + 单 Agent先分类再派发
步骤依赖中间结果且需试错单 Agent (ReAct)动态决策
子任务可并行且视角不同多 Agent并行/校验收益 > 协调成本
长任务需重规划Plan-and-Execute降低每步负担
★
工程铁律:能用确定性流水线解决的,绝不上 Agent;能上单 Agent 的,绝不上多 Agent;能上多 Agent 的,先确认「协调开销 < 它带来的收益」。这一条能帮你避开 80% 的 Agent 项目失控。
python# 形态决策: 两个问题定形态, 而不是"先上多 Agent 再说"
def choose_form(steps_known, needs_retry, parallel_views):
    if steps_known and not needs_retry: return "workflow"      # 固定流水线
    if steps_known and needs_retry:     return "router+agent"
    if parallel_views:                  return "multi-agent"   # 真需要才上
    return "single-react"
assert choose_form(True, False, False) == "workflow"
assert choose_form(False, True, False) == "single-react"       # 预期输出
# 判据: 若"步骤完全确定"却选了 Agent, 属过度设计, 单测与回放都更难

1.7 终止条件设计

终止条件决定 Agent 会不会「跑飞」。必须显式建模三类终止:① 显式完成(模型输出 final / 完成信号);② 硬上限(max_steps、max_tokens、deadline);③ 无进展检测(连续 N 步 Observation 无变化 / 重复调用同一工具 / 评分不提升)。没有终止条件的 Agent 在异常输入下会无限调用工具烧钱。

python# 把"何时停"显式建模, 而不是交给模型自觉
def should_stop(state, cfg):
    if state.get("done"):                            # ① 显式完成信号
        return "completed", True
    if state["steps"] >= cfg.max_steps:              # ② 步数硬上限
        return "max_steps", False
    if state["tokens"] >= cfg.max_tokens:            # ② token 预算
        return "budget", False
    if state["now"] >= cfg.deadline:                 # ② 时间 deadline
        return "deadline", False
    win = state["obs_window"][-cfg.no_progress:]     # ③ 无进展检测
    if len(win) >= cfg.no_progress and len(set(win)) == 1:
        return "no_progress", False
    return None, False
策略适用代价
显式完成绝大多数任务依赖模型诚实输出
步数上限所有 Agent可能提前停(设宽松些)
token 预算长上下文任务需实时累计用量
no-progress易死循环任务需定义"进展"判据
⚠
no-progress 比纯步数上限更省:纯步数上限是「到了才停」,期间已烧 tokens;no-progress 检测能在「明显卡住」时立刻停。两者叠加使用:平时靠 no-progress 早停,极端情况靠步数兜底。
python# 实时预算表: 随时知道"还剩多少", 而不是事后才发现超支
class Budget:
    def __init__(self, max_steps=20, max_tokens=200_000):
        self.steps = 0; self.tok = 0; self.cost = 0.0
        self.max_steps, self.max_tokens = max_steps, max_tokens
    def add(self, t_in, t_out, p_in=3e-6, p_out=1.5e-5):
        self.steps += 1; self.tok += t_in + t_out
        self.cost += t_in * p_in + t_out * p_out
    def exhausted(self):
        return self.steps >= self.max_steps or self.tok >= self.max_tokens
b = Budget(); b.add(1200, 180); b.add(900, 240)
print(b.steps, b.tok, round(b.cost, 5))
# 预期输出: 2 2520 0.0126
# 经验: 单任务 token > 200k 或步数 > 20 后, 成功率不再提升而成本线性上涨

1.8 动手练习与自测

✔
自测目标:完成这 6 题后,你应能独立写出一个带预算、终止条件与状态外置的最小 Agent,并能解释每个设计取舍。
  1. 给 1.1 的最小 Agent 加「预算表」(步数 + token + 成本),每步打印增量;判据:正常任务步数 ≤ 12 且成本与手算一致,超限返回 None 且 reason 为 budget。
  2. 同一任务分别用 ReAct 与 Plan-and-Execute 跑,记录步数与 token;判据:≥8 步任务 Plan 形态 token 更低,≤5 步任务 ReAct 更省。
  3. 构造「Action → Observation 完全重复」的输入,验证 no-progress 在 3 次内触发;判据:触发步数 ≤ 3 且不抛异常。
  4. 把 1.7 的 should_stop 扩展为同时支持 deadline 与 token,写出 4 组状态输入的期望返回值(completed / max_steps / budget / deadline)。
  5. 计算题:128k 窗口下注入 20 个工具 schema(每个 ≈120 token)与 40 步轨迹(每步 ≈800 token),原始占用约多少 token?摘要后能降到多少?参考:2400 + 32000 ≈ 34.4k token,摘要后约 1.5k + 最新一轮。
  6. 简答:为什么「能用 workflow 就不用 Agent」?参考答案:workflow 路径确定、可单测、可复现、成本低;Agent 的价值只在运行期动态决策 + 依 Observation 自我纠正,无此需求时引入只会增加不可控性。
题号参考要点 / 判据
1预算表每步打印 Δsteps/Δtoken/Δcost;超限返回 None 且 reason=budget;正常任务 ≤12 步
2≥8 步任务 Plan-and-Execute token 更低(先规划);≤5 步 ReAct 更省(省规划开销)
3no-progress 计数达 3 即终止,触发步 ≤3 且不抛异常
4四态优先级:deadline > budget > max_steps > completed
5原始 ≈34.4k token(2400+32000);摘要后 ≈1.5k + 最新一轮
6workflow 确定、可单测、可复现、成本低;无动态决策需求时用 Agent 只会增加不可控性

2. 工具调用与 MCP 协议

知识结构图 · 工具调用与 MCP 协议
工具调用与 MCP 协议5 大知识域 · 21 个知识点
Function Calling 机制JSON Schema 签名模型只输出调用意图权限在你这一侧禁 additionalProperties
学习路径
  1. 读 2.1:理解模型只输出调用意图、权限在己侧与禁 additionalProperties
  2. 跑内置代码:用严格 schema 请求一次调用意图并亲手执行权限控制
  3. 完成动手练习:为工具写 JSON Schema 并收紧参数约束
  4. 对接 M14:为自建 MCP server 定义严格函数签名并落实授权检查
✔ 能拦截越权 / 超额调用意图并只在己侧放行合法执行
核心知识点详解
  • 模型只输出调用意图,权限在你这一侧:Function Calling 的边界:模型只从你给的工具 schema 里选一个并返回参数化的调用意图(tool_calls),真正执行永远由你的代码完成。因此一切权限校验、额度检查都做在执行前,模型天然没权限「自己扣你账户」。
  • JSON Schema 是你的输入闸门:用 strict: true + additionalProperties: false(禁额外字段)收紧参数范围,让模型只能产出 schema 内合法形状,从源头减少脏参数执行。描述里写清格式 / 单位 / 示例,能用 enum 就用 enum。
  • 执行前必备三道检查:① 工具名在黑名单 / 白名单内;② 参数通过 runtime 校验;③ 高风险动作走审批(见 4.4)。常见坑:只在 prompt 里说「不要调用 X」而没有硬校验,模型一旦被注入就被诱导越权。
工具设计四规则动词短语命名参数含格式 / 枚举 / 示例返回结构化错误码粗 / 细粒度取舍tool router 限 5–10
学习路径
  1. 读 2.3:吃透动词命名、参数带格式枚举示例、结构化错误码等设计规则
  2. 跑内置代码:把功能相近的多个工具收敛进 router,控制工具总数
  3. 完成动手练习:为你的工具写命名 + 参数约束 + 错误码规范
  4. 对接 M14:设计并实现检索 / SQL / 沙箱执行三个工具的粒度与错误语义
✔ 能让模型稳定选出正确工具且错误以结构化码返回
核心知识点详解
  • 四规则:命名 / 参数 / 错误码 / 粒度:① 工具名用动词短语(search_orders 而非 orders)表达用途;② 参数描述写清格式 / 单位 / 枚举 / 示例;③ 返回结构化错误码而非裸文本;④ 粒度取舍:功能相近的工具收敛进 router。四条都做到,模型选错工具的几率显著下降。
  • 工具总数收敛到 5–10 个:给模型暴露太多工具会让选择准确率骤降。用 tool router 做一层分流:先一个分类 router 决定走哪个工具族,再暴露该族内少数工具给模型。实测工具数从 20+ 收敛到 ~8 个,选择准确率可明显抬升。
  • 错误码要可被模型推理:工具返回用统一格式 {ok, code, message, data},.message 藏中文可读原因(不暴露内部实现),.code 让模型能按码分支处理。常见坑:错误直接返 InternalServerError 全屏堆栈,模型既读不懂又把它当成功继续走,导致错误被静默吞掉。
MCP 能力与原语Tools / ResourcesPrompts / SamplingN×M → N+M仅约三成有审批
学习路径
  1. 读 2.2:理解 Tools / Resources / Prompts / Sampling 与 N×M → N+M
  2. 跑内置代码:实现一个可被 Host 调用的 resource + tool server
  3. 完成动手练习:说出各原语的适用场景并评估是否需要审批
  4. 对接 M14:用一个自建 MCP server 暴露检索与只读 SQL 能力
✔ 能按原语各司其职地组织工具并说明为何 N×M → N+M
核心知识点详解
  • 四个原语各司其职:tools(可调用的动作)、resources(可读的结构化数据)、prompts(复用提示模板)、sampling(模型向 host 请求补 token / 补参数)。工具是动作,资源是数据源,两者概念不同,别把检索结果硬塞进 tool 参数里。
  • N×M → N+M 是 MCP 的价值公式:没有标准时 N 个应用接 M 个工具要写 N×M 次对接;MCP 标准化后只需 N+M(每个应用写 1 次客户端 + 每个工具写 1 次 server)。这正是「写一次、处处用」的复利所在。
  • 审批只给真正需要的那部分:把只读 / 低危工具标为安全直接执行,读外网、写系统、改数据等高危原语才要求审批;实践中仅约三成原语需要 gate。常见坑:要么全放行(工具投毒风险)要么全审批(体验崩坏、agent 卡在等批),应精细化分级。
MCP 协议细节Host / Client / Serverinitialize 能力协商stdio / HTTP 传输elicitation 补参数
学习路径
  1. 读 2.4:吃透 Host / Client / Server 角色、initialize 协商与传输方式
  2. 跑内置代码:完成一次 initialize 握手并协商出双方能力
  3. 完成动手练习:对比 stdio 与 HTTP 传输的多进程 / 远程场景
  4. 对接 M14:让自建 MCP server 正确处理握手与能力协商
✔ 能完成一次标准握手并说明 stdio / HTTP 传输的取舍
核心知识点详解
  • 三角色分工:server 暴露能力,host(应用,如 IDE / Agent 平台)持有 UI 与权限,client 是连接两者的会话管道(通常每个 host 内嵌一个 client)。协议让同一 server 可被任意 host 复用。
  • initialize 协商双方能力:连接建立时 client 与 server 通过 initialize / initialized 握手,用 protocolVersion + capabilities 互相声明支持哪些(tools / resources / sampling),版本与能力不匹配就降级或拒绝,避免老 host 调新 server 炸掉。
  • stdio vs HTTP 的选择:stdio 走子进程管道,配置简单,适合本地多进程隔离;HTTP(sse / streamable)支持远程跨机,但网络暴露面大,远程传输要默认收紧权限并上 TLS。常见坑:本地 server 直接开 HTTP 且不鉴权,等于把内网工具暴露给任意进程。
MCP 安全风险过度授权工具投毒间接提示注入远程传输默认收紧
学习路径
  1. 读 2.4:理解过度授权、工具投毒与间接提示注入三类风险
  2. 跑内置代码:模拟一条通过工具描述注入的指令并复盘拦截
  3. 完成动手练习:给工具配最小权限并默认收紧远程传输
  4. 对接 M14:为 MCP 层加最小权限 + 审批以防范工具投毒
✔ 能识别注入路径并证实最小权限已把越权工具调用挡住
核心知识点详解
  • 三类风险要分开认:过度授权(excessive agency):给 agent 超出任务所需的能力;工具投毒:恶意工具 / 恶意数据伪装成合理工具诱使模型调用;间接提示注入:攻击者把指令藏在检索文档 / 网页里。三者的共同点都是「模型被诱导执行了不该执行的调用」。
  • 最小权限是治本手段:永远按「任务所需最小能力集」授予工具,且高危动作单独挂审批。additionalProperties: false + 参数白名单 + 只读挂载 + 沙箱是硬防线;权限越小,被投毒 / 注入后可造成的事故越小。
  • 远程传输默认收紧:MCP server 若被远程暴露,要校验来源身份(TLS 双向认证)、限制可用原语、默认拒绝写操作。常见坑:把 agent 的代码执行工具设成可写整个文件系统 + 可访问公网,一次注入 = 一台机器沦陷。
学习路径

2.1 Function Calling 的机制与工具设计

Function Calling 的流程是:把工具的 JSON Schema 放进请求 → 模型返回一个结构化的调用意图 → 你的代码执行 → 把结果回传。模型不执行任何代码,它只是输出「想调用什么」。理解这一点,安全问题就清楚了:所有权限控制都在你这一侧。

python# 工具设计的四条硬规则(决定 Agent 可靠性的关键)
TOOLS_SPEC = [
  {
    "name": "search_orders",
    # 规则1:名字是动词短语,说明用途而不是实现
    "description": "按条件查询订单。用于回答订单状态、金额、时间相关问题。"
                   "如果用户只给了手机号,请先用 find_user_by_phone 拿 user_id。",
    # 规则2:参数描述写清格式、单位、边界与示例
    "parameters": {"type": "object", "properties": {
        "user_id":   {"type": "string", "description": "用户ID,形如 U123456"},
        "status":    {"type": "string", "enum": ["paid", "shipped", "done", "refunded"],
                      "description": "订单状态;不传表示全部"},
        "start_date":{"type": "string", "description": "起始日期,格式 YYYY-MM-DD"},
    }, "required": ["user_id"]},
  },
  {
    "name": "refund_order",
    "description": "对已支付订单发起退款。属于高风险操作,需要用户明确确认。",
    "parameters": {"type": "object", "properties": {
        "order_id": {"type": "string"}, "reason": {"type": "string"},
    }, "required": ["order_id", "reason"]},
  },
]

# 规则3:返回值结构化且信息完整(含 ID、单位、错误码),便于模型推理
def search_orders(user_id, status=None, start_date=None):
    rows = db.query(user_id=user_id, status=status, start_date=start_date)
    return {"count": len(rows), "orders": [
        {"order_id": r.id, "amount_cents": int(r.amount * 100),   # 用整数分,避免浮点误差
         "status": r.status, "created_at": r.created_at.isoformat()}
        for r in rows[:20]]}                                       # 规则4:限制返回条数

# 规则要点回顾:
#  1) 名字用动词短语  2) 参数描述含格式/单位/枚举
#  3) 返回结构化且带错误码  4) 限制返回体量,避免一次灌爆上下文
#  5) 高风险工具必须走审批(needs_approval)
python# 严格模式: 用 JSON Schema 约束参数, 让模型输出 100% 可校验
ORDER_SCHEMA = {
    "type": "object",
    "properties": {
        "status": {"type": "string", "enum": ["paid", "shipped", "done"]},
        "limit":  {"type": "integer", "minimum": 1, "maximum": 50},
    },
    "required": ["status"],
    "additionalProperties": False,          # 关掉"瞎编参数"的入口
}
import jsonschema
def strict_call(args):
    jsonschema.validate(args, ORDER_SCHEMA)  # 不合法 -> 立即回传纠正提示
    return "OK"
print(strict_call({"status": "paid", "limit": 20}))     # 预期: OK
# 传 {"status": "PAID"} -> ValidationError(枚举不匹配), 回传模型让它改;
# 实测: 开 additionalProperties:False 后, 参数幻觉率与重试次数明显下降

2.2 MCP:工具生态的事实标准

MCP(Model Context Protocol)解决的问题是:以前每接一个数据源或工具,都要为每个客户端写一遍适配代码。MCP 定义了统一的客户端-服务端协议,于是工具(Server)写一次,任何支持的客户端(Claude Desktop、IDE、自研 Agent)都能用。它在 2025 年底被捐赠给 Linux 基金会下的中立组织时,已有超过一万个公开的 MCP Server。

能力说明典型用途
Tools可被模型调用的函数查库、发邮件、调用内部 API
Resources可读取的数据(类似文件/URI)文档、配置、日志内容
Prompts可复用的提示模板标准化的工作流入口
Sampling服务端请求客户端模型生成工具内部需要模型能力时
Roots / 传输stdio、HTTP/SSE 等本地进程或远程服务
python# 一个最小可用的 MCP Server(Python SDK)
# pip install mcp
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("company-tools")

@mcp.tool()
def query_inventory(sku: str, warehouse: str = "SZ") -> dict:
    """查询指定 SKU 在某个仓库的库存数量。

    Args:
        sku: 商品编码,形如 SKU-12345
        warehouse: 仓库代码,可选 SZ / SH / BJ
    """
    rows = db.query(sku=sku, warehouse=warehouse)
    return {"sku": sku, "warehouse": warehouse, "available": rows.qty,
            "reserved": rows.reserved, "updated_at": rows.ts.isoformat()}

@mcp.resource("config://inventory/policy")
def inventory_policy() -> str:
    """库存管理规则,供模型在决策时参考。"""
    return open("policy.md").read()

if __name__ == "__main__":
    mcp.run()          # 默认 stdio;远程部署可切 HTTP/SSE 传输
⚠
MCP 的安全现实(重要):行业调研显示,仅约三分之一出头的 MCP 应用实现了审批机制——这是当前 Agent 生态最大的安全缺口。MCP 让工具接入变得极简,也意味着一个恶意的 Server 可以直接读你的数据、调用你的接口。生产使用必须:只用可信来源的 Server、对高风险工具做人工审批、最小权限(只给读就不给写)、沙箱隔离、并记录完整调用审计。
python# MCP Client: 发现能力 -> 调用工具 -> 读资源(错误分层处理)
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def use_server():
    params = StdioServerParameters(command="python", args=["server.py"])
    async with stdio_client(params) as (r, w):
        async with ClientSession(r, w) as s:
            await s.initialize()
            tools = await s.list_tools()                  # 能力发现
            print([t.name for t in tools.tools])           # 预期: ['query_inventory']
            res = await s.call_tool("query_inventory", {"sku": "SKU-1"})
            return res.content[0].text                     # JSON 字符串
# 预期返回: {"sku": "SKU-1", "warehouse": "SZ", "available": 42, ...}
# 安全: tools 的 description 来自 Server, 必须视为"待审查的不可信输入"

2.3 工具设计:最容易做错的一环

工具设计是 Agent 可靠性最容易被低估、也最容易被做错的一环。五个关键维度:粒度、schema 描述质量、错误可恢复性、幂等性、数量。模型不执行代码,它只根据描述「猜」怎么调用——描述越含糊,调用越错。

粒度优点缺点适用
粗粒度往返少、步骤少、易成功不灵活、实现成本高稳定、高频、多步骤组合动作
细粒度灵活、可组合、易测试往返多、模型需多步编排探索性、参数多变的动作

schema 描述质量直接决定调用准确率:参数名要用「像 API 的动词/名词」而非内部变量;description 必须含格式、单位、枚举、示例与边界;缺示例的枚举参数调用错误率明显更高。错误信息也要可恢复——返回给模型的是「可操作的提示」而非裸异常(给模型 500 它无从纠正)。

python# 工具描述写得"模型友好": 含格式/单位/枚举/示例/边界
TOOLS_SPEC = [{
    "name": "query_weather",
    "description": "查询城市天气。用于回答出行/穿衣类问题。"
                   "城市用中文名或机场三字码; 日期不填表示今天。",
    "parameters": {"type": "object", "properties": {
        "city":   {"type": "string",
                   "description": "城市名, 如 北京 / 上海, 或 ICAO 三字码 PEK",
                   "examples": ["北京", "PEK"]},
        "date":   {"type": "string", "enum": ["today", "tomorrow", "+3d"],
                   "description": "相对日期, 不填表示今天",
                   "examples": ["today", "tomorrow"]},
        "unit":   {"type": "string", "enum": ["c", "f"], "description": "温度单位"},
    }, "required": ["city"]},
}]
# 错误可恢复: 返回操作提示, 而不是抛 500
def query_weather(city, date="today", unit="c"):
    if city not in CITIES:
        return {"error": "unknown_city",                 # 结构化错误码
                "hint": f"城市 {city} 不支持, 支持: 北京/上海/PEK 等"}
上下文中可见工具数选择准确率(经验)对策
≤ 10高(>90%)无需处理
10–30中(80–90%)分组 + 描述优化
> 30明显下降检索式工具选择 / tool router, 可见集限 5–10
⚠
工具数量的隐形成本:给模型 50 个工具,它大概率在前面几个里选错,且上下文被 schema 占满。用 tool router 或检索式选择把「当前可见工具」压到 5–10 个,按任务动态注入,既能提准确率又能省 token。
python# tool router: 从 50 个工具里检索出当前任务最相关的 5-8 个再注入
def select_tools(task, all_tools, top_k=8):
    q = embed(task)
    return sorted(all_tools, key=lambda t: cos(q, embed(t.desc)),
                  reverse=True)[:top_k]
# 经验数字: 可见工具 ≤10 时选择准确率 >90%; >30 时明显下降;
#   用 router 把可见集压到 5-8, 准确率回升, 每请求还省下约 2000-4000 token

2.4 MCP 协议详解:角色、原语与握手

MCP 三方角色:Host(运行 Agent 的客户端,如 IDE / 桌面应用,是信任边界的拥有者,负责 UI、权限与用户确认)、Client(Host 为每个 Server 创建的一个连接,负责协议转发)、Server(暴露能力,可为本地子进程或远程服务)。Host 决定「这个 Server 能做什么、能不能碰我的数据」。

原语方向用途备注
ToolsClient 调 Server执行动作 / 查询模型可决策调用
ResourcesClient 读 Server文档/配置/数据URI 寻址
PromptsClient 拉 Server复用提示模板标准化工作流
SamplingServer 经 Client 请求 LLM工具内部需生成Host 代发, 受审批
ElicitationServer 经 Client 向用户要输入补缺失参数用户确认
RootsClient 告知 Server 可访问根限定文件范围防越权读
json// MCP 初始化握手(基于 JSON-RPC 2.0 帧, 能力协商取交集)
// Client -> Server
{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": { "protocolVersion": "2025-06-18",
              "capabilities": { "sampling": {}, "roots": { "listChanged": true } },
              "clientInfo": { "name": "hamauls-orion-host", "version": "1.4.0" } } }
// Server -> Client: 返回自身能力, 双方取交集
{ "jsonrpc": "2.0", "id": 1, "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": { "tools": { "listChanged": true }, "resources": {}, "prompts": {} },
    "serverInfo": { "name": "company-tools", "version": "2.1.0" } } }
// 之后 Client 发 notifications/initialized, 握手完成, 进入能力调用

传输方式决定部署形态:stdio(本地子进程,默认,低延迟,但共享本机权限,适合本机工具)、HTTP+SSE(远程,Server 推事件,但 SSE 单向)、streamable HTTP(2025 年引入,单端点同时支持请求与 SSE 流式,服务器可无状态也可恢复会话,是远程部署首选)。sampling 让 Server 反向借 Host 的模型能力(受用户审批约束);elicitation 向用户索要缺失输入;roots 约束 Server 可读的文件根。

风险形态缓解
过度授权Host 给 Server 超出所需的文件/网络最小权限, 只读, 沙箱
工具投毒恶意 Server 的 description 诱导越权人工审查 description, 只信来源
间接提示注入tool 返回内容含指令标记不可信, Spotlighting, 分隔
权限边界模糊远程与本地同权按 transport 分级, 远程默认收紧
★
MCP 的真正价值:N×M → N+M:没有 MCP 时,N 个客户端要为每个工具写一遍适配(N×M)。MCP 后,客户端只需实现一次 MCP Client(N),Server 只需实现一次 MCP Server(M),两两互通。这就是协议收敛降低整个生态集成成本的本质。
json// MCP 工具调用帧(JSON-RPC 2.0): 请求 + 成功 / 失败响应
{ "jsonrpc": "2.0", "id": 42, "method": "tools/call",
  "params": { "name": "query_inventory", "arguments": { "sku": "SKU-1" } } }
// 成功响应
{ "jsonrpc": "2.0", "id": 42, "result": {
    "content": [{ "type": "text", "text": "{\"available\": 42}" }],
    "isError": false } }
// 失败: isError=true, 文本给"可操作"错误码, 而不是裸堆栈
{ "jsonrpc": "2.0", "id": 42, "result": {
    "content": [{ "type": "text",
      "text": "unknown_sku: SKU-1 不存在, 示例 SKU-10001" }],
    "isError": true } }

2.5 动手练习与自测

✔
自测目标:完成这 5 题后,你应能独立开发并安全接入一个 MCP Server,并能解释协议原语的分工。
  1. 用 FastMCP 写一个 Server,暴露 1 个 tool + 1 个 resource,并用 Client 调用;判据:list_tools 返回 1 个工具,call_tool 返回结构化 JSON,resource 可读。
  2. 给某工具写 description,要求含格式、单位、枚举与 examples;判据:故意传错参数时,模型能依据提示自我纠正(重试后成功)。
  3. 设计 tool router:准备 30 个工具描述、10 个任务,测 top-8 召回;判据:相关工具召回率 ≥ 90%,且注入 token 下降 ≥ 50%。
  4. 简答:MCP 的 sampling 与 elicitation 各解决什么问题?参考:sampling 让 Server 反向借 Host 的模型能力(受用户审批);elicitation 让 Server 向用户索要缺失输入。
  5. 安全题:接入一个第三方 MCP Server 前,列出必须做的 4 项检查。参考:来源可信、审查工具 description、最小权限(只读优先)、高风险工具走人工审批并全量审计。
题号参考要点 / 判据
1FastMCP Server 暴露 1 tool + 1 resource;list_tools 返回 1,call_tool 返回结构化 JSON
2description 含格式/单位/枚举/examples;传错参数可自我纠正并重试成功
3tool router top-8 召回 ≥90%,注入 token 下降 ≥50%
4sampling:Server 反向借 Host 模型(受用户审批);elicitation:Server 向用户索要缺失输入
5来源可信 + 审查 description + 最小权限(只读优先)+ 高风险人工审批并全量审计

3. A2A 与多 Agent 协作

知识结构图 · A2A 与多 Agent 协作
A2A 与多 Agent 协作5 大知识域 · 19 个知识点
A2A 定位Agent ↔ AgentAgent Card 发现MCP 管能力 / A2A 管任务
学习路径
  1. 读 3.1:分清 MCP 管能力与 A2A 管任务及 Agent Card 发现
  2. 跑内置代码:让一个 agent 通过 Agent Card 发现并委托另一个 agent
  3. 完成动手练习:判断自己是否真需要跨 agent 互操作
  4. 对接 M14:规划 MCP 能力层 + A2A 任务层并存的多 agent 架构
✔ 能在 MCP 管能力、A2A 管任务的边界上画出分工
核心知识点详解
  • MCP 管能力,A2A 管任务:MCP 是「agent 连接工具 / 数据源」的能力协议;A2A 是「agent 连接 agent」的任务协作协议。要查库、执行代码走 MCP;要把任务委托给另一个 agent 并追踪其状态走 A2A。边界画清楚,架构才不会拧成一团。
  • Agent Card 是发现机制:每个 A2A agent 发布一份 agent.json(Card),声明 name / description / skills(可用的能力清单)。调用方先取 Card → 比对 skills 是否满足需求 → 决定要不要委托。GET /.well-known/agent.json 即入口。
  • 委托时要带上下文物:把任务 + 关键约束 + 必要的上下文传给委托 agent,并在返回结果里带上 artifact / message 供校验。常见坑:把整个大上下文原样塞给对端,token 暴涨且可能泄漏无关敏感信息;应只传任务所需的最小子集。
框架格局LangGraph 生产编排LangChain 原型OpenAI Agents SDKCrewAI / Google ADK
学习路径
  1. 读 3.2:横向对比 LangGraph / Agents SDK / CrewAI / ADK 的定位
  2. 跑内置代码:用所选框架跑通一个多步编排 demo
  3. 完成动手练习:按状态可控性与可测试性做出选型
  4. 对接 M14:用所选编排框架实现多 Agent 分工协作
✔ 能按状态可控 / 可观测 / 可测试原则选出框架并跑通 demo
核心知识点详解
  • 框架用「三试一可」筛:生产选框架看四个标准:状态可控性(能显式读写状态)、可观测性(能看每步做了什么)、可测试性(能注入 / 回放)、能 checkpoint(中断可续)。LangGraph 三者兼得但学习曲线陡;LangChain 适合快速原型;Agents SDK 适合 OpenAPI 生态内快速交付。
  • 原型框架与生产框架要分开:PoC 用最顺手最快的(LangChain / smolagents),生产再迁移到有状态机的(LangGraph / ADK)。别让原型框架的便利绑架了生产架构。
  • 选型先写可测试清单:动手前先列「我这套一定要能:导出状态、回放轨迹、注入 mock、断点续跑」,拿到 demo 上逐条验证。常见坑:demo 能跑就定了框架,上线才发现无法回放失败 / 无法 checkpoint,只能重写。
A2A 协议细节Agent Card skillsTask 状态机Message / Artifactpush 通知
学习路径
  1. 读 3.3:掌握 Agent Card skills、Task 状态机与 Message / Artifact
  2. 跑内置代码:走一遍 Task 状态流转并接收 push 通知
  3. 完成动手练习:为自己的委托任务定义消息与产物契约
  4. 对接 M14:用 A2A 风格契约让规划 / 检索 / 执行 agent 交换任务
✔ 能让一个任务在两个 agent 间按状态机正常流转
核心知识点详解
  • Task 状态机驱动委托全流程:A2A 用显式 Task 对象跟踪任务生命周期,典型状态:submitted → working → input-required / completed / failed。发起方轮询或订阅状态,直到终态。状态机让「任务到哪一步了」可观测可恢复。
  • Message 与 Artifact 分离:对话消息用 Message(一来一往的文字 / 指令),实际产物用 Artifact(文件 / 结构化数据 / 引用)承载。Artifact 可校验可版本化,是「做没做成」的客观证据,别只靠消息文本判断。
  • 长任务用 push 而非死等:对长任务支持 push 通知(callback / webhook)或 pull 轮询,避免长连接挂死。常见坑:为「快」用短超时轮询,长任务还没跑完就被判断超时;应区分「任务结束」与「连接空闲」。
编排模式SupervisorRouter / HandoffFan-out / Fan-inDebate / Vote
学习路径
  1. 读 3.4:对比 Supervisor / Router-Handoff / Fan-out-in / Debate 模式
  2. 跑内置代码:用 Supervisor 或 Handoff 编排一次多 agent 协作
  3. 完成动手练习:说明你的任务适用哪种编排并定夺角色分工
  4. 对接 M14:用 Supervisor 共编排规划者 / 检索者 / 执行者 / 校验者
✔ 能选定编排模式并证明它在多 agent 协作中跑通
核心知识点详解
  • Supervisor:一个总管派活收活:有一个 supervisor agent 负责分解任务、派给 worker、汇总结果并决定下一步。是最常用也最可控的编排,适合「要按任务动态决策」的场景;代价是 supervisor 本身是个单点(它的调度能力决定全局质量)。
  • Router / Handoff:按输入分流:用一个 router 根据输入特征决定交给哪个专用 agent(如客服 → 技术 / 售后),handoff 是角色移交。适合功能边界清晰、任务可归类的系统。
  • Fan-out / Fan-in:并行快,别过度:拆解 → 并行子任务 → 合并结果,适合可并行独立子任务;Debate / Vote 用多视角互相校验,适合生成 + 批判类任务但成本高。常见坑:Fan-out 救不了串行依赖的任务,拆了也是白拆还拖慢;协调开销超过并行收益就该缩回单 agent。
多 Agent 代价上下文隔离是主收益2–4 倍 token角色 >4–5 收益转负重复副作用
学习路径
  1. 读 3.4:理解上下文隔离收益与 2–4 倍 token 及角色上限
  2. 跑内置代码:对比单 agent 与多 agent 的 token 消耗与副作用次数
  3. 完成动手练习:估算自己的多 agent 方案是否值得投 token
  4. 对接 M14:控制角色数量并用数据说明上下文隔离带来的净收益
✔ 能量出多 agent 的 token 代价并与上下文隔离收益做取舍
核心知识点详解
  • 主收益是上下文隔离:每个 agent 只看自己角色相关的上下文,互不污染——这是多 agent 的核心收益:避免一个大 prompt 装满所有角色信息导致互相干扰、记忆稀释。隔离越干净,收益越明显。
  • 代价:token 翻 2–4 倍:多 agent 需要重复的系统提示、任务传递与结果汇总,实测 token 总量约为单 agent 的 2–4 倍。要量化对比「隔离的收益 vs token 的代价」,数据说话而不是感觉。
  • 角色数量有上限,>4–5 个收益转负:角色越多,协调往返越多、越混乱,收益在 4–5 个之后转负。常见坑:堆一堆「专家 agent」抢同一任务,既烧 token 又频繁重复副作用(同一工具被多个 agent 各调一次)。先算清是否值得。
学习路径

3.1 A2A:Agent 之间的握手协议

如果 MCP 是「Agent 用工具」,A2A(Agent-to-Agent)就是「Agent 找 Agent」。它解决的是跨系统、跨厂商的 Agent 互操作问题:一个 Agent 如何发现另一个 Agent 的能力(Agent Card)、如何委托任务、如何追踪长任务的状态、如何处理需要补充信息的多轮交互。

维度MCPA2A
连接对象Agent ↔ 工具 / 数据源Agent ↔ Agent
解决的问题工具接入的标准化跨系统的任务委托与协作
核心概念Tools / Resources / PromptsAgent Card、Task、Message、Artifact
典型场景让 Agent 能查库、能执行代码让客服 Agent 把工单交给处理 Agent
状态2026 年已成为工具调用事实标准协作层标准,生态快速补齐中
python# A2A 发现: 先取 Agent Card, 再据 skills 决定是否委托
import httpx
async def discover(base):
    card = (await httpx.AsyncClient().get(
        f"{base}/.well-known/agent.json")).json()
    return {s["id"]: s["name"] for s in card["skills"]}
# 预期输出: {"refund": "退款处理", "logistics": "物流查询"}
# 判断: 若对端 skills 不含所需能力 -> 不委托(避免无效往返与成本)

3.2 框架格局与选型

框架定位适合注意
LangGraph图式编排,状态机 + 检查点 + 人工介入生产级有状态工作流学习曲线略陡,但生产控制力最强
LangChain组件库,快速原型探索与 PoC生产复杂场景建议迁移到 LangGraph
OpenAI Agents SDK轻量多 Agent 编排 + 工具 + tracingOpenAI 生态内的快速交付生态绑定需评估
CrewAI角色 + 任务 + 流程业务流水线式协作复杂状态管理能力有限
AutoGen → Microsoft Agent Framework对话式多 Agent研究与企业迁移新项目建议直接用 MAF 而非旧 AutoGen
Google ADKGoogle 生态的 Agent 开发套件Gemini / GCP 场景生态绑定
Agno / smolagents轻量高性能需要极致控制与低开销生态相对小
python# LangGraph:把 Agent 写成显式状态图 —— 生产级编排的关键是「状态可见、步骤可查」
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
import operator

class S(TypedDict):
    task: str
    plan: list[str]
    findings: Annotated[list[str], operator.add]     # 累加式状态更新
    draft: str
    review: str
    rounds: int

def planner(s: S):     return {"plan": decompose(s["task"]), "rounds": 0}
def researcher(s: S):  return {"findings": [search(q) for q in s["plan"]]}
def writer(s: S):      return {"draft": write(s["task"], s["findings"])}
def reviewer(s: S):    return {"review": critique(s["draft"]), "rounds": s["rounds"] + 1}

def need_revision(s: S):
    if s["rounds"] >= 2: return "end"                # 硬上限,防止无限修改
    return "revise" if "需修改" in s["review"] else "end"

g = StateGraph(S)
for name, fn in [("plan", planner), ("research", researcher),
                 ("write", writer), ("review", reviewer)]:
    g.add_node(name, fn)
g.set_entry_point("plan")
g.add_edge("plan", "research"); g.add_edge("research", "write")
g.add_edge("write", "review")
g.add_conditional_edges("review", need_revision, {"revise": "write", "end": END})

app = g.compile(checkpointer=MemorySaver())          # 检查点:可中断、可恢复、可回放
# app.invoke({"task": "..."}, config={"configurable": {"thread_id": "t1"}})
★
2026 年的框架趋势:行业判断很清晰:工具链已从「框架选择」转向「协议集成」——协议收敛(MCP + A2A + Skills 封装领域知识)、框架分化(LangGraph 主导生产编排、LangChain 回归原型定位、Microsoft Agent Framework 继承 AutoGen)、工程成熟(可观测、评估、安全从可选变必须)、治理优先(审批机制是最大缺口)。
python# LangGraph 的 checkpoint + 人工介入: 生产编排真正需要的能力
cfg = {"configurable": {"thread_id": "t1"}}
app.invoke({"task": "..."}, cfg)
snap = app.get_state(cfg)                    # 任意时刻可读当前状态
print(snap.next)                            # 预期: ('review',) 下一步节点
app.update_state(cfg, {"review": "人工批准"}, as_node="reviewer")
app.invoke(None, cfg)                       # 从中断点续跑, 不重跑已完成的节点
# 关键: 状态可见 + 可中断 + 可恢复, 这三点决定了长任务能否被信任

3.3 A2A 协议详解:Agent Card、任务与工件

如果 MCP 是「Agent 用工具」,A2A(Agent-to-Agent)就是「Agent 找 Agent」。它解决跨系统、跨厂商的 Agent 互操作:一个 Agent 如何发现另一个的能力(Agent Card)、如何委托任务、如何追踪长任务状态、如何处理需要补充信息的多轮交互。A2A 把「协作」标准化,让不同团队/厂商的 Agent 能互相派活。

json// Agent Card: 放在 /.well-known/agent.json, 可被对端发现与评估
{
  "name": "工单处理 Agent",
  "description": "接收客服 Agent 委托, 处理退款与物流工单",
  "url": "https://ops.internal/a2a",
  "capabilities": { "streaming": true, "pushNotifications": true, "stateTransitionHistory": false },
  "skills": [
    { "id": "refund", "name": "退款处理", "examples": ["为用户 U123 发起退款"] },
    { "id": "logistics", "name": "物流查询", "examples": ["查订单 O9 的物流轨迹"] }
  ],
  "defaultInputModes": ["text/plain"], "defaultOutputModes": ["application/json"]
}
// 任务生命周期(状态机):
//   submitted -> working -> (input-required <-> working) -> completed
//   任意时刻可 -> failed
维度MCPA2A
连接对象Agent ↔ 工具 / 数据源Agent ↔ Agent
核心概念Tools / Resources / PromptsAgent Card / Task / Message / Artifact
交互单元单次工具调用Message(多 part) + Artifact(产物)
长任务单次返回任务状态机 + push 通知
典型场景让 Agent 能查库、执行代码客服 Agent 把工单交给处理 Agent

Message 是交互单元(parts 可为 text / file / data),Artifact 是任务产出(可多部分、可流式追加)。长任务用 webhook / push notification 通知进度,而不是让对端轮询。一个 Agent 同时是 MCP client 与 A2A server 是常态——它既调工具,又被别的 Agent 委托。

✔
分工的底线:MCP 管「能力怎么接」,A2A 管「任务怎么交」。不要试图用 MCP 做 Agent 间编排(它没有任务生命周期与委托语义),也不要用 A2A 重新发明工具调用。两者正交、互补。
python# A2A 任务状态机: 显式状态驱动, 而不是靠对端"猜"
TRANSITIONS = {
  "submitted":      {"working", "failed"},
  "working":        {"input-required", "completed", "failed"},
  "input-required": {"working", "failed"},     # 补完信息后回到 working
}
def advance(state, event):
    assert event in TRANSITIONS[state], f"非法转移 {state}->{event}"
    return event
print(advance("working", "completed"))          # 预期: completed
# advance("completed", "working") -> AssertionError(终态不可回退)
# 工程价值: 非法转移立即暴露, 避免对端把任务"卡死"在多轮里

3.4 多 Agent 编排:模式、隔离与代价

常见编排模式:supervisor(中心调度,子 Agent 无互聊)、router(按输入分类派发)、handoff(子 Agent 完成控制权转移,常用于客服长对话)、fan-out / fan-in(并行分治再汇总)、debate / vote(多视角生成 + 批判 + 投票)。模式选择看任务是否可并行、是否需要异构视角。

python# Supervisor 编排: 中心调度, 子 Agent 不直接互聊(降低失控风险)
def supervisor(task, workers, llm):
    plan = llm(f"把任务拆给下列 worker: {list(workers)}。输出 worker名:子任务")
    results = {}
    for name, subtask in plan.items():
        results[name] = workers[name](subtask)        # 每个子 Agent 只收自己的子任务
    return llm(f"基于各 worker 结果汇总: {results}")   # fan-in 汇总

# handoff: 主 Agent 把"退款"转交退款 Agent, 完成后交回
def handoff(conversation, router, specialists):
    while not conversation.done:
        target = router(conversation)                 # 决定下一步由谁处理
        conversation = specialists[target](conversation)   # 控制权转移
    return conversation.final
模式适用收益代价
Supervisor子任务需汇总可控, 易回放中心瓶颈
Router输入可分类简单高效分类错误放大
Handoff长对话转专业自然流转状态易丢
Fan-out/in可并行子任务延迟下降汇总需一致
Debate/Vote高风险决策质量提升成本翻倍

上下文隔离是多 Agent 的主要收益,而不是「更聪明」:每个子 Agent 只带自己的子任务上下文,避免单上下文被无关历史膨胀与污染,long-context 成本与错误率都下降。代价是子 Agent 间不共享中间状态,需显式传递。但诚实的结论是——多数任务「单 Agent + 好工具 + 好上下文工程」已足够;多 Agent 的成本(多倍 token、延迟、协调失败率)往往超过收益,只在并行 / 隔离 / 异构视角确有必要时才用。

⚠
多 Agent 的常见失败:① 子 Agent 各自重试导致重复副作用(需幂等 + 协调);② 上下文隔离后关键信息没传过去(需显式交接契约);③ 中心 supervisor 成为瓶颈与单点故障;④ 成本失控(N 个 Agent 同时跑强模型)。先用单 Agent 打到天花板,再考虑拆。
python# fan-out / fan-in: 并行但给每个子 Agent 独立上下文 + 独立超时
import asyncio
async def fan_out(subtasks, workers, timeout=60):
    async def run(name, sub):
        try:
            return name, await asyncio.wait_for(workers[name](sub), timeout)
        except asyncio.TimeoutError:
            return name, None                    # 单个超时 -> 降级, 不拖垮整体
    pairs = await asyncio.gather(*(run(n, s) for n, s in subtasks.items()))
    return dict(pairs)
# 预期: N 个独立子任务延迟从 sum(t) 降到 max(t)+overhead;
# 注意: 有分支返回 None 时, fan-in 必须显式处理缺失, 否则汇总会出错或静默丢结论

3.5 动手练习与自测

✔
自测目标:完成这 5 题后,你应能判断「该不该上多 Agent」,并能实现带隔离与降级的编排。
  1. 写一个 supervisor 编排(3 个 worker + 汇总);判据:日志显示每个 worker 只收到自己的子任务上下文,汇总结果包含三者结论。
  2. 给 handoff 加「显式状态传递」:交接时序列化对话状态并校验接收方;判据:缺一个必填字段时接收方拒收并回报原因。
  3. 用 asyncio 实现 fan-out/fan-in,并注入一个超时子任务;判据:整体不失败,汇总结果里标记该分支缺失。
  4. 计算题:单 Agent 每步 800 token 共 10 步;改为 3 个 worker + 1 个 supervisor,每 worker 5 步且各自 300 token 系统开销,估算总 token 并判断是否值得。参考:单 Agent ≈ 8k;多 Agent ≈ 3×(5×800+300)+supervisor ≈ 13.8k+,成本明显上升,只在并行或隔离必要时才值。
  5. 简答:多 Agent 的最大收益是什么?参考:上下文隔离——每个子 Agent 只带自己的上下文,降低 long-context 成本与错误率;而不是「更聪明」。
题号参考要点 / 判据
1supervisor 分发 3 子任务,每个 worker 只带自身上下文,汇总含三者结论
2handoff 显式序列化状态,缺必填字段接收方拒收并回报原因
3fan-out/fan-in 超时分支缺失但不整体失败,汇总标记该分支缺失
4单 Agent ≈8k;多 Agent ≈13.8k+;成本上升,仅并行/隔离必要时才值得
5最大收益是上下文隔离(降低 long-context 成本与错误率),而非更聪明

4. 长程任务与 Computer Use

知识结构图 · 长程任务与 Computer Use
长程任务与 Computer Use5 大知识域 · 20 个知识点
长程不崩状态外置子任务可验证检查点续跑进度汇报与预算
学习路径
  1. 读 4.1:掌握状态外置、子任务可验证与检查点续跑的设计
  2. 跑内置代码:让长任务中断后从检查点恢复而不是重跑
  3. 完成动手练习:为子任务设可验证标准并汇报进度预算
  4. 对接 M14:实现长程任务状态检查点与断点恢复
✔ 能证明长任务中断后从检查点无缝续跑
核心知识点详解
  • 状态外置,不靠上下文硬记:长任务的挑战是「跑几十步记住进度」而非「会不会做一步」。把任务清单、已完成项、关键结论写成结构化 PLAN 状态持久化,每轮按需注入,模型的上下文只承载当前几步而非全部历史。
  • 每步可验证 + 落盘:每个子任务要有客观完成判据(测试通过 / 文件生成 / 断言成立),每步执行的 artifact 与 evidence 落盘。这样「做完了」是可验证的事实,而不是模型的一句话声明。
  • 断点续跑是刚需:长任务失败重来代价极高,必须能从任意步骤续跑:启动时读入已完成 key,跳过 done 子任务。常见坑:状态存在内存变量里没了就全丢;应 JSON / DB 落盘,raise 前先 save。
Computer UseDOM / 无障碍树纯视觉截图混合定位误差 <0.5%高危动作门禁
学习路径
  1. 读 4.2:理解 DOM / 无障碍树与纯视觉定位的差异与精度
  2. 跑内置代码:对比 DOM 与视觉定位在同一界面的命中误差
  3. 完成动手练习:为高危 GUI 动作加门禁并复测
  4. 对接 M14:让 GUI agent 走混合定位并守住高危动作审批
✔ 能对比定位方案并保证高危动作不静默执行
核心知识点详解
  • DOM / 无障碍树 vs 纯视觉:DOM / 无障碍树拿到的是结构化元素(可精确定位、拿属性);纯视觉截图是「模型看屏点哪里」,自然但易误点。混合定位通常先用 DOM 骨架、缺失时回退视觉,实测可把定位误差压到 <0.5% 量级。
  • 定位误差直接决定事故率:点错按钮 = 点错副作用。凡是会改数据 / 发消息 / 触达外部的动作,都不能靠模型「大致点对」,要么 DOM 硬定位、要么加门禁确认。
  • 高危 GUI 动作必须门禁:删除 / 提交 / 发信等高风险点击,在执行前要人工确认或二次校验。常见坑:截图 agent「看得见就敢点」,一次误触就把生产数据改了;宁可多一档审批也不要静默执行。
记忆体系短期 / 工作 / 长期写入去重与冲突时间衰减检索工作记忆压缩 3–8%
学习路径
  1. 读 4.3:理清短期 / 工作 / 长期三层与写入去重冲突消解
  2. 跑内置代码:把工作记忆压缩 3–8% 后看检索相关性是否保留
  3. 完成动手练习:为 long-horizon 任务配置时间衰减检索
  4. 对接 M14:记忆层支撑长程任务的状态持久与恢复
✔ 能压缩工作记忆并保持跨步相关性不丢失
核心知识点详解
  • 三层记忆各司其职:短期(当前对话上下文)+ 工作(当前任务的实施状态)+ 长期(跨会话经验 / 知识)。工作记忆写频繁、要控制体积;长期记忆要检索、要防重复写入。
  • 写入去重与冲突消解:长期记忆写入前先查重(同一条经验别存两遍),冲突时按时间 / 来源可信度取新弃旧,避免记忆自相矛盾。
  • 工作记忆压缩别伤相关性:长任务上下文会肥,压缩工作记忆(如把旧结论折叠成摘要,实测可压到 3–8% 体积)能省钱,但要验证检索相关性不丢失。常见坑:压缩后把「关键约束」也给折叠没了,后续步骤忘掉重要前提;压缩稿要保留不可丢的硬约束。
状态与审批显式状态机事件日志重放Human-in-the-loop幂等指纹 ledger
学习路径
  1. 读 4.4:掌握显式状态机、事件日志重放与幂等指纹 ledger
  2. 跑内置代码:用事件日志重放恢复一次崩溃前的状态
  3. 完成动手练习:为危险操作加 Human-in-the-loop 审批闸门
  4. 对接 M14:用幂等指纹 ledger 保证重放不产生重复副作用
✔ 能用重放恢复状态且危险操作每次都要人工审批
核心知识点详解
  • 显式状态机 + 事件日志重放:把 agent 状态建模成显式状态机(每个转移是一个事件),写事件日志(event sourcing)。崩溃后用日志重放即可恢复任意时刻的状态——重放是长任务恢复的最可靠手段。
  • Human-in-the-loop 审批闸门:危险操作(发送 / 付款 / 删除 / 写生产)必须人工确认后才执行。审批本身是一条事件记录,要可审计(谁 / 何时 / 哪版,见阶段 15 的 4.5)。
  • 幂等指纹 ledger 防重复副作用:给每次副作用调用算一个幂等指纹(参数哈希),写进 ledger;重放时若指纹已存在则标记已执行、跳过真正执行。常见坑:重放恢复成功了但副作用被重复执行(发了两次邮件 / 转了两笔账);指纹 ledger 才能拦住。
错误恢复指数退避 + 抖动降级换模型 / 工具补偿回滚连续 5 次失败熔断
学习路径
  1. 读 4.5:掌握最多重试次数判据,单独设计工具的全局危险和阻断策略
  2. 跑内置代码:实现重试降级并在连续 5 次失败后熔断
  3. 完成动手练习:为不可回滚操作写补偿回滚
  4. 对接 M14:接入失败恢复回路让长程 agent 持续可推进
✔ 能演示重试-降级-熔断链条并让任务不因单点失败而崩
核心知识点详解
  • 重试别死磕:指数退避 + 抖动:对瞬时错(429 / 超时 / 5xx)用指数退避 + 抖动,base × 2^n + jitter,给对端喘息;对永久错(4xx)立即失败不重试。别把重试和降级混为一谈。
  • 连续 5 次失败就熔断:同一类失败连续出现(如 5 次)说明不是瞬时抖动而是系统级问题,触发熔断:停止该路径调用、告警、切到降级(换模型 / 换工具 / 缓存兜底),而不是无限重试放大故障。
  • 不可回滚操作要补偿:已产生的副作用(如已发的部分请求)要写补偿回滚逻辑(对消 / 人工介入清单)。常见坑:只做了「重试成功」的正向路径,失败后已发生的部分副作用没人管;长任务里每类不可回滚操作都应配补偿。
学习路径

4.1 让 Agent 跑几小时不崩

长程任务(Long-horizon)是 2026 年最热门的技术方向之一(长程任务智能体与多智能体协同被列入年度最受关注技术)。它的挑战不是「会不会做一步」,而是能不能持续做几十步并记住进度。

python# 长任务状态文件:比任何花哨的框架都重要
PLAN = {
  "goal": "把 2026 上半年销售数据整理成季度报表并生成分析结论",
  "budget": {"max_steps": 60, "max_tokens": 2_000_000, "deadline": "2026-09-30T18:00"},
  "subtasks": [
    {"id": 1, "task": "从数据源导出原始数据", "status": "done",
     "artifact": "data/raw_2026H1.csv", "evidence": "rows=184320"},
    {"id": 2, "task": "清洗与校验数据质量", "status": "done",
     "artifact": "data/clean.csv", "evidence": "null_rate=0.2%, dup=0.01%"},
    {"id": 3, "task": "按季度聚合与计算同比", "status": "in_progress", "artifact": None},
    {"id": 4, "task": "生成图表与结论文档", "status": "pending", "artifact": None},
    {"id": 5, "task": "人工复核后导出", "status": "pending", "requires_approval": True},
  ],
  "notes": ["数据源 3 月有缺失,已与业务确认用插值补全", "Q2 口径与 Q1 不同,需在结论中注明"],
}

def next_action(plan):
    for st in plan["subtasks"]:
        if st["status"] == "pending":
            return st
        if st["status"] == "in_progress":
            return st
    return None                                   # 无待办 -> 结束

# 关键点:每一步的 artifact 与 evidence 都要落盘,
# 这样「做完了」是一个可验证的事实,而不是模型的一句声明。
python# 从状态文件续跑: 长任务的关键不是"能跑", 而是"崩了能续"
import json
def save(plan, path="plan.json"):
    json.dump(plan, open(path, "w"), ensure_ascii=False, indent=2)
def resume(plan):
    while (st := next_action(plan)):             # 取下一个 pending / in_progress
        try:
            art, ev = do(st)                      # 执行并产出可验证证据
        except Exception as e:
            st["status"], st["note"] = "failed", str(e)
            save(plan); raise                     # 先落盘再抛, 便于事后续跑
        st.update(status="done", artifact=art, evidence=ev)
        save(plan)                                # 每步幂等落盘
    return plan["subtasks"][-1]["artifact"]
# 预期: 崩溃后重启, next_action 跳过 done 的步骤, 从 in_progress 继续, 不重跑前 2 步

4.2 Computer Use / GUI Agent:能力与现实

Computer Use 让模型直接操作图形界面(点击、输入、滚动、读屏),适用于没有 API 的老系统、桌面软件、需要视觉判断的流程。2026 年它已可用于受控场景,但可靠性、速度与安全风险仍然是主要约束。

驱动方式原理优点缺点
DOM / 无障碍树读取网页结构定位元素准确、快速、便宜仅限有结构的网页;动态渲染可能失败
纯视觉(截图 + 坐标)看截图决定点击位置通用,任何界面都能用慢、贵、分辨率敏感、易点错
混合(视觉 + DOM)先用结构定位,无法定位时回退到视觉兼顾准确与通用实现复杂度最高,是主流选择
专用 API / 脚本直接调用接口或脚本最快最稳只适用于有接口的系统
⚠
GUI Agent 的安全底线:浏览器/GUI Agent 是当前最危险的攻击面之一:网页中的隐藏文本可以构成提示注入(视觉/排版注入),诱导 Agent 执行非预期操作;Agent 还可能误点「确认支付」「删除」「授权」这类按钮。生产使用必须:沙箱环境(独立浏览器 profile / 容器)、域名白名单、高危动作二次确认、操作录屏审计、以及只授予完成任务所需的最小权限(过度授权是把一个坏提示变成真实事故的根源)。
python# Computer Use: 归一化坐标 -> 无障碍树校验 -> 高危动作门禁
def to_abs(nx, ny, w, h):            # 模型常给 0-1000 归一化坐标
    return int(nx / 1000 * w), int(ny / 1000 * h)
RISKY = ["确认支付", "删除", "授权", "确认下单"]
def act(step, screen):
    x, y = to_abs(step.x, step.y, screen.w, screen.h)
    el = screen.a11y_at(x, y)                    # 用无障碍树校验点击目标
    if any(k in (el.text or "") for k in RISKY):
        return {"blocked": True, "need_human": True}   # 高危 -> 二次确认
    return screen.click(x, y)
# 经验: 纯视觉定位在 1080p 下坐标误差常达 1-3%; 混合 DOM / A11y 可降到 <0.5%

4.3 记忆体系:短期、工作与长期

三层记忆:短期=对话窗口(易溢出)、工作记忆=当前任务状态(JSON / 草稿)、长期=向量库 + 结构化档案(跨会话)。真正的工程难点在「写入什么、怎么检索、怎么遗忘」。不是什么都记——值得记的是稳定事实(用户偏好、项目约定)、非显然结论、失败教训;不记瞬时中间值。

层介质容量生命周期典型实现
短期上下文窗口有限(数万 token)单次会话messages 列表
工作结构化状态中任务内JSON / 草稿文件
长期向量 + KV大跨会话pgvector / Redis

写入策略要做去重与冲突检测:同一事实只留最新(新信息覆盖旧,并记录来源与时间);检索要带「时间衰减 + 相关性」,纯向量最近邻会召回过时信息,结构字段(用户 ID / 主题)做预过滤。压缩与摘要:当工作记忆超长,把旧片段摘要成一段、保留最近 K 轮原文——这是控制 long-context 成本的核心手段。

python# 记忆写入: 向量召回相似 + KV 存最新, 解决"冲突/遗忘"
def remember(fact, user_id, store, vec):
    emb = vec.encode(fact)
    for h in vec.search(user_id, emb, top_k=3):
        if sim(h.emb, emb) > 0.92:                   # 高度相似 -> 同一事实
            if h.created_at < now():                 # 新信息覆盖旧, 保留来源
                store.overwrite(h.key, fact)
            return "updated"
    key = store.put(user_id, fact)                    # 新事实
    vec.add(key, emb)
    return "added"

def recall(user_id, query, vec, top_k=5):
    cand = vec.search(user_id, vec.encode(query), top_k=top_k * 2)
    # 结构预过滤(主题) + 时间衰减, 再取 top_k
    return rank(cand, decay=lambda m: 0.9 ** months_since(m.ts))[:top_k]
✔
遗忘与冲突:长期记忆若只增不删,会慢慢被过时信息污染(用户改了偏好,旧记忆仍被召回)。工程上必须:① 写入带时间戳与来源;② 命中相似时以新覆盖旧;③ 提供显式「用户纠正」入口,让纠正立即覆盖。
python# 工作记忆压缩: 超长时把旧片段摘要, 保留最近 K 轮原文
def compress(log, keep_recent=6, max_chars=8000):
    head = summarize(log[:-keep_recent]) if len(log) > keep_recent else ""
    tail = log[-keep_recent:]
    ctx = (f"历史摘要: {head}\n" if head else "") + render(tail)
    if len(ctx) > max_chars:                     # 仍超 -> 只留最近 3 轮
        ctx = render(log[-3:])
    return ctx
# 经验: 摘要通常压到原文的 3-8%; 保留最近 3-6 轮原文, 兼顾细节与成本;
#   检索记忆要带时间衰减(如 0.9**月数), 否则最近邻会召回过时偏好

4.4 状态与持久化:显式状态机与 Human-in-the-loop

生产 Agent 应把状态机作为一等公民:状态是结构化字段、转移可枚举,比「全靠对话历史推断」更可恢复、可测试、可审计。崩溃后可从事件日志重放恢复,而不是重跑整条轨迹。

python# checkpoint: 每步把(状态 + 事件)落盘, 崩溃后从事件日志重放恢复
def step(agent, state, event_log):
    action = agent.decide(state)
    if action.needs_approval:                         # human-in-the-loop 中断点
        ticket = open_approval(action, state)        # 生成审批单
        outcome = wait(ticket, timeout=3600)          # 超时默认拒绝
        if outcome != "approved":
            return state                             # 不执行, 保持状态
    state = agent.apply(action, state)
    event_log.append({"state": state, "action": action, "ts": now()})
    persist(state)                                    # 幂等写入
    return state

def recover(event_log):                               # 崩溃续跑
    return replay(event_log)                          # 重放事件, 不重算副作用
维度显式状态机隐式轨迹
可恢复强(重放状态)弱(需重跑)
可测试强(单测转移)弱
可审计强(状态可见)弱
成本低(只存状态)高(存全历史)
⚠
审批不是「弹个窗」:human-in-the-loop 必须记录「谁批的、批了什么、批的哪版输入、超时如何」,否则事故无法溯源。中断点即 checkpoint——审批后从断点续跑,而不是从头再来。长任务还要有异步执行与「完成/失败通知」,避免用户干等。
python# 幂等: 用"动作指纹"去重, 防止重试造成重复副作用
import hashlib
def fingerprint(action, state):
    key = f"{action.name}:{sorted(action.args.items())}:{state.version}"
    return hashlib.sha256(key.encode()).hexdigest()[:16]
def apply_once(action, state, ledger):
    fp = fingerprint(action, state)
    if fp in ledger:                             # 已执行过 -> 直接返回旧结果
        return ledger[fp]
    res = execute(action)
    ledger[fp] = res                             # 与状态一起落盘
    return res
# 预期: 同一动作在重试 3 次的情况下, execute 只真正执行 1 次(其余 2 次命中 ledger)

4.5 错误恢复:重试、降级、补偿与熔断

把失败显式建模,而不是让 Agent 无限重试烧钱。四类策略:重试(幂等前提下)、降级(换模型 / 换工具 / 简化目标)、补偿(回滚已发生的副作用)、熔断(连续失败则停手并报障)。

python# 降级 + 熔断: 失败显式建模, 不盲目重试
class CircuitBreaker:
    def __init__(self, fail_limit=5, cooldown=300):
        self.fails = 0; self.open_until = 0
    def allow(self):
        return time.time() > self.open_until
    def on_fail(self):
        self.fails += 1
        if self.fails >= 5:                          # 连续失败 -> 熔断
            self.open_until = time.time() + 300

def call_with_fallback(tool, args, breaker):
    if not breaker.allow():
        return fallback_simple(args)                 # 降级: 规则/小模型兜底
    try:
        return tool(args)
    except TransientError:
        return tool(args)                            # 重试(要求幂等)
    except PermanentError:
        breaker.on_fail()
        return llm(f"工具不可用, 给尽力而为的答案: {args}")
失败类型策略前提
限流 / 超时重试(指数退避)幂等
模型输出非法降级换模型/换解析有备选
写操作部分失败补偿回滚操作可逆
依赖持续不可用熔断 + 降级有兜底路径
⚠
无限重试是烧钱之源:熔断要在「连续失败阈值」触发,而非单失败。补偿(回滚)要求写操作可逆或记录 undo 日志——这是「显式建模失败」与「假装不会失败」的分界线。
python# 指数退避 + 抖动: 避免重试风暴(重试本身也可能压垮依赖)
import random, time
def backoff(attempt, base=0.5, cap=30):
    delay = min(cap, base * (2 ** attempt))
    return delay * (0.5 + random.random() * 0.5)   # 加抖动, 打散重试时刻
# 预期: attempt=0 -> 0.25-0.5s; attempt=5 -> 8-16s; attempt=10 -> 封顶 15-30s
# 经验: 重试 3-5 次已足够; 再失败应熔断或降级, 而不是无限重试

4.6 动手练习与自测

✔
自测目标:完成这 5 题后,你应能设计一个「崩溃可续跑、副作用不重复、高危需审批」的长任务 Agent。
  1. 实现带状态文件的 5 步任务,在第 3 步人为抛异常;判据:重启后从第 3 步继续,前 2 步不重跑,最终 artifact 与证据齐全。
  2. 给写操作加幂等指纹与 ledger;判据:同一动作重试 3 次,底层 execute 只被调用 1 次。
  3. 给重试加指数退避 + 抖动,并加连续 5 次失败熔断;判据:失败 5 次后进入 open 状态并走降级路径,不再调用依赖。
  4. 设计一个审批中断点:记录谁批、批了哪版输入、超时行为;判据:超时默认拒绝且状态不变,审批通过后从断点续跑。
  5. 简答:为什么 human-in-the-loop 的中断点要等于 checkpoint?参考:否则审批后只能从头重跑,既浪费成本又可能重复副作用,且无法让「批的是哪一版输入」可溯源。
题号参考要点 / 判据
1第 3 步崩溃后重启从第 3 步续跑,前 2 步不重跑,artifact 与证据齐全
2幂等指纹 + ledger:同一动作重试 3 次,底层 execute 只被调用 1 次
3指数退避 + 抖动,连续 5 次失败熔断进入 open 状态并走降级
4审批中断点 = checkpoint:记录谁批 / 批了哪版输入 / 超时默认拒绝且状态不变
5否则审批后只能从头重跑,浪费成本且可能重复副作用,无法溯源「批的是哪版」

5. 生产化:让 Agent 可以被信任

知识结构图 · 生产化
生产化:让 Agent 可以被信任5 大知识域 · 20 个知识点
指标体系端到端成功率p50 步数 / token人工介入率 >20% 偏高工具参数错误率
学习路径
  1. 读 5.1:吃透端到端成功率、p50 步数 / token、人工介入率等指标
  2. 跑内置代码:给一次任务结算指标并按阈值告警
  3. 完成动手练习:定义自己 agent 的指标口径与告警线
  4. 对接 M14:在多步任务集上产出成功率的步数分布与失败分类
✔ 能给出可复现的指标并用量化数据定位最弱环节
核心知识点详解
  • 核心指标一句话定义清:端到端成功率(任务达标的比例,需明确定义达标)、p50 步数 / token(效率)、人工介入率(>20% 说明自动化不足)、工具参数错误率(可靠性)。指标要先有口径再去算,别让「成功率」各自解释。
  • 过程指标帮定位,端到端指标定成败:端到端成功率只告诉你「好不好」,工具调用成功率、参数错误率、每步 token 才告诉「坏在哪」——优化时沿过程指标下钻,报告时看端到端。
  • 指标要可复现 + 带基准:同一评测集、固定模型版本、固定 prompt 版本跑出的数字才能对比。常见坑:每次改动都没重跑同口径基线,前后数字不可比,误以为提升了;应固定 golden set 与版本再结算。
纵深防御模型 / 提示层系统 / 流程层监控层Spotlighting
学习路径
  1. 读 5.2:理解模型 / 系统 / 监控三层与 Spotlighting 的纵深防御
  2. 跑内置代码:用 Spotlighting 给易受注入的字段加视觉标记
  3. 完成动手练习:为关键字段与流程设分层拦截点
  4. 对接 M14:让工具调用走纵深防御,隔离低权威数据免注入
✔ 能分层布防并演示注入被某一层拦截
核心知识点详解
  • 纵深防御多层叠,别只靠一层:从底层到顶:模型层(对齐 / 安全性)、提示层(系统提示加固 / Spotlighting 标记)、系统层(沙箱 + 最小权限)、流程层(审批)、监控层(告警)。任何单层都会漏,叠起来才接得住不同攻击。
  • Spotlighting:给关键字段贴视觉标签:对易被注入的字段用特殊符号包裹(如 / 色块标记),让模型能「看见」哪些是人类输入、哪些是系统指令,显著降低间接注入成功率,成本趋近于 0。
  • 低权威数据要与指令隔离:检索文档 / 网页内容属于低权威数据,不能让它与高权威系统指令同权混入。常见坑:把用户下载的网页原文直接拼进 system prompt,一条隐藏指令就改写了 agent 行为;应隔离并标记权威层级。
沙箱与最小权限默认禁网 + 白名单只读挂载资源限额 + seccompexcessive agency
学习路径
  1. 读 5.3:掌握默认禁网 + 白名单、只读挂载、资源限额的沙箱原则
  2. 跑内置代码:在沙箱里跑工具并用 seccomp 收紧系统调用
  3. 完成动手练习:为代码执行工具配置只读与网络白名单
  4. 对接 M14:让沙箱代码执行成为最小权限的默认执行通道
✔ 能证明沙箱内工具默认断网只读且越权被资源限制拦住
核心知识点详解
  • 沙箱默认禁网 + 只读:代码执行 / 工具通道放进沙箱,默认阻断网络(白名单放行)、文件系统只读挂载(需要写的目录单独映射)。这样即使 agent 被注入,能造成的破坏面也被锁死在同一沙箱内。
  • 资源限额 + seccomp 双重收紧:限制 CPU / 内存 / 超时(ulimit / cgroup),用 seccomp 收紧系统调用集(禁 fork / 禁截断 / 禁加载内核模块等)。越权操作即使写了也会在系统调用层被拦住。
  • excessive agency:权限按需最小:只授任务所需的最小能力集,别给 agent 一把「万能钥匙」。常见坑:图省事给代码执行加 root + 全盘写 + 公网,一次注入 = 一台机器沦陷;应默认最小、逐项加白。
成本与延迟预算截断prompt caching 降 10x语义缓存模型路由
学习路径
  1. 读 5.4:掌握预算截断、prompt caching、语义缓存与模型路由降低成本
  2. 跑内置代码:给长任务设预算并在超支时截断
  3. 完成动手练习:组合缓存 + 路由后实测成本与延迟
  4. 对接 M14:控制多 agent 长任务的预算与单步延迟
✔ 能把成本与延迟压到阈值内而成功率不跌
核心知识点详解
  • prompt caching 是降本大头:长任务里 system prompt + 工具 schema 几乎不变,命中了 context cache 就能对缓存部分打折,实测可把 token 成本降到 约 1/10。前提是把「炒作可变的请求」与「稳定的前缀」分开组织。
  • 语义缓存 + 模型路由:对完全类同 / 语义近似的请求命中缓存直接返回,省一次推理;简单任务路由到便宜的轻量模型、复杂任务上强模型,成本与质量都收敛。
  • 预算截断:超支即停:给长任务设 token / 金额上限,超限优雅停止并汇报进度,而不是继续烧。常见坑:只顾着缓存省了几个点,却没做预算截断和路由,一个失控的长任务就能把省的全赔回去。
框架选型状态可控性可观测性可测试性能 checkpoint 才生产
学习路径
  1. 读 5.5:按状态可控 / 可观测 / 可测试 / 能 checkpoint 评审框架
  2. 跑内置代码:验证所选框架支持状态导出与回放
  3. 完成动手练习:给框架写一份可测试性清单再决策
  4. 对接 M14:选出的框架能承载检查点与全链路追踪
✔ 能基于四标准评审框架并证明它支持生产化的大地基
核心知识点详解
  • 能 checkpoint 才上生产:一个框架再有流量也不能上生产,除非它能导出 / 恢复状态(checkpoint)——否则长任务一崩就重来。天花板判据:能 checkpoint 才生产。
  • 四标准:可控 / 可观测 / 可测 / 可续:状态可控性(显式读写状态)、可观测性(每步可追踪)、可测试性(可注入 / 回放)、可 checkpoint(中断可续)。LangGraph 这类建在状态图上的是首选,原型框架往往缺后两项。
  • 用数据验证再选型:别只看文档吹的 feature,拿自己的长任务场景实测:能不能导出状态、能不能回放一次真实失败。常见坑:demo 能跑就定了框架,上线做可观测 / 回放时发现底层不支持,只能返工甚至重选。
学习路径

5.1 指标体系与故障排查

维度指标说明
任务成功端到端成功率、子任务成功率最重要的指标,但要明确「成功」的定义
效率平均步数、平均 token、平均延迟、人工介入率人工介入率高说明自动化程度不足
工具质量工具调用成功率、参数错误率、无效调用率参数错误往往说明工具描述有问题
成本每任务成本、成本分布找出少数超贵任务并单独优化
可靠性异常恢复率、重试成功率、超时率决定能否长期无人值守运行
安全越权尝试次数、审批拦截数、注入命中数安全指标必须监控而不是假设没有
常见故障典型原因排查方向
反复调用同一个工具没有进度感知 / 终止条件不清在上下文里明确列出已完成步骤;加步数上限
参数总是错的工具描述含糊、参数格式未说明改描述、加示例、用 enum 约束
忘记之前的结论状态没有外置,全指望上下文把关键结论写成结构化状态并每轮注入
给出看似合理但错误的结论缺少验证环节增加工具校验、断言或独立复核步骤
任务卡住不动外部依赖失败但没被发现加超时与心跳;失败要显式回传
成本失控上下文膨胀、无步数上限、无缓存加预算限制、历史摘要、语义缓存
python# 从 trace 聚合指标: 成功率先定义, 再看步数 / token / 人工介入
def aggregate(traces):
    n = len(traces)
    ok = sum(1 for t in traces if t.outcome == "success")   # 成功需可判定
    steps = sorted(t.steps for t in traces)
    return {
        "success_rate":   ok / n,
        "p50_steps":      steps[n // 2],
        "tokens_per_task": sum(t.tokens for t in traces) / n,
        "human_rate":     sum(1 for t in traces if t.human) / n,
    }
# 预期样例: {'success_rate': 0.82, 'p50_steps': 7, 'tokens_per_task': 41200, 'human_rate': 0.09}
# 经验: 人工介入率 > 20% 说明自动化不足; "成功"的定义必须进口径文档

5.2 纵深防御:安全不能靠一层

模型层
用对齐训练降低模型本身的有害倾向;但不要把安全性完全寄托在这一层——对齐主要作用于对话通道,工具执行通道往往缺乏对等约束。
提示层
指令层级(明确系统提示优先于用户输入与工具返回)、Spotlighting(标记不可信内容是数据而非指令)、结构化分隔。
系统层
沙箱执行、工具权限最小化、网络与文件访问白名单、数据库只读账号、操作审计日志。
流程层
高风险动作人工审批、双人复核、金额与频次限额、可一键回滚。
监控层
全链路 tracing、异常行为告警(如短时间内大量工具调用)、定期红队测试。
★
面试终极问题的回答框架:当被问「怎么保证你的 Agent 可靠」,按这四层回答:① 结构上——能用流水线就不用 Agent,能用单 Agent 就不上多 Agent;② 上下文上——状态外置、子任务可验证、工具描述精确;③ 工程上——检查点、超时与预算、失败恢复、全链路 tracing;④ 安全上——纵深防御 + 人工门禁 + 审计。再加上「我们有自己的评测集和回归门禁」,这个回答就完整了。
python# 纵深防御配置: 一层挡不住, 每层各自独立生效
DEFENSE = {
  "prompt":  {"instruction_hierarchy": True, "spotlight": True},
  "system":  {"sandbox": True, "net_allow": ["api.internal"], "db_readonly": True},
  "process": {"approval": ["refund", "send_email", "delete"], "dual_review": True},
  "monitor": {"alert_on": ["mass_tool_call", "off_allowlist"], "redteam": "weekly"},
}
def check(action, cfg=DEFENSE):
    if action.name in cfg["process"]["approval"]: return "need_approval"
    if action.is_write and not cfg["system"]["db_readonly"]: return "review"
    return "allow"
# 预期: check(refund_action) -> 'need_approval'  (流程层独立兜底, 不依赖模型自觉)

5.3 沙箱与安全:隔离、最小权限与间接注入

代码执行必须隔离:容器 / VM、默认无网络或白名单、只读挂载、CPU / 内存 / 时间限额、禁止危险 syscall。给 Agent 的代码解释器默认只读 + 受限写临时区。间接提示注入(Indirect Prompt Injection)指工具返回内容(网页 / 文档 / 数据库行)里藏指令,模型把它当作指令执行——防护是把工具结果明确标记为「不可信数据」。

python# 间接提示注入检测: 工具结果进入上下文前先扫描
INJECT_PATTERNS = ["忽略", "ignore previous", "system prompt", "你是现在", "执行以下"]
def sanitize_tool_result(raw):
    flagged = [p for p in INJECT_PATTERNS if p.lower() in raw.lower()]
    if flagged:
        # 标记不可信 + 触发人工确认, 而非静默采纳
        return {"data": raw, "untrusted": True, "flags": flagged,
                "note": "工具返回疑似含指令, 按数据对待, 敏感动作需审批"}
    return {"data": raw, "untrusted": False}

# 沙箱执行: 限制资源与网络(伪代码, 真实用容器运行时)
def run_in_sandbox(code, mem_mb=256, secs=10, net=False):
    return container.run(code, memory_mb=mem_mb, timeout_s=secs,
                         network=net, read_only_paths=["/data"])
维度推荐目的
网络默认禁, 白名单防外泄 / 防下载恶意
文件系统只读 + 临时写区防篡改宿主
资源CPU/内存/时间限额防失控
权限非 root + seccomp减攻击面
审计录屏 / 记录所有动作可追溯
★
最小权限原则:工具按需授予:只读账号、受限 scope、域名白名单、临时凭证。一个坏提示只有在「有权限」时才能变成真实事故——过度授权(excessive agency)是 Agent 安全事故的头号放大器。敏感操作(删库、发钱、发外)必须二次确认 + 审计。
python# 沙箱策略: 默认禁网 + 只读挂载 + 资源限额, 白名单才放行
SANDBOX = dict(memory_mb=256, cpu=1.0, timeout_s=10, network=False,
               mounts=[("/data", "ro"), ("/tmp", "rw")], user="nobody")
def run(code, sb=SANDBOX):
    if sb["network"]: raise SystemExit("生产默认禁网")
    return container.run(code, **sb)
# 预期: 代码尝试访问外部域名 -> 连接被拒; 写 /data -> 只读报错;
#       死循环 -> 10s 超时并回传 {"error": "timeout"} 而非卡住主进程
# 经验: 256MB / 10s 覆盖多数数据清洗; 超时与 OOM 都要显式回传错误码

5.4 成本与延迟控制

成本主要来自 token(尤其长上下文反复注入)与模型单价。控制杠杆:预算截断、prompt caching、语义缓存、模型路由、并行 / 批量。把稳定前缀(系统提示 / 工具 schema / 知识)放在消息最前且不被改写,命中 prompt caching 后前缀单价可降约 10 倍。

python# 模型路由: 简单任务用小模型, 省成本
def route(task):
    if is_classification(task) or len(task) < 200:
        return "haiku-class"                          # 小模型
    if needs_reasoning(task):
        return "opus-reasoning"                       # 强模型
    return "sonnet-default"

# 语义缓存: 相似问题直接复用答案, 跳过一次生成
def answer(query, cache, llm):
    near = cache.search(embed(query), top_k=1)
    if near and near.score > 0.97:                    # 近重复 -> 命中
        return near.answer                            # 成本约等于 0
    ans = llm(query)
    cache.put(embed(query), ans)
    return ans
手段典型节省适用
预算截断避免单次爆量所有长任务
Prompt Caching前缀单价降约 10x稳定系统提示
语义缓存跳过生成(约 0)高频重复问
模型路由单价降 1–2 档任务异质
并行工具延迟降 N 倍独立调用
批量 API单价降约 50%离线大批量
✔
成本要先可观测再优化:没有 per-trace 的 token / 成本埋点,优化就是盲猜。先把「每任务成本 = input×单价_in + output×单价_out」算清楚,找出Top贵的 1% 任务单独优化,收益远大于全局微调。
python# 稳定前缀在前, 易变内容在后 —— 才能命中 prompt caching
def build_messages(task, tools_desc, retrieved, SYSTEM="你是任务助手。"):
    return [
      {"role": "system", "content": SYSTEM + tools_desc},        # 稳定前缀(可缓存)
      {"role": "user", "content": f"参考资料:\n{retrieved}"},     # 易变
      {"role": "user", "content": task},
    ]
# 预期: 前缀命中缓存后单价约降 10x; 若把时间戳/会话 ID 塞进 system, 缓存全失效
# 经验: 缓存命中率应 > 70%; 低于此多半是稳定前缀里混入了动态内容

5.5 框架与生态:选型看什么

框架分化:LangGraph(图 / 状态机式编排,生产控制力最强)、AutoGen(对话式多 Agent,研究向)、CrewAI(角色 + 任务 + 流程,业务流水线)、OpenAI Agents SDK(轻量多 Agent + 工具 + tracing)、Dify / Coze(低代码可视化)。选型看「状态可控性、可观测性、可测试性」,而不是流行度。

维度权重怎么看
状态可控性高是否显式状态机 + checkpoint
可观测性高是否有 trace/span, 能否回放
可测试性高能否单测单步与回放
生态中是否有你要的集成
流行度低不决定可靠性
python# OpenAI Agents SDK 概念(伪代码): handoff + guardrail + tracing 内建
from agents import Agent, handoff, guardrail
triage = Agent(name="triage", handoffs=[handoff(refund_agent), handoff(tech_agent)])
refund_agent = Agent(name="refund", tools=[refund_tool],
                     input_guardrails=[guardrail(check_pii)])   # 输入护栏
# 框架内建 tracing: 每次调用自动记录 trace/span, 可在 dashboard 回放
result = Runner.run(triage, "我要退昨天买的鞋")
★
不要为「炫」选框架:能给你 checkpoint / tracing / 审批 / 回放的才适合生产;只管「跑起来」不管「能不能查、能不能停、能不能复现」的框架,上线后会反噬。低代码(Dify / Coze)适合做原型与内部工具,复杂长程编排还是要回到代码化框架。
python# 判断一个框架是否"生产可用": 就看这三件事能不能做到
def audit_framework(fw):
    return {
      "state_inspectable": hasattr(fw, "get_state"),   # 能读当前状态
      "interruptible":     hasattr(fw, "interrupt"),   # 能中断 + 续跑
      "replayable":        hasattr(fw, "replay"),      # 能按 trace 回放
    }
# 预期(合格框架): {'state_inspectable': True, 'interruptible': True, 'replayable': True}
# 三者缺一, 长任务上线后基本无法定位问题 —— 这也是选型的第一过滤条件

5.6 动手练习与自测

✔
自测目标:完成这 5 题后,你应能给一个 Agent 系统配齐指标、防御、沙箱与成本控制,并能用数字证明收益。
  1. 从 100 条 trace 聚合成功率、p50 步数、每任务 token、人工介入率;判据:口径文档写清「成功」判据,四项指标可复现。
  2. 为一个含写操作的工具链配置纵深防御四层;判据:即使模型被注入,写操作仍被流程层审批拦截(用红队用例验证)。
  3. 写一个沙箱执行器并验证;判据:访问非白名单域名失败、超时被显式回传错误码、宿主文件不可写。
  4. 计算题:某任务 input 6 万 token、output 2k token,单价 in 3 元/百万、out 15 元/百万;开 prompt caching 后其中 5 万 token 前缀按 0.3 元/百万,估算单次成本变化。参考:改前 ≈ (60000×3+2000×15)/1e6 = 0.21 元;改后 ≈ (50000×0.3+10000×3+2000×15)/1e6 ≈ 0.075 元,降约 64%。
  5. 简答:没有 per-trace 成本埋点,为什么成本优化是盲猜?参考:无法定位最贵的 1% 轨迹,优化无从下手,也无法验证改动是否真的省了钱。
题号参考要点 / 判据
1口径文档写清「成功」判据;成功率、p50 步数、每任务 token、人工介入率四项可复现
2纵深防御四层;即使模型被注入,写操作仍被流程层审批拦截(红队用例验证)
3沙箱:非白名单域名失败、超时显式回传错误码、宿主文件不可写
4改前 ≈0.21 元;改后 ≈0.075 元,降约 64%
5无 per-trace 埋点则无法定位最贵 1% 轨迹,优化无从下手也无法验证

6. Agentic RL:长程训练的回报

知识结构图 · Agentic RL
Agentic RL:长程训练的回报3 大知识域 · 12 个知识点
为何回归 CriticGRPO 组相对不等长失真PPO + CriticGAE 优势估计TD 残差
学习路径
  1. 读 6.1:理解组相对对不等长轨迹的失真与为何回归 Critic
  2. 跑内置代码:用组相对公式算出 3 步 vs 30 步轨迹的优势失真
  3. 完成动手练习:对比 PPO-Critic 与 GRPO 口径并说明选型
  4. 对接 M14:为长程 agent 选用 Critic 基线以稳定长轨迹的梯度估计
✔ 能指出组相对失真的数学根因并说出何时该上 Critic
核心知识点详解
  • GRPO 组相对的前提是「长度相近」:GRPO 在同一 prompt 的 G 条轨迹内做归一化 (r - mu) / (sigma)。它假设这些轨迹长度接近、可公平比较方差;一旦组长短悬殊(一条 3 步、一条 30 步),同一步的贡献被稀释或放大,优势估计失真。
  • 长程回归 Critic(PPO 式):用价值网络估计 V(s),优势 A = r + γV(s′) − V(s)(TD 残差,GAE 累计),不依赖同组轨迹长度可比,对长轨迹更稳。代价是要多训一个 value network + TD 目标。
  • 何时该上 Critic 的数据判据:当你的任务集是长程(步数差异大、有分叉)时组相对失真明显,该上 Critic / ARPO / Tree-GRPO;短任务或长度均匀时 GRPO 足够便宜。常见坑:把 GRPO 硬套长程任务,优势被稀释后训练不动,还以为是数据问题。
ARPO / Tree-GRPO分叉点分支采样树节点优势按角色分组前缀共享降本
学习路径
  1. 读 6.2:理解 ARPO 在分叉点采样、Tree-GRPO 在树上加优势与按角色分组
  2. 跑内置代码:复现分叉点分支采样与前缀共享降本
  3. 完成动手练习:说明哪类长程任务适合 ARPO / Tree-GRPO
  4. 对接 M14:用按角色分组给多 agent 各目标分配适配优势
✔ 能揭示分叉点在长轨迹的价值并正确选型 ARPO / Tree-GRPO
核心知识点详解
  • ARPO:只在分叉点做分支采样:长轨迹真正需要「多探索」的是动作分叉点(下一步有多种选择),而不是整条从头到尾随机。ARPO 在分叉点克隆多条分支采样,其余前缀直接共享,既省采样又聚焦决策关键点。
  • Tree-GRPO:把轨迹整理成树再算优势:把共享前缀的多条轨迹组织成树,在树节点上算优势而非整条组内算,避免长度不一致带来的失真。前缀共享同时降低重算成本。
  • 按角色分组对齐多 agent 目标:多 agent 各角色(规划 / 检索 / 执行)目标不同,按角色分组各自计优势,别让不同角色的稀疏信号互相稀释。常见坑:把不同角色的轨迹混在同一个组里算优势,信号互相抵消,训练不收敛。
稀疏奖励信用分配过程奖励验证器子目标奖励reward hacking
学习路径
  1. 读 6.3:理解稀疏奖励下的信用分配与过程奖励验证器
  2. 跑内置代码:用过程奖励给中间步骤打分定位 reward hacking
  3. 完成动手练习:为长任务设计子目标奖励并防 hacking
  4. 对接 M14:用过程奖励节点校验 agent 每步工具调用质量
✔ 能量化稀疏奖励问题并用过程奖励缓解 reward hacking
核心知识点详解
  • 稀疏奖励的信用分配难题:长任务十几步后才一次性给奖励,中间哪一步做得好模型无从得知(信用分配)。解决办法:拆子目标奖励 + 用过程奖励验证器给中间步骤打分,把「一路对」引导出来。
  • reward hacking:模型钻奖励空子:模型会学着「看起来像在正确推进」来骗过程奖励(复读、贴金、游戏化指标),而不是真正完成任务。过程奖励要落在验证器判据上(如工具结果正确、测试通过),而不是人眼观感。
  • 验证器要对抗准备:给过程奖励验证器配对抗用例:检查模型是不是在 hack(关键信息未用 / 步骤未真正执行却声称完成)。常见坑:奖励设得太松,模型学成「形式正确、内容空洞」,端到端成功率反而下降。
学习路径

6.1 为什么长程 Agent 训练回归 Critic

GRPO 类「组相对」方法假设同一 prompt 的若干条轨迹长度相近、可公平比较方差;但在长程 Agent 里,子轨迹长度与分支差异巨大,组相对的方差估计会失真——同一步的贡献被稀释或放大。于是强方法回归 Critic(价值基线,PPO-style),或在组相对上做改进(ARPO 在分叉点分支采样、Tree-GRPO 在树上加优势)。

python# 组相对(GRPO)假设: 同一 prompt 的 G 条轨迹长度相近, 才能公平比较
def grpo_advantage(rewards, group):
    mu = mean(rewards[group]); sigma = std(rewards[group])
    return [(r - mu) / (sigma + 1e-6) for r in rewards[group]]
# 问题: 若 group 内一条走 3 步、另一条走 30 步, 同一步贡献被稀释
# 长程改用 Critic 更稳定: 训练 value network 估计 V(s)
#   优势 A = r + gamma * V(s_next) - V(s)   (TD 残差)
# 但需额外网络与 TD 目标, 工程更重
方法是否需要价值网络长程表现成本
GRPO / 组相对否中(不等长失真)低
PPO + Critic是好中-高(多训一个网络)
ARPO否(分叉采样)好低-中
Tree-GRPO否(树优势)好中
ℹ
何时值得做 Agentic RL:只有「同一类失败反复出现、且 prompt / 工具层面已无法解决」时才上 RL。绝大多数团队先用 Reflexion + 更好的工具 + 更好的上下文工程就能解决 80% 的问题;RL 是最后 20% 的精调手段,且需要可环境化的评测回路。
python# 用 Critic 估优势(GAE): 长程不必等"整个 group 齐了"才能比较
def gae(rewards, values, gamma=0.99, lam=0.95):
    # values 长度 = len(rewards)+1, values[-1] 为终止状态估值
    adv, last = [], 0.0
    for t in reversed(range(len(rewards))):
        delta = rewards[t] + gamma * values[t + 1] - values[t]   # TD 残差
        last = delta + gamma * lam * last
        adv.insert(0, last)
    return adv
# 预期: 稀疏奖励下中间步也能拿到非零优势(信用被"摊回"), 而非全为 0
# 代价: 需额外训练一个 value network 与 TD 目标, 工程更重

6.2 ARPO / Tree-GRPO 与按角色分组

ARPO 只在「决策分叉点」展开多轨迹、其余前缀共享,既保住比较公平性又大幅降本;Tree-GRPO 在树节点上累积优势而非线性轨迹;按角色分组(role-grouped)对 planner / executor 等异构角色分别做组相对,解决它们信用分配尺度不同导致的病态。

python# ARPO: 只在分叉点展开多轨迹, 其余前缀共享, 降本且保比较公平
def arpo_train(trajectory, fork_points, llm, reward, G=4):
    for fork in fork_points:                          # 仅决策分叉处分支
        branches = [complete(trajectory[:fork], seed) for seed in range(G)]
        adv = grpo_advantage([reward(b) for b in branches], range(G))
        update(branches, adv)                          # 仅更新分叉后参数

# 按角色分组: planner 与 executor 各自组相对, 解决异构信用分配
def role_grouped(trajectories):
    for role in ["planner", "executor"]:
        grp = [t for t in trajectories if t.role == role]
        update(grp, grpo_advantage(grp))
改进核心思想解决什么
ARPO分叉点分支采样不等长轨迹的比较失真 + 成本
Tree-GRPO树节点优势多分支探索的信用分配
Role-grouped按角色分别组相对异构角色尺度不一
过程奖励每步验证器给信号稀疏奖励
✔
分支采样的工程前提:分叉点必须可被「重放」——即轨迹要从 checkpoint 续跑,而不是每次从头生成。这又把问题绕回「状态可持久化 + 环境可回放」,与第 4 节的工程要求同源。
python# Tree-GRPO: 在树节点上累积优势, 而不是只看线性轨迹的末端奖励
def tree_advantage(node, gamma=1.0):
    if not node.children:                    # 叶节点: 用自身奖励
        return node.reward
    child = [tree_advantage(c, gamma) for c in node.children]
    node.value = max(child)                  # 也可按访问次数加权
    return node.reward + gamma * node.value
# 预期: 同一分叉点下, 通向成功叶的分支优势显著高于失败叶;
#       相比线性 GRPO, 分叉点的比较不再被"轨迹长度不同"污染

6.3 稀疏奖励与信用分配

Agent 最常见的是稀疏奖励:只在任务末尾有一个二元成功信号,中间几十步完全没有监督。这导致「信用分配」难题——到底哪一步导致成功 / 失败?解法组合:过程奖励(每步用验证器给分)、子目标奖励(完成中间里程碑给分)、价值基线(Critic 估计每步期望回报)、轨迹级 Critic(整条轨迹打分后反传)。

信号粒度获取成本风险
任务末尾二元粗低(自动)信用分配难
子目标达成中中(需定义里程碑)里程碑定义偏则偏
过程验证器细高(写验证器)验证器被钻空子
Critic 估值每步高(训网络)泛化误差
⚠
稀疏奖励的坑:奖励越稀疏,越容易被「奖励黑客(reward hacking)」钻空子——Agent 找到一条看似达标实则违背意图的路径。过程奖励能缓解,但过程奖励本身要防被绕过。这是 Agentic RL 与对齐(第 15 阶段)共通的难题。
python# 过程奖励 + 结果奖励加权: 缓解稀疏奖励下的信用分配
def shaped_reward(traj, w_proc=0.3, w_final=1.0):
    proc = sum(verifier(s) for s in traj.steps) / len(traj.steps)
    return w_proc * proc + w_final * traj.final_success
# 预期: 纯结果奖励下中间步优势近乎为 0; 加 0.3 过程项后早期正确步被区分开
# 风险: 过程验证器会被"钻空子"(reward hacking), 需对抗评测持续校验

6.4 动手练习与自测

✔
自测目标:完成这 4 题后,你应能解释长程 Agent 训练为何回归 Critic,并能设计稀疏奖励的缓解方案。
  1. 实现 GAE 并对比「无 Critic」与「有 Critic」在稀疏奖励下的中间步优势;判据:前者中间步优势 ≈ 0,后者非零且逐步收敛。
  2. 说明 ARPO 为何只在分叉点分支;参考:既保住组内可比性(前缀相同),又把采样成本从 O(轨迹长度×G) 降到 O(分叉数×G)。
  3. 为某任务设计一个过程奖励验证器,并构造一个能骗过它的反例;判据:能明确写出该验证器被 hack 的具体路径。
  4. 简答:什么时候才值得上 Agentic RL?参考:同类失败反复出现、且 prompt / 工具层已无法解决,同时具备可环境化的评测回路。
题号参考要点 / 判据
1无 Critic 时中间步优势 ≈0;有 Critic 时非零且逐步收敛
2ARPO 只在分叉点分支:保住组内可比性(前缀相同),采样成本 O(长度×G)→O(分叉数×G)
3能明确写出该验证器被 hack 的具体路径(走捷径 / 形式满足)
4同类失败反复出现、prompt / 工具层已无法解决、且有可环境化的评测回路

7. Agent 评测:看轨迹而不是看答案

知识结构图 · Agent 评测
Agent 评测:看轨迹而不是看答案3 大知识域 · 12 个知识点
轨迹级评估工具序列比对参数正确性多余步 / 无效调用答案对 ≠ 做对了
学习路径
  1. 读 7.1:掌握按工具序列、参数正确性、多余步评估轨迹而非只看答案
  2. 跑内置代码:对工具序列做比对并标记多余步
  3. 完成动手练习:写一个答对但走错路径的样例并判不合格
  4. 对接 M14:把轨迹级评估接入多步任务的回归集
✔ 能抓到「答案对但路径错」的隐藏失败
核心知识点详解
  • 只看答案会漏掉「蒙对」:最终答案正确但走错了路径(调错工具、顺序错、参数错、有余步)在线上是隐蔽事故源。轨迹级评估的要点就是把工具调用本身当作被测对象,而不是只看 end answer。
  • 比对结构与参数而非整串相等:轨迹比对要看工具序列是否一致、参数取值是否正确、调用顺序是否合理,并单独统计「多余步」与「无效调用」。只做整串 JSON 字符串相等会漏掉字段级差异。
  • 答对但路径错的样例也要进回归:「答案对、路径错」是最容易逃过评估的失败类型,务必构造这种样例放进黄金集并设为不合格,让回归门禁真的拦得住这类退化。
环境化评测tau-bench 状态断言SWE-bench 单测ReplayEnv 回放WebArena
学习路径
  1. 读 7.2:理解 tau-bench 状态断言与 SWE-bench 用单测验收
  2. 跑内置代码:在环境里用状态断言验证一次任务是否真完成
  3. 完成动手练习:对比真环境评测与 ReplayEnv 回放
  4. 对接 M14:在多步任务集上做环境化评测并产出失败分类
✔ 能在环境里做状态断言而不被表面答案骗过
核心知识点详解
  • 用环境状态断言,而不是看模型自述:让 Agent 在真实环境里跑任务,评估端用环境的状态(文件内容、数据库记录、API 副作用、页面 DOM)来判断是否完成,而不是让模型自己说「我完成了」。
  • tau-bench / SWE-bench 的共性:二者都靠环境裁判:tau-bench 用状态断言、SWE-bench 用单测验收。凡是「结果可被环境客观判定」的任务都应环境化,把主观打分降到最低。
  • ReplayEnv 回放代替重复执行:真实环境执行贵且不可控,可把一次真实执行录成 fixture,用 ReplayEnv 回放到本地/CI 里做回归,保证同样输入走同一条确定性路径。
回放与确定性录像 fixturetape_hash 确定录制→回放→断言进回归集
学习路径
  1. 读 7.3:掌握录像 fixture 与 tape_hash 保证回放确定性
  2. 跑内置代码:录制一条轨迹再回放并断言二进制一致
  3. 完成动手练习:把录制-回放-断言接入回归集
  4. 对接 M14:用确定性回放把真实任务固化进 CI 回归
✔ 能保证回放可复现并让真实失败进入回归集
核心知识点详解
  • 录制 → 回放 → 断言的闭环:先把真实请求的输入/输出与工具结果录成 fixture,回放时用 fixture 驱动 Agent,最后对输出做断言。关键价值是把一次线上失败变成一个可在本地/CI 反复复现的确定性用例。
  • 用 tape_hash 保证确定性:回放要逐字节确定:对输入轨迹计算 tape_hash 并在回放时核对一致。任何非确定来源(模型采样、随机排序、时间戳)都要在录制时冻结,否则同一条路径回放结果不一致、无法断言。
  • 真实失败必须落地为回归用例:最怕线上失败死一次就没了。规范动作是:每次线上失败都录制 → 固化进回归集,让这次失败变成永久的 CI 检查项,防止同类问题静默回归。
学习路径

7.1 轨迹级评估

Agent 评测不能只看最终答案——「答案对但路径错」(蒙对、走错路、调了不该调的工具)在线上是隐患。轨迹级评估看工具调用序列、参数、顺序、是否多余步、是否有非法调用。它能在「答案巧合正确」时仍判为不合格。

python# 轨迹级评估: 不仅看最终答案, 看是否走了正确路径
def eval_trajectory(gold, pred):
    return {
        "final_correct":  gold.answer == pred.answer,
        "tool_seq_match": gold.tools == pred.tools,       # 工具调用顺序
        "param_correct":  all_eq(gold.args, pred.args),    # 参数正确性
        "redundant_steps": len(pred.tools) - len(gold.tools),  # 多余步(应≈0)
        "no_invalid_call": not any(is_invalid(c) for c in pred.tools),
    }
指标看什么暴露的问题
端到端成功率最终答案对不对「蒙对」漏判
工具调用准确率调了正确的工具没选错工具
步数效率走了几步绕路 / 死循环
成本花了多少 token上下文膨胀
轨迹合规路径是否合规走错路但答案对
⚠
答案对 ≠ 做对了:一个 Agent 可能用错误工具、错误参数,却因下游纠错或巧合得到正确答案。只测端到端会把这种「带病运行」放过——轨迹级评估是生产 Agent 的必选项。
python# 轨迹综合评分: 答案对但路径错 -> 仍判不合格
def score_traj(gold, pred):
    w = {"final": 0.4, "tools": 0.3, "params": 0.2, "efficiency": 0.1}
    eff = 1.0 - min(1.0, max(0, len(pred.tools) - len(gold.tools)) / 5)
    return (w["final"] * (gold.answer == pred.answer)
          + w["tools"] * (gold.tools == pred.tools)
          + w["params"] * all_eq(gold.args, pred.args)
          + w["efficiency"] * eff)
# 预期: 答案对但工具序列错 -> 约 0.4-0.5(不合格); 满分需四项全对
# 判据: 生产门禁建议对"轨迹合规"单列一个 0/1 硬指标, 不参与加权平均

7.2 环境化评测:tau-bench 与 SWE-bench

tau-bench 用「用户模拟器 + 工具环境」测多轮工具调用 Agent(零售 / 航空客服场景),看它能否按策略完成真实业务;SWE-bench 用真实 GitHub issue + 仓库,测代码修复 Agent 的 patch 是否通过测试。二者都是「环境可重置、结果可验证」的闭环评测,比开放问答可靠得多。

基准任务形态验证测什么
tau-bench多轮对话 + 工具调用环境状态断言指令遵循 + 工具正确性
SWE-bench读 issue + 改代码单测通过代码推理 + 执行
WebArena网页操作网页状态GUI Agent
AgentBench多环境综合各环境指标通用 Agent 能力
python# 用录制的环境回放代替真实外向调用, 保证确定性与零成本
class ReplayEnv:
    def __init__(self, tape): self.tape = tape; self.i = 0
    def call_tool(self, name, args):
        expected = self.tape[self.i]; self.i += 1
        assert expected.name == name, "轨迹偏离录制!"
        return expected.result                          # 固定返回, 无网络
def run_on_tape(agent, tape):
    return agent.run(ReplayEnv(tape))                   # 可复现评测
✔
自建环境化评测:没有公开基准覆盖你的业务,就自己造一个「录制环境」:把真实工具调用录成 tape,评测时回放。它把「真连生产 API」换成「回放固定 fixture」,成本≈0 且完全确定,是 CI 里跑 Agent 评测的最佳形态。
python# tau-bench 风格: 不看"说了什么", 看环境最终状态是否符合预期
def check_final_state(env, expected):
    db = env.snapshot()                       # 重置后可断言的真实状态
    return all(db.get(k) == v for k, v in expected.items())
# 示例: 用户要求"把订单 O9 退款" -> 断言
#   {"orders.O9.status": "refunded", "orders.O9.refunds": 1}
# 预期: 只回复"已退款"但环境未变 -> 判失败(这正是 tau-bench 的严格之处)
# 对比: SWE-bench 的等价断言是"patch 后目标单测由 fail 变 pass"

7.3 回放与确定性

生产 Agent 评测最大的敌人是非确定性(模型随机、工具返回变化、网络抖动)。做法:把每次失败 / 每次评测的「模型输入 + 工具返回」全量录制为 fixture,回放时用录制的工具返回替代真实外向调用。这样评测可复现、可定位、可进回归集。

策略确定性成本适用
真实在线调用低高仅灰度/线上
录制回放高低CI / 回归
模拟器高低有环境模型时
影子流量中中线上对照
★
评测的终极形态:把「录制 → 回放 → 断言轨迹 → 进回归集」做成流水线:每次线上失败都录成一条 fixture,加入回归集;改 Prompt / 工具 / 模型后跑回归,下降即阻断。这与第 15 阶段的 CI 门禁同源——Agent 评测本质是「轨迹的回归测试」。
python# 录制回放: 用输入 + 工具返回的哈希保证"同输入必同结果"
import hashlib, json
def tape_hash(case, tool_results):
    blob = json.dumps([case.input, tool_results], sort_keys=True,
                      ensure_ascii=False)
    return hashlib.sha256(blob.encode()).hexdigest()[:12]
# 预期: 同一 fixture 重跑 100 次, tape_hash 完全一致(确定性可验证);
#       若模型或 Prompt 改了, 轨迹偏离 -> 断言失败并输出首次差异位置

7.4 动手练习与自测

✔
自测目标:完成这 5 题后,你应能把「录制 → 回放 → 断言轨迹 → 进回归集」做成本阶段 Agent 的日常流水线。
  1. 给一次线上失败录制 fixture 并加入回归集;判据:改动 Prompt 后回归能复现该失败并阻断合并。
  2. 用 ReplayEnv 跑一条轨迹并注入「轨迹偏离」;判据:断言在正确步数处失败,并打印期望与实际调用。
  3. 计算题:某轨迹答案正确但工具序列错误,按 final 0.4 / tools 0.3 / params 0.2 / efficiency 0.1 加权,效率满分时综合分是多少?参考:0.4 + 0 + 0 + 0.1 = 0.5,仍判不合格。
  4. 简答:为什么 Agent 评测必须看轨迹?参考:答案对并不等于做对了,走错路、调错工具、多余步在线上是隐患。
  5. 设计:为 M14 里程碑 Agent 设计一条「录制 → 回放 → 断言 → 进回归」流水线,列出 3 个必须记录的字段。参考:模型版本、Prompt 版本、工具返回 fixture 哈希。
题号参考要点 / 判据
1改动 Prompt 后回归能复现线上失败并阻断合并
2断言在正确步数处失败,并打印期望与实际调用
3综合分 0.4+0+0+0.1 = 0.5,仍判不合格
4答案对不等于做对:走错路、调错工具、多余步在线上是隐患
5必须记录字段:模型版本、Prompt 版本、工具返回 fixture 哈希

项目里程碑

贯穿项目 · Hamauls Orion
M14 MCP 工具生态与多 Agent 编排 第 79–86 周

把 Hamauls Orion 从「问答」升级为「干活」:用 MCP 协议接入工具(检索、数据库、代码执行、日历等),实现规划-执行-反思循环、多 Agent 分工协作、以及长程任务的状态持久化与人工审批。

本阶段产出(直接进入项目仓库)
验收标准:能在 10 步以上的真实任务上稳定成功(成功率 > 70%);服务重启后能恢复未完成任务;所有危险工具调用都有审批记录。

阶段练习项目

PROJECT 1
自定义 MCP Server
为公司内部数据源(或自建的模拟数据)开发一个 MCP Server,包含 Tool / Resource 两类能力、参数校验、错误码规范与调用日志,并接入一个客户端验证。
要达成的效果
  • 交付一个可被客户端以 tools + resources 两种方式调用的 MCP Server
  • 覆盖参数校验、错误码规范与调用日志,并接入一个客户端完成整链验证
功能需求
  • 用 MCP SDK 或手写协议实现一个 Server,注册 ≥2 个 Tool 与 ≥2 个 Resource
  • 实现参数校验(必填、类型、范围)与统一错误码(成功 / 用户错误 / 工具错误 / 超时)
  • 每次调用输出结构化日志(入参、出参、耗时、错误码)
  • 用客户端(MCP Inspector 或自研 client)做一轮真实调用验证并记录结果
交付物
  • 可运行的 MCP Server 代码
  • 客户端接入验证记录(调用日志 / 截图)
  • 一份说明错误码规范与日志格式的简短文档
边界 · 不做

不做多协议兼容与鉴权计费;工具数量与语言栈不限。

PROJECT 2
Deep Research Agent
实现一个研究型 Agent:问题拆解 → 多源检索 → 交叉验证 → 带引用的结构化报告。要求有步数上限、检查点与成本统计。
要达成的效果
  • 交付一个完整的研究型 Agent:从问题拆解、多源检索、交叉验证到产出带引用的结构化报告
  • 运行时具备步数上限、检查点续跑与成本统计,能稳定跑完一次研究任务
功能需求
  • 实现问题拆解(拆成可检索的子问题清单)与多源检索(≥2 个来源)
  • 对检索结果做交叉验证(同一事实至少两个独立来源支撑才采信)
  • 报告以结构化 sections 输出并附引用,结论与证据对应关系可核查
  • 设置步数上限与成本统计,任务中断后可凭检查点续跑
交付物
  • 可运行的研究 Agent 代码
  • 一次完整研究的运行记录(步骤、成本、检查点恢复)
  • 一份带引用的结构化报告样例及交叉验证说明
边界 · 不做

不做对私域数据库的接入;检索源限于公开网页内容。

PROJECT 3
带审批门禁的运维 Agent
读日志 → 定位异常 → 给出修复建议 → 高风险操作需人工确认后执行。重点实现状态持久化、可中断续跑与完整审计日志。
要达成的效果
  • 交付一个带审批门禁的运维 Agent:读日志、定位异常、给建议,高风险操作必须人工确认后才执行
  • 具备状态持久化、可中断续跑与完整审计日志
功能需求
  • 接入日志源,能解析并按规则 / 启发式定位异常并给出修复建议
  • 定义高风险操作集合,操作前必须经过人工确认,未确认不执行
  • 任务状态持久化到存储,进程中断后可续跑
  • 每次操作(含审批动作)写入不可篡改的审计日志
交付物
  • 可运行的运维 Agent 代码与审批门禁实现
  • 一次「读日志 → 定位 → 审批 → 执行」的端到端演示记录
  • 审计日志样例与续跑演示说明
边界 · 不做

不做对真实生产系统的破坏性操作;用模拟 / 沙箱数据验证全流程。

PROJECT 4
GUI Agent 安全性测试
在沙箱中让浏览器 Agent 完成一个任务,并故意构造页面内提示注入,观察它是否会被诱导;输出防护建议清单。
要达成的效果
  • 在沙箱中让浏览器 Agent 完成一个任务,并构造页面内提示注入观察是否被诱导
  • 输出一份含风险等级与缓解措施的安全防护建议清单
功能需求
  • 用浏览器自动化在沙箱中执行一个真实任务(如填表 / 搜索 / 点击流程)
  • 构造 ≥2 种页面内提示注入(直接指令注入、伪装成页面内容的注入)观察是否被诱导
  • 记录被诱导与否的路径与证据,判断诱导是否导致非预期操作
  • 把发现归类并给出对应的防护建议
交付物
  • 沙箱内浏览器任务脚本与构造的注入样例
  • 被诱导 / 未诱导的实验记录与证据
  • 一份含风险等级与缓解措施的防护建议清单
边界 · 不做

不做对操作系统内嵌文件的访问与真实账户操作;仅浏览器自动化测试。

PROJECT 5
M14 里程碑:MCP 工具生态与多 Agent 编排
交付一个「MCP Server 市场 + 多 Agent 编排」系统:开发至少 3 个 MCP Server(覆盖 tools / resources / prompts,并演示 sampling 与 elicitation),用 supervisor + handoff 模式把工单 / 检索 / 执行类 Agent 编排起来,支持 checkpoint 续跑与人工审批;用 tau-bench 风格的录制环境验证工具调用准确率与端到端成功率,并产出调用成本与步数效率报告。
要达成的效果
  • 交付「MCP Server 市场 + 多 Agent 编排」系统:≥3 个 MCP Server(tools / resources / prompts 全覆盖并演示 sampling / elicitation)
  • 用 supervisor + handoff 把工单 / 检索 / 执行类 Agent 编排起来,支持 checkpoint 续跑与人工审批
  • 用 tau-bench 风格录制环境验证工具调用准确率与端到端成功率,并产出成本与步数效率报告
功能需求
  • 开发至少 3 个 MCP Server,覆盖 tools / resources / prompts 三类能力,并演示 sampling 与 elicitation
  • 用 supervisor + handoff 模式编排工单 / 检索 / 执行类 Agent
  • 实现 checkpoint 续跑与人工审批门禁
  • 搭一个 tau-bench 风格的录制-回放评估环境,测工具准确率与端到端成功率
  • 统计调用成本与步数效率并写入报告
交付物
  • MCP Server 市场代码 + ≥3 个可运行的 Server
  • 多 Agent 编排 demo(supervisor + handoff + 审批门禁)
  • tau-bench 风格评测结果 + 调用成本与步数效率报告
边界 · 不做

不做对真实生产系统的影响性操作;Agent 在沙箱 / 录制环境内运行。

常见误区

面试高频问题速答

MCP 和 Function Calling 是什么关系?

Function Calling 是模型能力:把工具 schema 给模型,模型输出结构化调用意图,由调用方执行。MCP 是工程协议:它标准化了「工具与应用如何对接」,让工具(Server)写一次就能被所有兼容客户端复用,并额外提供 Resources(数据读取)、Prompts(模板)等能力。所以 MCP 建立在 Function Calling 这类能力之上,解决的是复用与生态问题,而不是替代它。

什么时候该用多 Agent?

只有在「单 Agent + 好工具 + 好上下文」确实做不到时才用。典型适用场景:子任务可并行且相互独立(可并行加速)、需要不同专业视角互相校验(生成 + 批判)、或者不同子任务需要不同的工具集与权限边界(隔离风险)。反之,步骤可预知的任务用固定流水线更可靠更便宜。判断标准是「多 Agent 带来的协调开销是否小于它的收益」。

怎么让长程任务不跑偏?

核心是「状态外置 + 子任务可验证 + 预算约束」:① 把任务清单、已完成项、关键结论写成结构化状态持久化,每轮按需注入,而不是指望模型记住上下文;② 每个子任务有客观完成判据(文件生成、测试通过、断言成立)而不是模型声称完成;③ 每步落盘支持中断续跑;④ 设定步数 / token / 时长上限,超限优雅停止并汇报;⑤ 高风险动作人工门禁。

Agent 的安全风险主要在哪里?

四大攻击面:多轮(通过渐进对话稀释拒绝机制)、多语言(低资源语言的安全对齐盲区)、多模态(图片/网页中嵌入指令做视觉注入)、Agent 工具通道(模型在对话中拒绝,但把有害逻辑写进代码或通过工具执行——即「文本拒绝、工具执行」的分离现象)。此外还有过度授权(excessive agency)——给了超出任务所需的权限,这是把坏提示变成真实事故的关键。防御要靠纵深:提示层、系统层(沙箱 + 最小权限)、流程层(审批)、监控层。

你会怎么评估一个 Agent 系统?

三个层次:① 端到端指标——任务成功率(需明确定义成功)、平均步数、平均成本、人工介入率;② 过程指标——工具调用成功率、参数错误率、步骤级正确性(有利于定位问题);③ 回归门禁——建一个覆盖典型与边界场景的黄金数据集,每次改动(Prompt / 工具 / 模型版本)都跑一遍,指标下降则阻止上线。另外必须有 tracing 能回放任意一次失败,否则优化就是盲猜。

学习资源

Model Context Protocol 官方文档文档 modelcontextprotocol.io/ MCP 规范与 SDK,包含 Server 与 Client 的完整示例。 MCP Servers 官方集合GitHub github.com/modelcontextprotocol/servers 文件系统、数据库、Git 等参考实现,可直接复用或改造。 LangGraph 官方文档文档 langchain-ai.github.io/langgraph/ 生产级有状态 Agent 编排:状态图、检查点、人工介入。 ReAct 论文论文 arxiv.org/abs/2210.03629 Agent 范式奠基论文,推理与行动交替的经典结构。 Reflexion 论文论文 arxiv.org/abs/2303.11366 自我反思机制:失败后生成语言反馈指导下次尝试。 OpenAI Deep Research 介绍文档 openai.com/index/introducing-deep-research/ 研究型 Agent 的设计思路:规划 + 多源检索 + 反思。 OWASP LLM Top 10文档 owasp.org/www-project-top-10-for-large-language-model-applications/ 提示注入位列头号风险,Agent 安全的必备清单。 Mem0(生产级记忆层)GitHub github.com/mem0ai/mem0 跨会话记忆的写入筛选、检索与遗忘实现。
★
2026 形势提示:招聘数据里最惊人的一组数字:Agentic AI 相关岗位从 151 个涨到 16,541 个(增长超过一万倍),「AI agents」与「multi-agent systems」同样成倍增长。但需求集中在能做生产化的人而不是会调框架的人。把本阶段的可观测、评估、审批、状态管理做扎实,你就站在了需求最旺的位置上。