前言
书接上回:【小白成长之路】第六章:Context Engineering
当 LLM 不仅能"听话",还能"做事"------调用工具、规划步骤、反思纠错------它就从 Chatbot 进化成了 Agent。本章拆解 Agent 的四要素、三大架构,以及从单 Agent 到多 Agent 的工程实践。
学习目标
- 理解 Agent(智能体)的核心概念及其与普通 LLM 的本质区别
- 掌握 Agent 的四大组成要素:LLM 大脑、工具集、记忆系统、规划能力
- 熟悉主流 Agent 架构模式:ReAct、Plan-and-Execute、Reflection
- 熟练运用 Function Calling 进行工具调用与参数提取
- 了解并对比主流 Agent 框架:LangChain、LlamaIndex、AutoGen、CrewAI
- 设计 Multi-Agent 协作系统与通信机制
- 掌握 Agent 状态、终止条件、失败恢复与人工介入等运行时控制方法
- 避免 Agent 开发中的常见误区与陷阱
详细内容
知识地图
#mermaid-svg-FQkAWzk3dDo6RSMz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FQkAWzk3dDo6RSMz .error-icon{fill:#552222;}#mermaid-svg-FQkAWzk3dDo6RSMz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FQkAWzk3dDo6RSMz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FQkAWzk3dDo6RSMz .marker.cross{stroke:#333333;}#mermaid-svg-FQkAWzk3dDo6RSMz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FQkAWzk3dDo6RSMz p{margin:0;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge{stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 text{fill:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth--1{stroke-width:17;}#mermaid-svg-FQkAWzk3dDo6RSMz .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-0{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-0{stroke-width:14;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-1{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-1{stroke-width:11;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 text{fill:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-2{stroke-width:8;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-3{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-3{stroke-width:5;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-4{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-4{stroke-width:2;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-5{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-5{stroke-width:-1;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-6{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-6{stroke-width:-4;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-7{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-7{stroke-width:-7;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-8{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-8{stroke-width:-10;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-9{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-9{stroke-width:-13;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 polygon,#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 text{fill:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .node-icon-10{font-size:40px;color:black;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .edge-depth-10{stroke-width:-16;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled circle,#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:lightgray;}#mermaid-svg-FQkAWzk3dDo6RSMz .disabled text{fill:#efefef;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-root rect,#mermaid-svg-FQkAWzk3dDo6RSMz .section-root path,#mermaid-svg-FQkAWzk3dDo6RSMz .section-root circle,#mermaid-svg-FQkAWzk3dDo6RSMz .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-FQkAWzk3dDo6RSMz .section-root text{fill:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-root span{color:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .section-2 span{color:#ffffff;}#mermaid-svg-FQkAWzk3dDo6RSMz .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-FQkAWzk3dDo6RSMz .edge{fill:none;}#mermaid-svg-FQkAWzk3dDo6RSMz .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-FQkAWzk3dDo6RSMz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent Engineering
基础概念
Agent 与 LLM
模型、工具、状态、控制循环
架构模式
ReAct
Plan-and-Execute
Reflection
工具调用
JSON Schema
参数校验
执行与回传
框架选择
LangChain 与 LangGraph
LlamaIndex
AutoGen 与 CrewAI
Multi-Agent
协作架构
通信机制
角色边界
运行时控制
状态与终止
失败恢复
人工介入
轨迹评测
7.1 Agent 基础概念
7.1.1 什么是 Agent?
Agent(智能体) 是围绕目标持续执行"获取状态→决策→行动→读取反馈"的应用系统。LLM 通常负责理解与决策,应用代码负责保存状态、调用工具、检查结果和决定是否继续。因此,Agent 不是某一种模型,而是由模型与运行时共同构成的软件系统。
#mermaid-svg-JGDWkBoxdFX2fRey{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JGDWkBoxdFX2fRey .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JGDWkBoxdFX2fRey .error-icon{fill:#552222;}#mermaid-svg-JGDWkBoxdFX2fRey .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JGDWkBoxdFX2fRey .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JGDWkBoxdFX2fRey .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JGDWkBoxdFX2fRey .marker.cross{stroke:#333333;}#mermaid-svg-JGDWkBoxdFX2fRey svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JGDWkBoxdFX2fRey p{margin:0;}#mermaid-svg-JGDWkBoxdFX2fRey .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JGDWkBoxdFX2fRey .cluster-label text{fill:#333;}#mermaid-svg-JGDWkBoxdFX2fRey .cluster-label span{color:#333;}#mermaid-svg-JGDWkBoxdFX2fRey .cluster-label span p{background-color:transparent;}#mermaid-svg-JGDWkBoxdFX2fRey .label text,#mermaid-svg-JGDWkBoxdFX2fRey span{fill:#333;color:#333;}#mermaid-svg-JGDWkBoxdFX2fRey .node rect,#mermaid-svg-JGDWkBoxdFX2fRey .node circle,#mermaid-svg-JGDWkBoxdFX2fRey .node ellipse,#mermaid-svg-JGDWkBoxdFX2fRey .node polygon,#mermaid-svg-JGDWkBoxdFX2fRey .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JGDWkBoxdFX2fRey .rough-node .label text,#mermaid-svg-JGDWkBoxdFX2fRey .node .label text,#mermaid-svg-JGDWkBoxdFX2fRey .image-shape .label,#mermaid-svg-JGDWkBoxdFX2fRey .icon-shape .label{text-anchor:middle;}#mermaid-svg-JGDWkBoxdFX2fRey .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JGDWkBoxdFX2fRey .rough-node .label,#mermaid-svg-JGDWkBoxdFX2fRey .node .label,#mermaid-svg-JGDWkBoxdFX2fRey .image-shape .label,#mermaid-svg-JGDWkBoxdFX2fRey .icon-shape .label{text-align:center;}#mermaid-svg-JGDWkBoxdFX2fRey .node.clickable{cursor:pointer;}#mermaid-svg-JGDWkBoxdFX2fRey .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JGDWkBoxdFX2fRey .arrowheadPath{fill:#333333;}#mermaid-svg-JGDWkBoxdFX2fRey .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JGDWkBoxdFX2fRey .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JGDWkBoxdFX2fRey .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JGDWkBoxdFX2fRey .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JGDWkBoxdFX2fRey .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JGDWkBoxdFX2fRey .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JGDWkBoxdFX2fRey .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JGDWkBoxdFX2fRey .cluster text{fill:#333;}#mermaid-svg-JGDWkBoxdFX2fRey .cluster span{color:#333;}#mermaid-svg-JGDWkBoxdFX2fRey div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JGDWkBoxdFX2fRey .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JGDWkBoxdFX2fRey rect.text{fill:none;stroke-width:0;}#mermaid-svg-JGDWkBoxdFX2fRey .icon-shape,#mermaid-svg-JGDWkBoxdFX2fRey .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JGDWkBoxdFX2fRey .icon-shape p,#mermaid-svg-JGDWkBoxdFX2fRey .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JGDWkBoxdFX2fRey .icon-shape .label rect,#mermaid-svg-JGDWkBoxdFX2fRey .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JGDWkBoxdFX2fRey .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JGDWkBoxdFX2fRey .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JGDWkBoxdFX2fRey :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 反馈
行动层
工具调用
API 执行
推理层
LLM 大脑
任务规划
感知层
用户输入
环境状态
图 7-1:Agent 的基本工作流程------感知、推理、行动形成闭环
💡 提示:可以把 Agent 想象成一个"有手的 LLM"------普通 LLM 只能输出文字,而 Agent 可以通过工具实实在在地改变世界(查天气、订机票、写文件、调用 API 等)。
7.1.2 Agent 与普通 LLM 的区别
| 维度 | 普通 LLM | Agent(智能体) |
|---|---|---|
| 能力边界 | 被动应答,仅生成文本 | 主动行动,可调用外部工具 |
| 记忆机制 | 无状态(单次对话窗口) | 有状态(支持长期记忆) |
| 工具使用 | 模型只能生成工具调用意图,不能自行执行 API | 应用运行时解析意图并执行搜索、数据库、计算器等工具 |
| 规划能力 | 一次模型调用通常只完成当前响应 | 可在应用循环中拆解任务、执行并根据反馈调整 |
| 自主性 | 低(需明确指令) | 高(可自主探索解决方案) |
| 持续性 | 一次性响应 | 可持续执行任务直到完成 |
| 反馈循环 | 无 | 有(根据执行结果调整策略) |
打个比方:普通 LLM 像一个"博学但手无缚鸡之力的顾问",他能给你详细的建议,但自己什么都做不了;Agent 则像"有执行力的助理",不仅给建议,还能帮你订票、发邮件、查资料。

