你在做一个大模型应用时,大概率遇到过这样的画面:本地联调时表现极好的聊天机器人,一上线就开始在一些奇怪问题上胡说八道。你说不清是提示词写得不稳,还是知识库版本被某个同事悄悄替换了;你打开监控面板,看到请求成功率 99.9%,延迟也很平稳,却没有一个指标能告诉你“为什么用户普遍反馈变笨了”。
这是传统监控体系面对大模型应用时最尴尬的盲区:系统没有故障,但模型行为在悄悄劣化。AI 可观测性要解决的,正是这类“应用活着、但效果在崩”的问题。它并不是传统监控的改版,而是从埋点、追踪、评估、成本治理到回归测试的一整套新链路。今天想借一个行业事件来聊透这件事:Dynatrace 宣布计划收购 AI 可观测性公司 Arize AI。
这则消息对后端工程师和 AI 应用开发者的真正含义,不是又多了一桩资本并购,而是“AI 应用的可观测性正在成为平台级能力”这一判断,开始被主流监控厂商验证。读完这篇文章,你会理解 AI 可观测性的概念边界、它与传统 APM 的本质差异,并拿到一套可以最小化跑通的 LLM 链路追踪、质量评估和成本统计示例,直接用到自己的大模型项目里。
1. 这则消息为什么值得开发者关注
Dynatrace 一直是应用可观测性领域的头部厂商,核心能力是面向企业级 IT 系统的监控、链路追踪和智能运维,且很早就把和 AI 结合起来的思路放进了产品中,比如在故障定位时用 AI 辅助判断根因。Arize AI 则有所不同,它更聚焦在模型本身的行为监控上,做得比较深的是 LLM 追踪、评估体系、实验对比和模型生产环境的性能监控。
从公开信息来看,这是一次典型的能力拼图式收购:一家拥有成熟基础设施监控能力的大厂,去买一个在模型评估与链路追踪上有技术积累的团队。对开发者来说,真正的信号有两层。
第一层信号是“模型行为本身正在成为系统监控的一部分”。过去我们的监控体系围绕服务、容器、数据库、中间件来建,关心的是请求能否成功返回。但大模型应用的核心价值在于生成内容的质量,请求成功不等于回答正确。Arize 这类工具的切口,正好就是模型输出的质量评估、归因和回放调试。这件事如果被主流监控平台整合,意味着以后的监控告警不再只是“应用挂了”,还会包含“模型输出跑偏了”。
第二层信号是 AI 可观测性的技术栈正在逐步标准化。很多团队做 LLM 应用排查时,最麻烦的不是看不到日志,而是每个团队都有自己的埋点方式,有的把 prompt 直接打到日志里,有的只在出问题时才临时打印上下文。这种混乱状态很难支撑规模化排查。主流监控平台开始整合模型评估能力,会推动更多团队沿 OpenTelemetry GenAI 语义约定这一套通用规范来埋点,让链路追踪、模型调用、评估结果、成本数据从“各方自定义”走向“统一格式”。
当然,这笔收购的最终完成还会受监管审批和交割条件影响,本文不作任何落地时间推断。我们更应该关注的是技术趋势本身:AI 可观测性正在从少数团队的“自研补丁”,变成一个平台级的基础设施问题。
2. AI 可观测性到底是什么:概念边界与核心要素
AI 可观测性,也叫 AI Observability,指对 AI 应用内部状态、模型行为和输出质量进行观测、追踪、评估与诊断的能力。它不等同于传统的应用监控,也不只是给日志加几个字段,而是把“模型调用链”和“输出质量”纳入可观测范围。
传统可观测性覆盖三大支柱:指标、日志、链路追踪。AI 可观测性在这三个支柱之上,又增加了几层新内容:
- 模型调用追踪:记录一次大模型请求从提示词组装、模型调用、工具调用、知识库检索到最终结果返回的完整链路。
- 输出质量评估:不仅记录模型输出了什么,还要评估这个输出对不对、是否忠于上下文、是否有幻觉、是否符合安全要求。
- 成本与用量治理:统计 token 消耗、模型成本、不同业务线的调用配额,避免大模型应用上线后成本失控。
- 实验与回归:把生产环境抓到的失败样本沉淀成回归集,用来验证新提示词或新模型版本是否会修复问题,并引入新问题。
理解 AI 可观测性时,最容易混淆的是它和 MLOps 的边界。MLOps 关注的是模型训练、实验、部署和模型版本管理的完整生命周期,核心对象是模型训练流程;AI 可观测性更关注模型部署上线后,在生产环境中运行的行为、质量、成本和链路。简单说,MLOps 解决“模型怎么上线”,AIObservability 解决“上线后怎么知道它还好不好、出了问题怎么查”。
| 维度 | 传统应用监控 | MLOps | AI 可观测性 |
|---|---|---|---|
| 核心对象 | 服务、容器、数据库 | 模型训练、实验、部署流程 | 生产环境中的模型调用与输出质量 |
| 主要关心的指标 | 可用率、延迟、错误率、资源占用 | 模型指标、训练收敛、特征分布 | 输出质量、幻觉率、成本、链路正确性 |
| 链路追踪粒度 | HTTP 调用、数据库 SQL | 实验版本、数据版本 | 一次 LLM 调用内的 prompt、context、模型输出 |
| 典型使用时机 | 系统故障排障 | 上线前与训练阶段 | 上线后持续监控与排障 |
对做 AI 应用的人来说,理解这个概念的关键点是:模型本身不是黑盒,但它的行为受到提示词、上下文、模型版本、历史会话等多重因素影响。AI 可观测性就是把黑盒拆开,让你能回答三个问题:模型这次为什么这样回答、这次回答质量如何、这次调用花了多少钱。
3. 传统 APM 为什么管不住大模型应用
很多团队刚做大模型项目时,第一反应是把 OpenAI SDK 或自有模型的调用包装一层日志,然后在原有的监控系统上加一个自定义指标。这种方案在 Demo 阶段没有任何问题,但当应用进入生产环境,问题就会逐渐暴露。
传统 APM 以“服务”和“资源”为中心。它假设一个系统的故障模式是服务不可用、接口超时、数据库连接异常、CPU 或内存被打满。可大模型应用的主要故障模式完全不同:模型服务本身没有崩溃,接口响应也非常快,但返回内容质量明显下降。这种故障无法通过可用率指标发现,传统监控面板上看起来一切都是绿的。
举个例子,一个 RAG 类知识库问答系统上线后,工程师突然收到大量用户反馈“回答变差了”。他们打开监控面板,发现模型服务请求成功率还是 99.9%,平均延迟甚至比前几天还低。真正的问题可能出在知识库向量化脚本在某次发布时遗漏了重建索引入口,导致检索召回了一批过期文档;也可能是上游改了 prompt 模板,在拼接用户问题时引入了一段错误的指令。这些原因都不在传统监控的关注范围内,因为请求链路本身是通的。
另一个典型场景是 Agent 应用。AI Agent 会在一轮用户请求中多次调用模型,并穿插调用工具、查询数据库、读取文件。如果某个中间工具返回了空数据,Agent 可能会“强行”基于缺失信息继续往下编造。这时候排查路径不是看某个服务的错误率,而是要恢复完整的调用链:用户问题、模型思考过程、工具返回结果、最终模型输出。传统 APM 的调用链不会记录模型的思考文本和工具返回细节,因此无法完成这类定位。
日志系统也没办法简单解决。直接把完整的 prompt 和模型输出打到常规日志中,会带来明显的隐私和性能问题;PII 信息、敏感业务数据、token 费用的统计格式,都不是普通日志框架擅长的。更麻烦的是,模型输出质量是一个需要“带参考系”才能判断的指标,必须结合业务上下文和评估基准来看,常规日志没有这种结构。
所以,与其说传统 APM“不够用”,不如说大模型应用引入了一种新的故障类型:行为劣化。这种故障需要新的数据模型、新的评估方法和新的调试流程,这就是为什么 AI 可观测性会成为一个独立方向。
4. AI 可观测性的三个核心层:追踪、评估、成本治理
如果把一个可落地的 AI 可观测性体系拆开,大概率会得到三个相互独立又需要打通的层次。
4.1 第一层:链路追踪
链路追踪是 AI 可观测性的地基。它记录一次用户请求中发生了多少次模型调用、每次调用的模型名和参数、输入的 prompt、输出的 response、token 消耗和时间开销,以及上下文信息和工具调用结果。没有这层数据,后续的评估和成本分析都无从谈起。
链路追踪的关键设计点在于统一 Span 语义。建议直接参考 OpenTelemetry 社区推动的 GenAI 语义约定:gen_ai.system记录模型供应商,gen_ai.request.model记录模型名,gen_ai.usage.prompt_tokens和gen_ai.usage.completion_tokens记录消耗的 token 数。采用统一约定之后,无论底层是大模型供应商、开源模型、还是自研小模型,上层的追踪平台都能用同一套逻辑解析数据。
4.2 第二层:质量评估
追踪告诉我们模型“做了什么”,但无法回答“做得好不好”。质量评估层负责判断输出质量,常见的做法包括:基于规则的检查,比如是否包含特定敏感词、长度是否异常;基于统计的方法,比如输出文本与源文本的相似度、不确定性估计;以及基于模型的评估,由另一个大模型作为 Judge 对输出进行打分。
生产环境中,质量评估不需要覆盖所有请求。更稳妥的做法是采样评估:对重要的业务流量做全量标记,对普通流量按比例采样。同时把生产环境发现的错误样本存入评估数据集,形成回归集。下一次更新 prompt、升级模型版本或调整 RAG 参数前,先用回归集跑一遍,可以提前发现“修复 A 问题却引入 B 问题”的情况。
4.3 第三层:成本治理
大模型应用的成本问题是很多团队上线后才意识到的“隐性地雷”。一次普通问答可能消耗几百 token,看起来不多,但流量放大后就是一笔不小的开支。如果不按业务线、用户、功能场景做 token 消耗统计,成本一旦失控,很难定位是哪部分流量导致。
成本治理需要配合链路追踪中的用量数据,给每个 Span 打上业务标签,比如product.name、feature.name、user.segment,再按照标签维度聚合 token 消耗和费用。这样既能做成本报表,也能做预算告警。比如某个运营活动上线后,如果单体用户调用量异常上升,成本聚合面板能快速发现。
这里要特别强调:三个层不是独立部署,而是共享同一份追踪数据。追踪数据采集后,评估层从 Span 中读取模型输入输出,成本层从 Span 中读取 token 统计。一份数据,多种用途,这是 AI 可观测性与传统“监控大杂烩”的本质区别。
5. 最小可落地的 LLM 可观测性示例
下面用一个最小化示例演示前面讲的链路。我会构造一个模拟的 LLM 客户端,核心目的是让你在没有真实模型 API 的情况下,也能启动一个完整的追踪与评估链路,看到数据长什么样。实际项目中,你只需要把FakeLLMClient.generate()替换成真实模型调用。
5.1 环境准备
本示例基于 Python 3.9 及以上版本,需要安装 OpenTelemetry SDK。建议新建虚拟环境:
mkdir llm-obs-demo && cd llm-obs-demo python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install -U opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp为了让代码更贴近生产场景,可以加上opentelemetry-exporter-otlp,后面需要接入 OTLP Collector 时直接复用。如果只是本地验证,使用 SDK 自带的 ConsoleSpanExporter 即可。
5.2 示例一:为一次 LLM 调用构建完整链路
先写一个模拟的 LLM 客户端。这个客户端会在启动 Span 后,记录和真实模型调用一致的关键字段。代码路径为llm_obs_demo/llm_client.py。
# 文件路径:llm_obs_demo/llm_client.py import random import time from opentelemetry import trace from opentelemetry.trace import Status, StatusCode tracer = trace.get_tracer("llm-obs-demo") class FakeLLMClient: """最小模拟客户端,用于演示链路结构。实际项目中替换为你使用的模型服务。""" def __init__(self, model_name: str = "demo-model"): self.model_name = model_name # 按实际模型价格填写,单位:美元 / 千 token self.cost_per_1k_prompt = 0.0 self.cost_per_1k_completion = 0.0 def generate(self, prompt: str) -> dict: with tracer.start_as_current_span("llm.generate") as span: span.set_attribute("gen_ai.system", "demo") span.set_attribute("gen_ai.request.model", self.model_name) span.set_attribute("gen_ai.request.prompt", prompt) latency = random.uniform(0.1, 0.5) time.sleep(latency) response_text = f"针对「{prompt}」的模拟生成内容" prompt_tokens = max(1, len(prompt) // 2) completion_tokens = max(1, len(response_text) // 2) span.set_attribute("gen_ai.response.text", response_text) span.set_attribute("gen_ai.usage.prompt_tokens", prompt_tokens) span.set_attribute("gen_ai.usage.completion_tokens", completion_tokens) span.set_attribute("gen_ai.response.latency_ms", round(latency * 1000, 2)) span.set_status(StatusCode.OK) return { "text": response_text, "prompt_tokens": prompt_tokens, "completion_tokens": completion_tokens, "latency_ms": round(latency * 1000, 2), }代码逻辑很简单:每次调用generate()时,创建一个名为llm.generate的 Span,然后把“模型系统、模型名、prompt、响应文本、token 数、延迟”作为 Span 属性写入。生产环境接入真实 SDK 时,OpenTelemetry 的集成库通常会自动完成这些字段的写入,但理解底层结构仍然非常重要。
5.3 示例二:把质量评估结果写入 Span
追踪只解决“看到了什么”,这一层解决“这次回答好不好”。为简化演示,我用一个基于规则的评估函数模拟“groundedness”和“安全分数”,生产环境中可以替换为更复杂的评估模型。代码路径为llm_obs_demo/evaluator.py。
# 文件路径:llm_obs_demo/evaluator.py from opentelemetry import trace def evaluate_response(prompt: str, response: dict) -> dict: """将评估结果作为 Span 属性写入,便于后续按标签检索。""" span = trace.get_current_span() text = response["text"] # 简化规则:包含“模拟”字样时给一个偏低的接地分数 groundedness = 0.95 if "模拟" not in text else 0.60 safety_score = 0.99 if "敏感词" not in text else 0.10 span.set_attribute("ai.evaluation.groundedness", groundedness) span.set_attribute("ai.evaluation.safety", safety_score) return { "groundedness": groundedness, "safety": safety_score, }重点在于:评估结果被写回当前 Span,意味着以后回溯链路时,可以直接看到“这一次生成的质量评分”,而不需要再次调用模型评估。生产环境可以把评估做成独立服务,通过异步方式回写这些属性。
5.4 示例三:成本统计与指标导出
成本统计需要让追踪数据“上价值”。这里给出一个最简单的方式,用 OpenTelemetry Metrics 创建一个 Counter,每调用一次模型就累计成本。代码路径为llm_obs_demo/cost_monitor.py。
# 文件路径:llm_obs_demo/cost_monitor.py from opentelemetry import metrics meter = metrics.get_meter("llm-cost-meter") llm_cost = meter.create_counter( "llm.cost.usd", unit="USD", description="累计 LLM 调用成本", ) def record_cost(response: dict, cost_per_1k_prompt: float, cost_per_1k_completion: float) -> float: prompt_cost = response["prompt_tokens"] / 1000.0 * cost_per_1k_prompt completion_cost = response["completion_tokens"] / 1000.0 * cost_per_1k_completion total_cost = prompt_cost + completion_cost llm_cost.add(total_cost, {"model": "demo-model", "feature": "qa"}) return total_cost这里用 Counter 语义做累计成本,并打上 model 和 feature 标签。实际工程中,建议把用户等级、业务线、调用来源等维度都放进标签,方便后期按维度做成本聚合。
在主程序main.py里串起来:
# 文件路径:main.py from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.sdk.resources import Resource from llm_obs_demo.llm_client import FakeLLMClient from llm_obs_demo.evaluator import evaluate_response from llm_obs_demo.cost_monitor import record_cost resource = Resource.create({"service.name": "llm-obs-demo"}) provider = TracerProvider(resource=resource) provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter())) trace.set_tracer_provider(provider) client = FakeLLMClient(model_name="gpt-demo-1") response = client.generate("今天天气怎么样?") evaluation = evaluate_response("今天天气怎么样?", response) total_cost = record_cost(response, client.cost_per_1k_prompt, client.cost_per_1k_completion) print("response:", response) print("evaluation:", evaluation) print("total_cost_usd:", total_cost)如果要启用 OTLP 导出,只需把ConsoleSpanExporter替换成OTLPSpanExporter,并配置 endpoint 指向你的 Collector 或后端平台。本地验证阶段先用控制台导出器,这样可以直观看到 Span 结构。
6. 运行结果与验证方法
运行上面的main.py,你会在控制台看到类似下面的结构化输出:
{ "name": "llm.generate", "context": { "trace_id": "...", "span_id": "..." }, "attributes": { "gen_ai.system": "demo", "gen_ai.request.model": "gpt-demo-1", "gen_ai.request.prompt": "今天天气怎么样?", "gen_ai.response.text": "针对「今天天气怎么样?」的模拟生成内容", "gen_ai.usage.prompt_tokens": 8, "gen_ai.usage.completion_tokens": 9, "gen_ai.response.latency_ms": 213.45, "ai.evaluation.groundedness": 0.6, "ai.evaluation.safety": 0.99 } }同时,程序末尾会打印:
response: {'text': '针对「今天天气怎么样?」的模拟生成内容', 'prompt_tokens': 8, 'completion_tokens': 9, 'latency_ms': 213.45} evaluation: {'groundedness': 0.6, 'safety': 0.99} total_cost_usd: 0.0如何判断这个示例跑通了?观察三点:
- 控制台是否输出了带
trace_id和span_id的 Span 数据; - Span 属性里是否同时包含
gen_ai.*和ai.evaluation.*两组字段; total_cost是否按照你配置的价格正确计算。
如果运行时没有输出,先检查venv是否激活,以及opentelemetry-api和opentelemetry-sdk是否安装成功。可以执行pip list | grep opentelemetry确认版本。如果出现ModuleNotFoundError,通常是包未安装或虚拟环境没有激活。
这个示例的价值在于:它把 AI 可观测性最核心的数据结构落到了真实代码层面。后面要接任何监控后端,只需要把导出器换成对应平台提供的 OTLP 配置。
7. 生产环境常见问题与排查
在真实项目中,AI 可观测性落地最常见的坑,往往不是监控平台本身,而是埋点数据不完整、评估口径不一致、成本数据对不上。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 链路中只有模型调用,看不到 RAG 检索和工具调用 | 埋点只覆盖了模型层,没有为检索和工具调用创建独立 Span | 查看全链路 Span 列表,确认是否有非gen_ai.*的 Span | 在检索、工具调用、文件读取等关键节点创建独立的子 Span |
| 进入生产后评估分数普遍偏低 | 评估规则或评估模型与生产业务场景不匹配 | 随机抽样人工复核,看评估器的判断是否合理 | 调整评估阈值,或用带标注的回归集重新验证评估器 |
| 成本报表显示异常偏高 | 没有按业务标签聚合,或 Token 统计重复计数 | 对比网关层日志与实际计费数据 | 确认一个请求链路中 Token 只统计一次,统一标签命名 |
| 无法快速定位某次坏回答 | 链路数据没有持久化,或采样率过低导致该条追踪丢失 | 确认采样策略是否覆盖了该用户和功能 | 对重点用户和重点功能使用全量采样,普通流量按比例采样 |
| prompt 中记录了用户手机号等敏感信息 | 埋点时未做脱敏 | 检查 Span 属性,确认是否存在敏感字段 | 在写入 Span 前做脱敏或截断,对非必要数据不记录 |
| 服务重启后历史链路查询不到 | 控制台导出器只能实时打印,无法回放 | 检查后端存储是否配置持久化 | 改用 OTLP 接入 Collector 和后端存储平台 |
这里要提醒一个容易被忽略的问题:AI 可观测性数据不同于普通日志,它的价值高度依赖“上下文完整性”。如果只记录模型输出而不记录当时的 prompt、检索上下文和工具返回值,问题发生时回溯链路基本等于盲猜。所以埋点的第一原则不是“变量越多越好”,而是“每个关键决策点必须有上下文”。
另一个高频问题是对评估口径没有统一管理。有的团队用规则评估,有的团队用模型评估,两个团队对“回答是否正确”的认定标准不同,最后做出来两个口径完全不一致的告警面板。建议评估方案作为统一平台能力维护,评估规则可配置,但口径必须全局一致。
8. 最佳实践与工程落地建议
看完示例,你可能会觉得 AI 可观测性的技术门槛并不高。真正难的是把它接入生产系统后,如何保持数据一致、成本可控、不引入新的安全风险。下面几条是工程落地中比较关键的建议。
8.1 统一使用 OpenTelemetry 语义约定
不要自己造一套链路字段规范。即使短时间看起来更灵活,后期对接任何监控平台都要做一遍字段映射,成本反而更高。建议在团队内直接采用gen_ai.*前缀的约定,并让各业务线在此基础上扩展自定义标签。统一语义约定的价值,会在你从 Demo 走向多业务线共用一套监控平台时迅速体现出来。
8.2 埋点从真实的排查痛点出发
先记录解决真实故障必需的最小字段集,再逐步扩展。比如刚上线时可以只记录模型名、prompt 摘要、token 数、延迟、评估分数、业务标签六个字段。等真正遇到工具调用问题,再补充工具调用的输入输出详情。一上来就把整个 prompt、完整上下文、所有思考过程全量存下来,不仅存储成本高,还会让真正重要的故障埋没在噪音中。
8.3 安全与隐私必须先于功能
prompt 中经常包含用户输入,而用户输入中可能包含姓名、地址、企业内网信息。在把 prompt 写入监控系统前,必须做脱敏处理和访问控制。推荐的策略是:默认不记录原始 prompt,只记录截断后的摘要;确需全量记录的场景,单独开启并按敏感数据标准管理。同时要保证 AI 可观测性平台的数据访问权限独立于业务日志,需要严格审计。
8.4 评估要和回归集绑定
评估如果只用于实时告警,效果往往有限。更有价值的是把生产环境中标记为“坏回答”的样本收集起来,沉淀成回归集。每次调整 prompt、升级模型、修改 RAG 参数前,用同一份回归集做批处理测试,对比改动前后的评估分数。这样你就能用数据回答“新 prompt 是否值得上线”,而不是靠感觉。
8.5 成本统计要提前考虑标签维度
成本治理不是简单地统计“今天花了多少 token”,而是要能回答“是哪个功能、哪个用户群体、哪个模型版本花的”。在初次埋点时,就给 Span 打上product.name、feature.name、model.version、user.level这几个基础标签。后续要按维度分析时,数据已经准备好了,不用再回填历史数据。
8.6 渐进式引入,不要一次性全量改造
AI 可观测性建设可以按照“单业务验证 → 跨业务推广 → 平台化沉淀”的节奏推进。先在一个重要的业务场景上跑通全链路,验证数据质量和告警价值,再逐步推广到其他业务线。全量改造的最大风险,是评估指标还没验证就被铺到所有业务上,最后告警变成噪音,团队反而失去对这套系统的信任。
8.7 关注模型调用层之外的上下文
大模型应用的可观测性问题,往往出在模型调用层之外。RAG 检索到的文档是否正确、Agent 调用的工具是否返回了符合预期的结构化数据、多轮会话历史是否泄漏了越权上下文,这些都值得设计独立的 Span。把模型调用、RAG 检索、工具调用、提示词组装拆成不同的 Span 层级,排障时的第一反应才是从链路图上找断点,而不是翻日志猜问题。
9. 总结与后续学习方向
回到最开始的问题:Dynatrace 收购 Arize AI,对普通开发者最直接的影响,是让 AI 可观测性从一个模糊的概念变成了明确的技术方向。以后大模型应用的可观测性不会停留在“请求成功”这一层,而是会深入到“模型输出是否可信、是否忠于上下文、是否符合业务预期”。这套能力不再是大厂专属,而是每个认真做 AI 应用的团队都需要补齐的基础设施。
这篇文章从概念、原理、示例到生产落地建议,把 AI 可观测性的主要脉络梳理了一遍。建议你先跑通文中的最小示例,把链路追踪、评估、成本这三个模块在本地跑明白,然后回到自己的项目中,选择一条核心业务链路做全链路埋点。
接下来值得深入的内容包括:OpenTelemetry GenAI 语义约定的最新进展、更复杂的评估指标设计、多步 Agent 调用的链路建模、以及基于生产数据构造回归集的具体方法。如果你正在做 AI Agent 开发,建议特别关注工具调用的 Span 设计和上下文恢复,这是目前绝大多数排查事故中最容易卡住的一环。