Files
SuperBizAgent-java/mvp/engineering/harness/Harness application+audit 学习笔记-从 Run 编排到可回放审计.md

9.6 KiB
Raw Permalink Blame History

Harness application + audit 学习笔记:从 Run 编排到可回放审计

更新日期:2026-08-06 主题:application 域(Run 全生命周期编排 + 安全落库)+ audit 域(可观测账本)——重点讲清 audit 与 trace 的设计与区别 配套:证据安全链笔记、执行控制笔记

1. 一句话定位

application = Run 应用所有者:创建 Run / 路由意图 / 执行分支 / 持久化 / SSE 输出
audit       = 可观测账本:Trace 时序回放 + Token 对账 + 各明细审计表(metadata-only)

2. application 域:ChatApplicationUseCase 六步编排

flowchart TD
    A["Controller → execute(request, observer)"] --> B["① 读会话上下文<br/>RoutingHistory + PreviousTurn"]
    B --> C["② core.startRun<br/>创建 Run 边界"]
    C --> D["③ persistStart + observer.onStarted<br/>(SSE metadata + 取消句柄 CoreRunControl)"]
    D --> E["④ router.route<br/>意图路由(单次模型调用)"]
    E --> F["⑤ executePath 按 intent 分叉<br/>SYSTEM_CHAT / KNOWLEDGE_QUERY / DIAGNOSIS"]
    F --> G["⑥ completePath + persistFinish + 返回"]
    G -.异常.-> H["统一失败出口<br/>terminalOutcome + safeFailure"]

2.1 关键设计点

设计 代码事实 意义
取消句柄 observer.onStarted(new CoreRunControl(core, context)) → core.cancel(context, CLIENT_DISCONNECTED) 客户端断连 → 取消广播 → 强杀 in-flight 调用
取消有原因 RunCancellationReason.CLIENT_DISCONNECTED 区分断连/用户取消,可审计
sessionId 白名单 SAFE_ID = [A-Za-z0-9][A-Za-z0-9._-]{0,63} 信任边界校验
多轮记忆有界 RoutingHistory(intent+query) + PreviousTurn(PublishedResult 有界化) 上一轮只传安全摘要,无 tool ids / raw evidence
预算终态特殊处理 handledBudgetTermination() 时不二次 completeSuccess 不破坏 first-terminal-wins
统一失败出口 terminalOutcome → CANCELLED/FAILED + ChatFailureCode(文案安全) 不暴露内部堆栈
路由输出契约 OUTPUT_FIELDS = {intent},值必须枚举名 防模型夹带

2.2 持久化(JpaChatRunStore + PublishedResultPolicy)

  • start / markIntent / finish(@Transactional),finish 写 outcome + safeContentJson + publishedResult;
  • PublishedResultPolicy:只有 SUCCESS 且 draft 有结论才构造 PublishedResult;sanitize 全套有界(query 2000/结论 2000/scope 1000/limitations 10×500/文档 10);
  • sourceDocuments 只收 RAG 类型证据的 document_id(去重)——MySQL/日志证据不进发布文档列表;
  • PreviousTurn = sanitize 后的有界摘要(多轮记忆来源)。

3. audit 域:可观测账本的层次

flowchart LR
    subgraph 写入侧["写入侧(不阻断主流程)"]
        H1["HarnessAgentAuditHook<br/>每模型步 → agent_step + agent_reasoning_audit"]
        H2["ToolInvocationAuditSink<br/>工具 → tool_invocation"]
        H3["ModelCallAuditor<br/>Token → ledger + core + agent_step 回写"]
        H4["JpaDiagnosisTraceRecorder<br/>事件 → diagnosis_trace_event"]
        H5["JpaChatRunStore<br/>Run → diagnosis_run"]
    end

    subgraph 读取侧["读取侧(回放)"]
        S["DiagnosisTraceService"]
        S --> R["DiagnosisTraceResponse<br/>timeline + steps + toolInvocations + run + summary"]
    end

    H1 --> DB[(MySQL 各表)]
    H2 --> DB
    H3 --> DB
    H4 --> DB
    H5 --> DB
    DB --> S

3.1 各落库点(谁写哪张表)

落库点 表 内容
HarnessAgentAuditHook agent_step 每模型步摘要(stepIndex/耗时/token/工具计划)
HarnessAgentAuditHook agent_reasoning_audit 推理 + assistant_text 正文(受限)
ToolInvocationAuditSink tool_invocation 工具入参/输出预览/检索明细
JpaDiagnosisTraceRecorder diagnosis_trace_event 全链路事件时序线
ModelCallAuditor agent_step.token_count Token 回写(仅 DIAGNOSIS_AGENT)
JpaChatRunStore diagnosis_run / chat_session Run 生命周期 + 发布契约

3.2 audit 的三个核心边界(fail-safe / metadata-only / 对账)

  1. 审计不阻断主流程:三个落库点全部 try-catch + log.warn——审计挂了不能让 Run 跟着挂;
  2. metadata-only 分层:正文只允许出现在 agent_reasoning_audit(受限)和 tool_invocation(入参/输出预览),其余全部摘要化;
  3. Token 三写闭环:ledger 分账 → core.recordTokens(Run 预算)→ agent_step.token_count 回写——审计与预算同源可对账。

