首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >ooderAgent 规模化可观测实录: 耗时、Token 成本与失败回溯,如何"一树到底"

ooderAgent 规模化可观测实录: 耗时、Token 成本与失败回溯,如何"一树到底"

原创
作者头像
OneCode
发布2026-08-31 08:52:35
发布2026-08-31 08:52:35
120
举报
文章被收录于专栏:ooderAgentooderAgent

作者:ooder 团队 · 2026-08-31 · 关联专栏:Agent 可观测 / 分布式 Agent / 调用链

Agent 可观测|ooderAgent|Trace / SpanToken |归因A2A |分布式SSE 事件流

当 Agent 从"单机玩具"变成"组织级基础设施",团队的关注点就只剩下三件事: 耗时花在模型推理还是工具执行上;Token 消耗集中在哪些会话、哪些模型上; 失败与中断发生在哪一步,过程能不能回溯

DSH(DeepSeek Harness)的解法,是给一个单机 ReAct 编码 Agent挂一个观测插件, 把执行过程还原成 entry / agent / step / chat / tool 五层调用链。 这个思路很干净,但它隐含了一个前提:执行模型是确定的"一轮任务 + 若干 step",数据链路是单机的

ooderAgent 不一样。它是一个 Scene=Agent 的分布式 Agent 框架:

  • 执行模型不是经典 ReAct,而是 CommandPacket 命令驱动的协议型架构——NLP 意图 → 命令树 → 场景编排 → 能力调用;
  • 事件是一等公民,运行时天然产生 三层事件流(API / Core / Engine)与一路完整的 SSE 流式推送
  • 它跑在 自组织 Agent 集群 上(Discovery + Gossip + 心跳),一次任务可以跨越多个 Agent 节点;
  • Token 计量自带 DeepSeek 前缀缓存感知(cacheHit / cacheMiss),成本归因比"输入 / 输出"更细一档。

因此,DSH 的观测插件逻辑不能照搬。本文沿着原文"导语 → 运行原理 → 观测平台 → 落地实践 → 总结"的叙事结构, 把原图逐张重画,按 ooderAgent 的真实设计重新架构出一套可观测平台: 一次任务一条 Trace、五层调用树一树到底、A2A 跨节点横向拼接、Token 缓存感知归因

一、ooderAgent 的运行原理:为什么观测比"单机 ReAct"难一个维度

1.1 不是 ReAct,而是"Scene=Agent"的命令驱动架构

DSH 的执行单元是"turn / step":一个 turn 对应一次任务,turn 内模型反复推理、调工具、看结果。 执行结构在运行前无法确定,这是所有 Agent 观测的第一性困难。

ooderAgent 的 agent-sdk-core 里没有 ReAct 循环类。它的运行主体是 Agent 接口下的五类 Agent:

Agent 类型

职责

SceneAgent

Scene=Agent的核心,持 SceneId / DomainId / Capability 注册表

WorkerAgent

工人模型,execute(capId, params)返回 CompletableFuture

McpAgent/RouteAgent/EndAgent

MCP 接入 / 路由转发 / 终端

每个 Agent 有完整状态机(CREATED → INITIALIZING → INITIALIZED → STARTING → RUNNING → … → ERROR), 由 AgentFactory 统一创建,AgentSession 承载会话(sessionId / capabilities / state / context)。

1.2 命令树:CommandPacket 是执行的一等公民

执行的最小可观测单元不是"step",而是 CommandPacket:

代码语言:javascript
复制
public class CommandPacket {
    private String packetId;
    private CommandDirection direction;        // NORTHBOUND / SOUTHBOUND
    private String parentCommandId;            // 命令树父节点
    private List<String> childCommandIds;      // 命令树子节点 → 天然形成调用链
    private int retryCount;
    private String llmIntent;                  // LLM 意图
    private String reasoningChain;             // 推理链(文本),可拆出推理步数
    private ContextLevel contextLevel;         // GLOBAL/DOMAIN/SCENE/SESSION/EXECUTION
    private TokenUsage tokenUsage;             // 内嵌 token 用量
    public int getReasoningStepCount() { return reasoningChain.split("step").length - 1; }
    public void recordTokenUsage(int promptTokens, int completionTokens, String model) {...}
}

