构建可观测性:如何监控和调试复杂的 Multi-Agent 系统
既然传统的可观测性三支柱对 MAS 无效,那我们应该怎么办?——我们需要一套专门针对 MAS 设计的可观测性体系,我把它叫做“MAS 可观测性的新三支柱”传统可观测性三支柱MAS 可观测性的新三支柱核心区别Metrics(指标)Collaboration Metrics(协作指标)从“固定结构的技术指标”升级到“动态结构的协作指标”,包含任务级、Agent 级、LLM 级、State 级四个维度的
构建可观测性:如何监控和调试复杂的 Multi-Agent 系统
各位同行、分布式系统/Multi-Agent 爱好者,大家好!我是深耕分布式可观测性与 Agent 协作领域多年的老周。
最近这一年,Multi-Agent 系统(以下简称 MAS)的热度简直是“火箭上天——直窜云霄”:从 OpenAI 的 Devin 程序员代理人框架、LangChain 的 Agents 4.0 迭代、微软的 Semantic Kernel 自动团队协作(AutoGen 开源后更是火到 GitHub 星标破 10 万),再到国内的智谱 AI 多智体平台、阿里通义千问的 Agent Studio,越来越多的企业和开发者开始尝试用 MAS 解决复杂问题——从企业内部知识库问答升级到“多角色团队协作完成需求分析-设计-编码-测试-部署全流程”,再到金融风控的“多维度风险排查 Agent 集群”、智慧城市的“多区域监控-调度-决策 Agent 联盟”……
但现实是骨感的:当我们把 MAS 从玩具级的 Demo(比如“搜索 Wikipedia 回答问题”的单链 Agent)搬到生产环境,把 Agent 数量从 1-2 个扩展到 10-100 个甚至跨区域、跨语言、跨框架的“超级 Agent 联盟”时,监控和调试 MAS 简直是一场噩梦!
昨天晚上还在和朋友吐槽:“Devin 要是上线出问题,你根本不知道是‘需求理解 Agent’读错了用户输入、‘技术调研 Agent’找了过时的 Python 2.7 文档、‘代码生成 Agent’偷偷加了 import * 引发了命名空间污染、‘代码审查 Agent’和‘测试 Agent’在‘代码覆盖率标准’上吵架导致任务卡死,还是‘Docker 部署 Agent’忘拉镜像、‘任务调度层’(比如 Celery 或者 LangGraph 的 StateGraph 分布式执行引擎)掉了链——没有可观测性的 MAS,就是黑箱里的一群无头苍蝇!”
别慌,今天我就把这几年踩过的坑、总结的经验、实践过的最佳方案,从基础概念到架构设计、从监控指标到链路追踪、从告警策略到调试工具、从 Demo 级实现到生产级落地,全流程、全维度、深入浅出地 分享给大家!
1. 引言:MAS 可观测性的痛点与价值
1.1 痛点引入:你踩过这些坑吗?
为了让大家更有共鸣,我们先来看几个我亲身体验或亲眼所见的生产级 MAS 事故:
事故1:金融风控 Agent 联盟的“误杀率暴增”
场景:某头部互联网金融公司上线了一套“多维度风险排查 Agent 联盟”,由 8 个 Agent 组成:
UserInfoAgent:提取用户基本信息(年龄、职业、征信报告)TransactionAgent:分析用户近 3 个月的交易流水SocialAgent:爬取(合规授权的)用户社交关系风险(比如是否和失信人员有联系)DeviceAgent:检测用户登录设备的风险(比如是否是模拟器、是否是新设备)BehaviorAgent:分析用户的行为轨迹风险(比如是否是异地登录、是否在凌晨频繁申请贷款)BlacklistAgent:查询内部/外部黑名单RiskWeightAgent:根据业务规则给每个维度的风险评分分配权重DecisionAgent:根据加权总分输出“通过/拒绝/人工审核”的结果问题:上线第 3 天,人工审核团队的工单量暴增了 500%,而正常通过的贷款申请数量下降了 40%——误杀率(即应该通过但被拒绝/人工审核的比例)从原来的 1% 飙升到了 25%!
排查过程的噩梦:
- 一开始怀疑是
TransactionAgent的阈值改了?翻遍所有 Agent 的配置文件和代码历史,没有找到任何修改;- 然后怀疑是
SocialAgent爬取的数据有问题?但SocialAgent的数据源是第三方合规平台,API 返回的 JSON 格式看起来没问题;- 接着怀疑是
RiskWeightAgent的权重算错了?但手动测试了几个样本,权重分配完全符合业务规则;- 最后怎么找到问题的?——靠人工!排查人员手动跑了 100 个误杀的样本,每个样本都手动打印了 8 个 Agent 的输入输出,花了整整 3 天,才发现问题:
UserInfoAgent从征信报告里提取“收入”字段时,把“月收入:12000元”里的数字当成了字符串存储,然后传给RiskWeightAgent和DecisionAgent时,直接用字符串进行了比较(“12000” < “2000” 是 True!),导致低风险的高收入用户被当成了高风险低收入用户!损失:
- 直接经济损失:估算流失了约 2000 个正常客户,预计损失年化收益约 120 万元;
- 间接损失:客户投诉量暴增 300%,品牌口碑受损;
- 人力成本:排查问题花了 3 天,修复+回测+重新上线花了 2 天,共占用 5 名资深工程师的时间。
事故2:多角色协作 Agent 团队的“任务无限循环”
场景:我自己的团队做了一套“需求文档生成 Agent 团队”的 Demo,由 3 个 Agent 组成,用 LangChain 的
SequentialAgent升级成了带状态回溯的LangGraph StateGraph:
ProductManagerAgent:根据用户的一句话需求(比如“做一个在线点餐系统的后端API”),生成“需求规格说明书初稿”TechLeadAgent:根据“需求规格说明书初稿”,生成“技术架构设计初稿”和“接口文档初稿”,如果发现需求有问题,会把状态回退给ProductManagerAgent补充/修改QAEngineerAgent:根据“需求规格说明书初稿”、“技术架构设计初稿”和“接口文档初稿”,生成“测试用例初稿”,如果发现技术架构或接口文档有问题,会把状态回退给TechLeadAgent补充/修改;如果发现需求有问题,会把状态回退给ProductManagerAgent问题:上线测试(其实是内部演示)时,输入“做一个在线点餐系统的后端API”,整个团队无限循环了 2 个小时——
ProductManagerAgent生成初稿 →TechLeadAgent回退补充“用户角色权限” →ProductManagerAgent补充后再次生成 →TechLeadAgent回退补充“支付系统对接” →ProductManagerAgent补充后再次生成 →QAEngineerAgent回退补充“压力测试要求” →ProductManagerAgent补充后再次生成 →TechLeadAgent又回退补充“数据库缓存策略”…… 我当时在客户面前脸都绿了!排查过程的噩梦:
- 一开始以为是
LangGraph的ConditionalEdge(条件边)写错了?翻了好几遍代码,逻辑看起来没问题——只有当TechLeadAgent的输出包含“需要补充需求”时才会回退给ProductManagerAgent;- 然后以为是 Prompt 写得不好?把 Prompt 改了又改,加上了“最多只能回退 3 次需求”的限制,但没用——LLM(大语言模型)根本不听指令!
- 最后怎么找到问题的?——靠手动打印
LangGraph的State(状态)每一步的变化!花了 1 个小时,才发现问题:ProductManagerAgent每次补充需求时,都会把新补充的内容加在旧文档的末尾,而不会覆盖旧文档里的冗余内容(比如一开始旧文档里写了“支付系统对接支付宝”,后来TechLeadAgent要求补充微信支付,ProductManagerAgent就在末尾加了“还需要对接微信支付”,但没有整合到原来的支付系统章节);然后TechLeadAgent又会觉得需求文档结构混乱,需要重新组织,所以又回退给了ProductManagerAgent!
事故3:跨区域 MAS 调度层的“消息丢失”
场景:某智慧城市公司上线了一套“多区域交通监控-调度-决策 Agent 联盟”,由 3 个城市(北京、上海、广州)的本地 Agent 集群和 1 个位于杭州的中央调度 Agent 集群组成,用 Kafka 作为消息队列传递跨区域的调度指令和监控数据:
- 本地 Agent 集群:每个城市有 5 个 Agent(
TrafficCameraAgent、SignalLightAgent、PublicTransportAgent、EmergencyVehicleAgent、LocalDecisionAgent)- 中央调度 Agent 集群:由 3 个 Agent 组成(
GlobalDataAggregationAgent、GlobalDecisionAgent、GlobalTaskAssignmentAgent)问题:上线第 5 天,上海浦东机场附近的高架发生了严重拥堵,但 中央调度 Agent 集群没有收到任何上海本地的监控数据,也没有发出任何跨区域的调度指令(比如临时调整虹桥机场到浦东机场的地铁班次、临时开放应急车道给救护车)——导致拥堵持续了 4 个小时,严重影响了市民的出行!
排查过程的噩梦:
- 一开始怀疑是上海本地的
TrafficCameraAgent或LocalDecisionAgent挂了?登录上海的服务器一看,所有 Agent 的进程都在运行,CPU、内存占用也正常;- 然后怀疑是 Kafka 挂了?登录杭州的 Kafka 集群一看,所有 Broker 都在运行,Topic 也存在,消费者也正常订阅;
- 接着怀疑是网络问题?用 ping 和 telnet 测试了上海到杭州的网络连接,看起来没问题;
- 最后怎么找到问题的?——靠检查 Kafka 的
Producer日志和Consumer偏移量!花了 2 个小时,才发现问题:上海本地的GlobalDataAggregationAgent的 Kafka Producer 配置里,acks参数被设成了0(即不需要等待 Broker 的确认就直接发送下一条消息),而那天上海到杭州的网络发生了 短暂的丢包(丢包率约 0.1%),导致约 10% 的监控数据没有成功发送到 Kafka 集群;同时,上海本地的GlobalDataAggregationAgent也没有设置任何消息重试机制或失败告警!
1.2 为什么传统的可观测性工具对 MAS 无效?
看到这里,可能有朋友会问:“老周,你不是深耕分布式可观测性多年吗?传统的分布式可观测性三支柱(Metrics、Tracing、Logging)不是已经很成熟了吗?为什么不能直接用在 MAS 上?”
没错,传统的分布式可观测性三支柱确实解决了很多“单体应用→微服务架构”转型过程中的监控和调试问题——比如 Prometheus+Grafana 监控 Metrics、Jaeger/Zipkin 做链路追踪、ELK/Loki 做日志收集…… 但 MAS 和传统的微服务架构有本质的区别,这些区别导致传统的可观测性工具“水土不服”,甚至完全无效:
| 对比维度 | 传统微服务架构 | Multi-Agent 系统(MAS) |
|---|---|---|
| 交互模式 | 同步/异步调用,调用关系相对固定 | 协作模式(协商、竞争、拍卖),交互关系动态变化 |
| 执行逻辑 | 确定性的代码逻辑,输入输出可预测 | 基于 LLM/规则引擎的非确定性逻辑,输入输出不可预测 |
| 状态管理 | 无状态/数据库/Redis 管理状态,状态结构固定 | 有状态的协作上下文(State),状态结构动态变化(比如随着 Agent 的交互不断添加新的字段) |
| 故障模式 | 常见的故障:服务挂了、超时、网络丢包、数据库死锁 | 常见的故障:任务无限循环、LLM 幻觉、Agent 之间的冲突、上下文溢出、Prompt 失效 |
| 数据量级 | Metrics/Tracing/Logging 的数据量级相对可控 | 每个 Agent 调用 LLM 都会产生大量的 Prompt/Response 数据,协作上下文(State)的大小也会随着交互次数的增加呈指数级增长 |
我们来具体分析一下:
1.2.1 交互模式的区别:从“固定调用链”到“动态协作图”
传统的微服务架构是**“请求-响应”或“事件驱动”的固定调用链/拓扑结构**——比如用户登录请求会经过“API Gateway → User Service → Auth Service → Database”,拓扑结构是预先设计好的,很少会发生变化(除非我们部署了新的服务或修改了调用逻辑)。
但 MAS 是**“多角色协作”的动态交互图**——比如我们的“需求文档生成 Agent 团队”,拓扑结构可能是“ProductManagerAgent → TechLeadAgent → QAEngineerAgent”,也可能是“ProductManagerAgent → TechLeadAgent → ProductManagerAgent → TechLeadAgent → QAEngineerAgent”,甚至可能是“ProductManagerAgent → TechLeadAgent → QAEngineerAgent → TechLeadAgent → ProductManagerAgent → ……(无限循环)”——拓扑结构完全由 LLM 的输出或 Agent 的协作规则动态决定,没有任何预先设计好的固定调用链!
这就导致传统的链路追踪工具(比如 Jaeger/Zipkin)“水土不服”——传统的链路追踪工具是基于“Span(跨度)”和“Trace(追踪)”的概念,每个 Trace 对应一个固定的请求,每个 Span 对应一个微服务的调用,Span 之间的父子关系是预先确定的(比如 API Gateway 的 Span 是 User Service 的 Span 的父 Span)。但 MAS 里的 Trace 是什么?是整个协作任务的生命周期吗?那 Span 又是什么?是每个 Agent 的一次执行吗?那 Span 之间的父子关系怎么确定?比如 TechLeadAgent 把状态回退给 ProductManagerAgent 时,TechLeadAgent 的 Span 是 ProductManagerAgent 的新 Span 的父 Span 吗?如果是,那整个 Trace 的 Span 树就会变成“循环树”,传统的链路追踪工具根本无法渲染!
1.2.2 执行逻辑的区别:从“确定性代码”到“非确定性 LLM/规则”
传统的微服务架构是基于确定性代码的——比如 User Service 里的 login() 函数,输入是 username 和 password,输出要么是 success 要么是 failure,只要输入相同,输出就一定相同(除非代码有 Bug 或外部依赖发生了变化)。
但 MAS 里的 Agent 是基于非确定性的 LLM 或复杂规则引擎的——比如我们的 ProductManagerAgent,输入是同一句话“做一个在线点餐系统的后端API”,今天生成的需求文档可能包含“用户角色权限”,明天生成的可能就没有;比如 RiskWeightAgent 用 LLM 分配权重(很多 MAS 现在会用 LLM 动态调整业务规则),输入是同一份用户信息,今天分配的收入权重可能是 0.3,明天分配的可能就是 0.5——LLM 的输出是有温度(Temperature)的,输入相同,输出也可能不同!
这就导致传统的日志收集和分析工具(比如 ELK/Loki)“不够用”——传统的日志收集工具只能收集“确定性的代码日志”(比如 INFO: User xxx logged in successfully),但 MAS 里我们需要收集的是“非确定性的 Agent 日志”:
- LLM 调用日志:每次 Agent 调用 LLM 的完整 Prompt、完整 Response、调用时间、调用成本、Token 消耗、Temperature 等参数;
- 协作上下文(State)日志:每次 Agent 执行前后的完整 State 快照、State 的变化量;
- Agent 决策日志:Agent 为什么做出这个决策?比如 TechLeadAgent 为什么把状态回退给 ProductManagerAgent?是因为需求文档里缺少“用户角色权限”吗?如果是,LLM 在 Response 里具体是怎么说的?
传统的日志收集工具虽然可以收集这些数据,但很难分析这些数据——比如我们怎么快速找到“导致任务无限循环的那一次 LLM 调用”?怎么快速对比“两次相同输入的 Agent 执行,State 和 Response 有什么不同”?怎么快速量化“LLM 的 Temperature 对任务成功率的影响”?
1.2.3 状态管理的区别:从“固定结构状态”到“动态结构协作上下文”
传统的微服务架构是无状态为主,有状态为辅——如果需要管理状态,一般会用数据库(比如 MySQL、PostgreSQL)或缓存(比如 Redis、Memcached),而且状态的结构是固定的(比如 User 表的字段是 id、username、password、email,很少会发生变化)。
但 MAS 是完全有状态的——整个协作任务的所有信息(用户输入、每个 Agent 的执行结果、LLM 的调用历史、协作规则的调整记录……)都存储在一个动态结构的协作上下文(State)里——比如我们的“需求文档生成 Agent 团队”,State 一开始可能只有 user_input 一个字段,后来 ProductManagerAgent 执行完后会添加 prd_draft 字段,然后 TechLeadAgent 执行完后会添加 tech_arch_draft 和 api_doc_draft 字段,再然后 QAEngineerAgent 执行完后会添加 test_cases_draft 和 feedback 字段——State 的字段、大小、结构完全由 Agent 的交互动态决定,没有任何预先设计好的固定 Schema!
这就导致传统的监控工具(比如 Prometheus+Grafana)“很难监控到关键信息”——传统的监控工具主要监控“固定结构的指标”(比如 CPU 使用率、内存占用、API 响应时间、请求成功率……),但 MAS 里我们需要监控的是“动态结构的协作指标”:
- 任务级指标:任务的成功率、任务的平均执行时间、任务的平均 LLM 调用次数、任务的平均 LLM 调用成本、任务的无限循环率……
- Agent 级指标:每个 Agent 的执行成功率、每个 Agent 的平均执行时间、每个 Agent 的平均 LLM 调用次数、每个 Agent 的平均 LLM 调用成本、每个 Agent 的幻觉率(即输出错误信息的比例)、每个 Agent 的回退率……
- State 级指标:State 的平均大小、State 的最大大小、State 的字段数量变化趋势、上下文溢出率(即 State 的 Token 数量超过 LLM 的上下文窗口限制的比例)……
这些指标里,很多是“非数值型的”或“动态计算的”——比如“幻觉率”需要我们人工或用另一个 LLM 来判断 Agent 的输出是否正确;比如“任务的无限循环率”需要我们监控 State 的变化趋势,如果 State 在一段时间内没有实质性的变化(比如只是在相同的几个字段之间来回修改),就认为任务进入了无限循环——传统的 Prometheus 虽然可以通过自定义 Exporter 来收集这些指标,但很难实现这些动态的、非数值型的指标的计算和可视化!
1.2.4 故障模式的区别:从“常见技术故障”到“新型协作故障”
传统的微服务架构的故障模式是相对固定的、常见的技术故障——比如服务挂了、超时、网络丢包、数据库死锁、内存泄漏、CPU 过载…… 这些故障我们已经有了成熟的监控和告警策略(比如用 Prometheus 监控服务的健康检查接口,如果连续 3 次健康检查失败就告警;比如用 Jaeger 监控 API 的响应时间,如果超过 5s 就告警……)。
但 MAS 的故障模式是完全新型的、由协作引起的故障——比如:
- 任务无限循环:Agent 之间来回回退状态,没有任何实质性的进展;
- LLM 幻觉:Agent 输出了错误的、不存在的信息(比如
TechLeadAgent说“我们用 Python 5.0 来开发”,但 Python 5.0 根本不存在); - Agent 之间的冲突:两个或多个 Agent 对同一个问题有不同的看法,无法达成一致(比如
RiskWeightAgent认为收入权重应该是 0.3,而DecisionAgent认为应该是 0.5); - 上下文溢出:State 的 Token 数量超过了 LLM 的上下文窗口限制(比如 GPT-4 Turbo 的上下文窗口限制是 128K Token,如果 State 的 Token 数量超过了 128K,LLM 就会报错或忽略前面的内容);
- Prompt 失效:随着 LLM 的版本更新或微调,原来有效的 Prompt 现在变得无效了(比如 GPT-3.5 Turbo 的某个 Prompt 可以让 LLM 输出 JSON 格式的结果,但 GPT-4 Turbo 的同一个 Prompt 就不行);
- 任务死锁:两个或多个 Agent 互相等待对方的输出,导致任务无法继续执行(比如 Agent A 等待 Agent B 的输出,Agent B 等待 Agent C 的输出,Agent C 等待 Agent A 的输出)。
这些新型的协作故障,传统的监控和告警工具根本无法识别——比如传统的监控工具只能监控服务是否挂了,但无法监控任务是否进入了无限循环;只能监控 API 的响应时间,但无法监控 LLM 是否产生了幻觉;只能监控内存占用,但无法监控上下文是否溢出!
1.3 解决方案概述:MAS 可观测性的“新三支柱”
既然传统的可观测性三支柱对 MAS 无效,那我们应该怎么办?——我们需要一套专门针对 MAS 设计的可观测性体系,我把它叫做“MAS 可观测性的新三支柱”:
| 传统可观测性三支柱 | MAS 可观测性的新三支柱 | 核心区别 |
|---|---|---|
| Metrics(指标) | Collaboration Metrics(协作指标) | 从“固定结构的技术指标”升级到“动态结构的协作指标”,包含任务级、Agent 级、LLM 级、State 级四个维度的指标 |
| Tracing(链路追踪) | Interaction Tracing(交互追踪) | 从“固定的 Span 父子关系树”升级到“动态的交互图(Interaction Graph)”,可以清晰地展示 Agent 之间的协作过程、State 的变化趋势、LLM 的调用历史 |
| Logging(日志) | Contextual Logging(上下文日志) | 从“分散的、无关联的代码日志”升级到“完整的、关联的上下文日志”,包含用户输入、每个 Agent 的完整输入输出、每次 LLM 调用的完整 Prompt/Response、每次 State 的变化量、Agent 的决策依据 |
除了“新三支柱”之外,我们还需要一套专门针对 MAS 设计的调试工具和告警策略——比如“任务回放工具”(可以回放整个协作任务的执行过程,就像看电影一样)、“幻觉检测工具”(可以用另一个 LLM 来自动检测 Agent 的输出是否有幻觉)、“上下文窗口预警工具”(可以在 State 的 Token 数量接近 LLM 的上下文窗口限制时发出预警)、“无限循环检测工具”(可以监控 State 的变化趋势,自动识别任务是否进入了无限循环)……
好消息是,现在已经有一些开源的 MAS 可观测性工具了——比如 LangChain 官方推出的 LangSmith(虽然现在还是 Beta 版,而且需要付费,但功能非常强大)、开源的 LangFuse(完全开源,支持 LangChain、LlamaIndex、Semantic Kernel 等主流框架,功能也非常不错)、开源的 Phoenix(主要用于 LLM 的评估和调试,但也可以用于 MAS 的可观测性)…… 我们在后面的章节会详细介绍这些工具的安装、配置和使用。
1.4 最终效果展示:用 LangFuse 监控和调试我们的“需求文档生成 Agent 团队”
为了让大家更直观地感受到 MAS 可观测性的价值,我们先来看一下用 LangFuse 监控和调试我们的“需求文档生成 Agent 团队”的最终效果:
1.4.1 任务级监控面板
在 LangFuse 的“Traces”面板里,我们可以看到所有协作任务的执行情况:
- 任务的 ID、创建时间、执行时间、执行状态(Success/Failure/Running);
- 任务的用户输入;
- 任务的平均 LLM 调用次数、平均 LLM 调用成本、总 Token 消耗;
- 任务的交互图(Interaction Graph)预览。