图 7-2:普通 LLM 生成文本,Agent 通过运行时调用工具并读取反馈
7.1.3 Agent 的四大核心要素
工程上通常从模型、工具、记忆和规划四个维度理解 Agent。最小 Agent 可以只有模型、一个工具和控制循环;记忆与显式规划是否需要,应由任务跨度和复杂度决定。

图 7-3:Agent 四大核心要素------LLM 大脑、工具集、记忆和规划
| 要素 | 作用 | 技术实现 | 示例 |
|---|---|---|---|
| LLM 大脑 | 核心推理引擎 | GPT-4、Claude、Qwen | 理解用户意图、决定调用哪个工具 |
| 工具集 | 扩展行动能力 | API 封装、函数定义 | 天气查询 API、机票预订接口 |
| 记忆 | 存储上下文信息 | 向量数据库、对话历史 | 记住用户偏好、历史订单 |
| 规划 | 任务拆解与调度 | ReAct、ToT(Tree of Thought,思维树)、CoT(Chain of Thought,链式思考) | 将"规划旅行"拆分为订机票→订酒店→查景点 |
💡 提示:模型负责提出下一步,工具负责改变或查询外部状态,记忆保存跨步骤信息,规划组织多步任务。真正让四者运转起来的是应用侧控制循环。
7.1.4 Agent 能力层次模型
Agent 的能力可以分为五个层次,从低到高:

图 7-4:Agent 能力五层次模型,从基础问答到自主代理
| 层次 | 能力描述 | 典型场景 |
|---|---|---|
| Level 1 | 基础问答,单次 LLM 响应 | 聊天机器人、知识问答 |
| Level 2 | 简单推理,CoT(Chain of Thought,链式思考) | 数学题解答、逻辑推理 |
| Level 3 | 工具使用,调用 API 或执行代码 | 查天气、计算汇率 |
| Level 4 | 多步规划,拆解任务并调用工具链 | 旅行规划、数据分析报告 |
| Level 5 | 自主代理,独立完成复杂目标 | 开发完整应用、管理项目 |
这个五层模型用于帮助理解能力递进,不是统一的行业分级标准。判断一个 Agent 是否成熟,也不能只看"自主程度",还要看成功率、可控性、成本和失败后的恢复能力。
7.2 Agent 架构模式
7.2.1 ReAct 循环(Reason + Act)
💡 过渡提示:7.1.3 节介绍的"规划能力"正是通过这些架构模式来实现的------ReAct、Plan-and-Execute、Reflection 是三种主流的规划与执行策略。
ReAct 是最经典的 Agent 架构模式,由 Yao et al. 在 2022 年提出。核心思想是交替进行推理 (Reasoning)和行动(Acting)。
工具/API Agent 用户 工具/API Agent 用户 #mermaid-svg-JWZ79Fcg3ARyqwrZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .error-icon{fill:#552222;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .marker.cross{stroke:#333333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JWZ79Fcg3ARyqwrZ p{margin:0;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-JWZ79Fcg3ARyqwrZ text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-JWZ79Fcg3ARyqwrZ .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .sequenceNumber{fill:white;}#mermaid-svg-JWZ79Fcg3ARyqwrZ #sequencenumber{fill:#333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .messageText{fill:#333;stroke:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .labelText,#mermaid-svg-JWZ79Fcg3ARyqwrZ .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .loopText,#mermaid-svg-JWZ79Fcg3ARyqwrZ .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-JWZ79Fcg3ARyqwrZ .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .noteText,#mermaid-svg-JWZ79Fcg3ARyqwrZ .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .actorPopupMenu{position:absolute;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-JWZ79Fcg3ARyqwrZ .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-JWZ79Fcg3ARyqwrZ .actor-man circle,#mermaid-svg-JWZ79Fcg3ARyqwrZ line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-JWZ79Fcg3ARyqwrZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 任务:查询北京天气并推荐穿衣 Thought: 需要查询北京天气 Action: weather_api("北京") Observation: 北京晴,15°C Thought: 根据温度推荐穿衣 建议穿薄外套,北京今天晴朗
图 7-5:ReAct 循环的时序图,展示 Thought→Action→Observation 的迭代过程
ReAct 循环三要素:
| 要素 | 含义 | 示例 |
|---|---|---|
| Thought(思考) | 分析当前状态,决定下一步 | "我需要先查询北京的天气" |
| Action(行动) | 执行具体操作 | weather_api(city="北京") |
| Observation(观察) | 获取行动结果的反馈 | "北京晴,气温 15°C" |
ReAct 论文使用 Thought 描述模型在行动前的推理。在生产系统中,不应依赖模型输出或长期保存完整的私有推理过程;可观测轨迹通常记录简短的行动理由、工具名称、参数、结果和停止原因,既便于调试,也避免把冗长推理塞回上下文。
ReAct 伪代码实现:
python
def react_agent(task: str, max_steps: int = 10) -> str:
"""
ReAct 循环实现
:param task: 用户任务
:param max_steps: 最大循环次数,防止死循环
:return: 最终答案
"""
history = []
for step in range(max_steps):
# Decision: 生成结构化行动,不要求输出完整思维过程
decision = llm.generate_action(task=task, history=history)
action = parse_action(decision)
if action.is_final(): # 如果是最终答案
return action.answer
# Observation: 执行工具并获取反馈
observation = tool.execute(action)
history.append({
"action": action,
"observation": observation
})
return "未能完成任务,已达到最大步数"
关键点解析:
| 设计要点 | 说明 | 原因 |
|---|---|---|
max_steps 限制 |
设置最大循环次数(如 10) | 防止 Agent 陷入死循环 |
| 历史记录 | 保存行动、参数、结果和必要摘要 | 让模型了解有效上下文,同时控制 Token 与敏感信息 |
| 终止条件 | 检测到 final answer 时结束 | 避免不必要的额外调用 |
7.2.2 Plan-and-Execute(规划 - 执行)
核心思想:先由 Planner(规划器)制定完整计划,再由 Executor(执行器)逐一执行每个步骤。
#mermaid-svg-q5ottVTU7f9ooMbL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-q5ottVTU7f9ooMbL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-q5ottVTU7f9ooMbL .error-icon{fill:#552222;}#mermaid-svg-q5ottVTU7f9ooMbL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-q5ottVTU7f9ooMbL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-q5ottVTU7f9ooMbL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-q5ottVTU7f9ooMbL .marker.cross{stroke:#333333;}#mermaid-svg-q5ottVTU7f9ooMbL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-q5ottVTU7f9ooMbL p{margin:0;}#mermaid-svg-q5ottVTU7f9ooMbL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-q5ottVTU7f9ooMbL .cluster-label text{fill:#333;}#mermaid-svg-q5ottVTU7f9ooMbL .cluster-label span{color:#333;}#mermaid-svg-q5ottVTU7f9ooMbL .cluster-label span p{background-color:transparent;}#mermaid-svg-q5ottVTU7f9ooMbL .label text,#mermaid-svg-q5ottVTU7f9ooMbL span{fill:#333;color:#333;}#mermaid-svg-q5ottVTU7f9ooMbL .node rect,#mermaid-svg-q5ottVTU7f9ooMbL .node circle,#mermaid-svg-q5ottVTU7f9ooMbL .node ellipse,#mermaid-svg-q5ottVTU7f9ooMbL .node polygon,#mermaid-svg-q5ottVTU7f9ooMbL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-q5ottVTU7f9ooMbL .rough-node .label text,#mermaid-svg-q5ottVTU7f9ooMbL .node .label text,#mermaid-svg-q5ottVTU7f9ooMbL .image-shape .label,#mermaid-svg-q5ottVTU7f9ooMbL .icon-shape .label{text-anchor:middle;}#mermaid-svg-q5ottVTU7f9ooMbL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-q5ottVTU7f9ooMbL .rough-node .label,#mermaid-svg-q5ottVTU7f9ooMbL .node .label,#mermaid-svg-q5ottVTU7f9ooMbL .image-shape .label,#mermaid-svg-q5ottVTU7f9ooMbL .icon-shape .label{text-align:center;}#mermaid-svg-q5ottVTU7f9ooMbL .node.clickable{cursor:pointer;}#mermaid-svg-q5ottVTU7f9ooMbL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-q5ottVTU7f9ooMbL .arrowheadPath{fill:#333333;}#mermaid-svg-q5ottVTU7f9ooMbL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-q5ottVTU7f9ooMbL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-q5ottVTU7f9ooMbL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q5ottVTU7f9ooMbL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-q5ottVTU7f9ooMbL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q5ottVTU7f9ooMbL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-q5ottVTU7f9ooMbL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-q5ottVTU7f9ooMbL .cluster text{fill:#333;}#mermaid-svg-q5ottVTU7f9ooMbL .cluster span{color:#333;}#mermaid-svg-q5ottVTU7f9ooMbL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-q5ottVTU7f9ooMbL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-q5ottVTU7f9ooMbL rect.text{fill:none;stroke-width:0;}#mermaid-svg-q5ottVTU7f9ooMbL .icon-shape,#mermaid-svg-q5ottVTU7f9ooMbL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q5ottVTU7f9ooMbL .icon-shape p,#mermaid-svg-q5ottVTU7f9ooMbL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-q5ottVTU7f9ooMbL .icon-shape .label rect,#mermaid-svg-q5ottVTU7f9ooMbL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q5ottVTU7f9ooMbL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-q5ottVTU7f9ooMbL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-q5ottVTU7f9ooMbL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 任务输入
Planner 规划器
计划:步骤 1, 2, 3, ...
Executor 执行器
执行步骤 1
执行步骤 2
执行步骤 N
汇总结果
最终输出
图 7-6:Plan-and-Execute 架构流程图,规划器生成计划后由执行器依次执行
代码示例:
python
def plan_and_execute(task: str) -> str:
# 步骤 1:Planner 生成计划
plan = llm.generate(
prompt=f"请为以下任务制定详细计划:{task}",
system_prompt="你是一个规划专家,输出格式:1. xxx 2. xxx 3. xxx"
)
# 步骤 2:Executor 逐一执行
steps = parse_steps(plan)
results = []
for i, step in enumerate(steps):
result = execute_step(step)
results.append(f"步骤{i+1}: {result}")
# 步骤 3:汇总结果
final_answer = llm.generate(
prompt=f"任务:{task}\n执行结果:{results}",
system_prompt="请根据执行结果给出最终答案"
)
return final_answer
适用场景:
| 适合 | 不适合 |
|---|---|
| 任务结构清晰、步骤可预定义 | 环境动态变化、需要实时调整 |
| 需要可解释的执行计划 | 探索性任务(如开放域问答) |
| 步骤之间有明确依赖关系 | 步骤无法预先确定的任务 |
7.2.3 Reflection(反思)
核心思想:执行完成后评估结果质量,必要时进行修正和优化。
#mermaid-svg-zBV9noOEKxM4mIrK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zBV9noOEKxM4mIrK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zBV9noOEKxM4mIrK .error-icon{fill:#552222;}#mermaid-svg-zBV9noOEKxM4mIrK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zBV9noOEKxM4mIrK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zBV9noOEKxM4mIrK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zBV9noOEKxM4mIrK .marker.cross{stroke:#333333;}#mermaid-svg-zBV9noOEKxM4mIrK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zBV9noOEKxM4mIrK p{margin:0;}#mermaid-svg-zBV9noOEKxM4mIrK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zBV9noOEKxM4mIrK .cluster-label text{fill:#333;}#mermaid-svg-zBV9noOEKxM4mIrK .cluster-label span{color:#333;}#mermaid-svg-zBV9noOEKxM4mIrK .cluster-label span p{background-color:transparent;}#mermaid-svg-zBV9noOEKxM4mIrK .label text,#mermaid-svg-zBV9noOEKxM4mIrK span{fill:#333;color:#333;}#mermaid-svg-zBV9noOEKxM4mIrK .node rect,#mermaid-svg-zBV9noOEKxM4mIrK .node circle,#mermaid-svg-zBV9noOEKxM4mIrK .node ellipse,#mermaid-svg-zBV9noOEKxM4mIrK .node polygon,#mermaid-svg-zBV9noOEKxM4mIrK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zBV9noOEKxM4mIrK .rough-node .label text,#mermaid-svg-zBV9noOEKxM4mIrK .node .label text,#mermaid-svg-zBV9noOEKxM4mIrK .image-shape .label,#mermaid-svg-zBV9noOEKxM4mIrK .icon-shape .label{text-anchor:middle;}#mermaid-svg-zBV9noOEKxM4mIrK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zBV9noOEKxM4mIrK .rough-node .label,#mermaid-svg-zBV9noOEKxM4mIrK .node .label,#mermaid-svg-zBV9noOEKxM4mIrK .image-shape .label,#mermaid-svg-zBV9noOEKxM4mIrK .icon-shape .label{text-align:center;}#mermaid-svg-zBV9noOEKxM4mIrK .node.clickable{cursor:pointer;}#mermaid-svg-zBV9noOEKxM4mIrK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zBV9noOEKxM4mIrK .arrowheadPath{fill:#333333;}#mermaid-svg-zBV9noOEKxM4mIrK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zBV9noOEKxM4mIrK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zBV9noOEKxM4mIrK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zBV9noOEKxM4mIrK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zBV9noOEKxM4mIrK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zBV9noOEKxM4mIrK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zBV9noOEKxM4mIrK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zBV9noOEKxM4mIrK .cluster text{fill:#333;}#mermaid-svg-zBV9noOEKxM4mIrK .cluster span{color:#333;}#mermaid-svg-zBV9noOEKxM4mIrK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zBV9noOEKxM4mIrK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zBV9noOEKxM4mIrK rect.text{fill:none;stroke-width:0;}#mermaid-svg-zBV9noOEKxM4mIrK .icon-shape,#mermaid-svg-zBV9noOEKxM4mIrK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zBV9noOEKxM4mIrK .icon-shape p,#mermaid-svg-zBV9noOEKxM4mIrK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zBV9noOEKxM4mIrK .icon-shape .label rect,#mermaid-svg-zBV9noOEKxM4mIrK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zBV9noOEKxM4mIrK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zBV9noOEKxM4mIrK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zBV9noOEKxM4mIrK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 需要改进
质量合格
任务输入
初次执行
执行结果
质量评估
生成反馈建议
修正后重试
输出最终结果
图 7-7:Reflection 反思机制流程图,通过评估、反馈和修正提升质量
代码示例:
python
def reflection_agent(task: str, max_reflections: int = 3) -> str:
result = execute_initial(task)
for i in range(max_reflections):
# 评估当前结果
feedback = llm.evaluate(task=task, result=result)
if feedback.is_satisfactory:
return result
# 根据反馈修正
suggestions = feedback.suggestions
result = execute_with_feedback(task, result, suggestions)
return result # 达到最大反思次数后返回最佳结果
典型应用:
- 代码生成:生成→运行→修复 bug→重新运行
- 文章写作:初稿→审稿意见→修改→终稿
- 数据分析:初步分析→发现异常→修正方法→最终报告
7.2.4 架构模式对比
| 模式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| ReAct | 灵活、适应性强、适合探索 | 可能陷入循环、调用次数多 | 开放域任务、需要动态探索 |
| Plan-and-Execute | 可解释、可控、效率高 | 缺乏灵活性、无法应对变化 | 结构化任务、工作流自动化 |
| Reflection | 自我修正、输出质量高 | 执行成本高、耗时长 | 关键任务、需要高精度 |
💡 提示 :实际项目中经常混合使用多种模式------例如先用 Plan-and-Execute 制定计划,执行每个步骤时用 ReAct 探索,关键步骤后用 Reflection 验证质量。
7.3 工具调用 Function Calling
Function Calling(函数调用) 是 Agent 与外部工具交互的常用方式。它让 LLM 生成结构化的工具调用请求;真正的 API 查询、数据库操作或代码执行仍由应用运行时完成。
核心流程:
#mermaid-svg-Ptbsgjrs6UdRj3Ua{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .error-icon{fill:#552222;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .marker.cross{stroke:#333333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua p{margin:0;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .cluster-label text{fill:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .cluster-label span{color:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .cluster-label span p{background-color:transparent;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .label text,#mermaid-svg-Ptbsgjrs6UdRj3Ua span{fill:#333;color:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .node rect,#mermaid-svg-Ptbsgjrs6UdRj3Ua .node circle,#mermaid-svg-Ptbsgjrs6UdRj3Ua .node ellipse,#mermaid-svg-Ptbsgjrs6UdRj3Ua .node polygon,#mermaid-svg-Ptbsgjrs6UdRj3Ua .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .rough-node .label text,#mermaid-svg-Ptbsgjrs6UdRj3Ua .node .label text,#mermaid-svg-Ptbsgjrs6UdRj3Ua .image-shape .label,#mermaid-svg-Ptbsgjrs6UdRj3Ua .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .rough-node .label,#mermaid-svg-Ptbsgjrs6UdRj3Ua .node .label,#mermaid-svg-Ptbsgjrs6UdRj3Ua .image-shape .label,#mermaid-svg-Ptbsgjrs6UdRj3Ua .icon-shape .label{text-align:center;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .node.clickable{cursor:pointer;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .arrowheadPath{fill:#333333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ptbsgjrs6UdRj3Ua .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ptbsgjrs6UdRj3Ua .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ptbsgjrs6UdRj3Ua .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .cluster text{fill:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .cluster span{color:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ptbsgjrs6UdRj3Ua rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .icon-shape,#mermaid-svg-Ptbsgjrs6UdRj3Ua .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .icon-shape p,#mermaid-svg-Ptbsgjrs6UdRj3Ua .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .icon-shape .label rect,#mermaid-svg-Ptbsgjrs6UdRj3Ua .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ptbsgjrs6UdRj3Ua .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ptbsgjrs6UdRj3Ua .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ptbsgjrs6UdRj3Ua :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
用户输入
LLM 解析意图
是否调用工具?
输出函数名 + 参数
直接回答
执行函数
返回结果给 LLM
生成自然语言回答
图 7-8:Function Calling 完整流程------从用户输入到最终回答
7.3.1 JSON Schema 定义规范
Function Calling 的核心是将工具定义为JSON Schema,让 LLM 理解如何调用。
完整示例:天气查询工具
json
{
"type": "function",
"function": {
"name": "search_weather",
"description": "查询指定城市在指定日期的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如'北京'或'上海'"
},
"date": {
"type": "string",
"description": "日期,格式 YYYY-MM-DD"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位,默认 celsius"
}
},
"required": ["city"]
}
}
}
字段说明:
| 字段 | 必填 | 说明 |
|---|---|---|
type |
是 | 工具类型,此处为 function |
function.name |
是 | 函数名称,用于运行时路由 |
function.description |
是 | 帮助模型理解何时使用该函数 |
function.parameters |
是 | 参数定义,遵循 JSON Schema 规范 |
parameters.properties |
是 | 每个参数的类型、含义和约束 |
parameters.required |
否 | 必填参数列表;没有必填项时可以省略 |
7.3.2 参数提取流程
用户输入:"帮我查一下北京 2026-08-01 的天气"
LLM 处理过程:
- 理解用户意图 → 需要调用天气查询工具
- 提取参数 →
city="北京",date="2026-08-01" - 输出结构化调用
LLM 输出:
json
{
"function": "search_weather",
"arguments": {
"city": "北京",
"date": "2026-08-01"
}
}
7.3.3 Python 完整实现
python
import json
from typing import Literal
from openai import OpenAI
from pydantic import BaseModel, Field, ValidationError
class WeatherSearch(BaseModel):
"""天气查询参数模型"""
city: str = Field(..., description="城市名称,如'北京'、'上海'")
date: str | None = Field(None, description="日期 YYYY-MM-DD,默认今天")
unit: Literal["celsius", "fahrenheit"] = Field(
"celsius",
description="温度单位"
)
WEATHER_TOOL = {
"type": "function",
"function": {
"name": "search_weather",
"description": "查询指定城市在指定日期的天气信息",
"parameters": WeatherSearch.model_json_schema()
}
}
def search_weather(args: WeatherSearch) -> dict:
"""Mock 工具;生产环境中替换为真实天气 API。"""
return {
"city": args.city,
"date": args.date or "today",
"temperature": 25 if args.unit == "celsius" else 77,
"condition": "晴",
"humidity": 60
}
class WeatherAgent:
"""天气查询 Agent"""
def __init__(self, model: str):
self.client = OpenAI()
self.model = model
def call_llm(self, user_query: str) -> str:
"""完成一次"模型决策→本地执行→结果回传"循环。"""
messages = [{"role": "user", "content": user_query}]
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=[WEATHER_TOOL]
)
message = response.choices[0].message
if not message.tool_calls:
return message.content or ""
messages.append(message)
for tool_call in message.tool_calls:
if tool_call.function.name != "search_weather":
result = {"error": "unsupported_tool"}
else:
try:
args = WeatherSearch.model_validate_json(
tool_call.function.arguments
)
result = search_weather(args)
except (ValidationError, json.JSONDecodeError) as exc:
result = {"error": "invalid_arguments", "detail": str(exc)}
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False)
})
final_response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=[WEATHER_TOOL]
)
return final_response.choices[0].message.content or ""
代码关键点解析:
| 步骤 | 关键代码 | 作用 |
|---|---|---|
| 定义模型 | class WeatherSearch(BaseModel) |
用 Pydantic 确保参数类型正确,Field(...) 中 ... 表示必填字段 |
| 定义 Schema | WEATHER_TOOL |
告诉模型工具名称、用途和参数结构 |
| 参数校验 | model_validate_json() |
不信任模型参数,先做类型与取值校验 |
| 执行函数 | search_weather() |
应用代码真正执行外部操作 |
| 结果回传 | role="tool" |
用 tool_call_id 将结果绑定到对应调用 |
| 二次调用 | final_response |
让模型根据工具结果生成最终回答 |
⚠️ 关键边界:Function Calling 只让模型生成结构化调用请求。参数校验、鉴权、超时、重试、幂等和真正的函数执行,都由 Agent 运行时负责。
7.3.4 多工具调用示例
实际 Agent 通常需要支持多个工具。以下是多工具场景:
python
TOOLS = [
WEATHER_TOOL,
SEARCH_FLIGHT_TOOL,
CALCULATE_CURRENCY_TOOL,
]
TOOL_HANDLERS = {
"search_weather": search_weather,
"search_flight": search_flight,
"calculate_currency": calculate_currency,
}
其中每个工具都应采用 7.3.1 的完整 type→function→parameters 结构。多工具处理循环与 7.3.3 相同,区别是运行时根据 tool_call.function.name 从白名单 TOOL_HANDLERS 中路由。不要直接使用模型生成的名称反射调用任意 Python 函数。
⚠️ 注意:工具数量增加会占用上下文并提高误选概率,但不存在适用于所有模型和任务的固定上限。工具较多时,应按用户权限、任务阶段和场景动态筛选,只把本轮相关工具暴露给模型。
7.4 主流 Agent 框架对比
7.4.1 LangChain / LangGraph
LangChain 提供高层 Agent 抽象与模型、工具集成;LangGraph 提供较底层的有状态编排运行时,适合需要持久化、人工介入和失败恢复的长流程。
特点:
- 组件全面,覆盖 Chains、Agents、Tools、Memory
- 生态成熟,社区活跃
- 支持多种 LLM 提供商
- 学习曲线较陡,概念较多
基本用法:
python
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def search_weather(city: str) -> str:
"""查询指定城市的天气。"""
return f"{city}:晴,25°C"
agent = create_agent(
model="openai:your-model-name",
tools=[search_weather],
system_prompt="你是天气助手。需要实时天气时调用工具。"
)
result = agent.invoke({
"messages": [{"role": "user", "content": "查询北京天气并推荐穿衣"}]
})
⚠️ 版本注意 :框架 API 更新较快。这里展示的是
create_agent形式;实际运行时应以项目锁定版本的官方文档为准,并在依赖文件中固定版本。
LangGraph 状态机编排:
LangGraph 是 LangChain 的扩展,支持更复杂的状态机工作流。
python
from typing import TypedDict, Annotated, List
from langgraph.graph import StateGraph, END
import operator
# 1. 定义状态
class AgentState(TypedDict):
# Annotated[List[str], operator.add] 表示累加器:每次更新时将新列表追加到现有列表
messages: Annotated[List[str], operator.add]
current_step: str
results: dict
# 2. 定义节点
def agent_node(state: AgentState):
# Agent 决策逻辑
return {"current_step": "search_weather"}
def tool_node(state: AgentState):
# 执行工具
result = search_weather(state["current_step"])
return {"results": result}
# 3. 构建图
workflow = StateGraph(AgentState)
workflow.add_node("agent", agent_node)
workflow.add_node("tools", tool_node)
workflow.set_entry_point("agent")
# 4. 定义边和条件
workflow.add_conditional_edges(
"agent",
lambda x: "tools" if x["current_step"] else "end",
{"tools": "tools", "end": END}
)
workflow.add_edge("tools", "agent")
# 5. 编译运行
app = workflow.compile()
result = app.invoke({"messages": ["查询北京天气"], "current_step": "", "results": {}})
💡 提示 :
Annotated[List[str], operator.add]是 LangGraph 的状态累加器语法------每次节点返回messages时,新值会追加到现有列表而非覆盖。
图 7-9:LangChain 提供高层组件,LangGraph 管理有状态流程,两者可以组合使用
7.4.2 LlamaIndex
LlamaIndex 专注于 RAG(检索增强生成)和数据处理,与 Agent 结合紧密。
特点:
- RAG 优化和数据处理能力强
- 与向量数据库集成完善
- 适合知识库问答场景
- 通用 Agent 抽象不如 LangChain 集中
典型接入路径:
- 使用数据连接器加载文档,并构建索引或查询引擎。
- 将检索器或查询引擎封装成带清晰描述的工具。
- 把数据工具与业务工具一同交给 Agent。
- 评测时分别检查检索质量、工具选择和最终答案,避免只看最终文本。
LlamaIndex 的 Agent 与工具封装接口曾有较多版本变化,因此这里不提供容易过期的可复制代码。实际项目应先固定依赖版本,再按照对应版本文档实现。
7.4.3 AutoGen
AutoGen 是 Microsoft 出品的 Multi-Agent 协作框架。
特点:
- 专注于 Multi-Agent 对话协作
- 支持代码执行和人工介入
- 角色定义清晰
- 单 Agent 场景通常显得笨重
基本用法:
python
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
async def main() -> None:
model_client = OpenAIChatCompletionClient(model="your-model-name")
assistant = AssistantAgent(
name="assistant",
model_client=model_client,
system_message="你是一个有帮助的 AI 助手。"
)
result = await assistant.run(task="计算斐波那契数列第 10 项")
print(result.messages[-1].content)
await model_client.close()
asyncio.run(main())
7.4.4 CrewAI
CrewAI 是基于角色的 Multi-Agent 框架,强调角色分工。
特点:
- 角色定义清晰(Role-based)
- 易用性好,学习曲线平缓
- 适合团队协作模拟
- 生态成熟度不如 LangChain
基本用法:
python
from crewai import Agent, Task, Crew, Process
# 1. 定义角色 Agent
researcher = Agent(
role='首席研究员',
goal='深入调研 AI Agent 最新进展',
backstory='你是一位资深的 AI 研究员,擅长快速搜集整理前沿信息',
verbose=True,
allow_delegation=False
)
writer = Agent(
role='技术作家',
goal='根据调研结果撰写技术文章',
backstory='你是一位经验丰富的技术作家,擅长将复杂概念通俗化',
verbose=True,
allow_delegation=False
)
# 2. 定义任务
task1 = Task(
description='调研 2024 年最新的 Agent 框架和技术',
expected_output='一份包含 5 个关键趋势的报告',
agent=researcher
)
task2 = Task(
description='基于调研报告撰写一篇 2000 字的技术文章',
expected_output='一篇结构清晰的技术文章',
agent=writer
)
# 3. 组建 Crew 并执行
crew = Crew(
agents=[researcher, writer],
tasks=[task1, task2],
process=Process.sequential, # 顺序执行
verbose=True
)
result = crew.kickoff()
print(result)
7.4.5 框架全面对比表
| 框架 | 抽象重点 | 更适合的任务 | 选择时重点验证 |
|---|---|---|---|
| LangChain | 模型、工具和 Agent 的高层集成 | 快速构建通用工具调用 Agent | 当前版本 API、所需模型提供商集成 |
| LangGraph | 图状态、持久化和可恢复执行 | 长流程、分支、人工介入 | 状态模型、检查点和部署方式 |
| LlamaIndex | 数据、索引、检索与 Agent 结合 | 以企业数据和 RAG 为核心的 Agent | 数据连接器、检索质量和权限隔离 |
| AutoGen | AgentChat、团队和消息式协作 | 对话型 Multi-Agent 与研究原型 | 终止条件、共享上下文和版本迁移 |
| CrewAI | 角色、任务、Crew 与 Flow | 角色分工明确的自动化流程 | Crew 与 Flow 的边界、状态和可观测性 |
框架选择建议:
| 需求场景 | 推荐框架 | 理由 |
|---|---|---|
| 快速原型、通用 Agent | LangChain | 组件丰富,文档完善 |
| 知识库问答系统 | LlamaIndex | 数据与检索抽象集中 |
| 多 Agent 协作模拟 | AutoGen / CrewAI | 专为协作设计 |
| 复杂工作流编排 | LangGraph | 显式图状态和条件边便于控制流程 |
| 需要持久化的复杂工作流 | LangChain + LangGraph | 高层工具抽象与图运行时可以组合 |
按团队技术栈选择:
- Python 熟练团队:LangChain/LangGraph(灵活性强)
- 角色分工明显的流程:CrewAI(Crew 与 Flow 抽象直接)
- 微软生态:AutoGen(与 Azure 集成好)
- RAG 为核心:LlamaIndex(数据与索引抽象集中)
7.5 Multi-Agent 协作系统
7.5.1 为什么需要 Multi-Agent?
Multi-Agent 不是"任务一复杂就多建几个 Agent",而是一种边界拆分手段。多个 Agent 如果使用同一模型,并不会自然获得更多知识或更强推理能力;相反,它们还会引入消息传递、上下文同步、终止控制和调试成本。
应先用单 Agent 加合适工具验证任务。当出现以下真实边界时,再考虑拆分:
| 拆分依据 | 为什么需要独立 Agent | 示例 |
|---|---|---|
| 职责边界 | 不同阶段需要稳定、互斥的行为规则 | 生成者与审核者分离 |
| 上下文边界 | 各子任务需要不同材料,混在一起会互相干扰 | 法律条款检索与营销文案创作 |
| 权限边界 | 不同角色只能访问特定工具或数据 | 查询 Agent 只读,执行 Agent 可写 |
| 并行边界 | 子任务互不依赖,可以真正并行 | 同时调研多个独立市场 |
| 责任边界 | 输出需要由不同负责人或策略分别确认 | 自动生成后交给风控 Agent 校验 |