4. audit vs trace:设计与区别(重点)

4.1 核心区别:包含关系,不是并列

audit = 域(可观测账本的总集合,17 个文件)
  ├─ ★ trace = 域内的事件回放子体系(诊断时序线)
  ├─ ModelCallLedger / Auditor(Token 记账)
  ├─ HarnessAgentAuditHook(模型步审计)
  ├─ ToolInvocationAuditSink(工具审计)
  ├─ RagLookupAuditEnricher(RAG 检索审计)
  └─ RunConclusionExtractor(结论提取)

常见误解修正:trace 不是「agent 执行记录」,而是全链路七阶段时序线(RUN/ROUTING/AGENT/TOOL/EVIDENCE/SEMANTIC/RELEASE);audit 也不只是「tool 审计」,tool 审计只是其中一小块。

4.2 一张表讲清区别

维度 trace(diagnosis_trace_event) audit(各明细账本)
本质 时序事件流(按 sequence_no 排序) 实体化明细记录
回答 发生了什么、按什么顺序 每个细节落在哪本账上
粒度 每帧只带摘要 + 关联键(step_id 等) 完整字段(入参/输出/token/耗时)
结构 一张表、一个序列 多张表(agent_step/tool_invocation/...)
排序保证 sequence_no 单调(ConcurrentHashMap 分配) step_index / id / createdAt 排序
典型查询 findByRunIdOrderBySequenceNoAscIdAsc findByRunIdOrderByStepIndex 等
与明细的关系 靠 step_id / run_id 互链,不重复存储 承载被关联的实体数据

4.3 真实数据对照(run 1b584a01)

trace(15 帧时序线):
  RUN_STARTED → ROUTING_DECISION → AGENT_MODEL_STEP×2 → TOOL_INVOCATION
  → EVIDENCE_GUARD_INITIAL → SEMANTIC_GUARD_DECISION → RELEASE_DECISION → RUN_FINISHED

audit 各账本(同 Run):
  agent_step           2 行(token 2461/4415,耗时 1418/8542ms)
  agent_reasoning_audit 2 行(step1 = 完整 Draft JSON)
  tool_invocation      1 行(lookup_knowledge,step_id=979)
  diagnosis_run        outcome=SUCCESS + published_result 完整 JSON

关联示例:trace 第 7 帧 TOOL_INVOCATION 的 details 里 step_id=979 = agent_step.id=979 = tool_invocation.step_id——时序帧与明细账本通过 id 互链。

5. 可回放机制(DiagnosisTraceService)

GET /api/diagnosis/{sessionId}/trace?runId=xxx
  → DiagnosisTraceResponse 七块:runId / chatSession / session / run /
    steps[] / toolInvocations[] / timeline[] / summary

GET /api/diagnosis/{sessionId}/trace/reasoning?runId=xxx(受限:runId 必填)
  → agent_reasoning_audit(reasoning + assistantText)

三级回放深度:时间线(timeline)→ 明细(steps/toolInvocations)→ 推理(reasoning,按需受限读取)。

回放能成立的四个保证:

  1. sequence_no 单调(索引 idx_trace_event_run_sequence);
  2. 事件与明细靠 step_id 互链;
  3. summary 的 persisted vs returned 双计数对账(发现落库不完整);
  4. 双查询入口兼容新旧会话(buildLegacyTraceResponse)。

6. 面试话术(30 秒)

"application 域是 Run 的应用所有者:一次请求六步编排——建 Run 边界、意图路由(单次模型调用、输出契约严格为 {intent} 枚举)、按意图分叉执行、路径完成后写终态并持久化发布契约,异常统一走失败出口映射成安全的 ChatFailureCode;取消能力通过 SSE 句柄暴露给客户端(断连即 core.cancel)。audit 域是可观测账本,trace 是它内部的事件回放子体系:trace 用一张 diagnosis_trace_event 表按 sequence_no 记录全链路七阶段的事件时序线(每帧只带摘要和关联键),audit 的明细账本(agent_step / tool_invocation / agent_reasoning_audit / diagnosis_run)承载完整字段,两层通过 step_id/run_id 互链不重复存储。三个边界:审计不阻断主流程(fail-safe)、metadata-only(正文只在受限审计表)、Token 三写闭环(ledger 分账 → Run 预算 → 明细回写)。回放由 DiagnosisTraceService 按 runId 聚合排序,三级深度:时间线 → 明细 → 推理。"

7. 代码位置索引

组件 文件
ChatApplicationUseCase / ChatFailureCode / ChatApplicationStatus src/main/java/com/superbiz/agent/harness/application/
DiagnosisChatExecutor / 其他 executor .../application/executor/
IntentRouter / IntentRouterPrompt .../application/routing/
JpaChatRunStore / PublishedResultPolicy / RoutingHistory .../application/persistence/
Trace 体系(Recorder/Event/Type/Status/AuditEvents) src/main/java/com/superbiz/agent/harness/audit/(前半)
ModelCallLedger / ModelCallAuditor / HarnessAgentAuditHook / RunConclusionExtractor .../audit/(后半)
DiagnosisTraceService / DiagnosisTraceController src/main/java/com/superbiz/agent/service/ + controller/
V014 建表(diagnosis_trace_event) src/main/resources/db/migration/V014__create_diagnosis_trace_event.sql