parentCommandId / childCommandIds 就是命令树即调用树。跨 Agent 时由 A2ACommand 接力, 它带着 traceId + List<String> spanIds 跨节点透传——这是 ooderAgent 相对 DSH 最本质的差异: 链路在"协议层"就预留了分布式拼装位

1.3 场景编排:五大场景组流水线

scenario 包把一次复杂任务切成 SG-UNDERSTAND → SG-DESIGN → SG-GENERATE → SG-QUALITY → SG-INTEGRATE 五组, 每组由 ScenarioStep 组成(带 FailureStrategy: FATAL/RECOVERABLE/SKIPABLE、requiredCapabilities、executionTimeMs 结果)。 这是 ooderAgent 独有的"任务中间层"——比 turn 粗、比 step 细,是天然的一级 Span 切分点。

1.4 LLM 函数调用循环在 llm-sdk

真正接近 ReAct 的循环在 llm-sdk:LlmService.chatWithTools + ToolCallingApiImpl, 由 UnifiedLlmService 统一编排,LlmResponse 携带 latency / tokenUsage / finishReason / reasoningContent。 每个真实模型调用都能拿到端到端耗时与 token,这就是 chat 层 Span 的数据来源。

1.5 A2A 与自组织集群:分布式是本分,不是例外

AgentSdkConfig(aiserver)把本节点注册进 CLUSTER_NODE,按角色声明能力(buildCapabilities): ROUTE_AGENT / MCP_AGENT / BPM_AGENT / VFS_STORE_AGENT / VFS_NAMENODE_AGENT / ORG_AGENT / KNOWLEDGE_AGENT / SCENE_AGENT / STUDIO_AGENT / TEST_AGENT / MESSAGE_AGENT。 节点间用 DiscoveryProtocol(UDP 广播)+ GossipProtocol(UDP P2P)+ 心跳/失联清理自组织。 观测对象不是"一个 Agent",而是一整个动态 Agent 舰队。

1.6 事件是一等公民:自带三层事件流 + SSE

ooderAgent 把事件做成一等公民,且严格分三层:

事件

语义

API 层

Event/EventBus

对外可订阅(publish / subscribe / publishSync / publishAndWait)

Core 层

CoreEvent/EventBean

不可变、只观察,内置EventStatistics(published / processed / error)

Engine 层

EngineEvent

可中断、可审计(CallerInfo+AuditLevel),携带状态

下行流式侧,ooder-pro 的 StudioChatSseController → SseEventPushService → SseEmitter 已经推一路完整事件流: connected / token / thinking / step / flow_start / flow_step / flow_tool_call / flow_tool_output / tool_call / tool_result / skill_orchestrate / agent_message / harness_plan / guard_escalation / complete / error …

这意味着观测平台不需要像 DSH 那样"在模型流式管道上包中间件"——事件本来就是现成的数据管道。

图 1 ooderAgent 的分层结构、一次任务的执行时序,以及对外两条数据产出(对应原文图 1,按 ooderAgent 重画)

1.7 自带观测 vs 规模化缺口的对照

维度

ooderAgent 自带

规模化缺口

所需数据

会话轨迹

SSE 实时轨迹(token/thinking/step/flow_*)

跨会话聚合、历史回放

链路与时间区间

Token

每次 LLM 调用 tokenUsage + 流程级_total_tokens_used

会话/模型/缓存命中率多维归因

分层用量归因

失败

EngineEvent 可审计 + error 事件

模型/工具/循环/回滚的分类定位

状态与错误码可追溯

链路

分散的 TraceSpan/ExecutionTrace/ObservationTrace/CommandTrace

一树到底的父子关系与耗时占比

统一状态树 → Span 发射

二、ooderAgent 可观测平台:基于现有埋点"一树到底"

2.1 三个设计原则(对齐原文,但落地到 ooderAgent)

① 订阅

直接订阅三层事件(API 层 EventBus + Engine 层 EngineEvent)与 SSE 事件流,不插桩、不改业务代码——因为事件本来就是一等公民。

订阅即采集

② 建模