图 7-10:单 Agent 与 Multi-Agent 的选择边界------默认先单后多
以下场景通常不适合 Multi-Agent:任务本身一步即可完成、多个角色需要共享大量相同上下文、子任务强依赖难以并行,或者只是希望通过"互相讨论"碰运气提高正确率。此时增加 Agent 数量往往只会增加延迟和错误传播路径。
7.5.2 典型协作架构
1. 中心化架构(Manager-Worker)
#mermaid-svg-PZtpdk7iexaSPrKO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PZtpdk7iexaSPrKO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PZtpdk7iexaSPrKO .error-icon{fill:#552222;}#mermaid-svg-PZtpdk7iexaSPrKO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PZtpdk7iexaSPrKO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PZtpdk7iexaSPrKO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PZtpdk7iexaSPrKO .marker.cross{stroke:#333333;}#mermaid-svg-PZtpdk7iexaSPrKO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PZtpdk7iexaSPrKO p{margin:0;}#mermaid-svg-PZtpdk7iexaSPrKO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PZtpdk7iexaSPrKO .cluster-label text{fill:#333;}#mermaid-svg-PZtpdk7iexaSPrKO .cluster-label span{color:#333;}#mermaid-svg-PZtpdk7iexaSPrKO .cluster-label span p{background-color:transparent;}#mermaid-svg-PZtpdk7iexaSPrKO .label text,#mermaid-svg-PZtpdk7iexaSPrKO span{fill:#333;color:#333;}#mermaid-svg-PZtpdk7iexaSPrKO .node rect,#mermaid-svg-PZtpdk7iexaSPrKO .node circle,#mermaid-svg-PZtpdk7iexaSPrKO .node ellipse,#mermaid-svg-PZtpdk7iexaSPrKO .node polygon,#mermaid-svg-PZtpdk7iexaSPrKO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PZtpdk7iexaSPrKO .rough-node .label text,#mermaid-svg-PZtpdk7iexaSPrKO .node .label text,#mermaid-svg-PZtpdk7iexaSPrKO .image-shape .label,#mermaid-svg-PZtpdk7iexaSPrKO .icon-shape .label{text-anchor:middle;}#mermaid-svg-PZtpdk7iexaSPrKO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PZtpdk7iexaSPrKO .rough-node .label,#mermaid-svg-PZtpdk7iexaSPrKO .node .label,#mermaid-svg-PZtpdk7iexaSPrKO .image-shape .label,#mermaid-svg-PZtpdk7iexaSPrKO .icon-shape .label{text-align:center;}#mermaid-svg-PZtpdk7iexaSPrKO .node.clickable{cursor:pointer;}#mermaid-svg-PZtpdk7iexaSPrKO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PZtpdk7iexaSPrKO .arrowheadPath{fill:#333333;}#mermaid-svg-PZtpdk7iexaSPrKO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PZtpdk7iexaSPrKO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PZtpdk7iexaSPrKO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PZtpdk7iexaSPrKO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PZtpdk7iexaSPrKO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PZtpdk7iexaSPrKO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PZtpdk7iexaSPrKO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PZtpdk7iexaSPrKO .cluster text{fill:#333;}#mermaid-svg-PZtpdk7iexaSPrKO .cluster span{color:#333;}#mermaid-svg-PZtpdk7iexaSPrKO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PZtpdk7iexaSPrKO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PZtpdk7iexaSPrKO rect.text{fill:none;stroke-width:0;}#mermaid-svg-PZtpdk7iexaSPrKO .icon-shape,#mermaid-svg-PZtpdk7iexaSPrKO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PZtpdk7iexaSPrKO .icon-shape p,#mermaid-svg-PZtpdk7iexaSPrKO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PZtpdk7iexaSPrKO .icon-shape .label rect,#mermaid-svg-PZtpdk7iexaSPrKO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PZtpdk7iexaSPrKO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PZtpdk7iexaSPrKO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PZtpdk7iexaSPrKO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Manager 管理 Agent
Worker 1
数据搜集
Worker 2
数据分析
Worker 3
报告撰写
图 7-11:中心化架构,Manager 负责任务分配和结果汇总
特点:
- Manager 负责任务拆解和分配
- Workers 并行执行各自任务
- 适合层次清晰的团队结构
2. 流水线架构(Pipeline)
#mermaid-svg-rysik8bJhgHxG6yt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rysik8bJhgHxG6yt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rysik8bJhgHxG6yt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rysik8bJhgHxG6yt .error-icon{fill:#552222;}#mermaid-svg-rysik8bJhgHxG6yt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rysik8bJhgHxG6yt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rysik8bJhgHxG6yt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rysik8bJhgHxG6yt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rysik8bJhgHxG6yt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rysik8bJhgHxG6yt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rysik8bJhgHxG6yt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rysik8bJhgHxG6yt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rysik8bJhgHxG6yt .marker.cross{stroke:#333333;}#mermaid-svg-rysik8bJhgHxG6yt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rysik8bJhgHxG6yt p{margin:0;}#mermaid-svg-rysik8bJhgHxG6yt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rysik8bJhgHxG6yt .cluster-label text{fill:#333;}#mermaid-svg-rysik8bJhgHxG6yt .cluster-label span{color:#333;}#mermaid-svg-rysik8bJhgHxG6yt .cluster-label span p{background-color:transparent;}#mermaid-svg-rysik8bJhgHxG6yt .label text,#mermaid-svg-rysik8bJhgHxG6yt span{fill:#333;color:#333;}#mermaid-svg-rysik8bJhgHxG6yt .node rect,#mermaid-svg-rysik8bJhgHxG6yt .node circle,#mermaid-svg-rysik8bJhgHxG6yt .node ellipse,#mermaid-svg-rysik8bJhgHxG6yt .node polygon,#mermaid-svg-rysik8bJhgHxG6yt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rysik8bJhgHxG6yt .rough-node .label text,#mermaid-svg-rysik8bJhgHxG6yt .node .label text,#mermaid-svg-rysik8bJhgHxG6yt .image-shape .label,#mermaid-svg-rysik8bJhgHxG6yt .icon-shape .label{text-anchor:middle;}#mermaid-svg-rysik8bJhgHxG6yt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rysik8bJhgHxG6yt .rough-node .label,#mermaid-svg-rysik8bJhgHxG6yt .node .label,#mermaid-svg-rysik8bJhgHxG6yt .image-shape .label,#mermaid-svg-rysik8bJhgHxG6yt .icon-shape .label{text-align:center;}#mermaid-svg-rysik8bJhgHxG6yt .node.clickable{cursor:pointer;}#mermaid-svg-rysik8bJhgHxG6yt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rysik8bJhgHxG6yt .arrowheadPath{fill:#333333;}#mermaid-svg-rysik8bJhgHxG6yt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rysik8bJhgHxG6yt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rysik8bJhgHxG6yt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rysik8bJhgHxG6yt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rysik8bJhgHxG6yt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rysik8bJhgHxG6yt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rysik8bJhgHxG6yt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rysik8bJhgHxG6yt .cluster text{fill:#333;}#mermaid-svg-rysik8bJhgHxG6yt .cluster span{color:#333;}#mermaid-svg-rysik8bJhgHxG6yt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rysik8bJhgHxG6yt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rysik8bJhgHxG6yt rect.text{fill:none;stroke-width:0;}#mermaid-svg-rysik8bJhgHxG6yt .icon-shape,#mermaid-svg-rysik8bJhgHxG6yt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rysik8bJhgHxG6yt .icon-shape p,#mermaid-svg-rysik8bJhgHxG6yt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rysik8bJhgHxG6yt .icon-shape .label rect,#mermaid-svg-rysik8bJhgHxG6yt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rysik8bJhgHxG6yt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rysik8bJhgHxG6yt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rysik8bJhgHxG6yt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入
Agent 1
信息搜集
Agent 2
内容创作
Agent 3
审核修改
最终输出
图 7-12:流水线架构,任务按顺序在 Agents 之间传递
特点:
- 每个 Agent 负责一个环节
- 输出传递给下一个 Agent
- 适合内容创作、代码开发等流程化任务
3. 去中心化架构(网状协作)
#mermaid-svg-CGcWgGZjUk14cYo2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CGcWgGZjUk14cYo2 .error-icon{fill:#552222;}#mermaid-svg-CGcWgGZjUk14cYo2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CGcWgGZjUk14cYo2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CGcWgGZjUk14cYo2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CGcWgGZjUk14cYo2 .marker.cross{stroke:#333333;}#mermaid-svg-CGcWgGZjUk14cYo2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CGcWgGZjUk14cYo2 p{margin:0;}#mermaid-svg-CGcWgGZjUk14cYo2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 .cluster-label text{fill:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 .cluster-label span{color:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 .cluster-label span p{background-color:transparent;}#mermaid-svg-CGcWgGZjUk14cYo2 .label text,#mermaid-svg-CGcWgGZjUk14cYo2 span{fill:#333;color:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 .node rect,#mermaid-svg-CGcWgGZjUk14cYo2 .node circle,#mermaid-svg-CGcWgGZjUk14cYo2 .node ellipse,#mermaid-svg-CGcWgGZjUk14cYo2 .node polygon,#mermaid-svg-CGcWgGZjUk14cYo2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CGcWgGZjUk14cYo2 .rough-node .label text,#mermaid-svg-CGcWgGZjUk14cYo2 .node .label text,#mermaid-svg-CGcWgGZjUk14cYo2 .image-shape .label,#mermaid-svg-CGcWgGZjUk14cYo2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CGcWgGZjUk14cYo2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CGcWgGZjUk14cYo2 .rough-node .label,#mermaid-svg-CGcWgGZjUk14cYo2 .node .label,#mermaid-svg-CGcWgGZjUk14cYo2 .image-shape .label,#mermaid-svg-CGcWgGZjUk14cYo2 .icon-shape .label{text-align:center;}#mermaid-svg-CGcWgGZjUk14cYo2 .node.clickable{cursor:pointer;}#mermaid-svg-CGcWgGZjUk14cYo2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CGcWgGZjUk14cYo2 .arrowheadPath{fill:#333333;}#mermaid-svg-CGcWgGZjUk14cYo2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CGcWgGZjUk14cYo2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CGcWgGZjUk14cYo2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CGcWgGZjUk14cYo2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CGcWgGZjUk14cYo2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CGcWgGZjUk14cYo2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CGcWgGZjUk14cYo2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CGcWgGZjUk14cYo2 .cluster text{fill:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 .cluster span{color:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CGcWgGZjUk14cYo2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CGcWgGZjUk14cYo2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CGcWgGZjUk14cYo2 .icon-shape,#mermaid-svg-CGcWgGZjUk14cYo2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CGcWgGZjUk14cYo2 .icon-shape p,#mermaid-svg-CGcWgGZjUk14cYo2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CGcWgGZjUk14cYo2 .icon-shape .label rect,#mermaid-svg-CGcWgGZjUk14cYo2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CGcWgGZjUk14cYo2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CGcWgGZjUk14cYo2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CGcWgGZjUk14cYo2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent A
Agent B
Agent C
Agent D
图 7-13:去中心化架构,Agents 之间自由通信协作
特点:
- 无中心节点,Agents 平等协作
- 通过广播或点对点通信
- 适合开放讨论、头脑风暴场景
7.5.3 通信机制
Multi-Agent 系统的核心是 Agent 之间的通信方式:
| 通信方式 | 描述 | 优点 | 缺点 | 示例 |
|---|---|---|---|---|
| 共享内存 | 所有 Agent 访问同一状态空间 | 简单、高效 | 状态冲突风险 | LangGraph State |
| 消息传递 | Agent 之间发送消息 | 解耦、清晰 | 消息可能丢失 | AutoGen Chat |
| 黑板模式 | 公共信息板供读写 | 灵活、可扩展 | 需要协调机制 | 任务白板 |
| API 调用 | 通过 API 相互调用 | 标准化、可远程 | 延迟较高 | REST/gRPC |
7.5.4 实战案例:内容创作团队
下面使用 AutoGen AgentChat 的 Team 和显式终止条件实现一个简化内容创作团队。三个 Agent 按"研究→写作→审核"的顺序共享消息;编辑输出 APPROVE 时正常结束,消息数达到上限时强制停止。
python
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import (
MaxMessageTermination,
TextMentionTermination,
)
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_ext.models.openai import OpenAIChatCompletionClient
async def main() -> None:
model_client = OpenAIChatCompletionClient(model="your-model-name")
researcher = AssistantAgent(
name="researcher",
model_client=model_client,
system_message=(
"你负责调研主题,整理关键事实并标明来源。"
"完成后明确写出:调研完成。"
),
)
writer = AssistantAgent(
name="writer",
model_client=model_client,
system_message=(
"你只根据对话中的调研材料撰写初稿,不补造事实。"
"完成后明确写出:初稿完成。"
),
)
editor = AssistantAgent(
name="editor",
model_client=model_client,
system_message=(
"你审核事实依据、结构和可读性。"
"通过时输出 APPROVE;不通过时给出具体修改意见。"
),
)
termination = (
TextMentionTermination("APPROVE")
| MaxMessageTermination(max_messages=7)
)
team = RoundRobinGroupChat(
participants=[researcher, writer, editor],
termination_condition=termination,
)
result = await team.run(task="调研并撰写一篇 AI Agent 框架入门文章")
print(result.stop_reason)
print(result.messages[-1].content)
await model_client.close()
asyncio.run(main())
执行流程:
- 用户提出主题,Researcher 整理事实和来源。
- Writer 读取共享消息,根据调研材料完成初稿。
- Editor 审核;通过时输出
APPROVE,否则给出修改意见。 - 命中
APPROVE或最大消息数后停止,并记录stop_reason。
💡 提示:这个示例用于说明 Team、共享消息和终止条件。实际项目还要考虑 Agent 选择策略、上下文裁剪、失败恢复和人工审批;如果流程固定且无需自主选角,普通工作流可能比 Multi-Agent 更简单。
7.5.5 Multi-Agent 设计最佳实践
| 实践 | 说明 | 示例 |
|---|---|---|
| 明确角色边界 | 每个 Agent 职责清晰不重叠 | 研究员只负责搜集,不负责写作 |
| 设定终止条件 | 避免无限循环对话 | "当审核通过后终止" |
| 引入人工审核 | 关键节点允许人类介入 | 发布前人工确认 |
| 限制对话轮数 | 防止无意义循环 | max_turns=10 |
| 统一信息格式 | 规范 Agent 间通信格式 | 使用结构化 JSON |
| 添加校验环节 | 关键输出需多个 Agent 确认 | 重要数据双人复核 |
7.6 Agent 运行时控制
模型决定"下一步想做什么",运行时决定"这一步是否允许、如何执行、执行后是否继续"。如果没有运行时控制,ReAct 只是一段循环提示词,无法成为可靠的软件系统。

