【AI应用开发工程师】第七章:Agent 工程与实践

前言

书接上回:【小白成长之路】第六章: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 处理过程:

  1. 理解用户意图 → 需要调用天气查询工具
  2. 提取参数 → city="北京"date="2026-08-01"
  3. 输出结构化调用

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 集中

典型接入路径:

  1. 使用数据连接器加载文档,并构建索引或查询引擎。
  2. 将检索器或查询引擎封装成带清晰描述的工具。
  3. 把数据工具与业务工具一同交给 Agent。
  4. 评测时分别检查检索质量、工具选择和最终答案,避免只看最终文本。

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())

执行流程:

  1. 用户提出主题,Researcher 整理事实和来源。
  2. Writer 读取共享消息,根据调研材料完成初稿。
  3. Editor 审核;通过时输出 APPROVE,否则给出修改意见。
  4. 命中 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 工具失败与恢复策略

工具调用失败后,应先判断错误类型,再决定是否重试:

  1. 瞬时错误:网络超时、限流等,可采用退避重试。
  2. 参数错误:把校验错误返回给模型,允许其修正参数,但限制修正次数。
  3. 权限错误:通常不能靠重试解决,应停止并请求授权。
  4. 副作用不确定:付款、发消息、创建订单等操作超时后,必须先查询执行结果,不能直接重试。

最后一类尤其重要。对于有副作用的工具,应使用幂等键或业务流水号,把"请求超时"和"操作未执行"区分开来,避免重复扣款、重复发信等问题。

7.6.4 人工介入点

Human-in-the-loop 不是让人逐步确认所有动作,而是在高风险或高不确定节点暂停。常见介入点包括:执行不可逆操作前、候选方案分数接近时、连续失败后,以及最终结果对外发布前。

人工处理后,结果也应写回状态,例如 approvedrejected 或修改后的工具参数,随后从原检查点继续,而不是重新运行整个任务。

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
  • 工具定义清晰,描述完整
  • 有错误处理和重试机制
  • 有副作用的工具已设计鉴权、幂等键和结果确认
  • 关键操作有人工审核点
  • 已进行充分的回归测试
  • 已记录结构化执行轨迹和明确的停止原因
  • 有成本监控和告警
  • 记忆系统有清理策略(避免无限增长)

本章小结

  1. Agent 是模型与运行时组成的目标驱动系统,工具、记忆和规划按任务需要组合
  2. ReAct 是最通用的架构模式,通过 Thought-Action-Observation 循环实现探索
  3. Plan-and-Execute 适合结构化任务,先规划后执行
  4. Reflection 通过自我评估和修正提升输出质量
  5. Function Calling 是 Agent 与外界交互的标准方式,核心是 JSON Schema
  6. 框架选择 需根据场景:LangChain(通用)、LlamaIndex(RAG)、AutoGen(Multi-Agent)
  7. Multi-Agent 通过角色分工和协作应对复杂任务,但只有职责、上下文或执行确实需要隔离时才值得引入
  8. 运行时控制负责状态、终止、预算、失败恢复和人工介入,是 Agent 可靠执行的基础
  9. 轨迹评测同时检查最终结果、工具选择、参数、执行路径和资源消耗

延伸阅读

下一章预告:第 8 章将介绍 Harness Engineering(驾驭工程),学习让 LLM 在生产环境中安全、可靠、可控运行的工程设施。

相关推荐
CIO_Alliance1 小时前
AI+iPaaS解决方案:跨系统业务流程自动化助力企业AI化转型
运维·人工智能·自动化
综合资讯1 小时前
2026年打开设备ETF的产品清单:八只同类,两只能买
人工智能·科技·芯片·半导体·科创
声讯电子2 小时前
A-59 双麦双通道语音处理模块:重新定义全双工通话的极限性能
人工智能·语音识别·ai降噪·usb接口·回音消除
菜鸟‍2 小时前
【论文学习】Frontiers in Physics 2024 || Cap2Seg:基于文本描述生成的 COVID-19 医学图像分割性能提升方法
人工智能·学习
陕西企来客2 小时前
生成式引擎优化(GEO)行业白皮书:从流量分配到认知占有的战略跃迁
人工智能·算法·机器学习·技术好geo优化
梦想的颜色2 小时前
飞书 CLI + Skill 完全硬核指南|让 AI Agent 全自动操控飞书(消息 / 文档 / 日历 / 多维表)
人工智能·飞书·办公自动化·飞书 skill·飞书全自动工作流·agent 工具集成
蓝速科技2 小时前
蓝速科技丨 AI 双屏翻译机:动静双模解放双手的商务沟通实测
人工智能·科技
武子康2 小时前
VLA 已经能输出动作,为什么机器人仍需要多时间尺度闭环
人工智能·机器人·agent
阿里云云原生2 小时前
AI Agent 上线容易稳定难?阿里云 AgentLoop 推出“经验自进化”闭环治理方案
人工智能·阿里云·mybatis·agentscope