已有 TraceSpan / ExecutionTrace / ObservationTrace / CommandTrace 是分散埋点;平台在其上收敛为状态树,再统一发射为语义一致的 Span——收敛而不是重造

收敛即能力

③ 上报

批量直传(对齐 ContextAuditLog 的 50 条 / 60s 批量落盘模式),不经过常驻采集进程;存量埋点与新增 Span 双写兼容。

双写兼容

2.2 数据地基:重新架构的层级 Span 模型

原文的五层是 entry / agent / step / chat / tool,对应一台机器上的 DSH。 ooderAgent 的任务结构是"会话 → 场景编排 → 命令树 → 模型调用 → 能力调用",且多一层"跨 Agent"。 因此重新架构为 五层纵向 + 一维横向

图 2 ooderAgent 的层级 Span 模型与各层承载信息(对应原文图 3,重新架构为五层 + A2A 横向)

2.3 Token 成本建模:缓存感知归因

ooderAgent 的 TokenUsage 比"输入 / 输出"多一档——DeepSeek 前缀缓存

代码语言:javascript
复制
private Integer cacheHitTokens;   // prompt_cache_hit_tokens,按 ~10% 价格计费
private Integer cacheMissTokens;  // prompt_cache_miss_tokens,正常输入价
public double getEffectiveInputTokens() {
    return (cacheHitTokens * 0.1) + cacheMissTokens;   // 有效输入成本
}

TokenConsumption(scope / prompt / completion / model / operationId / timestamp)与 TokenQuotaService(checkQuota / consumeQuota / getUsageStats)提供配额与用量统计; 流程侧 SkillFlowEngine.recordTokenUsage 把 token 沉淀到 _total_tokens_used / _llm_prompt_tokens / _llm_completion_tokens。 观测平台在此之上做 session / scene / model 多维聚合,并可直接回答"缓存命中率是否下滑、成本涨在哪"。

2.4 失败定位:分层状态 + 错误码

每个 Span 独立状态,并允许自定义错误类型,用于区分: 模型侧失败(FinishReason.ERROR / CONTENT_FILTER)、工具侧失败(ToolCall 异常 / 超时)、循环中断(FC-Loop 轮数 / 悬挂)、流程回滚(ScenarioStep.RECOVERABLE / FATAL)。 CommandTrace.retryCount 与 EngineEvent 审计级别让"重试了几次、在哪一步、能不能回放"一查便知。

2.5 整体技术架构与数据路径

图 3 ooderAgent 可观测整体技术架构与数据路径(对应原文图 4,基于现有事件/埋点重画)

2.6 一次任务的完整处理逻辑

图 4 一次任务的完整处理逻辑:事件流 → 状态树 → Span 发射 → 批量上报(对应原文图 5)

三、接入可观测平台后能看到什么

完整调用链

session / scene / command / llm / capability 逐层展开,A2A 跨节点子树挂在同一条 Trace 上,各层耗时占比一目了然。

一树到底

耗时分布

端到端与单轮耗时、模型推理与工具执行各自占用、首 Token 延迟与 P95 分位数。

慢在哪

Token 与成本

输入 / 输出 / 缓存命中分别统计,可下钻到单次模型调用,也可按会话、模型、场景组聚合排行。

贵在哪

调用明细

模型名称、结束原因与重试次数;工具名称、耗时、错误情况。

调用级

失败定位

每层 Span 独立状态 + 错误类型(模型 / 工具 / 循环中断 / 流程回滚)。

错在哪

检索与告警

Traces / Spans / Sessions 三种视角,按 Trace ID、Session ID、状态检索,对耗时、失败率、Token 突增配置告警。

可回放

图 5 可观测面板 · Token 消耗部分(对应原文图 6,按 ooderAgent 缓存感知语义绘制)

图 6 调用链面板 · 一次完整的 ooderAgent 任务执行过程(对应原文图 7)

四、落地实践

4.1 前提条件

  • 已部署 ooderAgent 集群(agent-sdk + aiserver + ooder-pro / scene-engine),节点按角色声明 capabilities;
  • 具备日志 / 指标存储访问凭证(建议最小权限子账号或临时密钥)。