图 7-14:可靠 Agent 运行时的五类控制能力
这五类控制共同包围 Agent 的决策与行动循环:状态让任务可以保存和恢复,终止与预算限制循环边界,工具安全约束外部操作,人工介入处理高风险决策,轨迹评测负责解释结果为什么成功或失败。
7.6.1 状态与状态转移
Agent 每执行一步,都应产生可保存、可恢复的结构化状态。至少包括任务目标、当前步骤、历史消息、工具结果、剩余预算和运行状态。
python
from typing import Literal, TypedDict
class AgentState(TypedDict):
task: str
step: int
messages: list[dict]
tool_results: list[dict]
status: Literal["running", "waiting", "succeeded", "failed"]
remaining_budget: int
状态不能只存在于 Prompt 字符串中。结构化状态便于断点恢复、并发控制、人工审核和问题回放;传给模型时,再从状态中选择本轮真正需要的内容。
7.6.2 终止条件与预算
可靠 Agent 不能把"模型说完成了"作为唯一终止条件。运行时应组合多种条件:
| 终止条件 | 作用 | 示例 |
|---|---|---|
| 目标完成 | 正常结束 | 目标文件已生成且校验通过 |
| 最大步数 | 防止无限循环 | step >= max_steps |
| Token 或费用预算 | 控制资源消耗 | remaining_budget <= 0 |
| 重复行动检测 | 识别原地打转 | 连续调用同一工具且参数相同 |
| 不可恢复错误 | 及时失败 | 无权限、参数永久无效 |
| 人工暂停 | 等待外部决策 | 涉及付款、发布或删除数据 |
终止不是简单的 break。结束时还应记录停止原因、最后一个有效状态和未完成事项,供用户或下一次运行判断能否继续。
7.6.3 工具失败与恢复策略
工具调用失败后,应先判断错误类型,再决定是否重试:
- 瞬时错误:网络超时、限流等,可采用退避重试。
- 参数错误:把校验错误返回给模型,允许其修正参数,但限制修正次数。
- 权限错误:通常不能靠重试解决,应停止并请求授权。
- 副作用不确定:付款、发消息、创建订单等操作超时后,必须先查询执行结果,不能直接重试。
最后一类尤其重要。对于有副作用的工具,应使用幂等键或业务流水号,把"请求超时"和"操作未执行"区分开来,避免重复扣款、重复发信等问题。
7.6.4 人工介入点
Human-in-the-loop 不是让人逐步确认所有动作,而是在高风险或高不确定节点暂停。常见介入点包括:执行不可逆操作前、候选方案分数接近时、连续失败后,以及最终结果对外发布前。
人工处理后,结果也应写回状态,例如 approved、rejected 或修改后的工具参数,随后从原检查点继续,而不是重新运行整个任务。
7.6.5 从最终答案评测到轨迹评测
只检查最终答案,无法解释 Agent 为什么失败。评测还应覆盖中间轨迹:
| 评测层次 | 关注问题 | 常用指标 |
|---|---|---|
| 任务结果 | 最终目标是否完成 | 任务成功率、结果正确率 |
| 工具选择 | 是否选对工具 | 工具选择准确率、无效调用数 |
| 参数质量 | 参数是否完整有效 | Schema 校验通过率 |
| 执行路径 | 是否存在绕路或循环 | 平均步数、重复调用率 |
| 安全控制 | 高风险动作是否被拦截 | 越权调用率、人工介入命中率 |
| 资源消耗 | 完成任务用了多少资源 | Token、耗时、工具调用次数 |
第12章会系统讲模型评测,第13章会讲应用评测;这里先建立一个关键认识:Agent 的评测对象不是一段文本,而是一条包含决策、工具调用和状态变化的执行轨迹。
7.7 常见误区与避坑指南
7.7.1 架构设计误区
| 误区 | 问题 | 正确做法 |
|---|---|---|
| 过度依赖 ReAct | 所有任务都用 ReAct,导致不必要的探索 | 根据任务选择:结构化任务用 Plan-and-Execute |
| 单一 Agent 解决所有 | 复杂任务硬塞给一个 Agent | 必要时用 Multi-Agent 分工 |
| 忽视记忆管理 | 所有信息都塞进上下文 | 设计分层记忆:短期/长期/工作记忆 |
7.7.2 工具设计误区
| 误区 | 问题 | 正确做法 |
|---|---|---|
| 工具定义过粗 | 一个大工具做所有事 | 细粒度工具 + 组合使用 |
| 工具描述模糊 | LLM 不知道何时调用 | 详细描述 + 使用场景示例 |
| 缺少错误处理 | 工具失败导致 Agent 卡住 | 完善的异常捕获 + 重试机制 |
7.7.3 Agent 调试技巧
调试 Agent 行为的实用方法:
| 技巧 | 说明 | 工具/方法 |
|---|---|---|
| 开启开发日志 | 查看工具调用、状态变化和停止原因 | 框架日志或事件流 |
| 记录完整轨迹 | 保存每次交互的历史 | 自定义 Callback Handler |
| 逐步执行 | 单步调试 Agent 决策 | 断点 + 手动检查中间状态 |
| 简化问题 | 从简单查询开始逐步复杂化 | 分层测试策略 |
| Mock 工具 | 用固定返回值的 Mock 替代真实 API | 单元测试框架 |
| 可视化状态 | 查看 LangGraph 状态变化 | LangGraph Studio |
调试示例:
python
def record_step(trace: list[dict], step: dict) -> None:
"""记录与框架无关的结构化执行轨迹。"""
trace.append({
"step": step["step"],
"tool": step.get("tool"),
"arguments": step.get("arguments"),
"result": step.get("result"),
"latency_ms": step.get("latency_ms"),
"status": step["status"],
})
框架的 verbose 日志适合本地查看,但生产调试更需要结构化轨迹,并为每次运行保留 run_id、步骤序号、耗时、Token 和停止原因。
7.7.4 性能与成本误区
| 误区 | 问题 | 正确做法 |
|---|---|---|
| 无限循环风险 | ReAct 可能陷入死循环 | 设置 max_steps + 终止条件检测 |
| 忽视成本控制 | 大量工具调用成本飙升 | 缓存结果 + 采样 + 限流 |
| 测试不足 | 上线后才发现行为异常 | 建立评估基准 + 单元测试 |
7.7.5 完整检查清单
在部署 Agent 前,请确认:
- 已设置最大执行步数(如
max_steps=10) - 工具定义清晰,描述完整
- 有错误处理和重试机制
- 有副作用的工具已设计鉴权、幂等键和结果确认
- 关键操作有人工审核点
- 已进行充分的回归测试
- 已记录结构化执行轨迹和明确的停止原因
- 有成本监控和告警
- 记忆系统有清理策略(避免无限增长)
本章小结
- Agent 是模型与运行时组成的目标驱动系统,工具、记忆和规划按任务需要组合
- ReAct 是最通用的架构模式,通过 Thought-Action-Observation 循环实现探索
- Plan-and-Execute 适合结构化任务,先规划后执行
- Reflection 通过自我评估和修正提升输出质量
- Function Calling 是 Agent 与外界交互的标准方式,核心是 JSON Schema
- 框架选择 需根据场景:LangChain(通用)、LlamaIndex(RAG)、AutoGen(Multi-Agent)
- Multi-Agent 通过角色分工和协作应对复杂任务,但只有职责、上下文或执行确实需要隔离时才值得引入
- 运行时控制负责状态、终止、预算、失败恢复和人工介入,是 Agent 可靠执行的基础
- 轨迹评测同时检查最终结果、工具选择、参数、执行路径和资源消耗
延伸阅读
- LangChain 官方文档 --- Agents 模块
- AutoGen 论文:AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation
- ReAct 论文:ReAct: Synergizing Reasoning and Acting in Language Models
- Anthropic --- Building effective agents
- CrewAI 官方文档
下一章预告:第 8 章将介绍 Harness Engineering(驾驭工程),学习让 LLM 在生产环境中安全、可靠、可控运行的工程设施。