(图片来源:LangFuse 官方文档)
1.4.2 交互追踪(Interaction Tracing)面板
点击某个任务的 ID,我们可以进入该任务的“交互追踪”面板,在这里我们可以看到:
- 动态的交互图(Interaction Graph):清晰地展示 Agent 之间的协作过程——每个节点代表一个 Agent 的执行或一次 LLM 的调用,每条边代表 Agent 之间的交互或 State 的传递;如果任务进入了无限循环,交互图会明显地显示出一个循环结构。
- 完整的 State 快照和变化量:每次 Agent 执行前后的完整 State 快照,以及 State 的变化量(即哪些字段被添加了、哪些字段被修改了、哪些字段被删除了)。
- 完整的上下文日志:每个 Agent 的完整输入输出、每次 LLM 调用的完整 Prompt/Response、调用时间、调用成本、Token 消耗、Temperature 等参数、Agent 的决策依据。

(图片来源:LangFuse 官方文档)
1.4.3 协作指标(Collaboration Metrics)面板
在 LangFuse 的“Dashboard”面板里,我们可以看到自定义的协作指标:
- 任务级指标:任务的成功率、任务的平均执行时间、任务的无限循环率、任务的上下文溢出率;
- Agent 级指标:每个 Agent 的执行成功率、每个 Agent 的平均执行时间、每个 Agent 的回退率;
- LLM 级指标:LLM 的平均响应时间、LLM 的平均调用成本、LLM 的总 Token 消耗、LLM 的错误率;
- 这些指标都可以用折线图、柱状图、饼图等方式可视化,而且可以根据时间范围、Agent 类型、LLM 类型等条件进行筛选。

