跳转到主要内容

未受监控的 Agent 是遥测缺口,而非信任缺口

Agent 之所以在无监控状态下运行,是因为框架输出的是日志,而非结构化 trace。解决办法是把可观测性作为构建期契约,而不是事后补上的工具。

Close-up of a robotic hand with a woman pointing, showcasing advanced prosthetic technology.

重新精确表述这一发现

四分之一的 agent 部署在无监控状态下运行。常见的解读是组织层面的:团队交付太快,没有人对可靠性负责,治理滞后。这种解读令人安心,但基本是错的。当一个系统没有稳定的步骤边界、没有共享的关联标识符、没有 span schema 时,监控就不是纪律问题——而是缺失的原语。你无法靠堆 dashboard 来弥补一个从未发出你想要告警的事件的架构。

为什么监控会被跳过

框架输出的是日志,不是 trace。 典型的 agent 循环写的是人类可读的行:发送了 prompt、选择了工具、解析了响应。日志行产生成本低,但几乎无法聚合。没有父子关系、没有时长、没有状态字段、没有属性命名空间。查询“哪些运行调用了退款工具超过三次”变成了对非结构化文本做正则匹配,这就是为什么没有人去构建这个告警。

数据分散在不同系统中。 模型调用在推理提供商那里。工具调用在应用日志里。检索在向量存储里。策略决策在网关里。每个系统对同一个逻辑操作都有自己的标识符,而且彼此不一致。如果没有在运行边界生成、并传播到每一跳的关联 ID,重建单个 agent 步骤就需要按时间戳 join 四家厂商的导出数据——而一旦两次调用落在同一毫秒内,这种方法就会失效。

埋点是在上线之后才加的。 等到团队决定需要 trace 时,agent 已经重构了两次,工具已经被包上了重试逻辑,步骤边界已经消融成一串异步回调。事后补 span 意味着重新定义什么才算一个步骤,这是设计变更,而不是可观测性变更。它会因为要与功能开发竞争、且在首次严重事故之前没有可见的用户影响而被无限期推迟。

把埋点作为构建期契约

Close-up of colorful illuminated DJ mixer control pad with buttons in vibrant lighting.

另一种做法是把可观测性视为 agent 接口的一部分,像类型签名或 schema 迁移一样强制执行。

每个步骤都发出一个 span。 步骤是系统能够独立重试、拒绝或计费的任何单元:一次模型调用、一次工具调用、一次检索、一次策略评估。span 携带输入、输出、成本、延迟以及允许该操作的政策决策。成本不是事后从 token 数推导出来的指标;它是发出时写入的属性,因为定价会变化,而在长保留窗口上做追溯重算正是审计轨迹的葬身之地。

关联 ID 跨边界传播。 运行 ID 只生成一次,然后贯穿出站 HTTP 头、数据库会话上下文和消息队列元数据。具体机制是由运行时注入、由每个适配器读取的上下文对象,因此调用外部 API 的工具不需要知道自己正在被追踪——HTTP 客户端包装器附加请求头,数据库驱动设置会话变量,队列发布者复制该字段。当下游服务记录同一个 ID 时,trace 就端到端闭合了,无需手工拼接。

采样策略要事先声明。 对每次运行做全保真追踪,在大规模下很少负担得起。构建期契约要说明采样策略:哪些运行始终被追踪(被拒绝的操作、高成本运行、每次部署的前 N 次),哪些按概率采样,以及什么会被丢弃。采样决策在根 span 处做出,这样被采样掉的一次运行是一致地缺席,而不是半存在——后者正是让 trace 数据不可信的失败模式。

一个最小的 span schema 长这样:

{
  "trace_id": "run_8f2c...",
  "span_id": "step_01",
  "parent_span_id": null,
  "kind": "model.invoke",
  "started_at": "2025-01-01T10:00:00.000Z",
  "duration_ms": 812,
  "attributes": {
    "model": "...",
    "input_tokens": 1042,
    "output_tokens": 233,
    "cost_units": 0.0041,
    "policy_decision": "allow",
    "policy_rule": "read_only_tools"
  },
  "status": "ok"
}

权衡是真实存在的:每个适配器都必须参与,而只要有一个工具没有埋点,整条链就断了。缓解办法是让运行时拒绝执行不接受上下文对象的工具——这是编译期或启动期的检查,而不是运行期的指望。这一约束不受那

Close-up of automated canning equipment in a modern brewery assembly line.

trace 只有在能回答关于具体操作的问题时才有用。

可查询性是审计的试金石。 一个无法按工具名、参数哈希、策略规则或操作者过滤的 trace 只是调试辅助,不是审计轨迹。这意味着 schema 必须包含监管者和事故响应者会问到的字段,而不只是框架碰巧发出的字段。如果“展示所有 agent 在没有人审批 span 的情况下调用支付工具的运行”这个问题无法用单次查询回答,那么埋点就是不完整的。

对行为不变量告警。 错误计数是 agent 系统中最弱的信号,因为失败模式通常是一次本不该发生的成功调用。有用的不变量是结构性的:每次运行的工具调用率对照声明的上限、每次运行的花费对照预算属性、被拒绝操作的数量、检索与模型调用的比率,以及工具出现在其许可策略集之外。这些都可以从 span 计算得出,并且在模型升级后保持稳定,不像延迟阈值会随提供商变化而漂移。

保留与脱敏属于 schema 的一部分。 事后才决定哪些字段包含个人数据,意味着要重新处理历史 trace,这既昂贵,而且一旦原始载荷已经消失往往就不可能。相反,在定义时就把每个属性标记为保留、哈希或脱敏,让管道在写入时应用规则。代价是脱敏字段的调试保真度降低,以及 schema 必须随分类规则变化而版本化。这个成本低于在收到数据主体访问请求时才发现 prompt 和工具输出正躺在某家可观测性厂商的存储里、没有任何字段级策略。

当这成为构建期要求时,会发生什么变化

“四分之一 agent”这个统计数字描述的是一群从未拥有这些原语的系统。那些在启动前就定义步骤边界、生成运行 ID、将其传播到每个适配器并声明采样与保留策略的团队,之后面对的不是一个监控决策——而是一次 schema 迁移,这是一项被充分理解的工程任务。令人不适的部分在于,这项工作发生在有任何可见问题来证明其必要性之前,而且它会限制新工具添加的速度。这就是诚实的权衡:以更慢的工具集成为代价,换取一个其行为可以被重建、查询和控制的系统。另一种选择是一群 agent,它们之所以被信任,恰恰是因为没有人能看到它们在做什么。

封面照片:Suki Lee / Pexels。

分享XLinkedIn永久链接5 分钟阅读

相关阅读

这能回答的问题

Why do so many agent deployments lack monitoring?

Most agent frameworks emit unstructured logs rather than spans with parent-child relationships, tool calls and model invocations live in separate systems without a shared correlation ID, and instrumentation is typically added after launch when the step boundary is already unstable. These are missing primitives, not lapses in discipline.

What should an agent span contain?

At minimum a trace ID, span ID, parent span ID, span kind, start time, duration, status, and attributes covering inputs, outputs, cost, latency and the policy decision that permitted the action. Each attribute should also carry a retention and redaction classification.

What should agent alerting be based on?

Behavioural invariants rather than error counts: tool call rate per run, spend per run against a declared budget, denied action counts, retrieval-to-invocation ratios, and tools invoked outside their permitted policy set.

What is the main trade-off of build-time instrumentation?

Every adapter must participate, and the runtime should refuse to execute tools that do not accept the tracing context. This slows tool integration and adds schema versioning work, in exchange for traces that can be queried for specific actions and used as an audit trail.