4.2 接入步骤

  1. 开启可观测采集:在 AgentSdkConfig 装配处注入 ObservationProtocol(ObservationTrace / ObservationMetric 直传),或在 SseEventPushService 增加一个 SseEventPushListener 侧写(订阅 flow_* / tool_* / skill_* / harness_* 事件批量转 Span);
  2. 配置上报端点与批量参数(见下表);
  3. 发起一次测试任务(至少触发一次 LLM 调用与一次工具调用);
  4. 在控制台按 Trace ID / Session ID 检索校验。

4.3 关键配置项(示意)

设置

默认值

说明

ood.obs.enabled

true

禁用采集但不卸载

ood.obs.endpoint

上报接入点

ood.obs.captureContent

true

是否捕获 prompts / responses / tool 内容

ood.obs.contentMaxChars

128000

单个内容属性最大字符数

ood.obs.batchMaxSize

32

每批最大 Span 数

ood.obs.flushIntervalMs

5000

定时刷新间隔

ood.obs.retryTimes

3

上报重试次数

ood.obs.auditPath

logs/audit/audit-yyyy-MM-dd.jsonl

审计落盘(对齐 ContextAuditLog)

访问凭证属敏感信息,建议经环境变量或密钥管理注入,不要提交真实密钥到代码仓库

五、平台还提供哪些能力

审计回放

ContextAuditLog 以 JSONL 长期留存的审计流,可按 contextId / category 查询并 getTraceReport 恢复历史。

可回溯

指标与告警

MonitoringApi(recordMetric / queryMetrics / createAlert / checkHealth / startProfiling),EventBean 的 EventStatistics 提供事件健康度。

可告警

配额治理

TokenQuotaService 的 checkQuota / reserveQuota / confirmReservation,让可观测与成本治理闭环。

成本闭环

多端接入

web / 集群节点(aiserver)/ 流程引擎(scene-engine)写入同一套数据模型,可在同一控制台内横向对比。

统一口径

六、总结

DSH 的观测插件解决的是单机、单会话、实时的调试问题;ooderAgent 的观测平台要解决的是 分布式、跨会话、长期留存的治理问题。本文没有照搬 entry/agent/step/chat/tool, 而是按 ooderAgent 的真实结构重建为 session / scene / command / llm / capability 五层 + a2a 横向拼接, 并利用它"事件即一等公民"的既有管道——订阅不插桩、收敛不重造、缓存感知归因—— 让"慢在哪、贵在哪、错在哪"都能一树到底。

所有架构结论基于 ooderAgent 仓库源码实读;示例中的 Trace / 面板数据为示意,非真实线上数据。 相关标签:Agent 可观测 · ooderAgent · Trace · Token · A2A · SSE · 分布式。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、ooderAgent 的运行原理:为什么观测比"单机 ReAct"难一个维度
  • 1.1 不是 ReAct,而是"Scene=Agent"的命令驱动架构
  • 1.2 命令树:CommandPacket 是执行的一等公民
  • 1.3 场景编排:五大场景组流水线
  • 1.4 LLM 函数调用循环在 llm-sdk
  • 1.5 A2A 与自组织集群:分布式是本分,不是例外
  • 1.6 事件是一等公民:自带三层事件流 + SSE
  • 1.7 自带观测 vs 规模化缺口的对照
  • 二、ooderAgent 可观测平台:基于现有埋点"一树到底"
  • 2.1 三个设计原则(对齐原文,但落地到 ooderAgent)
  • ① 订阅
  • ② 建模
  • ③ 上报
  • 2.2 数据地基:重新架构的层级 Span 模型
  • 2.3 Token 成本建模:缓存感知归因
  • 2.4 失败定位:分层状态 + 错误码
  • 2.5 整体技术架构与数据路径
  • 2.6 一次任务的完整处理逻辑
  • 三、接入可观测平台后能看到什么
  • 完整调用链
  • 耗时分布
  • Token 与成本
  • 调用明细
  • 失败定位
  • 检索与告警
  • 四、落地实践
  • 4.1 前提条件
  • 4.2 接入步骤
  • 4.3 关键配置项(示意)
  • 五、平台还提供哪些能力
  • 审计回放
  • 指标与告警
  • 配额治理
  • 多端接入
  • 六、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档