(图片来源:LangFuse 官方文档)
1.4.4 任务回放(Task Replay)功能
最最最重要的是,LangFuse 支持**任务回放(Task Replay)**功能——我们可以回放整个协作任务的执行过程,就像看电影一样:
- 可以快进、快退、暂停;
- 可以跳转到任意一个 Agent 的执行或任意一次 LLM 的调用;
- 可以修改某个 Agent 的输入或某次 LLM 的参数,然后重新执行该任务的某个部分,看看会有什么不同的结果;
- 这个功能对于调试 MAS 来说简直是“神器”!
1.5 文章脉络:我们接下来会讲什么?
好了,引言部分就到这里了。接下来,我们会按照以下的脉络来详细讲解如何构建 MAS 的可观测性:
-
第 2 章:基础概念——什么是 MAS?什么是可观测性?MAS 可观测性的核心要素是什么?
- 我们会先回顾一下 MAS 的定义、分类、架构、核心概念(Agent、协作、State、交互图);
- 然后再回顾一下可观测性的定义、传统可观测性三支柱的概念;
- 最后再详细讲解 MAS 可观测性的核心要素(新三支柱、调试工具、告警策略)。
-
第 3 章:核心步骤 1——数据收集:如何收集 MAS 的协作指标、交互追踪数据、上下文日志?
- 我们会详细讲解如何在主流的 MAS 框架(LangChain、LlamaIndex、Semantic Kernel、AutoGen)中集成可观测性工具(LangFuse、LangSmith、Phoenix);
- 我们会给出具体的 Python 代码示例;
- 我们会讲解如何自定义数据收集器,收集我们自己需要的特定数据。
-
第 4 章:核心步骤 2——数据存储:如何存储 MAS 产生的海量可观测性数据?
- 我们会讲解 MAS 可观测性数据的特点(海量、非结构化、动态结构、关联关系复杂);
- 我们会对比不同的存储方案(关系型数据库、NoSQL 数据库、时序数据库、向量数据库、对象存储);
- 我们会给出 LangFuse 的存储架构分析(LangFuse 用 PostgreSQL 存储结构化数据,用 S3/GCS 存储非结构化的 Prompt/Response 数据);
- 我们会讲解如何优化存储方案,降低存储成本。
-
第 5 章:核心步骤 3——数据分析与可视化:如何分析 MAS 的可观测性数据,发现问题?
- 我们会详细讲解如何用 LangFuse、Grafana 等工具可视化 MAS 的协作指标;
- 我们会讲解如何用交互图(Interaction Graph)分析 Agent 之间的协作过程;
- 我们会讲解如何用上下文日志分析 Agent 的决策依据和 LLM 的幻觉;
- 我们会给出具体的数据分析示例(比如如何分析任务无限循环的原因、如何分析 LLM 的 Temperature 对任务成功率的影响)。
-
第 6 章:核心步骤 4——告警与调试:如何及时发现 MAS 的故障,快速修复?
- 我们会详细讲解如何设计 MAS 的告警策略(比如什么情况下应该告警、告警的级别是什么、告警的通知方式是什么);
- 我们会讲解如何用 LangFuse 的告警功能、Prometheus+Alertmanager 等工具实现告警;
- 我们会详细讲解如何用任务回放(Task Replay)、幻觉检测、上下文窗口分析等工具调试 MAS;
- 我们会给出具体的调试示例(比如如何调试任务无限循环的问题、如何调试 LLM 幻觉的问题)。
-
第 7 章:最佳实践与案例分析:生产级 MAS 可观测性的最佳实践是什么?
- 我们会分享生产级 MAS 可观测性的最佳实践(比如如何采样可观测性数据、如何保护可观测性数据的隐私、如何优化 LLM 的调用成本、如何评估 MAS 的性能);
- 我们会给出一个完整的生产级案例分析(比如如何用 LangFuse 监控和调试某金融公司的“多维度风险排查 Agent 联盟”);
- 我们会对比不同的 MAS 可观测性工具的优缺点(LangSmith vs LangFuse vs Phoenix)。
-
第 8 章:总结与展望:MAS 可观测性的未来发展趋势是什么?
- 我们会总结文章的核心内容和关键步骤;
- 我们会展望 MAS 可观测性的未来发展趋势(比如 AI 驱动的可观测性、自动化调试、跨框架的可观测性标准);
- 我们会提供相关的学习资源、文档链接或后续可以深入研究的方向。
2. 基础概念:MAS 可观测性的基石
在正式开始构建 MAS 的可观测性之前,我们需要先回顾一些基础概念——这些概念是我们后续讨论的基石,如果你已经对这些概念非常熟悉,可以跳过这一章,但我建议你还是快速浏览一遍,因为我会在这一章里定义一些专门针对 MAS 可观测性的术语,这些术语在后面的章节里会频繁用到。
2.1 什么是 Multi-Agent 系统(MAS)?
2.1.1 MAS 的定义
关于 Multi-Agent 系统(MAS)的定义,学术界和工业界有很多不同的说法,但我比较认可的是 Wooldridge 和 Jennings 在 1995 年提出的定义:
A Multi-Agent System (MAS) is a system composed of multiple interacting intelligent agents within an environment. These agents can be autonomous, heterogeneous, and capable of acting in pursuit of individual or collective goals.
翻译成中文就是:
多智能体系统(MAS)是由多个在同一环境中交互的智能体组成的系统。这些智能体可以是自主的、异构的,并且能够为了实现个体或集体目标而采取行动。
不过,这个定义是针对传统的基于规则引擎或强化学习的 MAS 的。现在我们常说的 MAS,大多是基于大语言模型(LLM)的 MAS(我把它叫做 LLM-MAS),所以我对这个定义做了一个小小的修改:
基于大语言模型的多智能体系统(LLM-MAS)是由多个在同一协作上下文(State)中交互的 LLM 驱动的智能体组成的系统。这些智能体可以是自主的、异构的、使用不同 LLM 的,并且能够为了实现个体或集体目标而采取行动(比如调用工具、生成内容、与其他智能体交互)。
2.1.2 MAS 的核心属性
根据 Wooldridge 和 Jennings 的定义,以及 LLM-MAS 的特点,我们可以总结出 MAS 的 5 个核心属性:
| 核心属性 | 定义 | LLM-MAS 的具体表现 |
|---|---|---|
| Autonomy(自主性) | 智能体能够在没有人类或其他智能体直接干预的情况下,自主地做出决策和采取行动。 | LLM 驱动的智能体能够根据协作上下文(State)和自己的 Prompt,自主地决定下一步做什么(比如调用搜索工具、生成代码、与其他智能体交互)。 |
| Heterogeneity(异构性) | 智能体可以是不同的——可以使用不同的编程语言、不同的框架、不同的模型(比如 GPT-4 Turbo、Claude 3 Opus、Llama 3)、不同的工具集。 | 比如我们的“需求文档生成 Agent 团队”,ProductManagerAgent 可以使用 GPT-4 Turbo,TechLeadAgent 可以使用 Claude 3 Opus,QAEngineerAgent 可以使用 Llama 3。 |
| Social Ability(社交能力) | 智能体能够与其他智能体或人类进行交互——比如协商、竞争、拍卖、共享信息。 | LLM 驱动的智能体能够通过协作上下文(State)或消息队列与其他智能体进行交互——比如 TechLeadAgent 把状态回退给 ProductManagerAgent 补充需求。 |
| Reactivity(反应性) | 智能体能够感知环境(或协作上下文)的变化,并及时做出反应。 | LLM 驱动的智能体能够感知协作上下文(State)的变化(比如 ProductManagerAgent 补充了需求),并及时做出反应(比如 TechLeadAgent 根据新的需求重新生成技术架构设计)。 |
| Pro-activeness(主动性) | 智能体不仅能够被动地感知环境的变化并做出反应,还能够主动地采取行动,实现自己的个体或集体目标。 | LLM 驱动的智能体不仅能够根据协作上下文(State)执行任务,还能够主动地提出建议(比如 TechLeadAgent 主动建议使用 Redis 作为缓存,而不是等 ProductManagerAgent 要求)。 |
2.1.3 MAS 的分类
根据不同的分类标准,MAS 可以分为不同的类型:
2.1.3.1 根据协作方式分类
根据智能体之间的协作方式,MAS 可以分为以下 3 种类型:
| 类型 | 定义 | 示例 |
|---|---|---|
| Cooperative MAS(协作型 MAS) | 所有智能体都有一个共同的集体目标,智能体之间的交互是为了实现这个共同目标。 | 我们的“需求文档生成 Agent 团队”、某金融公司的“多维度风险排查 Agent 联盟”。 |
| Competitive MAS(竞争型 MAS) | 智能体之间的目标是相互冲突的,智能体之间的交互是为了击败对方,实现自己的个体目标。 | 下棋 AI(AlphaGo Zero 其实可以看成是一个由两个 Agent 组成的竞争型 MAS)、拍卖系统。 |
| Semi-Cooperative MAS(半协作型 MAS) | 智能体之间既有共同的集体目标,又有相互冲突的个体目标,智能体之间的交互是为了在实现集体目标的前提下,最大化自己的个体目标。 | 供应链管理系统(供应商和采购商有共同的目标——完成交易,但也有冲突的目标——供应商想卖高价,采购商想买低价)。 |
现在我们常说的 LLM-MAS,大多是协作型 MAS——因为我们用 LLM-MAS 主要是为了解决复杂的、需要多角色协作的问题,比如需求文档生成、代码开发、风险排查等。
2.1.3.2 根据架构分类
根据智能体之间的架构关系,MAS 可以分为以下 3 种类型:
| 类型 | 定义 | 示例 | 优点 | 缺点 |
|---|---|---|---|---|
| Centralized MAS(集中式 MAS) | 有一个中央调度智能体(Central Coordinator),负责控制所有其他智能体的执行、分配任务、协调冲突。 | 早期的 LangChain SequentialAgent、MultiActionAgent。 |
架构简单、易于实现、易于协调冲突。 | 中央调度智能体是单点故障(Single Point of Failure)——如果中央调度智能体挂了,整个 MAS 就会崩溃;可扩展性差——随着智能体数量的增加,中央调度智能体的负担会越来越重。 |
| Decentralized MAS(分布式 MAS) | 没有中央调度智能体,所有智能体都是平等的,智能体之间通过协商或消息传递来协调冲突、分配任务。 | AutoGen、一些基于区块链的 MAS。 | 没有单点故障、可扩展性好、鲁棒性强。 | 架构复杂、难以实现、难以协调冲突、可能会出现任务死锁或无限循环。 |
| Hierarchical MAS(分层式 MAS) | 有一个分层的架构——上层有几个中央调度智能体,负责控制下层的智能体;下层的智能体之间可以通过协商或消息传递来协调冲突。 | 某智慧城市公司的“多区域交通监控-调度-决策 Agent 联盟”(上层是杭州的中央调度 Agent 集群,下层是北京、上海、广州的本地 Agent 集群)。 | 结合了集中式 MAS 和分布式 MAS 的优点——没有完全的单点故障、可扩展性好、易于协调冲突、鲁棒性强。 | 架构比集中式 MAS 复杂,但比分布式 MAS 简单。 |
现在我们常说的 LLM-MAS,大多是分层式 MAS——因为分层式 MAS 既避免了集中式 MAS 的单点故障问题,又避免了分布式 MAS 的架构复杂和协调冲突困难的问题。
2.1.3.3 根据智能体的智能程度分类
根据智能体的智能程度,MAS 可以分为以下 3 种类型:
| 类型 | 定义 | 示例 |
|---|---|---|
| Reactive Agents(反应式智能体) | 只能根据环境(或协作上下文)的当前状态做出反应,没有记忆,没有规划能力。 | 早期的基于规则引擎的智能体、一些简单的 LLM 驱动的智能体(比如只会调用搜索工具回答问题的智能体)。 |
| Deliberative Agents(慎思式智能体) | 有记忆,有规划能力,能够根据环境(或协作上下文)的历史状态和当前状态,制定规划,实现自己的目标。 | 现在大多数 LLM 驱动的智能体(比如能够生成代码、然后审查代码、然后修改代码的智能体)。 |
| Hybrid Agents(混合式智能体) | 结合了反应式智能体和慎思式智能体的优点——对于简单的问题,能够快速做出反应;对于复杂的问题,能够制定规划,实现自己的目标。 | 现在最先进的 LLM 驱动的智能体(比如 Devin 程序员代理人)。 |
2.2 LLM-MAS 的核心概念与架构
为了后面讨论 MAS 可观测性的方便,我们需要先定义一些专门针对 LLM-MAS 的核心概念,并给出一个通用的 LLM-MAS 架构。
2.2.1 LLM-MAS 的核心概念
2.2.1.1 Agent(智能体)
在 LLM-MAS 中,Agent 是一个独立的执行单元,由以下 5 个部分组成:
- Identity(身份):Agent 的唯一标识符(比如
product_manager_agent_001)、角色(比如“产品经理”、“技术负责人”、“测试工程师”)、描述(比如“你是一位资深的产品经理,负责根据用户的一句话需求生成需求规格说明书初稿”)。 - LLM(大语言模型):Agent 的“大脑”,负责理解输入、生成输出、做出决策。可以是任何 LLM——比如 GPT-4 Turbo、Claude 3 Opus、Llama 3、Gemini Pro 1.5。
- Prompt(提示词):Agent 的“指令集”,告诉 Agent 应该做什么、怎么做、用什么格式输出。Prompt 一般包含以下几个部分:
- System Prompt(系统提示词):定义 Agent 的身份、角色、描述、输出格式、限制条件等。
- User Prompt(用户提示词):当前任务的具体要求(比如用户的一句话需求)。
- Context Prompt(上下文提示词):协作上下文(State)的内容,让 Agent 了解之前的协作过程。
- Tools(工具集):Agent 可以调用的外部工具——比如搜索工具(Google Search、Wikipedia Search)、代码执行工具(Python REPL、Docker)、数据库查询工具(MySQL Connector、PostgreSQL Connector)、文件操作工具(Read File、Write File)等。
- Memory(记忆):Agent 的“短期记忆”和“长期记忆”——短期记忆一般存储在协作上下文(State)里,长期记忆一般存储在向量数据库(比如 Pinecone、Chroma、Weaviate)里,用于存储 Agent 的历史执行结果、用户的历史反馈等。
2.2.1.2 State(协作上下文)
在 LLM-MAS 中,State 是整个协作任务的“单一数据源”(Single Source of Truth),存储了协作任务的所有信息——比如:
- Task Info(任务信息):任务的唯一标识符、创建时间、用户输入、集体目标。
- Agent Execution History(Agent 执行历史):每个 Agent 的执行时间、输入、输出、决策依据。
- LLM Call History(LLM 调用历史):每次 LLM 调用的时间、模型、参数(Temperature、Top P、Max Tokens 等)、完整 Prompt、完整 Response、Token 消耗、调用成本。
- Tool Call History(工具调用历史)
更多推荐



所有评论(0)