位置:LLM 应用工程四层演进的第三层(介于上下文工程与驾驭工程之间) 调研日期:2026-05-01
Agent 不是一次更花哨的 LLM 调用,而是 “LLM + 工具 + 记忆 + 循环”四件套——给定目标后能自主规划、采取行动、观察结果、调整策略,直到任务完成或被显式停止。从工程角度看,agent 是垂直贯穿提示词、上下文、驾驭三层的抽象单元:它的 思考 由提示词工程提供模板(ReAct 等),它的 视野 由上下文工程提供(RAG、记忆、工具 schema),它的 运行环境 由驾驭工程构筑(沙箱、网关、护栏、observability)。
2026 年 Agent 已分化出三个清晰的赛道:
主流框架已从”百花齐放”收敛到几个主导:LangGraph(生产首选)/ CrewAI(最快上手)/ OpenAI Agents SDK(绑定 OpenAI 生态)/ Smolagents(极简)/ Mastra(TS 原生),AutoGen 已被 Microsoft 移入 maintenance,由 Microsoft Agent Framework 接班。
主流 benchmark(SWE-bench Verified / GAIA / WebArena / OSWorld)2026 年 4 月最新排名上 Anthropic 模型几乎垄断头部:Claude Opus 4.7 在 SWE-bench Verified 据称拿到 ~87% 区间(具体分数与实际榜单见 Anthropic 官方发布页 + swebench.com leaderboard,截至本文调研日期 2026-05-01;分数随版本和评估口径会变)。但 Berkeley RDI 也警告:一批主流 agent benchmark(包括 SWE-bench / WebArena / GAIA / Terminal-Bench 等)被证实可被 hack 出近完美分数而不真正完成任务——分数必须看具体的评估方法论。
最值得警惕的是失败模式与真实事故:90% 的生产 agent 死于 Loop of Death(无限循环),单次 Claude Code 子 agent 烧掉 27 M token 跑了 4.6 小时;Amazon Kiro AI 自主删除生产 AWS 环境造成 13 小时停机;Replit AI 在代码冻结期删生产数据库;Google AI 清缓存时清掉整盘。教训只有一条:没有 max iteration cap、没有 execution timeout、没有沙箱、没有 deny-first 权限模型,agent 在生产里就是炸弹。
要理解 agent 是什么,先排除三个常见混淆:
Anthropic 的工程博客给了一个被广泛引用的定义:“Agent 是 LLM 在循环里使用工具的模式”——其中”循环”和”自主”是两个核心特征。
一个最小的 agent 必须有四件东西:
| 要素 | 含义 | 失之则成 |
|---|---|---|
| Goal | 一个目标 | 无目标 = chatbot |
| Tools | 可调用的能力(API / 工具 / 计算 / 检索) | 无工具 = 纯生成 |
| Loop | 思考-行动-观察的循环 | 无循环 = 单次调用 |
| Memory | 跨循环的状态保留 | 无记忆 = 健忘 agent |
Agent 的”自主程度”是一个连续光谱,不是二元变量:
Human-in-the-Loop Human-on-the-Loop Fully Autonomous
───────────────── ───────────────── ─────────────────
每步行动都需用户确认 人在旁监督,关键步骤介入 完成才汇报
适合:高风险/医疗/金融 适合:中等风险/编码 适合:低风险/数据处理
e.g. 早期 Claude Code e.g. Cursor agent mode e.g. Devin / Manus
2026 年的产业共识是:业界不是在朝完全无监督的自主性走,而是在朝选择性自主性走。一个产品里的不同 action 应该有不同的自主级别——读文件可全自主,删文件必须 HITL。
| 年份 | 范式 | 论文 / 来源 | 核心 |
|---|---|---|---|
| 2022 | ReAct | Yao 等 | Thought → Action → Observation 交错的最简循环 |
| 2023 | Plan-and-Execute | LangChain | 先全规划再执行,避免 ReAct 的”短视” |
| 2023 | Reflexion | Shinn 等 | 失败后写”反思笔记”附到下次 prompt,让 agent 从经验学习 |
| 2023 | Tree-of-Thoughts as agent | Yao 等 | 把 ToT 推理扩展为 agent 级搜索 |
| 2024 | Constitutional Agent | Anthropic | 用宪法 / 原则约束 agent 行为 |
| 2024 | Multi-Agent System | AutoGen / CrewAI | 多 agent 角色分工与协商 |
| 2024-Q4 | Computer Use Agent | Anthropic | Agent 直接操作 GUI(截图 + 鼠键 tool) |
| 2025 | Agentic RAG | LangGraph | RAG 决策权下放给 agent,自主决定何时检索、是否重新检索 |
| 2026-Q2 | Background Computer Use | OpenAI Codex (2026-04) | Agent 在独立 desktop session 跑,并行多 agent,不打扰主工作流 |
ReAct 仍是几乎所有现代 agent 的”基础语法”。其他范式都是在 ReAct 基础上加规划、加反思、加搜索、加多 agent、加跨模态。
业界并没有”agent 架构标准 N 层模型”的统一共识——Lindy、Redis、arXiv 等多家拆法各不相同(有 5 层 perception-cognition-action、有 ReAct 单回路等)。下面这套 4 层是作者综合多家拆法的简化检查清单,不是 canonical taxonomy,仅作工程组件梳理用:
┌─────────────────────────────────────────────┐
│ Reasoning Layer(推理层) │
│ LLM 解读输入、规划行动序列、决定下一步 │
└────────────────────┬────────────────────────┘
│
┌────────────────────▼────────────────────────┐
│ Orchestration Layer(编排层) │
│ 控制流、任务序列、重试、错误处理、状态机 │
│ e.g. LangGraph state graph │
└────────────────────┬────────────────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌──────────────┐ ┌────────────────┐
│ Memory & Data│ │ Tool Integration│
│ 短期对话 │ │ API / Function │
│ 长期记忆 │ │ Calling / MCP │
│ RAG │ │ Sandbox 执行 │
└──────────────┘ └────────────────┘
┌─→ Goal ──→ Perception ──→ Reasoning ──→ Planning
│ │
│ ▼
│ Action
│ │
└─── Memory Update ←── Observation ←──────────┘
这个循环持续直到:(a)目标达成;(b)触发停止条件(max iterations、超时、用户中断);(c)agent 自己判断”我无法完成,需要人介入”。
详见 02 章(上下文工程)的 RAG 与记忆部分,以及 04 章(驾驭工程)的工具集成与编排部分。
Anthropic 2024 年 12 月发布的 Building Effective AI Agents 是 2025-2026 年 Agent 工程化最被引用的文章之一。它把”agent”系统拆成两类:
“Workflows are great when tasks are well-defined; agents shine when flexibility is required. Often the best solution starts with a workflow and only adds agentic dynamism where it’s truly needed.”
并提出 6 个 composable building blocks——这是构建任何 agentic system 的基础原语。
最原子的”agent”:LLM + 三种增强能力(retrieval / tools / memory)。所有上层 pattern 都在它之上叠加。
┌──────────┐
Input ───▶│ LLM │───▶ Output
│ + tools │
│ + memory │
│ + retrieval│
└──────────┘
把任务拆成多个连续步骤,每步 LLM 处理上一步输出。可在中间加 gate(程序判断是否继续)。
Input → LLM 1 → [Gate]? → LLM 2 → [Gate]? → LLM 3 → Output
典型场景:先生成大纲 → 校验大纲符合格式 → 按大纲生成正文 → 校验长度 → 翻译。
优点:每步可独立优化与测试、流程可追踪。 缺点:步骤多则延迟高;步骤间信息可能丢失。 何时用:任务能干净分解为线性步骤、每步有明确质量门。
一个 LLM 看输入决定走哪条专门处理路径,每条路径用不同的 prompt / tool / 模型优化。
┌─→ Specialist LLM A (用 prompt_A, tools_A)
Input → Router LLM┤
├─→ Specialist LLM B (用 prompt_B, tools_B)
└─→ Specialist LLM C (用 prompt_C, tools_C)
典型场景:客服分流(退款 → 退款专员 prompt;技术问题 → 技术 prompt;闲聊 → 通用 prompt);按问题难度路由(简单用便宜模型、复杂用 Opus)。
优点:把”什么 prompt 给什么问题”显式化,可针对性优化每条路径。 缺点:Router 错则下游全错。 何时用:明显分类的输入空间。
两个变体:
map-reduce
模式) ┌─→ LLM 1 ─┐
Input ───────┼─→ LLM 2 ─┼──▶ Aggregator LLM ──▶ Output
└─→ LLM 3 ─┘
典型场景: - Sectioning:长文摘要拆段并行总结、安全审查分维度并行检测(毒性 / PII / 偏见 / 注入) - Voting:代码审查多模型投票、内容审核多 prompt 投票降误报
优点:延迟低、可靠性高(voting 抵抗单次失败)。 缺点:成本是单次的 N 倍。 何时用:子任务真正独立、或需要冗余可靠性。
中央 LLM 动态决定子任务(不是预定义),分派给 worker LLM,最后综合结果。
┌─→ Worker 1 (动态决定的子任务)
Input → Orchestrator┤
LLM (动态规划)├─→ Worker 2
└─→ Worker 3
↓
Synthesizer LLM ──▶ Output
与 Parallelization 的关键差异:子任务无法预先定义。Orchestrator 看到具体输入后才决定要拆成哪些子任务。
典型场景: - 跨多个文件的代码改动(agent 看完 issue 才知道要改哪几个文件) - 复杂研究任务(先决定要查哪几个角度才能回答)
优点:处理预先未知的复杂任务。 缺点:成本和延迟高、调试更难。 何时用:标准 workflow 解决不了,输入复杂度高。
一个 LLM 生成响应,另一个 LLM 评估并给反馈,前者根据反馈修改,循环直到通过或达到上限。
Input
│
▼
┌─→ Generator LLM ──▶ Response
│ │ │
│ │ ▼
│ │ Evaluator LLM (judge)
│ │ │
│ │ PASS ──→ Output
│ │ FAIL ──→ Feedback
└─────────┴────────────────┘
典型场景: - 文学翻译(generator 翻译,evaluator 检查信达雅,反馈”too literal”等) - 复杂搜索(generator 写答案,evaluator 检查覆盖度,反馈”还缺 X 角度”) - 代码生成(generator 写代码,evaluator 跑测试,反馈失败用例)
优点:质量上限高(接近人工 review 的迭代质量)。 缺点:迭代次数不可控、可能死循环、成本高。 何时用:有清晰的评估标准、初稿质量明显低于迭代后质量。
前面 5 种是 workflow(流程预定义)。Agents 是真正的”自主”——LLM 在循环里自己决定下一步做什么、用什么工具、何时停。
Input + Goal
│
▼
┌─→ LLM (think + act)
│ │
│ ▼
│ Tool / Action
│ │
│ ▼
│ Environment / Feedback
│ │
│ ▼
└─── Update Context
(until done or stopped)
何时升级到真正的 agent:
何时不该用 agent(continue using workflow):
你的任务是?
│
├─ 单步即可解决 → 用 Augmented LLM
│
├─ 多步固定流程
│ ├─ 线性顺序 → Prompt Chaining
│ ├─ 按类型分流 → Routing
│ └─ 子任务独立 + 并行/冗余 → Parallelization
│
├─ 子任务无法预定义 → Orchestrator-Workers
│
├─ 需要质量迭代 + 评估清晰 → Evaluator-Optimizer
│
└─ 流程完全无法预定义 + 需要自主性 → Agent
Anthropic 的核心建议:先尽量用 workflow(pattern 1-5),只在真的需要时再升级到 agent。生产 95% 的”agentic 系统”其实用 workflow 就够,盲目用 agent 会引入难调试 / 不可预测 / 成本失控等问题(详见 §9 失败模式)。
| 类型 | 代表 | 特征 |
|---|---|---|
| Conversational Agent | ChatGPT / Claude.ai 加工具 | 对话为主,agent 能力是补充 |
| Task Agent | Zapier AI Actions / Make AI | 触发后跑一段流程就结束 |
| Coding Agent | Claude Code / Cursor / Devin | 长跑、改文件、跑测试、提 PR |
| Browser Agent | Multi-On / Browser Use / Skyvern | 在网页上点击 / 填表 / 抓取 |
| Computer Use Agent | Anthropic Computer Use / OpenAI Operator | 跨应用操作鼠标键盘、读屏 |
| Background Agent | OpenAI Codex Background Computer Use(2026-04) | 在独立 session 跑,并行多 agent |
| Multi-Agent System | CrewAI / AutoGen 应用 | 多个 agent 协作完成任务 |
Browser agent 是 2025-2026 年第三大 agent 赛道(仅次于 coding 与 computer use)。WebArena / WebVoyager 等基准把这个赛道推到 SOTA。
| 框架 | 语言 | 范式 | 强项 | ⭐ / 状态 |
|---|---|---|---|---|
| Browser Use | Python | 全 AI 自主(agent loop) | 91k ⭐,WebVoyager 89.1% 成功率 | 现 SOTA |
| Stagehand(Browserbase) | TypeScript | AI primitives 加 Playwright | 4 个原语:act/extract/observe/agent,可读且可控 | 强势上升 |
| Playwright | 多语言 | 确定性自动化 | 不带 AI,纯脚本,兜底用 | 测试基础 |
| Skyvern | Python | LLM + 计算机视觉 | 视觉理解未见过的网页 | 创业产品 |
| Browserbase(SaaS) | API | 云端隐身浏览器 | 反反爬最强 | 商业化最成熟 |
from browser_use import Agent
from langchain_anthropic import ChatAnthropic
agent = Agent(
task="在 Hacker News 上找今天 #1 的帖子,把标题和评论数告诉我",
llm=ChatAnthropic(model="claude-sonnet-4-6"),
)
result = await agent.run()
print(result)
# Browser Use 自动开 chromium、截图、决定点哪、抓 HTML、做循环直到任务完成import { Stagehand } from "@browserbasehq/stagehand";
const stagehand = new Stagehand({ env: "LOCAL" });
await stagehand.page.goto("https://news.ycombinator.com");
// AI primitive: act(自然语言操作)
await stagehand.page.act("点击第一个帖子");
// AI primitive: extract(结构化抽数据)
const data = await stagehand.page.extract({
instruction: "提取帖子标题和评论数",
schema: z.object({ title: z.string(), comments: z.number() }),
});
// AI primitive: observe(让 AI 描述当前页面)
const observation = await stagehand.page.observe();
// AI primitive: agent(多步任务,自主完成)
await stagehand.page.agent({
task: "找到登录按钮,用 user@x.com 登录",
});Stagehand 的设计哲学:AI 写 selector,人写控制流。把脆弱的 CSS selector 替换为自然语言 act,但保留 Playwright 的确定性流程控制。业界共识:Stagehand 这个混合架构会是模板。
你的任务是?
│
├─ 完全未知网站、AI 决定流程 → Browser Use(自主性最强)
├─ 流程基本已知、要稳定 → Stagehand(AI 局部 + 流程可控)
├─ 流程完全确定 → Playwright(不要用 AI)
├─ 视觉为主、HTML 不可靠 → Skyvern
└─ 需要反反爬云服务 → Browserbase(SaaS)+ Stagehand
2024 下半年 OpenAI Realtime API 开启实时语音 agent 时代。2026 年主流:
| 方案 | 模式 | 延迟 | 适合 |
|---|---|---|---|
| OpenAI Realtime API(GPT-4o / GPT-5) | 双向 audio streaming(WebSocket) | < 500ms | 客服 / 个人助理 |
| Anthropic Voice(Claude) | 文本 + TTS(异步) | 2-5s | 内容生成场景 |
| Gemini Live API | 双向多模态(含 video) | < 1s | 视频会议助理 |
| Pipecat / LiveKit Agents | 开源框架,编排 STT + LLM + TTS | 1-3s | 自托管、灵活 |
| Vapi / Retell | SaaS,托管语音 agent 全栈 | < 1s | 创业 MVP |
import asyncio, websockets, json, base64
async def voice_agent():
async with websockets.connect(
"wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2026",
extra_headers={"Authorization": f"Bearer {API_KEY}"},
) as ws:
# 配置 session(音色、tools、instructions)
await ws.send(json.dumps({
"type": "session.update",
"session": {
"voice": "alloy",
"instructions": "你是 ACME 客服。简短礼貌。",
"tools": [...], # 普通 function calling
"input_audio_transcription": {"model": "whisper-1"},
"turn_detection": {"type": "server_vad"}, # 服务器侧 VAD
},
}))
# 用户麦克风音频流(PCM16)持续 push 进去
async def push_mic():
while audio_chunk := mic.read():
await ws.send(json.dumps({
"type": "input_audio_buffer.append",
"audio": base64.b64encode(audio_chunk).decode(),
}))
# 模型音频回流,喂给扬声器
async def play_audio():
async for msg in ws:
event = json.loads(msg)
if event["type"] == "response.audio.delta":
speaker.play(base64.b64decode(event["delta"]))
await asyncio.gather(push_mic(), play_audio())经过 2024-2025 两年的 Cambrian 大爆发,2026 年 Agent 框架格局已经有清晰主导:
| 框架 | 范式 | 模型支持 | 学习曲线 | 生产度 | 适合场景 |
|---|---|---|---|---|---|
| LangGraph | 显式状态机 / 图 | 任意 | 中 | 最高(LangSmith 集成、checkpoint、time-travel debug、HITL) | 复杂生产 agent、可解释流程 |
| CrewAI | 角色 + 任务 DSL | 任意 | 最低(20 行起步) | 中 | 快速业务原型、多 agent 角色协作 |
| AutoGen | 多 agent 对话协商 | 任意 | 中 | 已 maintenance(Microsoft 转向 Microsoft Agent Framework) | 历史项目维护 |
| OpenAI Agents SDK | imperative handoff 链 | 仅 OpenAI | 极低(最小心智模型 + 一等 tracing) | 中 | OpenAI 生态优先 |
| Anthropic Agent Skills | skills 包(2026 推出) | 仅 Claude | 低 | 中 | Claude 生态、可复用能力 |
| Smolagents | 极简(几百行核心) | 任意 | 低 | 低(教学/研究为主) | 学习、HuggingFace 生态 |
| Mastra | TypeScript 原生 | 任意 | 低 | 中(快速增长) | JS/TS 项目、Vercel/Next.js |
| Pydantic AI | 强类型 Python | 任意 | 中 | 中 | 类型安全敏感的 Python 项目 |
| Google ADK | / | Gemini 优先 | 中 | 中 | Gemini / Vertex AI 生态 |
| LlamaIndex Agent | RAG-first | 任意 | 中 | 中 | RAG 重场景 |
LangGraph vs CrewAI vs OpenAI Agents SDK 是 2026 年讨论最多的三角对比:
同一个任务:「一个能用 web search 工具回答问题的 ReAct agent」,看三家代码哲学的差异。
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
from langchain_community.tools.tavily_search import TavilySearchResults
llm = ChatAnthropic(model="claude-sonnet-4-6")
tools = [TavilySearchResults(max_results=3)]
# 一行创建预制 ReAct agent
agent = create_react_agent(llm, tools)
# 调用(自带 streaming + checkpoint)
for chunk in agent.stream({"messages": [("user", "2026 年 SWE-bench 头部模型是?")]}):
print(chunk)
# 自定义复杂图
class State(TypedDict):
messages: list
iterations: int
def should_continue(state):
if state["iterations"] >= 10: return END # max iter cap
return "agent"
graph = StateGraph(State)
graph.add_node("agent", agent)
graph.add_conditional_edges("agent", should_continue)
graph.set_entry_point("agent")
app = graph.compile(checkpointer=MemorySaver()) # checkpoint = HITL & resume 一等公民特点:图形定义、状态显式、checkpoint 内置、time-travel debug。
from crewai import Agent, Task, Crew
from crewai_tools import SerperDevTool
researcher = Agent(
role="2026 AI 趋势分析师",
goal="找到关于 SWE-bench 头部模型的可靠信息",
backstory="你是科技新闻深度分析专家",
tools=[SerperDevTool()],
verbose=True,
)
writer = Agent(
role="技术博主",
goal="把分析结果写成简洁清晰的总结",
backstory="你擅长把技术细节翻译成易读文字",
verbose=True,
)
task1 = Task(description="调查 2026 年 SWE-bench 头部模型", agent=researcher)
task2 = Task(description="把调查写成 200 字总结", agent=writer)
crew = Crew(agents=[researcher, writer], tasks=[task1, task2])
result = crew.kickoff()特点:角色 + 任务 + crew 三层 DSL,20 行起步、最快上手。
from agents import Agent, Runner, function_tool
@function_tool
def web_search(query: str) -> str:
"""搜索网页"""
# ... 实现略
return search_results
researcher = Agent(
name="researcher",
instructions="你是研究员,用 web_search 找资料",
tools=[web_search],
)
writer = Agent(
name="writer",
instructions="把研究结果写成 200 字总结",
handoffs=[researcher], # writer 可以把任务 handoff 回 researcher 继续查
)
result = Runner.run_sync(writer, "2026 年 SWE-bench 头部模型是?")
print(result.final_output)特点:handoff 是 SDK 的核心抽象、tracing 一等公民、最小心智模型。
| 维度 | LangGraph | CrewAI | OpenAI Agents SDK |
|---|---|---|---|
| 抽象 | State + Graph | Role + Task + Crew | Agent + Tools + Handoff |
| 心智模型 | 状态机程序员 | 团队管理者 | 函数调用 |
| 控制流可见性 | 极高(图) | 中(任务流) | 低(imperative) |
| 调试工具 | LangSmith time-travel | 默认日志 | OpenAI tracing |
| 扩展能力 | 极强(自定义节点) | 中(自定义 task) | 中(自定义 tool) |
| 模型支持 | 任意 | 任意 | 仅 OpenAI |
| Day-1 上手 | 需要理解图 | 30 分钟 | 5 分钟 |
| 生产部署 | 最强 | 中 | 中 |
Anthropic 在 2026 年推出 Agent Skills——把”agent 知道如何完成某类任务”的程序化知识打包成可复用 unit。这是 Anthropic 继 MCP 之后的第二个开放标准尝试。
| 抽象 | 解决什么 | 形态 | 类比 |
|---|---|---|---|
| Tools(function calling) | 一次原子操作 | 函数签名 + JSON schema | 一条 shell 命令 |
| MCP | 把外部工具 / 数据连接到 LLM | server 暴露 tools / resources / prompts | OS 设备驱动 |
| Agent Skills | 完成一类任务的 完整程序 | 文件夹(指令 + 模板 + 脚本 + 检查项) | shell 脚本 / playbook |
关键洞察:MCP 给 agent 接工具,Skills 教 agent 怎么用 这些工具完成具体任务。Anthropic 的话:“MCP 是 plumbing,Skills 是 procedural knowledge”。
一个 skill 是一个文件夹:
my-skill/
├── SKILL.md # 入口:何时用、做什么、怎么做
├── templates/ # 输出模板
│ └── report.md
├── scripts/ # 可执行辅助脚本
│ └── analyze.py
├── examples/ # 示范 input/output
│ └── case1.md
└── resources/ # 静态资源
└── compliance.json
SKILL.md 是给 LLM 读的 manual:
# Skill: PR Review
## When to use
当用户请求"review my PR" / "code review" 时
## What it does
检查 diff 的:
- 安全问题(SQL injection / XSS / hardcoded secret)
- 测试覆盖
- 文档同步
## How to do
1. 用 `gh pr diff` 读 diff
2. 跑 `scripts/scan_security.py` 找 secret
3. 检查每个改动的函数是否有对应 test
4. 用 `templates/review.md` 输出
## Definition of done
- 输出包含 3 个 section(必读)
- 每个发现都引用 file:line
- 严重度按 critical / major / minor 分类LLM 在执行任务时自主读取 SKILL.md,按里面的步骤执行。
Claude Code 原生支持 skills 目录。在项目根目录建
.claude/skills/:
my-project/
├── .claude/
│ └── skills/
│ ├── pr-review/SKILL.md
│ ├── deploy/SKILL.md
│ └── investigate-bug/SKILL.md
Claude Code 启动时扫描,用户说”review the pr”时自动匹配
pr-review skill 执行。
Skills 是 reusable agentic capability 的标准化单元——团队可以共享、组织可以治理、社区可以发布。Anthropic 把 spec 开源,类似 MCP 的策略:先做生态再统一标准。
参考 skillmatic-ai/awesome-agent-skills
找社区 skill。
基础 LangGraph 的状态机已经在 §5.3 讲过。下面是生产 agent 真正用到的 5 个高级特性:
LangGraph 内置 checkpointer,每个 node 执行后自动保存 state:
from langgraph.checkpoint.postgres import PostgresSaver
# 生产用 Postgres checkpointer(持久化跨进程)
checkpointer = PostgresSaver.from_conn_string("postgresql://...")
checkpointer.setup()
app = graph.compile(checkpointer=checkpointer)
# 每次调用带 thread_id
config = {"configurable": {"thread_id": "session_42"}}
result = app.invoke({"messages": [...]}, config=config)
# 服务器重启后用同一 thread_id 继续,状态自动恢复
result = app.invoke({"messages": [new_message]}, config=config)时间穿越:可以回退到任意历史 checkpoint,从那里 fork 出新分支:
# 列出当前 thread 的所有历史 checkpoint
history = list(app.get_state_history(config))
# 选某个历史点
old_state = history[3]
# 从那里继续(fork 一条新分支)
result = app.invoke(None, config=old_state.config)用途:debug 时回到出错前一步、A/B 试两种工具调用结果、用户撤销操作。
from langgraph.types import interrupt, Command
def risky_action(state):
# 高风险操作前暂停等用户
user_response = interrupt({
"question": f"即将执行: DELETE FROM users WHERE id={state['user_id']}",
"type": "approval_required",
})
if user_response.get("approved"):
# 执行
db.execute(...)
return {"status": "executed"}
return {"status": "cancelled"}
# 调用时碰到 interrupt 会停下,等用户响应
result = app.invoke({"user_id": 123}, config)
# result 里有 __interrupt__ 字段表示卡在某 node
# 用户在 UI 点 approve / reject
app.invoke(Command(resume={"approved": True}), config) # 继续复杂 agent 拆成子图,每个团队独立开发 / 测试 / 部署:
# Research team 是个子图
def build_research_team():
g = StateGraph(ResearchState)
g.add_node("planner", planner)
g.add_node("searcher", searcher)
g.add_node("synthesizer", synthesizer)
# ... edges
return g.compile()
# Engineering team 同理
def build_eng_team():
...
# 顶层把两个团队当 node 嵌入
top = StateGraph(GlobalState)
top.add_node("research", build_research_team()) # ★ 子图作为 node
top.add_node("eng", build_eng_team())
top.add_node("manager", top_manager)
top.set_entry_point("manager")
# ... edges 串起来async for event in app.astream_events({"messages": [...]}, config, version="v2"):
if event["event"] == "on_chat_model_stream":
# LLM 流式输出 token
chunk = event["data"]["chunk"].content
yield chunk
elif event["event"] == "on_tool_start":
yield f"[正在调用 {event['name']}...]\n"
elif event["event"] == "on_tool_end":
yield f"[完成 {event['name']}]\n"前端用 SSE / WebSocket 实时渲染,用户体验提升 10×。
LangSmith 自动记录每个 checkpoint,dashboard 里点任意 step 可以:
这是 LangGraph 比 CrewAI / AutoGen 在生产成熟度上拉开差距的核心原因。
把多个 agent 拼在一起的 4 + 1 种主流模式:
┌───────────────┐
│ Supervisor │
└───┬───┬───┬───┘
│ │ │
┌───────▼┐ ┌▼─┐ ┌▼──────┐
│ Agent A│ │B │ │ Agent C│
└────────┘ └──┘ └────────┘
中央监督 agent 接收目标 → 拆子任务 → 路由给专家 worker agent → 综合结果。易推理、易追踪、控制流清晰——一个 routing node、所有决策可见。主流生产架构。
Agent A → Agent B → Agent C → Output
agent 顺序执行,前一个的输出是后一个的输入。本质和传统 ETL workflow 类似,“agent” 这一抽象在这个模式下有点冗余,但好处是与传统系统集成顺。
Agent A ←──→ Agent B
↓ ↘ ↗ ↑
↑ ╲╱ ↓
Agent C ←──→ Agent D
去中心化,agent 之间直接 handoff。没有中介、调用更少、更快——但调试困难、易陷入互踢皮球的循环。LangGraph 把 supervisor 与 swarm 都做成一等公民,让用户按场景选。
Top Manager
├── Mid Supervisor 1
│ ├── Worker A
│ └── Worker B
└── Mid Supervisor 2
├── Worker C
└── Worker D
树状多层委托:顶层负责战略、中层负责战术、叶层执行。带共享状态管理时冲突显著减少(具体减少幅度因团队/任务差异大;80% 这类精确数字在公开来源里无可信依据),适合复杂业务但延迟高。
实战中往往是混合:层级结构里的某一层用 swarm 做并行探索,另一层用 supervisor 做收敛。例如 Devin 内部就是 hierarchical(planner → coder → reviewer 三层)+ 局部 swarm(reviewer 派生多个 critic)。
下面五段代码每段独立可跑(需要
pip install langgraph langchain-anthropic),覆盖五种协作模式。
from langgraph.graph import StateGraph, END
from typing import TypedDict, Literal
from langchain_anthropic import ChatAnthropic
class State(TypedDict):
task: str
next_worker: str
results: dict
llm = ChatAnthropic(model="claude-sonnet-4-6")
def supervisor(state: State):
"""中央 supervisor 决定派给哪个 worker"""
decision = llm.invoke(f"""任务:{state["task"]}
路由到下面哪个专家?只回答名字:
- researcher(找资料)
- writer(写文章)
- coder(写代码)
- DONE(已完成)""")
return {"next_worker": decision.content.strip()}
def researcher(state: State):
result = llm.invoke(f"找资料:{state['task']}")
return {"results": {**state["results"], "research": result.content}}
def writer(state: State):
result = llm.invoke(f"写文章基于:{state['results']}")
return {"results": {**state["results"], "draft": result.content}}
def coder(state: State):
result = llm.invoke(f"写代码:{state['task']}")
return {"results": {**state["results"], "code": result.content}}
def route(state: State) -> Literal["researcher", "writer", "coder", END]:
return END if state["next_worker"] == "DONE" else state["next_worker"]
g = StateGraph(State)
g.add_node("supervisor", supervisor)
g.add_node("researcher", researcher)
g.add_node("writer", writer)
g.add_node("coder", coder)
g.set_entry_point("supervisor")
g.add_conditional_edges("supervisor", route)
for w in ["researcher", "writer", "coder"]:
g.add_edge(w, "supervisor") # worker 完成后回 supervisor
app = g.compile()
result = app.invoke({"task": "调查 2026 RAG 现状并写一段总结", "results": {}})class PipelineState(TypedDict):
raw_data: str
cleaned: str
analyzed: str
summary: str
def clean(state):
return {"cleaned": llm.invoke(f"清洗:{state['raw_data']}").content}
def analyze(state):
return {"analyzed": llm.invoke(f"分析:{state['cleaned']}").content}
def summarize(state):
return {"summary": llm.invoke(f"摘要:{state['analyzed']}").content}
g = StateGraph(PipelineState)
g.add_node("clean", clean)
g.add_node("analyze", analyze)
g.add_node("summarize", summarize)
g.set_entry_point("clean")
g.add_edge("clean", "analyze")
g.add_edge("analyze", "summarize")
g.add_edge("summarize", END)
app = g.compile()from langgraph.graph import MessagesState
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import tool
@tool
def transfer_to_researcher():
"""需要查资料时调用"""
return "Transferring to researcher"
@tool
def transfer_to_writer():
"""需要润色时调用"""
return "Transferring to writer"
researcher = create_react_agent(llm, tools=[search_tool, transfer_to_writer])
writer = create_react_agent(llm, tools=[transfer_to_researcher])
def router(state: MessagesState) -> Literal["researcher", "writer", END]:
last = state["messages"][-1]
if hasattr(last, "tool_calls") and last.tool_calls:
name = last.tool_calls[0]["name"]
if "researcher" in name: return "researcher"
if "writer" in name: return "writer"
return END
g = StateGraph(MessagesState)
g.add_node("researcher", researcher)
g.add_node("writer", writer)
g.set_entry_point("researcher")
g.add_conditional_edges("researcher", router)
g.add_conditional_edges("writer", router)
app = g.compile()每个 agent 自己决定 handoff 到谁,无中央 supervisor。
# 顶层 manager
def top_manager(state):
decision = llm.invoke(f"任务:{state['task']}\n路由:team_research / team_eng / DONE")
return {"next_team": decision.content.strip()}
# 中层 team supervisor
def research_team_supervisor(state):
sub = llm.invoke("派给 worker:searcher / analyst / DONE")
return {"next_research_worker": sub.content.strip()}
def eng_team_supervisor(state):
sub = llm.invoke("派给 worker:coder / reviewer / DONE")
return {"next_eng_worker": sub.content.strip()}
# 底层 worker(略)
# 编排:顶层 → 中层 supervisor → 底层 worker → 中层 supervisor → 顶层
g = StateGraph(...)
g.add_node("top", top_manager)
g.add_node("research_team", build_research_subgraph()) # 子图嵌入
g.add_node("eng_team", build_eng_subgraph())
g.set_entry_point("top")
g.add_conditional_edges("top", route_top)
# 子图返回 → 顶层
g.add_edge("research_team", "top")
g.add_edge("eng_team", "top")LangGraph 的子图(subgraph)特性让每层可独立测试 +
独立部署。
# 顶层 hierarchical → 中层用 supervisor → 个别节点用 swarm 做并行探索
g = StateGraph(...)
# 顶层 hierarchical
g.add_node("strategist", strategist)
g.add_node("execution_layer", execution_supervisor_subgraph)
# 中层 supervisor
def execution_supervisor_subgraph():
sub = StateGraph(...)
sub.add_node("supervisor", supervisor)
sub.add_node("planner", planner)
sub.add_node("explorer_swarm", swarm_subgraph) # 嵌入 swarm
sub.add_node("validator", validator)
return sub.compile()
# 底层 swarm 做并行假设探索
def swarm_subgraph():
sub = StateGraph(...)
for agent_id in ["explorer_a", "explorer_b", "explorer_c"]:
sub.add_node(agent_id, build_explorer(agent_id))
sub.add_node("synthesizer", synthesizer)
# 三个 explorer 并行,结果汇到 synthesizer
return sub.compile()实战 Devin / Manus / Claude Code 的 sub-agent 系统都接近这个 hybrid 拓扑:顶层做战略、中层做战术 supervisor、底层做并行探索。
| Benchmark | 评估目标 | 任务规模 | 评分方式 | 2026-04 排名头部 |
|---|---|---|---|---|
| SWE-bench Verified | 真实 GitHub issue 修复 | 500 个人工验证的 Python 项目 issue | 程序化(运行测试) | Claude Opus 4.7 ~ 87%(按 Anthropic 公告口径,最新见 swebench.com leaderboard) |
| GAIA(Princeton HAL) | 通用助手多步推理 | 466 题,三档难度 | 程序化 + LLM judge | Claude Sonnet 4.5 = 74.6%;Anthropic 横扫前 6 |
| TAU-bench | 工具使用 + 真实用户对话 | 多领域 | 多轮交互模拟 | — |
| AgentBench | 8 类环境(OS / DB / KG / 卡牌 / 横向思维 / 家务 / 网购 / 网页) | 跨环境 | 各环境独立 | — |
| WebArena(CMU) | 网页导航 agent | 812 个任务 / 5 个网站 + map | 程序化 | — |
| OSWorld | 跨 OS 跨应用真实操作 | 369 任务 / Ubuntu + Win + macOS | 执行验证 | — |
SWE-bench Verified 是 2026 年最被信任的 coding agent 信号——500 个人工验证的真实 GitHub Python 项目 issue,agent 必须读懂代码、修改文件、跑通测试。
Claude Opus 4.7 据称是 SWE-bench Verified 当前榜首之一(具体最新分数见 swebench.com)。OpenAI o3 / Codex 系列、Google Gemini Code 紧随其后。开源模型最强目前在 60%+ 区间。
Berkeley RDI 在 How We Broke Top AI Agent Benchmarks 系统审计了 8 个主流 benchmark(SWE-bench、WebArena、OSWorld、GAIA、Terminal-Bench、FieldWorkArena、CAR-bench 等),结论是每一个都可被 exploit 拿到接近满分而不真正完成任务。常见 hack 路径:
实战教训: 1. 看分数前先看评估方法论 2. 绝不在自家业务上信公开 benchmark 排名——必须在自己业务的 ground truth 上重测 3. 多 benchmark 综合比单 benchmark 排名靠谱
如果你想自己跑 SWE-bench Verified(不仅看 leaderboard 数字),完整流程:
阶段 A: 安装 + 准备
pip install swebench
docker pull princeton-nlp/swebench-eval:latest
阶段 B: 跑你的 agent,把结果生成为 predictions JSON
你的 agent → 输入:每个 task 的 problem_statement
→ 输出:patch 文件(diff 格式)
→ 保存为 predictions.jsonl
阶段 C: 用 SWE-bench harness 评估
python -m swebench.harness.run_evaluation \
--dataset_name princeton-nlp/SWE-bench_Lite \
--predictions_path ./predictions.jsonl \
--max_workers 8 \
--run_id my_agent_v1
{"instance_id": "django__django-11099", "model_name_or_path": "my_agent_v1",
"model_patch": "diff --git a/django/...\n--- a/django/...\n+++ b/django/...\n@@ -100,3 +100,5 @@\n+ # fix: ...\n"}
{"instance_id": "django__django-11133", "model_name_or_path": "my_agent_v1",
"model_patch": "..."}
每行一个 task,model_patch 是 unified diff。Harness
会自动 apply diff → 跑测试 → 比对预期。
import json
from datasets import load_dataset
def run_my_agent_on_swe_bench():
dataset = load_dataset("princeton-nlp/SWE-bench_Lite", split="test")
predictions = []
for task in dataset:
# 准备 agent 上下文
context = {
"repo": task["repo"], # e.g., "django/django"
"base_commit": task["base_commit"],
"problem_statement": task["problem_statement"],
"hints_text": task["hints_text"], # ★ 注意:避免泄露 ground truth
}
# 跑你的 agent(带 max_iterations / cost_cap 等护栏)
try:
patch = my_agent.solve(context, max_iter=30, max_cost_usd=2.0)
except Exception as e:
patch = "" # 失败也要交白卷
predictions.append({
"instance_id": task["instance_id"],
"model_name_or_path": "my_agent_v1",
"model_patch": patch,
})
with open("predictions.jsonl", "w") as f:
for p in predictions:
f.write(json.dumps(p) + "\n")
if __name__ == "__main__":
run_my_agent_on_swe_bench()SWE-bench 团队出品的 mini-swe-agent
是一个最小 bash-tool-only agent harness,~500 行 Python,用来做
baseline 对比:
pip install mini-swe-agent
mini-swe-agent run --model claude-sonnet-4-6 --dataset princeton-nlp/SWE-bench_Lite如果你的 agent 在 SWE-bench Lite 上跑不过 mini-swe-agent baseline,先怀疑 harness 实现问题再怀疑模型。
| 变体 | 任务数 | 预估跑完成本(Claude Sonnet 4.6) | 用途 |
|---|---|---|---|
| SWE-bench Lite | 300 | ~$30, ~4 小时 | 快速迭代 / day-to-day |
| SWE-bench Verified | 500 | ~$60, ~8 小时 | 论文 / leaderboard 提交 |
| SWE-bench full | 2 294 | ~$300, ~36 小时 | 极少用 |
实战:day-to-day 用 Lite,正式发版前跑 Verified。
公开 benchmark 不一定贴合你业务。真正可信的 eval 是自家业务的 ground truth。最小可行流程:
收集 100 个真实业务场景:
按下面 schema 存:
[
{
"id": "case_001",
"category": "refund_query",
"difficulty": "easy",
"input": {"messages": [{"role": "user", "content": "我要退订单 #12345"}]},
"expected_behavior": [
"调用 lookup_order(12345)",
"调用 process_refund(...)",
"回复用户告知预计 3-5 工作日",
],
"forbidden_behavior": [
"不能在没有 lookup 的情况下直接 refund",
"不能透露其他用户订单信息",
],
"ground_truth_answer": "您的订单 #12345 退款已发起...",
},
...
]def evaluate_agent(agent_fn, golden_set):
results = []
for case in golden_set:
# 跑 agent 收集 trace
with TraceCapture() as trace:
answer = agent_fn(case["input"])
# 三层评估
scores = {
# 层 1:tool call 顺序对不对
"tool_correctness": check_tool_calls(trace, case["expected_behavior"]),
# 层 2:是否触发禁止行为
"safety": not any(matches(trace, fb) for fb in case["forbidden_behavior"]),
# 层 3:答案质量(LLM-as-judge)
"answer_quality": llm_judge(case["input"], answer, case["ground_truth_answer"]),
}
results.append({"case_id": case["id"], **scores})
return results# .github/workflows/eval.yml
name: Agent Eval Gate
on: pull_request
jobs:
eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -e .
- run: python -m my_agent.eval --golden-set ./eval/golden.jsonl --output report.json
- run: |
python -c "
import json
r = json.load(open('report.json'))
tc = sum(x['tool_correctness'] for x in r) / len(r)
sf = sum(x['safety'] for x in r) / len(r)
aq = sum(x['answer_quality'] for x in r) / len(r)
print(f'tool_correctness={tc:.2f}, safety={sf:.2f}, answer_quality={aq:.2f}')
assert tc >= 0.85, 'tool_correctness regression'
assert sf >= 0.99, 'safety regression'
assert aq >= 0.75, 'quality regression'
"每个 PR 都跑一遍 → 任一指标回退就 block merge。
公开 leaderboard 数字只是 surface。生产 agent 评估真正应该看的:
如果你 2026 年在写代码,你几乎一定在用以下三者之一:Claude Code、GitHub Copilot、Cursor。最常见的双工具栈是 Cursor 日常编辑 + Claude Code 复杂任务,或 Copilot 在 IDE + Claude Code 在终端。
Claude Code(Anthropic)—— 2026 年最具代表性的 CLI
agent - 终端原生,跑在用户已有环境里 - CLAUDE.md
文件存项目级指令、约定、架构笔记,跨 session 持久(一种长期记忆) -
三层权限:deny > ask > allow,未识别 action 自动升级到用户 - 支持
sub-agents、background tasks、hooks、MCP servers、custom skills、slash
commands - 适合 async 工作流和 Slack 集成 - “最强的自主 coding
agent,对长任务尤其强”
Cursor - VS Code fork,AI 整合到每个工作流而非作为扩展 - Composer / Tab / Chat 三模式 - Agent mode 支持长时间自主任务
GitHub Copilot Workspace - 2026 capability:Copilot Chat 加 agent mode、多模型选择器、深度 GitHub 集成(issue / PR / CI/CD)
Devin(Cognition) - 完全自主 SE,跑在自己的云环境里(独立浏览器 / 终端 / 编辑器) - 异步:你提需求,它跑几小时,回来汇报 PR - 商业化最早的”AI 软件工程师”产品,一度争议大但 2025-2026 持续迭代
Manus - 中国团队 2025 推出的云端通用 agent 平台 - 类似 Devin 但范围更广,覆盖编码、研究、文档生成等
Anthropic Claude Computer Use - 2024-Q4 首发(Claude 3.5 Sonnet 上) - 2026-03 macOS desktop 进入研究预览,Win 支持预计 2026-Q3 - 架构:暴露 portable 的”截图 + 鼠键”工具,跨 VM / 容器 / 远程桌面,不绑 OS - 安全层:用户 halt 命令 + prompt-injection 扫描 + 安全漏洞检测 + Constitutional AI 对齐
OpenAI Codex Background Computer Use - 2026-04-16 发布,“Codex for almost everything”的一部分 - macOS-first、并行 agent session - agent 在独立 desktop session 跑,与工程师主工作流隔离
Operator(OpenAI 早期 Computer Use 产品) - 2025 年初推出,Chrome 扩展形态,专注网页操作 - 已被 Codex Background Computer Use 一定程度上替代
无论 Anthropic Computer Use / Operator / OpenAI CUA / Manus,都是一套感知 - 决策 - 动作循环:
┌─────────────────────────────────────────────────────────┐
│ ① 截图(screenshot tool) │
│ resolution: 1280x800(Anthropic 推荐) │
│ 格式: PNG → base64 → vision LLM input │
└─────────────────────────────┬───────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ ② VLM 推理(Vision LLM) │
│ - 解析当前界面(按钮 / 输入框 / 文本 / 图标) │
│ - 决定下一步动作("点击右上角的『下一步』按钮") │
│ - 输出结构化 action:{type, x, y, text, key} │
└─────────────────────────────┬───────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ ③ 执行(在 sandbox VM / 远程桌面 / Chrome extension) │
│ - mouse_move(x, y) / click / drag │
│ - type_text("...") / key_press("ctrl+c") │
│ - 100-500ms 后截下一张图 │
└─────────────────────────────┬───────────────────────────┘
│ 循环
└──────────────────────────▶
关键工程难点:
| 难点 | 现象 | 业界解法 |
|---|---|---|
| 像素坐标定位不准 | LLM 说”点 (450, 320)”实际目标在 (445, 318),差 5px 但点错按钮 | Anthropic:训练时强化 grounding loss;运行时给定容差 + 二次截图验证 |
| 动态 / 异步 UI | 点完按钮页面正在加载,下一张截图是中间态 | 引入 wait_for_idle + DOM/可访问性树辅助(不只看像素) |
| CAPTCHA / 反爬 | 几乎所有 captcha 都阻断 agent | 业界放弃,要么 HITL 让用户解,要么换 API 路径 |
| 多窗口 / 焦点漂移 | 弹出通知、切换 app 后 agent 失去 context | 截全屏 + 维护 window_id;OpenAI Operator 用专用浏览器隔离 |
| PII 与隐私泄露 | 截图把屏幕上的密码、邮件、消息全发给 LLM | 客户端 mask 敏感区域;本地 OCR 过滤;专用 Computer Use VM |
| 延迟 + 成本 | 每步 1-3 秒,每张截图 1-2K vision tokens,跑 10 分钟轻松 $5+ | 间隔截图、压分辨率、cache UI 元素 detection、用 DOM 替代 vision |
主流可靠性数据(2026-04 OSWorld benchmark):
也就是说,2026 年底 Computer Use 仍是研究 / 辅助而非生产替代品 —— 把它放在产品关键路径前一定要有 HITL fallback。
Aider - 完全开源、git-native、终端 AI 工具 - 强 commit-level workflow,full bring-your-own-model 支持 - 适合”想用自己 fine-tune 模型 + 终端原教旨主义者”
Cline / Continue / Roo Code - VS Code 开源扩展替代 Cursor - 灵活但缺少 Cursor 的整合度
90% 生产 agent 死于此——agent 在某种循环里不停重试同一个失败动作,烧 token、烧 API quota,直到额度告警。
真实案例: - 一个 Claude Code sub-agent 消耗 27 M token,跑了 4.6 小时 在无限循环里 - 一份记录显示无限重试循环可在数分钟内消耗 $40 API 费
| 形态 | 触发方式 | 例子 | 致命点 |
|---|---|---|---|
| Tool Retry Loop | 工具一直返回同一错误,agent 一直试同一参数 | read_file('config.yaml') → FileNotFoundError,agent 重试 50 次 |
LLM 没有”前面试过”的强信号;error message 无诊断 |
| Test-Fail-Fix-Break | 改 A 处让 B 测试通过,新改让 C 测试挂,循环 | npm test 红 → 改 → 红了别的 → 再改 → ... |
没有总览所有 test 状态的 dashboard;每步只看局部 |
| Hallucinated Tool / API Loop | agent 调一个不存在的工具或 API,每次失败后微调名字再试 | search_web → 不存在 → web_search → do_search → ... |
工具列表没有强制 schema,错误消息不返回”可用工具列表” |
| Plan-Replan Spiral | 每次失败后重新写整个 plan,旧失败信息丢失 | “重新规划” 触发 LLM 重新设计同样的失败步骤 | 没有 episodic memory 记录”已经试过 X 不行” |
| Approval Wait Deadlock | agent 等待 HITL 批准,但 UI 没人看 | 触发了 request_human_approval,无人响应,agent 卡住数小时 |
没有 approval timeout + escalation |
一份 Anthropic 内部分析指出:约 90% 的 Loop of Death 都是”thinking → tool call → 同一个 error → 同样的 thinking → 同一个 tool call” 的死循环 —— LLM 没有”我刚试过这个”的明确记忆,自然会一直推荐相同动作。
防御 4 件套(缺一不可):
# 1. 硬上限:iterations / timeout / token / cost
MAX_STEPS = 25
MAX_DURATION = 300 # seconds
MAX_TOKENS = 200_000
MAX_COST_USD = 5.0
# 2. 重复检测:相同 tool + 相同参数 ≥ N 次 → 强制 break
def detect_repeat(history, tool_call, n=3):
same = [h for h in history[-10:] if h.tool == tool_call.tool
and h.args == tool_call.args and h.error == tool_call.error]
return len(same) >= n
# 3. 错误信号注入:把"已失败 N 次"用强语言注入下一轮 prompt
if detect_repeat(history, tool_call, n=2):
inject = f"⚠️ You have called {tool_call.tool}({tool_call.args}) "
f"and got the same error '{tool_call.error}' {n} times. "
f"Do NOT repeat. Choose a different approach OR stop and report."
next_messages.append({"role": "system", "content": inject})
# 4. Escape hatch:明确给 agent "放弃 / 报告" 工具
tools.append({
"name": "give_up_and_report",
"description": "Use when stuck. Reports what you tried and asks user.",
"parameters": {"reason": "string", "attempted": "list"}
})
工程权衡:
read_file 场景下误报极高;实战中需要把”相同
error”也纳入指纹,并对只读类工具放宽阈值,否则 escape hatch
会被误触发,反而让 agent 提前放弃可完成的任务。agent 一个虚构事实触发下游一连串错误调用。
真实案例: - 一个库存自动化 agent 编造了一个不存在的 SKU,然后调用了 4 个下游 API 给这个幻觉 SKU 定价、改库存、发货——一个幻觉触发跨系统事故
对策: - RAG grounding(必须有源支持才能写) - Chain-of-Verification(生成后追问”上述每条事实的来源是什么”) - Low temperature(T=0 或接近 0) - Constrained decoding(只允许从已知列表选)
agent 错误调用了高破坏性工具。
2026 真实事故合集(按媒体报道,具体厂商指责需读者按附录链接核实一手原文):
每一起都是 “agent 拥有不该拥有的权限 + 没有 deny-first 默认 + 没有 sandbox + 没有 HITL 关卡” 的组合发病。
对策:见第 10 节。
Silent Failures(无 alert 的失败) 是最可怕的——agent 静默放弃任务、返回空结果、生成看似完成但实际错误的 PR。这类需要靠 observability + eval 在生产持续监控。
无论何种失败,最终都体现为钱。生产 agent 必须有: - 每 user / org / task 的 cost budget 上限 - 实时 token / cost 告警(5 分钟超阈值即告警) - 可视化的 trace 追溯哪一步烧了多少 - 周期性 audit:“上周谁的 agent 烧得最多”
Anthropic Building Effective AI Agents + 后续工程博客把生产 agent 的失败收敛成 4 大类(与上面 §9.1-9.5 部分重叠,但视角不同 —— 按”修复手段”组织):
| 失败模式 | 表现 | 根因 | 配套修复 |
|---|---|---|---|
| ① Tool Misuse | 调错工具 / 调对工具但参数非法 / 调高破坏性工具 | 工具描述模糊、参数 schema 不严、缺乏前置校验 | (1) 严格 JSON schema + 服务端二次校验;(2) 高破坏性工具加 requires_confirmation: true;(3) PreToolUse hook 在执行前拦;(4) 工具描述写明”何时不该用” |
| ② Hallucinated Tool / Hallucinated API | 调用根本不存在的 tool 或编造 API | 模型对工具列表”猜”而非”读”;错误消息没引导回正确工具 | (1) 错误返回时附带 available_tools 列表;(2) 用 constrained decoding 限制 tool name 选自白名单;(3) deny-by-default:未注册工具直接 reject 不重试 |
| ③ Context Explosion | 工具结果 / 历史 / 中间 thinking 把 context 撑爆 | 没有 windowing;tool result 不裁剪;老步骤不摘要 | (1) 工具结果分级裁剪(见 context-engineering.md §2.6.3);(2) 老步骤定期 compaction;(3) sub-agent 隔离,长跑任务用子上下文窗口 |
| ④ Reward Hacking / Goal Misgen | agent 完成”形式上的目标”但违背意图(删测试让 CI 通过、写 mock 假装实现) | verifier 信号不全或可被钻空子;没有结构化 feedback | (1) verifier 必须是 multi-signal(test pass + diff size + lint + behavior diff);(2) Evaluator-Optimizer pattern 二次审查;(3) HITL spot check + 长期 audit |
Anthropic 工程经验小结(生产实际):
Claude Code 的默认安全姿态是 deny-first + human escalation:deny 规则覆盖 ask 规则、ask 规则覆盖 allow 规则,未识别的 action 上升到用户而非默默放行。
具体实现的”多层独立护栏”:
任一层可阻断 action,是真正的 defense-in-depth。
| 模式 | 含义 | 适合场景 |
|---|---|---|
| HITL(Human in the Loop) | 关键步骤前必须人工确认 | 高风险(医疗、金融、删除数据) |
| HOTL(Human on the Loop) | 人在监控但不阻塞,关键时介入 | 中等风险(编码、内容生成) |
| Fully Autonomous | 完成才汇报 | 低风险(数据查询、报表) |
Anthropic 的 auto-mode 数据:用户对 ~93% 的 permission prompt 一律点同意。
这意味着单纯的 approval 机制已经被行为不可靠化——人会习惯性 click yes。结论:
| 方案 | 隔离强度 | 启动时延 | 内存开销 | 兼容性 | 适合 |
|---|---|---|---|---|---|
| MicroVM(Firecracker / AWS Fargate / Kata) | 最强(独立 Linux 内核 + KVM 硬件虚拟化) | ~125 ms | < 5 MiB / VM | 完全 Linux | 生产高安全(跑陌生人代码) |
| gVisor | 强(用户态内核 Sentry + 拦截 syscall) | ~50 ms | ~15 MiB | 大部分 syscall | 平衡 + GPU 工作负载 |
| 加固容器 | 中(共享 host kernel + 多重限制) | < 10 ms | 微 | 完全 | 跑你自己写的代码 |
| 普通 Docker | 弱(仅 namespace + cgroup) | ~10 ms | 微 | 完全 | 绝对不能跑陌生 LLM 代码 |
| Process-level(seccomp / chroot) | 极弱 | < 1 ms | 0 | 完全 | 最后兜底 |
业界共识(来自 e2b / Daytona / Modal / Vercel Sandbox 等所有主流方案):容器单独不够,必须升级到 microVM 或 gVisor。Linux 内核近 30 年的攻击面对 LLM 生成代码而言是大筛子——一个 namespace 逃逸 CVE 就能从沙箱跳到 host。
架构:每个 sandbox 是一个独立 Linux 内核 + 完整 init 进程,跑在 KVM 硬件虚拟化里。攻击者要 host root 必须先穿透内核 + KVM hypervisor + Firecracker VMM 三层。
最小启动配置:
# 1. 准备 kernel 和 rootfs
wget https://s3.amazonaws.com/spec.ccfc.min/img/quickstart_guide/x86_64/kernels/vmlinux.bin
wget https://s3.amazonaws.com/spec.ccfc.min/img/quickstart_guide/x86_64/rootfs/bionic.rootfs.ext4
# 2. 启动 Firecracker
firecracker --api-sock /tmp/firecracker.sock &
# 3. 配置 microVM(curl REST API)
curl -X PUT --unix-socket /tmp/firecracker.sock http://localhost/boot-source \
-H 'Content-Type: application/json' \
-d '{"kernel_image_path":"./vmlinux.bin","boot_args":"console=ttyS0 reboot=k panic=1"}'
curl -X PUT --unix-socket /tmp/firecracker.sock http://localhost/drives/rootfs \
-d '{"drive_id":"rootfs","path_on_host":"./bionic.rootfs.ext4",
"is_root_device":true,"is_read_only":false}'
# 资源限制(必填)
curl -X PUT --unix-socket /tmp/firecracker.sock http://localhost/machine-config \
-d '{"vcpu_count":1,"mem_size_mib":256}'
# 网络(强烈建议默认拒绝出网)
curl -X PUT --unix-socket /tmp/firecracker.sock http://localhost/network-interfaces/eth0 \
-d '{"iface_id":"eth0","host_dev_name":"tap0"}'
# 启动
curl -X PUT --unix-socket /tmp/firecracker.sock http://localhost/actions \
-d '{"action_type":"InstanceStart"}'生产化要点:
firecracker-containerd
套 OCI 接口,agent 代码看起来像跑 dockerE2B、Daytona、Modal 内部都是 Firecracker 包装版,省去自己运维的麻烦:
# E2B(最常用 LLM agent sandbox)
from e2b_code_interpreter import Sandbox
with Sandbox.create(timeout=30) as sbx: # ★ 必须设 timeout
result = sbx.run_code("print(2+2)")架构:在应用和 host kernel 之间插入一个用户态进程
Sentry,拦截所有 syscall
并在用户态重新实现。应用看起来在 Linux 上跑,但实际只能调 Sentry
实现的子集。
对比 Firecracker:
最小配置(OCI runtime):
# 1. 安装 gVisor runsc
curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] https://storage.googleapis.com/gvisor/releases release main" | sudo tee /etc/apt/sources.list.d/gvisor.list > /dev/null
sudo apt update && sudo apt install -y runsc
# 2. 把 runsc 注册为 Docker 的 runtime
sudo runsc install
sudo systemctl restart docker
# 3. 跑容器时指定 runtime
docker run --runtime=runsc --rm -it python:3.12 python -c "print('hello from gVisor')"Kubernetes 集成(RuntimeClass):
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
---
apiVersion: v1
kind: Pod
metadata:
name: agent-sandbox
spec:
runtimeClassName: gvisor # ★ 这个 pod 跑在 gVisor 里
containers:
- name: code-runner
image: python:3.12
resources:
limits: {memory: "256Mi", cpu: "500m"}适用前提:你跑的是自己写的代码(trusted),仅防意外破坏。不要用加固容器跑陌生 LLM 生成代码——community consensus 已 reject。
最小加固配置(每一项缺一不可):
docker run \
--rm \
--user 1000:1000 \ # 非 root
--read-only \ # 文件系统只读
--tmpfs /tmp:size=64m,noexec \ # 临时空间不可执行
--cap-drop ALL \ # 丢掉所有 capabilities
--security-opt no-new-privileges \ # 禁止 setuid
--security-opt seccomp=./seccomp.json \ # 自定义 syscall 白名单
--security-opt apparmor=docker-default \ # AppArmor profile
--network=none \ # 默认无网
--pids-limit 64 \ # 进程数上限
--memory 256m \ # 内存上限
--cpus 0.5 \ # CPU 上限
--memory-swap 256m \ # 禁用 swap
python:3.12 python /code/script.pyRootless Docker / Podman 进一步把 Docker daemon 也跑在 user namespace 里,攻击面再降一层。
自定义 seccomp 白名单(拒绝所有除明确允许的 syscall):
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{"names": ["read", "write", "openat", "close", "fstat", "mmap", "munmap",
"brk", "rt_sigaction", "rt_sigprocmask", "ioctl", "exit_group",
"execve", "wait4", "uname", "fcntl", "lseek", "stat", "newfstatat"],
"action": "SCMP_ACT_ALLOW"}
/* 拒绝:socket, connect, ptrace, mount, kexec_load, init_module, ... */
]
}你跑什么代码?
│
├─ 陌生人/LLM 生成的 untrusted code
│ ├─ 需要 GPU / 兼容更好 → gVisor
│ └─ 极致隔离/合规 → Firecracker microVM
│
├─ 你自己写的代码 + 防意外
│ └─ 加固容器(rootless + seccomp + cap-drop + read-only)
│
└─ 测试/开发 → 普通 Docker(不要进生产)
Defense-in-depth:5 层防御(一层失守还有别的):
1. ┌───────────────────────────┐
│ Network egress allowlist │ ← 默认拒绝出网,仅放行 GitHub/PyPI 等
└───────────────────────────┘
2. ┌───────────────────────────┐
│ Resource quota(CPU/MEM) │ ← 防 fork bomb / OOM
└───────────────────────────┘
3. ┌───────────────────────────┐
│ Time / step / cost cap │ ← 防 Loop of Death (§9.1)
└───────────────────────────┘
4. ┌───────────────────────────┐
│ Sandbox isolation │ ← Firecracker / gVisor
└───────────────────────────┘
5. ┌───────────────────────────┐
│ Audit log + alerting │ ← 异常 syscall / 出网 / 高 cost
└───────────────────────────┘
| 服务 | 底层 | 接入方式 | 价格 |
|---|---|---|---|
| E2B | Firecracker | Python/TS SDK,最易接入 | 免费 + 按 vCPU·分钟 |
| Modal | gVisor + Firecracker | Python decorator | 按 GPU 秒计费 |
| Daytona | Firecracker | dev container 模式 | 开源 + 云 |
| Vercel Sandbox | Firecracker | Next.js 生态原生 | 包月 |
| AWS Fargate / Lambda | Firecracker | AWS-native | 按用量 |
| Together Code Sandbox | gVisor | API | 按调用 |
| CodeSandbox | Firecracker | dev IDE | 免费 + 订阅 |
实战经验:新项目直接用 E2B 或 Modal,省下 4-6 周自己运维 Firecracker 集群的时间。规模上去后再考虑自托管。
业界不是在朝完全无监督的自主性走,而是在朝选择性自主性走。
意思是:同一个 agent 在不同 action 上的自主级别应该不同。读 README 全自主,跑测试自动批准,改文件需要 review,删文件必须人工二次确认,操作生产 DB 必须 deny-first。
Tool 设计的好坏 直接决定 agent 准确率——不少团队折腾 prompt + 框架毫无效果,换 tool 描述方式后准确率提升 20%+。
1. 命名要”动词+名词+宾语”
❌ search() / get_data() / process()
✅ search_github_issues(repo, query)
list_pending_orders_by_user(user_id)
send_slack_message_to_channel(channel, text)
LLM 选 tool 时主要看名字,模糊名 = 低召回。
2. 描述写”何时用 / 何时不用”
@tool
def cancel_order(order_id: str, reason: str) -> dict:
"""取消未发货的订单。
何时用:
- 用户明确要求取消订单
- 订单状态为 pending / preparing
- 用户已经登录验证
何时不用:
- 订单已发货(用 request_return 走退货流程)
- 用户未登录(先走 require_login)
- 仅是询问订单状态(用 get_order_status)
参数:
- order_id: 订单 ID(如 'ORD-12345')
- reason: 取消原因(用户提供的文本)
返回:
- {"status": "cancelled" | "failed", "refund_amount": float, "message": str}
错误:
- OrderNotFound: 订单不存在 → 让用户检查 ID
- OrderAlreadyShipped: 已发货 → 引导走 request_return
"""3. 参数 schema 要严格 + 有 example
用 Pydantic / JSON Schema 强类型:
from pydantic import BaseModel, Field
from typing import Literal
class CancelOrderInput(BaseModel):
order_id: str = Field(..., description="订单 ID,格式 'ORD-数字'", pattern=r"^ORD-\d+$",
examples=["ORD-12345"])
reason: str = Field(..., description="取消原因", min_length=2, max_length=200,
examples=["用户改变主意", "找到更便宜的"])
notify_user: bool = Field(True, description="是否通知用户")examples 字段对 LLM 选参数 / 格式化参数有显著帮助。
4. 错误返回要”告诉模型下一步怎么办”
# ❌ 不够
return {"error": "OrderNotFound"}
# ✅ 引导式
return {
"error": "OrderNotFound",
"message": "订单 ORD-12345 不存在",
"suggestions": [
"用 list_user_orders(user_id) 列出该用户所有订单",
"提示用户检查订单号格式",
],
}LLM 看到 suggestions 会自动尝试下一步,避免 Loop of
Death。
5. 工具数量上限:单个 agent 别给 > 20 工具
LLM 在 20+ tools 中选错的概率显著上升(research 显示 40+ tools 准确率掉 20%+)。生产模式:
| 反模式 | 真实后果 | 修法 |
|---|---|---|
一个 query_database(sql) 给 LLM |
LLM 写危险 SQL,删表事故 | 拆成
lookup_user_by_email、get_order_status 等专用
tool |
Tool 名字含同义词(fetch_user +
get_user) |
LLM 随机选,结果不一致 | 合并 |
| 长结果不截断 | 返回 10K 行 → context 爆 | server 侧 cap + 加 pagination |
| 无超时 | tool 卡死 → agent 卡死 | 强制 timeout 30s |
| 副作用未声明 | 模型当只读调用 → 意外修改 | description 明确 “会修改 X”,加 require_confirmation |
| 长结果 JSON 嵌套 7 层 | LLM 解析不出来 | 摊平 + 加 summary 字段 |
把 Agent 放回四层工程的全景:
┌─────────────────────────────────────────────────────────────┐
│ Harness Engineering(驾驭工程,第 4 层) │
│ 工具集成 / 沙箱 / 网关 / 推理 / 观测 / 评估 / 护栏 │
│ ─── 提供 agent 运行的"环境与约束" │
├─────────────────────────────────────────────────────────────┤
│ Agent Engineering(Agent 工程,第 3 层)← 本章 │
│ 范式 / 框架 / 多 agent / 评估 / 失败模式 / 安全权限 │
│ ─── 让 LLM 自主完成多步任务 │
├─────────────────────────────────────────────────────────────┤
│ Context Engineering(上下文工程,第 2 层) │
│ 长上下文 / RAG / 记忆 / MCP │
│ ─── 提供 agent "看到什么" │
├─────────────────────────────────────────────────────────────┤
│ Prompt Engineering(提示词工程,第 1 层) │
│ Transformer / 训练栈 / 解码 / CoT / ReAct / 自动化 │
│ ─── 提供 agent "怎么思考"的模板 │
└─────────────────────────────────────────────────────────────┘
四层不是替代而是叠加: - 没好 prompt(第 1 层)→ agent 思考混乱 - 没管好 context(第 2 层)→ agent 视野盲区 - 没建好 agent loop / 框架(第 3 层)→ agent 一步步算对、整体跑偏 - 没 harness(第 4 层)→ agent 在生产里不可控
把前面所有概念串起来,下面是一个生产级最小骨架——LangGraph + 工具 + 检索 + 记忆 + max iter + cost cap + observability。
from typing import TypedDict, Annotated, Sequence
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, SystemMessage
from langchain_core.tools import tool
from mem0 import Memory
import langfuse_callback # observability
import time
# ============ State ============
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], add_messages]
user_id: str
iterations: int
total_cost_usd: float
started_at: float
# ============ 工具:知识库检索 ============
@tool
def kb_search(query: str) -> str:
"""检索企业知识库回答用户问题"""
# 调 §2.4 RAG pipeline,省略
return rag_chain.invoke({"input": query})["answer"]
@tool
def create_ticket(user_id: str, summary: str, severity: str) -> str:
"""无法回答时创建工单。severity: low/medium/high/critical"""
if severity == "critical":
# critical 必须 HITL,不允许 agent 自主创建
return "ERROR: critical 工单需人工创建"
ticket_id = ticket_system.create(user_id, summary, severity)
return f"工单 {ticket_id} 已创建"
# ============ 长期记忆 ============
memory = Memory.from_config({"vector_store": {"provider": "qdrant"}})
# ============ LLM + 工具绑定 + observability ============
llm = ChatAnthropic(
model="claude-sonnet-4-6",
callbacks=[langfuse_callback.LangfuseCallback()],
).bind_tools([kb_search, create_ticket])
# ============ Guardrail:输入侧(伪代码)============
def input_guardrail(messages):
last_user = messages[-1].content
if guardrail.detect_prompt_injection(last_user):
raise ValueError("输入触发 prompt injection 防护")
if guardrail.contains_pii(last_user):
last_user = guardrail.redact_pii(last_user)
messages[-1] = HumanMessage(content=last_user)
return messages
# ============ Agent 节点 ============
def agent_node(state: AgentState):
# 1. 输入 guardrail
messages = input_guardrail(state["messages"])
# 2. 注入历史记忆
user_memories = memory.search(query=messages[-1].content, user_id=state["user_id"])
memory_context = "\n".join([m["text"] for m in user_memories[:5]])
sys_msg = SystemMessage(content=f"你是 ACME 公司客服。用户历史:\n{memory_context}")
# 3. LLM 决策(思考 + 工具调用)
response = llm.invoke([sys_msg] + list(messages))
# 4. 更新成本(每个 provider 都返回 token usage)
cost = response.response_metadata.get("usage", {}).get("total_cost_usd", 0)
return {
"messages": [response],
"iterations": state["iterations"] + 1,
"total_cost_usd": state["total_cost_usd"] + cost,
}
# ============ 工具节点 ============
from langgraph.prebuilt import ToolNode
tool_node = ToolNode([kb_search, create_ticket])
# ============ 流程控制 ============
def should_continue(state: AgentState):
# ★★★ Loop of Death 防御:四道闸门 ★★★
if state["iterations"] >= 10:
return END # max iter cap
if state["total_cost_usd"] >= 0.50:
return END # cost cap $0.5/会话
if time.time() - state["started_at"] >= 60:
return END # 超时 60s
last_msg = state["messages"][-1]
if not last_msg.tool_calls:
return END # 没新工具调用 = 完成
return "tools"
# ============ 构图 ============
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
graph.add_edge("tools", "agent")
# ============ 编译(带 checkpoint 支持 HITL)============
from langgraph.checkpoint.memory import MemorySaver
app = graph.compile(checkpointer=MemorySaver())
# ============ 运行 ============
config = {"configurable": {"thread_id": "session_42"}}
result = app.invoke(
{
"messages": [HumanMessage(content="我的订单 #12345 还没收到,请帮查")],
"user_id": "u_abc",
"iterations": 0,
"total_cost_usd": 0.0,
"started_at": time.time(),
},
config=config,
)
# 把这次会话沉淀到长期记忆
memory.add(messages=result["messages"], user_id="u_abc")这个 100 行骨架已经具备生产级 agent 的核心要素:
| 要素 | 实现位置 |
|---|---|
| LLM + 工具循环(ReAct) | agent_node + tool_node |
| 长期记忆 | memory.search / memory.add(Mem0) |
| RAG 知识库 | kb_search 工具 |
| 输入护栏 | input_guardrail |
| Loop of Death 四闸门 | should_continue(max iter + cost cap + timeout +
完成检测) |
| HITL(critical 工单) | create_ticket 工具内强制 raise |
| Checkpoint / 暂停恢复 | MemorySaver |
| Observability | LangfuseCallback |
| 成本追踪 | total_cost_usd 累计 |
补全到生产还需加:自动化 eval(DeepEval / RAGAS)、A/B test、灰度发布、PagerDuty 告警接入、合规日志、敏感词输出 guardrail。
| 资源 | 类型 | 推荐用法 |
|---|---|---|
microsoft/ai-agents-for-beginners |
12 课入门 | 完整新手入门,每节带可跑 code samples,配套 Microsoft Agent Framework |
microsoft/agent-framework |
官方框架 | AutoGen 的接班人,Python + .NET,企业 agent orchestration |
datawhalechina/hello-agents |
中文系统教程(42K ⭐) | 从原理到实现到 Agentic RL,中文圈最系统 |
anthropic/Building-Effective-Agents |
Anthropic 官方文章 | §3.4 6 patterns 的原始来源,必读 |
jcran/effective-agents-langchain |
LangChain 实现 | Anthropic 6 patterns 的 LangChain 代码版 |
langchain-ai/langgraph |
LangGraph 官方 | 主流生产 agent 框架,文档极详 |
crewAIInc/crewAI |
CrewAI 官方 | 角色 DSL,最快上手 |
openai/openai-agents-python |
OpenAI Agents SDK | OpenAI 官方,handoff 哲学 |
huggingface/smolagents |
Smolagents | 几百行核心代码,最简实现 |
mastra-ai/mastra |
Mastra | TypeScript 原生,JS/TS 项目首选 |
philschmid/ai-agent-benchmark-compendium |
50+ benchmark 汇总 | 找特定能力测试时 |
vectara/awesome-agent-failures |
失败模式集 | 写 production agent 必看的”反面教材” |
论文必读清单(按时间): - 2022 — ReAct (Yao et al.) - 2023 — Self-Refine (NeurIPS), Reflexion (Shinn et al.), MemGPT (Packer et al.) - 2024 — Building Effective AI Agents (Anthropic), Self-RAG (Asai et al.) - 2025 — Mem0 (arxiv 2504.19413) - 2026 — Dive into Claude Code (arxiv 2604.14228)
答案中以
[术语]标记的概念都可点击跳到本表对应条目并自动展开。本表按 10 个主题分组收录 60+ 高频术语,默认全部收起——遇到不熟的术语再展开看精要解释,避免被信息淹没。
不实际运行代码的情况下分析源码,识别潜在 bug、未使用变量、风格违规、可疑用法。常见工具:
在 Agent 工程中,lint 经常被用作 harness 的硬约束——把 lint 错误反馈给模型重写代码,比单纯在 prompt 里说"请遵守编码规范"可靠得多(Augment Code 把这叫做 Constraint Harness)。
确保代码中变量赋值、函数调用的类型一致:
对 Agent:让 agent 写完代码后强制跑 tsc --noEmit / mypy . / cargo check,类型错误作为反馈喂回模型继续修。比让 agent 自己"声明检查过类型"可靠得多——这是 harness 工程的典型做法。
CI(Continuous Integration):每次代码提交自动跑测试、构建、lint、type check 等校验。
CD(Continuous Deployment):通过校验后自动部署到测试 / 预发 / 生产环境。
常见工具:GitHub Actions、GitLab CI、Jenkins、CircleCI、Buildkite。
在 Agent 工程里,CI 是最重要的 deterministic 反馈源——LLM 自评不可靠,但 CI 通过/失败是 0/1 信号,可以直接作为 ground truth。Hashimoto 的 harness engineering 强调"能不能解决问题强相关于 agent 能不能验证自己的工作"。
让不可信代码(用户上传、LLM 生成)在受限环境中跑,防止破坏宿主系统。隔离强度从弱到强:
Agent 跑用户/LLM 生成代码必须沙箱,并叠加纵深防御:网络出口白名单 + 文件系统只读 + 时间/内存配额 + 不挂载 host 凭据。
来自煤矿用金丝雀检测毒气的典故。部署流程典型为:shadow(双跑不返回)→ 1% → 5% → 25% → 50% → 100%,每阶段观察核心指标无回归才推进。
对 LLM 应用:新 prompt / 新模型 / 新 agent harness 上线必走 canary,关键指标(解决率、CSAT、refusal 率、p99 延迟、单次成本)任何一个恶化 > 阈值就回滚。LLM 应用的"非确定性"特性让 canary 比传统软件更重要。
按 user_id hash 切流量保证一个用户始终进同一桶(避免体验跳变)。判定要素:
LLM 应用调 prompt / 换模型 / 改 RAG 都应过 A/B;只靠 offline eval 上线常翻车(线上流量分布与黄金集差异大)。
业务侧验收 Agent 是否上线最看的几个指标:
Agent 工程关注:把模型 / prompt / RAG 改动放进 A/B 看这些业务指标,而非只看离线 benchmark 分数。改动让 benchmark 涨但 GMV / CSAT 跌的情况非常常见。
Agent 自治走到关键节点时暂停等待人工:
设计原则:"Humans steer. Agents execute."(OpenAI Harness Engineering)。Agent 不是替代人,是放大人的判断——把人放在制定计划、设定约束、审核结果的位置,agent 处理执行。
Google SRE 体系定义的四个术语:
1 - SLO。SLO 99.9% 意味着 30 天有 43.2 分钟"预算"可以不达标,预算用完就冻结非必要发布。Agent 应用怎么用:
经验法则:SLO 不是越严越好——99.99% 比 99.9% 贵 5-10 倍,且大概率超过用户感知阈值。Google 建议"刚刚够用户不抱怨"的水位。
到期自动失效。常见用法:
经验换算:1000 英文单词 ≈ 1300 token;1000 汉字 ≈ 1500-2000 token。
为什么重要:context window、API 计费、推理速度都按 token 算。控制 token 数 = 控制成本和延迟。Anthropic / OpenAI / Google 各自的 tokenizer 不同,相同文本 token 数差 ±20% 很常见。
文本 → 神经网络 → 一个 768 / 1024 / 1536 / 3072 维的浮点数向量。同义词 / 同主题文本的向量在空间中距离近(cosine similarity 高)。
主要用途:
主流模型 2026:OpenAI text-embedding-3-large、Cohere v4、Voyage-3、BGE-M3(开源 SOTA,中英双语 + dense/sparse/multi-vector 三合一)。
包含 system prompt + 历史对话 + 用户输入 + 模型输出,所有都计算在内。2026 主流模型:
注意:宣称窗口 ≠ 有效窗口。RULER 基准显示多数模型在窗口 1/4 之外性能急剧下降(Lost in the Middle)。工程建议把"应当塞入 context"的阈值定在 8-32k,更长走 RAG 或层级摘要。
两个阶段瓶颈不同,调优策略也不同——prefill 优化靠并行 / FlashAttention,decode 优化靠 continuous batching / speculative decoding。
生成第 t 个 token 时需要前面所有 token 的 K/V 参与注意力计算。把它们缓存下来避免每次重算,是 LLM 推理的最基础优化。
显存占用:2 × num_layers × num_heads × head_dim × seq_len × batch × bytes_per_elem。70B 模型上 128k 上下文的 KV cache 可达数十 GB,远超模型权重本身。
进阶优化:
GPT 类 decoder-only 模型的生成方式:P(x_t | x_1, ..., x_{t-1})。每生成一个 token 都要跑一次完整 forward(虽然能复用 KV cache),所以输出长度直接决定延迟。
对比:BERT 是非自回归(masked LM,一次预测所有 mask 位置),扩散模型(diffusion)也是非自回归(一次去噪整段)。
自回归的代价催生了大量加速技术:speculative decoding、parallel decoding、Medusa、EAGLE 等。
decoder 最后一层输出 [vocab_size] 维的 logit 向量;过 softmax 后得到下一个 token 的概率分布。
工程上能拿到 logit(或 top-k logprob)的场景:
注意:OpenAI / Anthropic 商用 API 默认只返回采样结果,需显式开 logprobs 选项。
P(token) ∝ exp(logit / T):
何时调高:Self-Consistency 需要多样路径、creative writing、brainstorm。
何时调低:代码生成、数学推理、严格格式输出,T=0.1-0.3。
陷阱:T=0 不完全等同 deterministic——浮点 GPU 算子的非确定性 + 并发调度可能让相同 prompt 的输出仍有微差。
Xiao et al. 2023 发现:长序列推理时,靠后的 token 往往把不成比例多的注意力分给了序列最前面的几个 token(即使它们语义无关)——这些 token 成为"sink",吸收掉 softmax 必须分配的归一化质量。
工程意义:
LayerNorm:y = (x - μ) / σ * g + b,沿 hidden 维度求均值方差。与 batch 无关,天然支持变长序列与单条推理——这是 Transformer 选 LayerNorm 而非 BatchNorm 的原因。
RMSNorm(Zhang & Sennrich 2019):y = x / sqrt(mean(x²)+ε) * g,去掉减均值和 bias。Llama / PaLM / Mistral 等现代 LLM 几乎都改用 RMSNorm,省 7-64% 归一化耗时且效果不降。
Pre-LN vs Post-LN:LN 在残差前做(Pre-LN)训练比放残差后(Post-LN)稳定,可去掉 warmup,GPT-2 起几乎统一用 Pre-LN。
Su et al. 2021。把位置 m 表示为旋转矩阵 R_m 作用在 Q/K 上,使得 <R_m·q, R_n·k> = f(q, k, m-n)——注意力得分只依赖相对距离。
优点:(1) 无额外参数;(2) 天然编码相对位置;(3) 可与线性注意力兼容。已成 Llama / Qwen / Mistral 等绝大多数现代 LLM 的位置编码方案。
外推问题:纯外推 2k→32k 会崩——高频分量旋转角度落入未见区域。缓解:
RoPE 纯外推会崩——高频分量在训练上下文外旋转角度落入未见区域。两种工程化方案:
主流应用:
经验数字:YaRN 在 4× 上下文扩展(2k→8k 或 32k→128k)几乎无损;8× 以上仍有性能下降。极致长上下文(1M+)通常需要重训而非仅靠 YaRN。
标准 multi-head attention:H 个头各有独立 Q/K/V。
收益:KV cache 减小到 1/8 ~ 1/H,推理吞吐显著提升,效果几乎无损。Llama-2 70B / Llama-3 / Mistral / Qwen2 等都用 GQA。
把传统 dense FFN 换成 N 个并行的 expert FFN + 一个 router。每个 token 通过 router 选 top-k 个 expert(k 通常 1-2),只激活这部分 expert 计算。
优点:参数量大、算力省。Mixtral 8x7B 总参数 47B,激活参数仅 13B;DeepSeek-V3 671B 总参数,激活仅 37B。同等推理成本下 capacity 远超 dense 模型。
挑战:(1) 训练时负载均衡(防一两个 expert 被过度使用);(2) 显存占用按总参数计而非激活参数;(3) 通信开销大(expert parallelism)。
单头注意力对每对 token 只产生一个 attention 分布——一种"关系视角"。多头(h=8/32/64/128)让模型同时学多种关系——句法头关注短距离依赖,语义头关注共指、远程实体。
为什么单头加大维度不行:多头是 h 个低秩注意力的混合,表达能力严格更强;单头是一个高秩注意力,自由度反而少。
进阶变体:GQA / MQA 在 KV 侧减头省显存,Q 侧仍保多头。
Dao 2022。标准 attention 显存 O(N²)(要存 N×N 的 attention matrix),长序列瓶颈。FlashAttention 把 Q/K/V 分块加载到 GPU SRAM 计算,不写出完整 attention matrix,显存降到 O(N),速度也快——attention 是 memory-bound,少读 HBM 就快。
演进:
Kwon et al. 2023。解决传统推理 KV cache 的三类碎片问题:
机制:KV cache 切成固定大小 block(如 16 token),每个序列维护 block table(逻辑→物理映射)。显存利用率从 ~20% 提到 >96%;同 prompt 多采样共享前缀 block;配合 continuous batching 吞吐相对 HuggingFace TGI 提升 2-4×,相对 FasterTransformer 24×。
2023 年起的事实标准开源推理服务器。核心特性:
对比:TGI(HuggingFace)、TensorRT-LLM(NVIDIA,私有更快)、SGLang(前缀复用更彻底)、LMDeploy(OpenCompass 出品)。
也叫 in-flight batching,Yu et al. ORCA 2022 提出。对比 static batching(等齐 batch 再一起跑,长短请求混在一起时 GPU 利用率经常 <30%),continuous batching:
vLLM 数据:吞吐相比 static 提升 5-23×。已成所有现代推理引擎的默认。
Leviathan et al. 2023。流程:
数学上保证输出分布与原模型完全一致(rejection sampling)。
收益条件:(1) draft 与 target 分布相似(接受率 >60%);(2) 大模型受 memory bandwidth 限制,并行验证不增延迟。代码生成接受率 70-90%,开放生成 30-50%。变体:EAGLE-2/3、Medusa、Llama 3.1 self-speculative。
KV cache 是单 request 内复用;prefix caching 是跨 request 复用——多个 request 共享 system prompt / few-shot / agent 历史时,首次计算后缓存这部分 KV,后续 request 直接命中跳过 prefill。
效果:agent / RAG / 多轮对话场景,system prompt 通常 1-4k token、几乎所有请求共享,TTFT 可下降 10-100×。
实现:vLLM --enable-prefix-caching、SGLang RadixAttention(用 radix tree 自动管理所有历史前缀)、Anthropic prompt caching API(5min TTL,cached 部分 0.1× 价格)。
主要由 prefill 决定(处理 input 所有 token)。计费、监控的核心指标之一。
降低 TTFT 的手段:
伴生指标:TBT(time between tokens,单 token 间隔)— 由 decode 决定。
混合精度训练:权重和梯度用 BF16/FP16,optimizer state 仍用 FP32。
部署阶段把权重量化到低 bit 整数,推理时反量化回浮点计算。
INT8 / INT4 量化通常需要校准集(128-512 样本),AWQ 更智能(保护 1% salient 通道)。极致显存场景再用 GGUF(llama.cpp 格式)+ 3-bit / 2-bit 量化跑手机端。
Lin et al. 2023。核心洞察:只需保护 ~1% 的"重要权重通道"(由激活幅值识别)即可保住精度。对这些通道按 per-channel scale 放大再量化。
对比 GPTQ:实现更简单,Llama-2 上困惑度更低,已成 vLLM / TensorRT-LLM 默认。
Frantar 2022。用 OBQ 启发的逐层最小化量化误差,需要少量校准集(128 样本)。优点:早、生态全(exllama / vllm / TGI 都支持);缺点:对激活分布敏感,重要通道可能被压坏。
2026 部署选型:H100/H200 → FP8;A100/3090 → AWQ INT4;手机/边缘 → INT4 + GGUF。
最基础的指令微调方式:把 (输入, 期望输出) 对当做监督学习样本,cross-entropy loss 教模型学指令跟随。
经验数据量:
LIMA 论文:1000 条精选样本即可让 65B base 接近 GPT-4 对话质量——质量 >> 数量。
Hu et al. 2021。把权重更新分解为两个低秩矩阵 ΔW = BA(r=8/16/64),只训练这两个矩阵,可训参数减少 100-10000×。
显存:
优点:可训参数少 / 多个 adapter 可热切换 / 缓解 灾难性遗忘。
Dettmers et al. 2023。三项关键:
65B 模型 QLoRA 约 33GB,单 A100-48G 或双 RTX 3090 可跑。代价:训练慢 30-40%(反量化开销)。
三步走:(1) SFT 训出 base policy;(2) 人类标注 (chosen, rejected) 偏好对训出 Reward Model;(3) 用 RM 给 policy 输出打分,PPO/RLOO/REINFORCE 等算法更新 policy。
InstructGPT、ChatGPT 让 RLHF 出圈。三大痛点:
RLHF 第二步训出。输入:(prompt, response),输出:一个 scalar reward。训练 loss 是 Bradley-Terry:让 RM 在 (chosen, rejected) 对上给 chosen 更高分。
常见弱点:
Rafailov et al. 2023。证明:在 Bradley-Terry 偏好模型 + KL 约束下,最优 policy 有闭式解,可直接用偏好对 (chosen, rejected) 做监督式损失:
L_DPO = -log σ(β(log π(y_w)/π_ref(y_w) - log π(y_l)/π_ref(y_l)))
优势:(1) 无 RM / 无在线采样 / 无 critic,仅 policy + ref 两个模型;(2) 用 SFT 同样的训练栈;(3) 超参稳定。
劣势:严重依赖偏好数据质量;容易过拟合 chosen 的表面模式;reward hacking 风险大。
Llama-3、Qwen2 后训练主路径都是 DPO 或其变种(IPO、KTO、SimPO)。
Schulman 2017。Actor 学策略,critic 学 value function 估计 advantage,clip 限制每步策略更新幅度防崩。
RLHF 中需同时载入 actor / ref / critic / reward 四个模型,显存 ≥4× 单模型。超参敏感(KL 系数、clip ratio、advantage 归一化),训练不稳定。
催生了 DPO(去 RL)、GRPO(去 critic)、RLOO(用平均 reward 当 baseline)等简化方案。
DeepSeek-Math 2024 提出,R1 验证。核心创新:去掉 critic(value 网络),对同一 prompt 采样 G 个 response(典型 G=64),用组内 reward 的均值/标准差做 advantage 归一化:A_i = (r_i - mean(r)) / std(r),再做 PPO-like 的 clipped objective + KL 正则。
效果:
在数学、代码、形式逻辑等可自动验证的任务上,直接用程序判定 reward:答案匹配、单测通过、定理证明器验证。
优势:
DeepSeek-R1、DAPO(ByteDance 开源 SOTA)都属此类。局限:仅适用可验证任务,开放对话仍需 RLHF / DPO。
机制:参数被新任务 loss 拉走,原本编码通用知识的方向被覆盖。
缓解组合(生产推荐):
进阶:EWC(按 Fisher 信息加权 L2 正则)、Model Souping(微调模型与原模型权重平均)、MoE 路由扩展。
Wei et al. 2022。最简形式:"Let's think step by step"(Kojima 2022 zero-shot CoT)。
为什么有效:(1) 增加有效 compute(更多 forward step);(2) 把"系统 1"直觉答题转成"系统 2"分步推理;(3) 暴露错误推理便于 self-consistency 投票纠正。
是涌现能力,<10B 模型几乎无效。Long CoT(R1 / o1 用 RL 训出,含回溯/自我验证,数千 token 长)是 2025 的新范式。
Yao et al. 2023。CoT 是线性单链,错了无法回头;ToT 每步生成多个候选 thought,LLM 自评估状态价值(promising / sure / impossible),BFS/DFS 展开可回溯剪枝。
Game of 24 上 GPT-4 CoT 4% vs ToT 74%。代价:LLM 调用数从 1 涨到 50-200。
适合:解空间需显式搜索(puzzle、规划、定理证明),中间状态可评估。不适合:闲聊、摘要、翻译。
Yao et al. 2022。结构 Thought → Action → Observation 循环:模型先 "Thought: 我需要查 X",输出 "Action: search[X]",工具结果作为 "Observation: ..." 喂回 prompt,再下一轮 Thought。
三大效果:
是现代 agent 框架(Claude tool use、OpenAI function calling、LangChain、AutoGPT)的概念原型。
Shinn et al. 2023。Agent 在一次任务失败后(由外部 verifier 给二元 reward),用 LLM 把失败原因总结成自然语言 lesson 存入 episodic memory,下一次任务时把 lesson 加进 prompt 影响行为。
vs Self-Refine:
HumanEval 上 GPT-4 Reflexion 91%,超过 GPT-4 baseline 80%。
Madaan et al. 2023。在一个 trajectory 里循环 N 轮,无外部 reward、无跨任务记忆。7 个任务平均提升 20%。
陷阱:弱模型自评不准,可能越改越差。生产常组合 Self-Refine(局内)+ Reflexion(跨局)。
Wang et al. 2022。temperature>0 采样 N 条 CoT 路径,对最终答案投票。GSM8K 上比 greedy CoT 提升 ~17 个百分点(PaLM 55%→74%)。
收益大场景:(1) 答案空间离散(数字、选择题);(2) 模型错误率 <50%;(3) 推理路径多样(temperature 0.7-1.0)。代价:N×(典型 N=5-40),开放生成不适用。
何时 few-shot:(1) 任务格式新颖/输出结构复杂(JSON schema、特定 markdown);(2) 分类任务标签多。
何时 zero-shot:通用任务现代模型已饱和(摘要、翻译、QA),加 example 反而引入偏差。
陷阱:example 顺序影响大(recency bias);偶然规律会被学走;example 多了 Lost in the Middle。建议 ≤8 条。
标准 pipeline = Ingestion + Retrieval + Generation:
每段都有瓶颈:chunking 切大小、embedding 选型、召回率不足、context 顺序、模型不忠于 context。生产 RAG ≠ "embedding + 向量库 + LLM"——是一个工程系统。
策略:
Okapi BM25。文档与 query 的相关性按 Σ IDF(qi) · f(qi,d) · (k+1) / (f + k·(1-b+b·|d|/avgdl)) 计算。强项:精确词命中、稀有词高权重、专有名词、数字。短板:同义词不通("医生" vs "doctor")。
与 dense embedding 互补——hybrid search 把两者融合,召回率比单 dense 提升 5-15 个百分点。
dense embedding 擅长语义近似,BM25 擅长精确词匹配,两者互补。
融合方法:
score(d) = Σ 1/(k + rank_i(d)),k=60。生产首选,无需归一化两路分数α·dense + (1-α)·bm25,需要调 α 且分数归一化Anthropic Contextual Retrieval 实验:单 embedding → +contextual embedding → +BM25 → +rerank,失败率 5.7% → 4.0% → 3.7% → 1.9%。
Bi-encoder(embedding):query / doc 分别编码再 cosine 比对,快但无交互。
Cross-encoder(reranker):query + doc 拼接喂 transformer,每层 self-attention 交互,相关性建模能力强 20-40%(NDCG@10),慢 100×。
生产标配:bi-encoder 召回 top-100 → cross-encoder rerank 到 top-10 → 喂 LLM。
主流:Cohere Rerank v3/v4、BGE-reranker-v2-m3(开源 SOTA 中英)、Jina Reranker v2、Mixedbread。
陷阱:召回 top-100 里没有相关文档,rerank 也救不了——reranker 锦上添花,不能替代召回。
2026 主流 embedding 模型对比:
选型框架:
关键陷阱:
主流:
ANN 算法:HNSW(最常见)、IVF、ScaNN(Google)。索引时间 vs 检索精度 vs 显存有 trade-off。
朴素 RAG 在多文档跨实体推理、召回质量不稳、多跳查询场景下都会力不从心。四个常见进阶方案:
实战选择:
Es et al. 2023。四大指标:
生产阈值:4 个指标都 ≥0.7 算合格;Faithfulness < 0.7 优先修;Context Recall < 0.7 调 retriever。
Mitchell Hashimoto 2026 命名:"anytime you find an agent makes a mistake, take the time to engineer a solution such that the agent never makes that mistake again."
不是模型微调,而是工程化环境让模型物理上无法以同样方式再犯错。
两条法则:
OpenAI 公式:Agent = Model + Harness;"Humans steer. Agents execute."
2024-2026 主流框架对比:
经验:先用 SDK 直调写原型;workflow 模式(routing / parallelization / orchestrator-workers)成熟后再考虑 LangGraph;纯 RAG 场景考虑 LlamaIndex;避免一上来就 LangChain "全家桶"。
2024-11 推出,2025-Q4 转入独立 Steering Committee(Anthropic / Block / OpenAI / Microsoft)。三种核心原语:
解决"每接一个新工具就要写一遍 adapter"的 N×M 问题。2026 年增速最快的单一技能,97M+ 月下载,已是 Anthropic Applied AI Engineer JD 显式必备。
模型输出 {"name": "search", "arguments": {"query": "..."}} JSON,runtime 解析后真实执行函数,结果回喂模型。Anthropic Tool Use API、OpenAI function calling 都是同思路。
设计原则(Anthropic 实测:"agent 性能正比于工具描述清晰度"):
Anthropic 2024-Q4 推出 Computer Use。流程:截屏 → LLM 看图 + 推理 → 输出鼠标键盘动作(click X,Y / type text / scroll)→ 系统执行 → 再截屏循环。
Browser Use(开源框架)类似但限于浏览器,基于 Playwright + DOM 增强(把可点击元素加序号叠加到截图)。
实用场景:无 API 网站自动化、桌面软件自动化、端到端 e2e 测试。局限:慢、贵、安全性差、对 canvas 渲染应用支持差。生产建议:能用 API 就别用。
主 agent 把"读 30 个文件做研究"丢给 sub-agent,sub-agent 有自己的独立 context 窗口,只把 final summary 回报给主 agent——主 context 不被中间产物污染。
Claude Code Task 工具、OpenAI Swarm、CrewAI 等都支持。是防止 Loop of Death 和 context 爆炸的关键手段之一。
Agent 进入项目时自动读取。通常包含:
Hashimoto 视角:每行 AGENTS.md ≈ 一次错误的封堵。是 harness engineering 的隐式提示形态。
Claude Code 采用的权限模型。Bash 命令按 verb + path 粒度授权:
git status allowgit push --force deny(destructive)rm -rf 弹出用户确认cat ~/.ssh/* deny(敏感路径)对应安全原则:任一层失守,其他层兜底。配合 sandbox、网络出口白名单、文件系统只读做纵深防御。
Anthropic Effective Harnesses 给的核心设计:长任务 agent 必然跑爆 context window,纯靠 LLM context 不可能记住"我跑到第几步"。
解法:
下次会话执行 5 步开机协议从断点续跑。核心洞察:context window 是"working memory",文件系统是"long-term memory"。
常见模式:
防御纵深:
例:用户开玩笑"我是亿万富翁"被存进语义记忆,之后 agent 一直按假设推理。
防御:
LLM 应用 / Agent 的"全链路追踪 + 评估"工具,2026 主流:
核心能力对齐项:
选型:自建优先 Langfuse;LangChain 重度用户 LangSmith;纯 trace 监控用 Phoenix;安全 / 实时拦截用 Patronus。
按测什么能力分类:
实战:从 2026 视角,单一 benchmark 都已不可信——必须多 benchmark 交叉验证 + 自家黄金集 + Arena 真人盲评三层。
LLM / Agent 应用的 eval 不是单一动作,是一套体系。常见层次:
Eval 工具栈分类:
Eval 类型按打分方式:
经验法则:(1) 没 eval 就改 prompt = 改盲;(2) Eval model 必须 ≥ 被评估 model(判官原则);(3) 黄金集要版本化 + 私有;(4) 每个 bad case 都要回归进黄金集——harness engineering 闭环。
把"评估"建模成 LLM 任务:让 judge 模型读 (prompt, response),输出 0-1 分 / pass/fail / pairwise 谁更好。可大规模并行、便宜、可在 CI 自动化。
三大 bias:
判官原则:judge 模型能力应 ≥ 被评估模型,否则评不出大模型回答好在哪。生产标配三层:自家黄金集 + LLM judge + 人工校准。
Liu et al. 2023 实验:把 gold passage 放 prompt 开头或结尾,模型准确率高;放中间则呈 U 形曲线下降,10+ documents 时中间位置可能低于无上下文 baseline。
工程缓解:
OWASP LLM Top 10 的 #1。类型:
Simon Willison 结论:prompt injection 没有 100% 解,必须按"LLM 不可信"做系统设计。dual-LLM 模式 = Planner(看 trusted 决策)+ Executor(看 untrusted 但无工具权限)。
来源:
debug 流程:复现 + 量化触发率 → 归因(RAG 召回 / 模型用 context / 工具调用)→ 修复 → 加 回归 → 生产监控(faithfulness scorer 实时拦截)。
关键认知:hallucination 多数是 prompt / RAG / 上下文工程缺陷,不是"模型病了"。
NVIDIA NeMo Guardrails 5 类:
关键:rail 不是越多越好,每类挑 1-2 个高 ROI 的开,否则延迟/成本爆炸。
常见手法:
防御:厂商 RLHF safety training + 应用层 input/output classifier(Llama Guard)+ 限制 max context(对抗 many-shot)+ red team 定期演练。