
1. 从一次 Agent 静默失败说起为什么日志、指标、追踪缺一不可如果你正在做 Agent 开发大概率遇到过这种场景本地跑得好好的任务上线后成功率突然掉到 60%但控制台没有任何报错模型返回也“看起来正常”。你翻遍 print 日志只能看到零散的 prompt 和 response根本串不起一次完整执行链路。问题往往出在第二步工具调用的参数被模型悄悄改写了而你没有留下任何结构化证据。这就是 Agent Harness 可观测性要解决的核心问题。Agent Harness 可以理解成套在 Agent 外面的一层“缰绳”它不改变 Agent 的推理逻辑但负责记录每一次 LLM 调用、工具调用、记忆读写和规划步骤。日志负责回答“发生了什么”指标负责回答“整体健康度如何”追踪负责回答“问题出在链路的哪一环”。三者通过同一个 trace_id 关联才能把黑盒变成可回放的执行记录。这篇内容面向正在用 LangChain、LlamaIndex 或自研 Agent 框架的开发者也适合刚接触 Agent 工程化、想给项目加上可观测能力的同学。我会先给出 TaoToken 统一 Key 与 API 通道的配置骨架再演示一次从报错到追踪定位的完整验证动作最后把日志、指标、追踪三件套的落地细节和常见坑讲清楚。全程可复制不需要你改 Agent 的核心业务代码。2. TaoToken 前置统一 Key 与 API 通道准备在给 Agent Harness 接可观测之前先把模型调用通道固定下来。TaoToken 提供统一的 API 入口兼容 OpenAI 风格的请求格式这样你的 Agent 无论底层换哪个模型Harness 采集到的 LLM 交互日志格式都是一致的追踪链路不会因为换模型而断裂。你需要先拿到一个 API Key。登录官网后进入控制台在 API Keys 页面创建一个新 Key建议按项目命名比如agent-harness-dev方便后续在日志里区分不同 Agent 实例的调用来源。创建后立即复制保存页面刷新后不会再完整显示。TaoToken 的 API 基础地址是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 base_url 使用。模型对话、Coding Plan、控制台和 API Keys 管理分别对应不同的入口接入阶段你只需要关心 API Key 和 base_url 两个信息。注意API Key 不要硬编码在 Agent 业务代码里建议通过环境变量注入Harness 的日志脱敏规则也要把sk-开头的字符串纳入替换范围避免 Key 泄露到观测数据里。3. 可复制配置config.toml 与 settings.json 骨架下面给出两份可直接落地的配置骨架。config.toml用于 Harness 运行时读取settings.json用于 Agent 框架或 IDE 插件读取。两者都指向 TaoToken 的统一通道并且把可观测相关的开关集中管理。3.1 config.tomlHarness 运行时配置# config.toml - Agent Harness 运行时配置 [llm] provider taotoken base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY default_model gpt-4o-mini timeout_seconds 60 max_retries 2 [observability] enabled true trace_id_header x-trace-id span_id_header x-span-id log_format json log_level info metric_port 8000 sample_rate 1.0 [observability.log] capture_prompt true capture_response true capture_tool_args true capture_tool_result true desensitize true [observability.trace] exporter otlp otlp_endpoint http://localhost:4318/v1/traces service_name agent-harness [observability.metric] exporter prometheus namespace agent_harness [harness] fuse_error_rate 0.3 fuse_window 20这份配置的关键点有三个。第一api_key_env指定从环境变量读取 Key避免明文。第二sample_rate设为 1.0 表示开发阶段全量采集生产环境可以降到 0.1 到 0.3只保留错误和慢请求的完整 Trace。第三fuse_error_rate是熔断阈值当最近 20 次调用的错误率超过 30% 时Harness 会主动中断 Agent 执行防止错误扩散。3.2 settings.jsonAgent 框架侧配置{ agent: { name: search_agent_v1, framework: langchain, harness_callback: obsagent_harness.ObsAgentHarnessCallback }, llm: { base_url: https://taotoken.net/api, api_key: ${TAOTOKEN_API_KEY}, model: gpt-4o-mini, temperature: 0 }, observability: { trace_enabled: true, log_enabled: true, metric_enabled: true, trace_context_propagation: true, sensitive_patterns: [ 1[3-9]\\d{9}, \\d{17}[\\dXx], sk-[a-zA-Z0-9]{48} ] }, tools: [ { name: Search, type: duckduckgo, timeout: 15 } ] }settings.json里的trace_context_propagation必须开启否则多 Agent 协作时 Trace ID 无法跨进程传递链路会在第二个 Agent 处断掉。sensitive_patterns是脱敏正则Harness 在写入日志和 Trace 属性前会先做替换。3.3 环境变量与启动export TAOTOKEN_API_KEY你的APIKey export OTEL_EXPORTER_OTLP_ENDPOINThttp://localhost:4318启动依赖服务时Jaeger 负责 Trace 展示Prometheus 负责指标抓取Grafana 负责日志和指标的可视化。三者用 Docker Compose 一键拉起即可不需要单独配置。4. 验证请求从报错到追踪定位的完整动作配置就绪后我们用一个会故意失败的 Agent 任务来验证三件套是否生效。这个任务让 Agent 先搜索一个关键词再调用一个不存在的工具观察 Harness 能否把错误定位到具体 Span。4.1 注入 Harness 回调并运行import os import time from langchain.agents import initialize_agent, Tool from langchain_openai import ChatOpenAI from obsagent_harness import ObsAgentHarnessCallback os.environ[TAOTOKEN_API_KEY] 你的APIKey llm ChatOpenAI( base_urlhttps://taotoken.net/api, api_keyos.environ[TAOTOKEN_API_KEY], modelgpt-4o-mini, temperature0 ) def broken_tool(query: str) - str: raise RuntimeError(tool backend unavailable: search_index_timeout) tools [ Tool(nameSearch, funclambda q: mock search result, descriptionsearch web), Tool(nameBrokenTool, funcbroken_tool, descriptiona tool that always fails) ] harness ObsAgentHarnessCallback( agent_idsearch_agent_v1, config{fuse_threshold: 0.3} ) agent initialize_agent( tools, llm, agentzero-shot-react-description, callbacks[harness], verboseTrue ) try: result agent.run(先用 Search 查一下 Python 版本再用 BrokenTool 处理结果) print(result:, result) except Exception as e: print(agent failed:, e) print(trace_id:, harness.current_trace_id)运行后你会看到控制台先输出 LLM 调用日志然后工具调用日志最后BrokenTool抛出异常。Harness 捕获到工具错误后会更新当前 Span 的状态为 ERROR并递增错误计数。当错误率超过阈值时熔断逻辑触发Agent 提前终止。4.2 在 Jaeger 中定位失败 Span打开http://localhost:16686在 Service 下拉框选择agent-harness点击 Find Traces。你会看到刚才那次任务的 Trace展开后结构大致如下trace: 7f3a9c2e1b8d4a6f ├── span: agent_run (duration: 3.2s, status: ERROR) │ ├── span: llm_call (duration: 1.1s, status: OK) │ ├── span: tool_call Search (duration: 0.3s, status: OK) │ ├── span: llm_call (duration: 0.9s, status: OK) │ └── span: tool_call BrokenTool (duration: 0.1s, status: ERROR) │ └── error: tool backend unavailable: search_index_timeout失败 Span 上直接挂着异常信息你不需要再去翻控制台日志。点击该 Span可以看到它关联的 trace_id 和 span_id用这两个 ID 去 Grafana 的 Loki 数据源里检索就能拿到同一时刻的结构化日志包括模型当时的 prompt 和工具参数。4.3 用指标确认影响范围访问http://localhost:8000/metrics搜索agent_harness_tool_calls_total你会看到类似输出agent_harness_tool_calls_total{agent_idsearch_agent_v1,tool_nameBrokenTool,statuserror} 1 agent_harness_tool_calls_total{agent_idsearch_agent_v1,tool_nameSearch,statussuccess} 1这说明错误被正确归类到BrokenTool这个工具维度上。如果这是生产环境你可以基于这个指标配置告警当某个工具的失败率在 5 分钟内超过 20% 时触发通知。指标的价值在于它不关心单次请求的细节而是让你快速判断“是个别问题还是系统性问题”。5. 本篇常见错排查日志、指标、追踪落地时的坑5.1 Trace ID 在异步调用中丢失Agent 里经常用asyncio并发调用多个工具如果直接asyncio.create_taskOpenTelemetry 的上下文不会自动传递导致子任务的 Span 变成孤儿节点。解决办法是用contextvars绑定当前上下文或者在创建任务时显式传入trace_id。Harness 的trace_context_propagation开关打开后会在每次工具调用前把当前 Span 的上下文注入到请求头里异步场景下需要你手动调用propagation.extract恢复。5.2 日志里出现明文 API Key这是最常见的低级错误。Harness 的脱敏规则默认只覆盖手机号、身份证和邮箱sk-开头的 Key 需要你自己加到sensitive_patterns里。另外模型返回内容里也可能包含用户粘贴的 Key所以脱敏要在写入日志之前做而不是在展示层做。我试过在 Grafana 里直接搜到过未脱敏的 Key排查后发现是工具返回结果没有走脱敏函数这个坑一定要提前堵上。5.3 指标基数爆炸如果你把user_id或session_id作为 Prometheus 指标的 label指标数量会随用户量线性增长很快把 Prometheus 打爆。正确做法是指标只保留agent_id、model_name、tool_name、status这类低基数维度用户级别的分析交给日志和 Trace。Harness 的metric配置里没有暴露user_id就是这个原因。5.4 采样率设置不当导致关键 Trace 丢失生产环境为了控制成本会把sample_rate调低但错误请求必须全量保留。Harness 支持尾采样策略正常请求按比例采样错误和慢请求强制采集。如果你用的是自定义采样器记得在on_tool_error和on_llm_error回调里把当前 Trace 标记为“必须保留”否则最需要排查的那条链路反而被采样掉了。5.5 熔断阈值过于激进fuse_error_rate设成 0.1 时Agent 可能因为一次网络抖动就触发熔断导致正常任务被中断。建议开发阶段设 0.3 到 0.5生产环境根据历史错误率基线调整。熔断触发后 Harness 会抛出异常你的业务代码需要捕获这个异常并决定是重试还是降级不要让异常直接冒泡到用户侧。6. 把可观测性变成 Agent 的默认能力日志、指标、追踪三件套在 Agent Harness 里的分工很明确追踪定位链路日志还原现场指标判断范围。三者通过 trace_id 串联后你排查问题的路径从“翻控制台猜”变成“打开 Jaeger 看失败 Span再用 trace_id 查日志最后看指标确认影响面”。接入阶段建议先用 TaoToken 的统一 Key 和 API 通道把模型调用固定下来再按本文的config.toml和settings.json骨架把 Harness 回调注入到 Agent 里。验证时故意制造一个工具调用失败确认 Jaeger 里能看到 ERROR Span、Grafana 里能查到关联日志、Prometheus 里能读到失败计数。这三步都通过后再逐步把采样率调低、把熔断阈值调到生产可用的范围。如果你正在做长期编码类 Agent 或需要多轮工具调用的场景可以进一步了解 Coding Plan 的接入方式把可观测配置和模型通道一起纳入版本管理。接入文档里有完整的参数说明和示例API Keys 页面可以随时轮换 Key。先把观测链路跑通再谈 Agent 的自动优化和自治顺序不能反。