
多 Agent 协同的分布式跟踪基于 OpenTelemetry 追踪 Agent 调用链与耗时分析在多智能体Multi-Agent复杂协作系统中主控规划 AgentSupervisor通常会发起多层嵌套、并发扇出的子任务派发体系主控 Agent 派发子任务给“检索 Agent”与“数据清洗 Agent”检索 Agent 内部触发了 3 次并行的 Tool Call查询向量数据库、搜索外部知识库、调用 Elasticsearch 倒排索引最终将结构化结果汇聚给“报告生成 Agent”调用大模型执行长文本流式生成。在这个错综复杂的多步骤链条中如果一次端到端生成耗时长达 15 秒到底是检索 Agent 查向量库发生了慢查询还是大模型在某一步决策反思时产生了长达 8 秒的思考延迟或者是子 Agent 之间的数据传输发生了序列化与反序列化阻塞甚至在并发执行子任务时某个 Tool 调用由于网络异常静默重试了 3 次如果缺乏细粒度的分布式链路追踪Distributed Tracing多 Agent 系统就是一个完全不可视的“黑盒迷宫”排障只能靠盲目打日志猜测极大地推高了线上故障定位成本。今天我们深入拆解如何利用云原生统一标准OpenTelemetryOTel在多 Agent 协同体系中构建Agent 决策级、Tool 执行级、LLM 推理级的三层树状分布式 Trace并在 Jaeger 中实现纳秒级调用瀑布图与 Token 成本透视。一、多 Agent 分布式链路追踪的三层树状模型全景图在多 Agent 系统中传统的基于 HTTP 接口粒度的 Trace 已经无法满足需求。我们必须构建精细化的三层嵌套 Span 模型flowchart TD UserQuery[用户请求: 生成行业研报分析] -- Span_Root[Span 1: Root - Supervisor Main Workflow] Span_Root -- Span_Plan[Span 2: Supervisor 意图规划 (LLM Call)] Span_Root -- Span_AgentA[Span 3: Research Agent 调研子任务] Span_Root -- Span_AgentB[Span 4: Synthesis Agent 汇总报告生成] Span_AgentA -- Span_Tool1[Span 5: Tool - VectorSearch (查向量库)] Span_AgentA -- Span_Tool2[Span 6: Tool - WebCrawler (抓取公开财报)] Span_AgentB -- Span_LLM_Gen[Span 7: LLM 流式长文本生成 (耗时 6.2s)]关键 OTel GenAI 语义约定规范Semantic Conventionsgen_ai.agent.name当前执行的 Agent 角色名称如Research_Agent、Critic_Agentgen_ai.system大模型供应商或推理引擎如vLLM/OpenAI/Qwengen_ai.usage.prompt_tokens与completion_tokens单步消耗的精确 Token 数量gen_ai.tool.name与tool.status工具名称与执行状态gen_ai.prompt与gen_ai.completion在合规前提下记录模型输入输出摘要。二、生产级 Python OpenTelemetry 多 Agent 追踪代码实现import time from typing import Dict, Any, List from opentelemetry import trace from opentelemetry.trace import Status, StatusCode from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import Resource # 1. 初始化 OpenTelemetry 全局 Tracer def setup_agent_telemetry(service_name: str multi-agent-system, otlp_endpoint: str localhost:4317): resource Resource.create({service.name: service_name, environment: production}) provider TracerProvider(resourceresource) # 异步批量导出器避免阻塞 Agent 主执行线程 exporter OTLPSpanExporter(endpointotlp_endpoint, insecureTrue) provider.add_span_processor(BatchSpanProcessor(exporter)) trace.set_tracer_provider(provider) return trace.get_tracer(agent-orchestrator) tracer setup_agent_telemetry() # 2. 核心带完整 Span 树状注入的多 Agent 执行框架 class TracedAgentRunner: def __init__(self, agent_name: str): self.agent_name agent_name def execute_subtask(self, parent_ctx: trace.Context, task_name: str, payload: dict) - dict: 在父级 Context 下开启子 Agent 的独立 Span span_name fAgent: {self.agent_name} - {task_name} with tracer.start_as_current_span(span_name, contextparent_ctx) as agent_span: agent_span.set_attribute(gen_ai.agent.name, self.agent_name) agent_span.set_attribute(gen_ai.task.type, task_name) agent_span.set_attribute(agent.input_payload_size, len(str(payload))) try: # 步骤 1: 模拟调用底层检索工具 self._execute_traced_tool(task_name) # 步骤 2: 模拟大模型推理与反思 result self._execute_traced_llm_call(task_name) agent_span.set_status(Status(StatusCode.OK)) return {status: SUCCESS, data: result} except Exception as e: # 记录异常事件与堆栈 agent_span.record_exception(e) agent_span.set_status(Status(StatusCode.ERROR, str(e))) raise e def _execute_traced_tool(self, tool_name: str): 内部工具调用的细粒度 Child Span with tracer.start_as_current_span(fToolCall: {tool_name}) as tool_span: tool_span.set_attribute(gen_ai.tool.name, tool_name) tool_span.set_attribute(tool.vendor, InternalQdrant) time.sleep(0.15) # 模拟工具耗时 150ms tool_span.set_attribute(tool.affected_records, 42) def _execute_traced_llm_call(self, prompt: str) - str: 内部大模型推理调用的细粒度 Child Span with tracer.start_as_current_span(LLM: ChatCompletion) as llm_span: llm_span.set_attribute(gen_ai.model, qwen2.5-14b) llm_span.set_attribute(gen_ai.temperature, 0.2) time.sleep(0.6) # 模拟模型生成耗时 600ms # 记录 Token 消耗指标与计费属性 llm_span.set_attribute(gen_ai.usage.prompt_tokens, 850) llm_span.set_attribute(gen_ai.usage.completion_tokens, 320) llm_span.set_attribute(gen_ai.usage.total_tokens, 1170) return 生成的分析报告内容三、主控编排执行与 Jaeger 瀑布图还原def run_full_workflow_orchestration(): # 开启全局 Root Span with tracer.start_as_current_span(Workflow: GenerateMarketReport) as root_span: root_span.set_attribute(user.id, user_884920) root_span.set_attribute(workflow.priority, HIGH) current_ctx trace.get_current_span().get_span_context() print([*] 正在执行多 Agent 协同任务...) # 1. 调研 Agent 并发执行 research_agent TracedAgentRunner(ResearchAgent) research_agent.execute_subtask(None, RetrieveCompetitorData, {target: tech_industry}) # 2. 汇总生成 Agent 执行 writer_agent TracedAgentRunner(ReportWriterAgent) writer_agent.execute_subtask(None, SynthesizeFinalDocument, {style: professional}) print([✓] 全流程执行完毕Trace 已异步上报至 Jaeger)四、深水区机制异步并发扇出Fan-Out时的上下文传递在多 Agent 系统中Supervisor 常常需要使用asyncio.gather或多线程同时触发 5 个子 Agent 协同工作。核心避坑点Python 的trace.get_current_span()基于contextvars。在跨线程派发任务时子线程默认不会继承父线程的 Context必须显式捕获当前的 Context并在子协程/子线程启动时将其作为上下文激活trace.use_span(span)确保所有的子任务 Span 均正确挂载在 Supervisor 的 Root Span 之下杜绝出现断裂的孤岛 Span五、生产治理三大黄金法则秒级定位慢 AgentBottleneck Identification打开 Jaeger 看板甘特图上能一眼看清哪个子 Agent 耗时占比超过 70%消除团队排障推诿单请求 Token 账本透视Token Cost Accounting在 Root Span 汇总计算整条调用链累计消耗的 Prompt / Completion Tokens精准核算单次复合任务的边际物理成本结合 Prometheus 建立性能大盘基于 Span 自动衍生出各 Agent 的 P99 延迟与错误率告警指标。把全链路追踪作为多 Agent 系统的标准骨架智能体的复杂协作才能从“不可捉摸的黑盒”转变为“透明可控的现代化工业流水线”。