Files
SuperBizAgent-java/mvp/issues/active/ISS-014-single-react-agent-harness-aci-ptk-refactor.md
T

72 KiB
Raw Blame History

ISS-014 单体 ReAct Agent、Harness 与 ACI 工具瘦身

状态:已完成(阶段 0-7 已验收并归档) 严重程度:高 发现时间:2026-07-20 目标分支:refactor/chat-single-react-harness 基线分支:refactor/mvp1.0 关联:ISS-003、ISS-012、ISS-013、executor-evidence-attribution-hallucination


1. 摘要

当前 Chat 诊断链路将一次完整 ReAct 生命周期拆成 Planner、Executor、Verifier、Composer 等多个 LLM 角色,再通过服务方法、Hook、ThreadLocal、结构化协议和多轮重试串联。该设计把 Agent 本身已经具备的“思考、行动、观察、继续行动、最终回答”重复提升为外层编排,造成职责分散、上下文重复、失败语义不一致和 Token 成本失控。

本 Issue 将后续实现收敛为:

一个负责实际工作的 Diagnosis ReAct Agent
  + 一个负责确定性控制的 Harness
  + 一个上下文隔离的 SemanticGuard Agent

Diagnosis ReAct Agent 和 SemanticGuard Agent 都通过同一个 Harness 执行边界运行;不为 SemanticGuard 再复制一套 Harness,也不引入新的 Graph 或编排器。

同时重构 Agent 可见 Tool Contract,使 RAG、日志和新增 MySQL Tool 遵守 ACI 原则,并通过工具结果清洗与投影层控制上下文体积、敏感数据和证据引用。

本 Issue 是后续实现的总设计来源。ISS-012 继续保留 Token/预算问题背景,ISS-013 继续保留入口/SSE 问题背景;实现范围和阶段顺序以本 Issue 最终确认版本为准。

2. 根因判断

2.1 ReAct 被重复实现

原有角色实际对应一个完整 ReAct 生命周期:

Planner  -> 内部规划与推理
Executor -> 工具调用与观察循环
Verifier -> 证据充分性自检
Composer -> 最终用户回答

将这些职责拆成多个 Agent 后,需要额外维护:

  • 多套 Prompt 和输出 Schema;
  • Agent 间 JSON 转换;
  • 多套重试状态;
  • 证据和上下文在不同角色之间重复搬运;
  • 失败、低置信度和 Fallback 的分支组合;
  • 主链路与审计链路之间的隐式 ThreadLocal 状态。

2.2 工具返回面向开发者而不是面向 Agent

当前 Tool 结果混合了:

  • Agent 真正需要的证据;
  • 检索/查询内部实现细节;
  • 调试 Trace 和 Rerank 数据;
  • 重复正文和 ContextPack;
  • 原始大结果;
  • Session 隐式记忆;
  • 无结果、错误和去重等含义不一致的状态。

这违反 ACI 的清晰、稳定、有界、可恢复和可继续操作原则,也是 Agent 上下文膨胀的重要来源。

2.3 安全约束与业务编排耦合

证据真实性校验属于确定性执行约束,不需要成为独立 LLM 节点或业务编排角色。语义推导校验确实需要独立上下文,但它不应拥有工具、记忆、ReAct 循环或回调主 Agent 的能力。

3. 目标架构

POST /api/chat (SSE)
      -> Chat Application Use Case
      -> Intent Router(一次轻量 Chat)
          -> SYSTEM_CHAT
          -> KNOWLEDGE_QUERY
          -> DIAGNOSIS

SYSTEM_CHAT
  -> 无 Tool 普通 Chat

KNOWLEDGE_QUERY
  -> 单次 lookup_knowledge
  -> 普通 Chat 基于 RAG Evidence 回答
  -> Harness 校验证据引用

DIAGNOSIS
  -> Harness 启动 Diagnosis ReAct Agent
      -> Agent 接收当前原始 Query 和可选 previous_turn
      -> Agent 内部规划
      -> Agent 自主调用受控 Tool
      -> Harness 在 Tool 边界校验、记录、清洗和投影
      -> Agent 内部检查证据是否足够
      -> Agent 输出结构化诊断草稿、Analysis Items、Conclusion 和 Tool Call Refs

  -> Harness EvidenceGuard(0 LLM)
      -> Schema 校验
      -> 当前 Run 证据所有权校验
      -> tool_call_id 当前 Run 归属和调用结果校验

  -> SemanticGuard Agent(独立隔离上下文)
      -> 接收原始 Query、完整 Draft 和已物理验真的精确证据
      -> 判断整份用户报告是否语义成立且没有超出证据范围

  -> Harness Release Policy
      -> SUPPORTED:释放完整答案
      -> UNSUPPORTED:安全降级
      -> TIMEOUT/ERROR:不释放未验证草稿

业务层不使用 StateGraph。底层 ReactAgent 框架内部是否使用 Graph 属于框架实现细节,不构成项目业务编排。

4. 已确认设计决策

4.1 单体 Diagnosis ReAct Agent

主 Agent 负责:

  1. 接收当前原始 Query 和 Harness 组装的可选极简 previous_turn;
  2. 理解诊断目标;
  3. 在内部形成排查方向;
  4. 选择并调用只读证据 Tool;
  5. 观察 Tool 结果并决定是否继续;
  6. 检查证据是否足以支持准备输出的结论;
  7. 形成结论先行的结构化诊断草稿、Analysis Items 和 Tool Call Refs;
  8. 证据不足时明确输出无法确认,不补造事实。

主 Agent 不负责:

  • 意图路由;
  • Session/Run 生命周期;
  • Token、工具、超时和取消预算;
  • 数据库存储和 Trace;
  • HTTP/SSE 协议;
  • 证据物理真实性校验;
  • 调用其他 Agent;
  • 外层重试状态机。

不要求 Agent 输出 Thought 或 Chain of Thought。内部规划不形成对外协议,也不持久化为业务事实。

4.2 Harness

Harness 负责确定性执行控制,而不是业务推理:

Run 控制

  • 创建和传播 sessionId + runId;
  • 建立请求 Deadline 和取消信号;
  • 限制模型调用、工具调用、Token 和总耗时;
  • 客户端断开时取消后续执行;
  • 保证 Run 进入明确终态。

Model 边界

  • 包装 ChatModel;
  • 记录 input/output/total Token;
  • 应用调用次数和上下文预算;
  • 不修改 Agent 的业务判断。

Tool 边界

  • Pre-Tool 参数 Schema、权限、只读和预算校验;
  • 执行真实 Tool;
  • 接收框架在 Tool 执行请求中提供的 tool_call_id,并在执行前完成校验;
  • Tool 返回后将请求、原始响应、状态和时间写入 Redis;当前版本暂不做持久化脱敏;
  • 调用对应 ToolResultProjector 生成规范化、聚合、截断后的 agent_result,并写回同一 Redis 调用记录;
  • 只把有界 agent_result 返回 Agent,禁止透传 raw_response;
  • 清洗失败时返回 Tool ERROR,禁止透传未清洗原始结果。

Redis 中的完整调用记录至少包含:tool_call_id、run_id、tool_name、request、raw_response、agent_result、调用状态和起止时间。tool_call_id 使用框架提供的 Tool Call 协议 ID,是一次 Tool 调用在当前 Run 内的唯一引用;Harness 不另造第二套调用 ID,并可按 runId + toolCallId 取得完整记录。

Redis 是 Harness 内部基础设施,只允许 Harness 访问。任何 Agent 都不能获得 Redis Client、Redis Tool、key、连接信息或完整调用记录。本 Issue 不提供历史来源召回 Tool;Redis 只用于 Harness 的证据验真、短期调用追踪和最终引用生成,不作为 Agent 记忆。当前诊断若需要新的日志或数据库事实,由 Diagnosis Agent 通过当前受控 Tool 重新查询。

Redis 存储契约固定为:

key = superbiz:harness:tool-call:{runId}:{toolCallId}
status = PROJECTING | READY | ERROR
evidence_status = EVIDENCE_FOUND | NO_EVIDENCE | ERROR
  • 一次 Tool Call 对应一个 Key,不建立额外 Evidence Index;Key 不包含 Query、Session 内容或 Tool 参数;
  • status 表示调用/投影生命周期:Tool 原始响应写入后为 PROJECTING,ToolResultProjector 成功并写入 agent_result 后为 READY,执行或清洗失败为 ERROR;
  • evidence_status 表示结果语义,只有 status=READY 时才允许为 EVIDENCE_FOUND 或 NO_EVIDENCE;失败记录为 ERROR;
  • EvidenceGuard 只接受当前 Run 下 status=READY 且存在 agent_result 的记录;evidence_status=ERROR 不可引用,NO_EVIDENCE 只能用于负向观察;
  • TTL 默认 2 小时并可配置,必须大于最大 Run 耗时、SemanticGuard 总耗时和安全缓冲;
  • TTL 在创建时设置,后续读取或更新不得续期;取消和失败记录保留到 TTL,首版不永久归档;
  • 首版默认 max-record-bytes=1MB、max-agent-result-bytes=64KB、max-run-bytes=5MB,均由 Harness 配置并根据运行数据校准;
  • raw_response 超过单记录上限时不静默截断,调用进入 ERROR/RESULT_TOO_LARGE;agent_result 可按投影预算截断并标记 truncated=true;
  • 使用 UTF-8 JSON,首版不压缩、不分片、不使用 Java 原生序列化或对象存储;
  • Redis 使用独立 Key 前缀和 ACL,应用日志不得输出 request/raw_response。

数据分层术语固定为:

  • Redis canonical invocation:短期保存 request/raw_response/agent_result 的完整调用记录;当前版本允许未脱敏,但受 Harness-only ACL、TTL 和容量上限保护;
  • Agent projection:ToolResultProjector 生成的有界 agent_result,经过 Tool-specific 聚合、截断和必要敏感字段清洗,只向 Diagnosis Agent、EvidenceGuard 和 SemanticGuard 的隔离快照开放;
  • Durable audit:应用日志或业务审计表中的长期记录,只保存调用元数据、脱敏参数、耗时、状态和有界结果摘要,不保存 Redis raw_response。
harness:
  evidence:
    key-prefix: "superbiz:harness:tool-call"
    ttl: 2h
    max-record-bytes: 1MB
    max-agent-result-bytes: 64KB
    max-run-bytes: 5MB

Output 边界

  • 校验主 Agent 输出 Schema;
  • 校验 Analysis Items 与 Tool Call IDs 的绑定;
  • 执行 EvidenceGuard;
  • 组装 SemanticGuard 的隔离输入;
  • 根据验证结果决定最终释放或降级。

SSE 与审计

  • 按最小 SSE 契约发送 metadata、脱敏 status/tool progress、最终 content 或 failure,以及 done;
  • 记录模型调用、工具调用、验证结果、预算消耗和降级原因;
  • 不输出内部 Prompt、Thought、原始 Tool 载荷和内部堆栈。

预算配置

所有暂时无法准确估算的预算先集中提取为 Harness 配置,不在本 Issue 中伪造固定数值:

  • 主 Agent 最大模型调用次数、总 Tool 次数、单 Tool 次数、上下文/Token 和总耗时;
  • SemanticGuard 单次超时、总耗时和输入大小;
  • RAG 最大证据数、单条摘录和总字符数;
  • 日志最大 Pattern/Event 数、消息长度、lookback 和总字符数;
  • MySQL 最大行数、单元格长度、总字节数和查询超时;
  • Redis Tool 调用记录的 TTL、单记录/Agent 投影/单 Run 大小上限。

首版使用静态应用配置和可调默认值,不建设配置中心、热更新、按租户覆盖或按模型路由配置。Harness 必须校验配置合法性、记录实际消耗和触发的预算原因;后续根据 Trace、Token、延迟和截断数据校准默认值。已经确认的“最多重试一次”属于失败语义,不允许通过配置放大为隐式重试循环。

重试策略装配

重试策略从业务流程中提取为小型类型化配置,由 Harness 统一装配,不分散在 Agent、Tool、Controller 或 SDK 中:

RetryPolicy
  -> max_attempts
  -> retryable_failures

HarnessRetryPolicies
  -> intent_router: max_attempts=2
  -> diagnosis_agent: max_attempts=1
  -> tool_call: max_attempts=1
  -> semantic_guard: max_attempts=2
  -> evidence_repair: max_attempts=1
  • HarnessRetryExecutor 只承载“同一操作再次执行”的技术重试,首版用于 Intent Router 和 SemanticGuard;
  • Intent Router 只在超时、传输失败或非法枚举输出时重试一次;第二次失败返回安全入口错误,不默认路由到 Diagnosis;
  • Diagnosis Agent 整体和其单次模型调用不自动重试,ReAct 的正常模型/Tool 轮次不算重试;
  • Tool 调用不自动重试;Tool ERROR 作为 Observation 返回,Agent 再次调用属于新的 Tool Action,必须由框架生成新的 tool_call_id 并计入预算;
  • EvidenceGuard 的一次无 Tool 结构修复不是同操作重试,由 Harness 按显式流程执行;
  • SemanticGuard 只在超时、传输失败、解析失败或 Schema 无效时使用同一输入重试一次;UNSUPPORTED 是有效业务结果,不重试;
  • NO_EVIDENCE、取消、预算耗尽和业务拒绝均不可重试;
  • 关闭或限制 SDK、HTTP Client 和数据库驱动的隐藏重试,所有实际 attempt 必须由 Harness 记录;
  • 首版不引入 Retry DSL、插件注册中心、动态策略脚本或多级退避状态机。

Harness 不应包含:

  • StateGraph;
  • Planner/Executor/Composer 节点;
  • Agent 间消息路由;
  • 通用工作流 DSL;
  • HarnessPlugin 注册中心;
  • 多级业务重试状态机;
  • 自行实现的 ReAct While 循环。

4.3 EvidenceGuard

原 Gatekeeper 不再作为独立编排组件存在。其能力进入 Diagnosis ReAct Agent 的 Harness:

Post-Tool
  -> 按 tool_call_id 保存完整调用记录和 agent_result

Pre-Release
  -> 校验 Draft Schema
  -> 校验 analysis_id 唯一
  -> 校验每条 Analysis 至少引用一个 tool_call_id
  -> 校验 Conclusion/Action Plan/Recommendation 引用的 analysis_id 均存在
  -> 校验 tool_call_id 是否存在且属于当前 Run
  -> 校验 Tool 调用返回可引用证据状态
  -> 校验 agent_result 存在
  -> 生成带真实性保证的 verified evidence snapshot

EvidenceGuard 使用确定性代码,不调用 LLM,不决定语义推导是否成立。它是原 Gatekeeper 的 Harness 内能力,而不是独立 Agent 或编排节点。具体规则包括:

  • analysis_id 在当前 Draft 内唯一;
  • 每条 Analysis 的 tool_call_ids 非空,且每个 ID 对应当前 Run 中 status=READY、存在 agent_result、evidence_status 可引用的 Tool Call;
  • kind=NORMAL 的 Analysis 只能引用 EVIDENCE_FOUND;kind=NEGATIVE_OBSERVATION 可以引用 NO_EVIDENCE,其 agent_result 必须保留原始查询条件、时间/数据范围和零匹配信息;
  • NO_EVIDENCE 只证明当前查询范围内无匹配结果,不能被 EvidenceGuard 当作问题不存在、根因排除或系统健康的正向证据;evidence_status=ERROR 一律不可引用;
  • 非空 Conclusion 的 based_on_analysis_ids 非空且全部指向已有 Analysis;
  • 每条 Action Plan 和 Recommendation 的 based_on_analysis_ids 非空且全部指向已有 Analysis;
  • conclusion=null 时允许保留有真实证据支撑、但尚不能形成结论的 Analysis;不要求每条 Analysis 都必须被 Conclusion 引用;
  • 最终引用清单只能从 Draft 实际引用且通过上述校验的 Tool Calls 确定性展开。

通过后,所引用 Tool 调用的 Run 归属、执行状态和 agent_result 被视为可信;ToolResultProjector 的投影正确性由代码和单元测试保证。EvidenceGuard 不判断 Analysis 是否正确解释证据,也不判断 Analysis 是否足以推出 Conclusion,这些属于 SemanticGuard。SemanticGuard 不再重复访问 Redis 或重新验证真实性。

4.4 SemanticGuard Agent

SemanticGuard 是独立审查 Agent,不加入主 ReAct Agent 上下文。

SemanticGuard 复用系统当前唯一配置的 ChatModel,不引入模型路由。它由 Harness 使用受限执行参数启动,Harness 负责隔离上下文、输入预算、调用超时、取消、最多一次重试、结构化输出校验、审计和最终释放策略。

必须满足:

  • 使用全新的隔离上下文;
  • 没有工具;
  • 没有隐式记忆;
  • 没有 ReAct 循环;
  • 不读取主 Agent Thought、完整历史或 System Prompt;
  • 不读取未通过 EvidenceGuard 的数据;
  • 不访问 Redis,不重新校验 tool_call_id 或 agent_result 真实性;
  • 不重新规划、查询、总结、润色、改写或补充用户答案;
  • 不回调主 Agent 形成循环;
  • 每次尝试只执行单轮语义和时间线审查,不允许 Agent 自身循环;仅 Harness 可在超时、调用失败或结构化输出无效时重试一次。

输入只包含:

  • 原始 Query;
  • 主 Agent Draft 的完整用户可见语义内容:Conclusion、Analysis、Action Plan、Recommendations 和 Limitations,但不包含内部 tool_call_id;
  • 经过 EvidenceGuard 验真的 Evidence snapshot,包括精确 excerpt/value 和必要的可读来源信息:RAG 的 document_id/title/breadcrumb,或日志/MySQL 的 source、timestamp、scope。

tool_call_id 只在主 Agent 与 Harness、EvidenceGuard 之间使用,不注入 SemanticGuard 或其他 Agent。Harness 在组装 snapshot 时取出所引用调用的完整有界 agent_result,不读取或注入 raw_response,并将其中的来源信息、精确摘录和结构化值按 analysis_id 分组。该转换使用确定性代码,不调用 LLM 重新摘要;Harness 在模型调用之外保留 Tool 调用映射。

{
  "analysis_id": "a1",
  "analysis_text": "连接池活跃连接达到 50/50",
  "verified_evidence": [
    {
      "source_type": "LOG",
      "source": "APPLICATION",
      "scope": "order-service,最近 30 分钟",
      "timestamp": "2026-07-21T10:30:00+08:00",
      "excerpt": "HikariPool active=50, max=50, pending=23"
    }
  ]
}

RAG 使用稳定 document_id/title/breadcrumb/excerpt,日志使用 source/scope/timestamp/pattern/event,MySQL 使用逻辑数据源、查询范围、列名和有界行/值。SemanticGuard 依靠 analysis_id -> verified_evidence 关系校验每条 Analysis,不需要理解 Tool ID,也不能访问完整工具正文。

不向 SemanticGuard 传递 Diagnosis Plan、Tool 调用过程或其他审计数据。SemanticGuard 对最终将展示给用户的完整 Draft 做报告级校验:

  • Evidence 是否支持 Analysis;
  • Analysis 是否能够推出 Conclusion;
  • Action Plan 是否与已支持的分析/结论相关,危险行动是否标记人工确认;
  • Recommendations 是否与诊断结果及 RAG/分析依据一致;
  • Limitations 是否准确覆盖实际查询范围和缺失信息;
  • 所有内容是否超出证据的服务、时间和数据范围。

SemanticGuard 只是审稿人,不是报告作者:它不能输出 corrected report、new conclusion、new action、new recommendation 或 user answer。真实性并不自动代表相关性、充分性或推导成立。

输出使用报告级二元状态,不使用未校准数字作为在线释放门禁,也不返回逐条 Analysis 状态:

{
  "verdict": "SUPPORTED",
  "reason": "已验证证据能够支持诊断草稿中的分析并推出结论"
}

verdict 只允许 SUPPORTED 或 UNSUPPORTED。Diagnosis Agent 是唯一报告作者;SemanticGuard 不生成、改写或裁剪用户报告;Harness 不总结报告,只发布原 Draft 或固定 Fallback。reason 只进入审计,不直接作为用户答案。

第一次超时、调用失败、解析失败或 Schema 校验失败时,Harness 使用相同的已验真证据快照重试一次,不重新运行主 Agent 或 Tool。第二次仍失败则按未通过处理:不释放未验证草稿,只返回安全降级报告并正常结束 SSE。单次与总超时由 Harness 配置提供,初期不冻结具体数值。

4.5 意图识别

使用一次轻量 Chat 对当前 Query 做三分类:

SYSTEM_CHAT
KNOWLEDGE_QUERY
DIAGNOSIS

约束:

  • 输入只包含当前原始 query、可选 last_intent 和可选 last_user_query;
  • 当前 Query 明确表达新主题时以当前 Query 为准;只有“继续”“那另一个服务呢”等追问才参考前一意图和问题;
  • 不改写 Query;
  • 不传完整历史、来源文档、evidence refs、Tool 结果或已发布答案;
  • 不配置 Tool、Skill、记忆和 ReAct 循环;
  • 输出只允许三个固定路由值;
  • 原关键词 QuestionComplexity 不再作为主路由。
{
  "query": "那退款服务呢?",
  "last_intent": "DIAGNOSIS",
  "last_user_query": "订单 order-123 支付超时,帮我排查"
}

三个意图使用以下固定执行器:

SYSTEM_CHAT

  • 用于系统定位、能力说明、使用方式、简单问候和非业务闲聊;
  • 使用无 Tool 的普通 ChatModel;
  • 系统能力来自简短、受控的能力说明,不依赖模型隐式知识;
  • 不进入 ReAct、EvidenceGuard 或 SemanticGuard;
  • 输出普通用户答案。

KNOWLEDGE_QUERY

  • 用于内部文档、流程、API、错误码、配置规范和排障手册;
  • 原始 Query 只执行一次有界 lookup_knowledge;
  • 使用普通 Chat 基于 RAG Evidence 生成答案;
  • Harness 校验证据引用;
  • 不开放 query_logs、query_metrics 或 query_mysql;
  • 不进入完整 Diagnosis ReAct 循环;
  • 输出 answer + references + limitations。

DIAGNOSIS

  • 用于故障排查、根因定位、实时状态分析和多证据组合;
  • 进入完整 Diagnosis ReAct Agent;
  • 可使用 RAG、日志和 MySQL 等受控证据 Tool;本 Issue 不提供 query_metrics;
  • 经过 Harness EvidenceGuard 和独立 SemanticGuard;
  • 输出完整诊断报告。

三个执行路径都接收同一个原始 Query,不做 Query 改写,不相互调用。原 DATABASE_QUERY 路由删除;MySQL Tool 只作为 DIAGNOSIS 的证据工具,不对应独立意图。

4.6 Diagnosis Agent 极简上下文

Diagnosis Agent 不接收完整 Session 历史,只接收当前 Query 和可选的上一个已完成回合:

{
  "query": "那退款服务呢?",
  "previous_turn": {
    "user_query": "订单 order-123 支付超时,帮我排查",
    "published_conclusion": "支付超时与连接池耗尽有关",
    "scope": "order-service,最近 30 分钟",
    "limitations": ["尚未取得长事务数据"],
    "source_documents": [
      {
        "document_id": "payment-timeout-guide",
        "title": "支付超时排查手册"
      }
    ]
  }
}
  • previous_turn 只取同一 Session 上一个已完成回合;无上一回合或上一回合未安全发布时为 null;
  • 只读取已安全发布的结构化 Conclusion、Scope、Limitations 和 RAG 来源文档元数据;
  • source_documents 只包含稳定 document ID 和 title,不包含正文、Tool Call ID、Tool 结果或内部引用;
  • 不复用历史日志或 MySQL 数据,需要当前运行事实时重新调用受控 Tool;
  • Harness 从上一回合结构化最终结果确定性组装,不调用 LLM 生成摘要;
  • 字段长度和来源文档数量使用集中配置,超限时按字段边界截断或删除末尾来源;
  • 当前 Query 始终优先,previous_turn 只辅助理解追问,不作为当前事实证据。

previous_turn 的持久化真理源固定为 diagnosis_run。Run 记录保存 intent、release_outcome 和 published_result;published_result 只包含 user_query/published_conclusion/scope/limitations/source_documents,不包含 Tool Call ID、原始证据、完整 Draft 或 SemanticGuard 审计原因。只允许读取同一 Session 最近一个 intent=DIAGNOSIS、release_outcome=SUCCESS 且 published_result 非空的 Run;FALLBACK/FAILED/CANCELLED 只用于审计,不进入下一轮上下文。Redis SessionContext 只作为短期会话缓存,不是该契约的真理源。

4.7 SSE 用户交互

SSE 采用“过程事件实时发送、最终报告安全释放”的口径:

  • SSE 连接在整个诊断期间保持打开;
  • 计划、Tool 进度、清洗、EvidenceGuard 和 SemanticGuard 状态实时发送;
  • SemanticGuard 完成前不发送最终结论;
  • 校验通过后以一个 content 事件释放结构化最终报告;
  • 不将已生成的完整答案切片伪装成 Token 流;
  • SemanticGuard 超时/失败时发送安全降级内容并结束;
  • 不引入 WebSocket、轮询或验证后的第二个 Composer Agent。

首版只定义五种业务事件,固定顺序为:

metadata -> status* -> content|failure -> done
  • metadata:固定第一个且只发送一次,包含 session_id 和 run_id;
  • status:可发送零到多次,只包含固定阶段码和安全的用户可见说明;
  • content:最多一次,承载正常答案或固定安全 Fallback,不做 Token 切片;
  • failure:最多一次,只用于 Router/Harness 等无法生成任何安全响应的技术失败,不能与 content 同时发送;
  • done:固定最后一个且只发送一次,outcome 只允许 SUCCESS/FALLBACK/FAILED。

最小事件结构:

event: metadata
data: {"session_id":"...","run_id":"..."}

event: status
data: {"code":"SEMANTIC_VALIDATING","message":"正在进行安全校验"}

event: content
data: {"content_type":"DIAGNOSIS_REPORT","payload":{...}}

event: failure
data: {"code":"ROUTING_UNAVAILABLE","message":"当前暂时无法处理该请求,请稍后重试"}

event: done
data: {"outcome":"SUCCESS"}

EvidenceGuard 或 SemanticGuard 降级使用 content + done(FALLBACK);Router 重试后仍失败等无法形成安全内容的技术错误使用 failure + done(FAILED)。客户端主动断开后不再尝试发送终态事件,Harness 必须取消当前模型和 Tool 调用,并只在内部将 Run 记录为 CANCELLED。首版不实现断线续传、事件重放、事件序号恢复、轮询或 WebSocket。

禁止输出:

  • Chain of Thought 和内部规划;
  • System Prompt、模型 Prompt 和完整上下文;
  • 未脱敏 Tool 参数;
  • 原始日志、完整数据库行和完整检索 Trace;
  • 内部异常、供应商错误和 Java 堆栈;
  • 尚未通过释放门禁的强结论;
  • Planner plan、Verifier verdict、Graph retry 等内部实现状态。

只保留一个 POST /api/chat SSE 接口,不保留同步 Chat 或 /api/chat_stream 兼容路径。

5. ACI Tool Contract

5.1 原则

Agent-facing Tool 必须满足:

  1. 名称说明 Agent 能做什么,不暴露内部实现;
  2. 描述说明什么时候调用、输入什么、不能用于什么;
  3. 参数数量最小、含义明确、具备 Schema;
  4. Agent 不控制连接、凭据、region、topK、limit 等基础设施参数,除非业务确有必要;
  5. 输出稳定、结构化、有界;
  6. 明确区分成功有证据、成功无证据和工具失败;
  7. 输出包含可继续使用的稳定 Tool Call Reference;
  8. 错误信息安全、可恢复,不泄露内部细节;
  9. 相同输入不因隐藏 Session 记忆产生不可解释的语义变化;
  10. Agent 只看到执行结果,不看到审计/调试实现。

5.2 通用状态语义

Agent-facing evidence Tool 统一使用 evidence_status:

evidence_status = EVIDENCE_FOUND 查询成功且返回可使用证据
evidence_status = NO_EVIDENCE   查询成功但范围内没有证据
evidence_status = ERROR         Tool 执行、参数、权限或清洗失败

EVIDENCE_FOUND 只表达 Tool 找到了证据,不声明证据支持任何分析或结论。NO_EVIDENCE 不是异常,只能支持明确标记为负向观察的 Analysis,不能推出问题不存在、问题已排除或系统健康。ERROR 不能伪装成无结果。SUPPORTED/UNSUPPORTED 只保留给 SemanticGuard。

5.3 通用 Tool Call Reference

每次可引用 Tool 调用只需要框架提供的一个稳定 ID:

tool_call_id

tool_call_id 由框架随 Tool Call 请求提供,Harness 不替换或重新生成该 ID,只负责在 Tool 执行前校验并贯穿 Agent response、Redis 调用记录、EvidenceGuard 和最终 Trace。该 ID 必须非空、满足长度/字符集约束,并在同一 Run 内唯一;重复、非法或缺失 ID 不得覆盖既有记录,直接进入 Tool ERROR。Redis Key 使用 runId + toolCallId 隔离不同 Run。SemanticGuard 不接收该 ID,只接收 Harness 从对应调用的 agent_result 组装的 verified evidence snapshot。

6. 工具结果清洗与投影层

本 Issue 使用中文“工具结果清洗与投影层”作为架构名称,不再使用 PTK/RTK 缩写。代码统一使用 ToolResultProjector,首版只有三个 Tool-specific 实现:RagResultProjector、QueryLogsResultProjector 和 MysqlResultProjector。不再拆分 Cleaner、Sanitizer、ContextBuilder 或通用转换 Pipeline。

统一处理顺序:

Agent Tool Request
  -> Pre-Tool Guard
  -> Mock Tool / MCP / DataSource
  -> Raw Invocation Persistence
  -> Tool-specific ToolResultProjector
  -> Agent Result Persistence
  -> Bounded Agent-facing Result

原则:

  • 完整结果只在可信边界内保存;
  • 当前版本不在 canonical evidence 持久化阶段做脱敏;Agent 仍只能接收有界的 Tool-specific 投影,原始 Redis 结果只能由 Harness 读取;
  • Agent 只接收有界投影;
  • Agent 看到的证据必须可回到 canonical result;
  • ToolResultProjector 使用确定性代码,不调用 LLM 做二次摘要;
  • 不建立万能清洗算法;统一 Envelope,下沉 Tool-specific projection;
  • 不把完整结果写入进程本地 refs/*.md 作为主存储;
  • 清洗失败不能绕过 Harness。

7. RAG Tool 设计

7.1 ACI 描述

Tool 只说明:

查询内部知识库中的文档、接口说明、错误码和排障手册。
适用于稳定背景知识,不用于查询实时日志、指标或数据库状态。
输入 query:需要查询的问题或关键词。

不向 Agent 解释 L0/L1、category filter、fallback attempt、rerank 和 VectorStore/Milvus 实现。

7.2 Agent-facing 输出

{
  "evidence_status": "EVIDENCE_FOUND",
  "tool_call_id": "tool-123",
  "query": "支付超时处理方式",
  "evidence": [
    {
      "document_id": "payment-timeout-guide",
      "source": "payment-timeout.md",
      "title": "支付超时排查",
      "breadcrumb": "支付系统 > 故障排查",
      "excerpt": "当支付请求出现 ERR_TIMEOUT 时,应先检查……"
    }
  ],
  "returned_count": 1,
  "truncated": false
}

7.3 Agent 不可见内容

  • ContextPack;
  • RetrievalTrace;
  • RerankTrace;
  • L0 hints;
  • 原始候选列表;
  • 向量原始分数;
  • hit reasons;
  • fallback attempts;
  • Session 级 retrieved domains;
  • 完整 Metadata;
  • 完整文档正文。

这些内容按审计需要保存或删除,但不进入 Agent 上下文。

7.4 RAG 结果投影

  • 删除 EvidenceBlock 与 ContextPack 的重复正文;
  • 返回精确文档摘录,不使用 LLM 摘要;
  • 相同文档/段落去重;
  • 限制 evidence 数量、单条 excerpt 和整体字符数;
  • 文档内容作为不可信证据数据,不执行其中的指令;
  • 明确 NO_EVIDENCE 和 ERROR;
  • 删除 Session 隐式去重或改为显式 Run 内重复查询控制。

8. query_logs Tool 设计

8.1 ACI 输入

删除 Agent 可见的 getAvailableLogTopics。固定/动态 Topic 目录由 Harness 或 Tool Adapter 管理。

当前环境没有真实日志数据,本 Issue 首版继续使用现有 Mock 日志实现;不新增 MCP 或 Java CLS 适配器。Mock 只作为数据源实现,仍必须经过相同的 ACI、Harness、canonical evidence 和 Agent projection 链路。后续真实适配器若接入,必须复用本节 Contract,不在本 Issue 提前设计适配平台。

{
  "topic": "APPLICATION",
  "query": "order-service HikariCP connection timeout",
  "lookback_minutes": 30
}

约束:

  • topic 使用稳定逻辑枚举;
  • query 表达日志检索目标;
  • lookback 有默认值和最大值;
  • region、TopicId、limit 由系统控制;
  • Agent 不需要先调用发现工具;
  • 当前仅验证本地 Mock 返回 Agent-facing Contract;真实 CLS/MCP 的兼容性留待后续接入时验证。

8.2 Agent-facing 输出

{
  "evidence_status": "EVIDENCE_FOUND",
  "tool_call_id": "tool-456",
  "source_kind": "MOCK",
  "scope": {
    "topic": "APPLICATION",
    "query": "order-service HikariCP connection timeout",
    "start_time": "...",
    "end_time": "..."
  },
  "match_count": 126,
  "returned_count": 1,
  "patterns": [
    {
      "count": 84,
      "first_seen": "...",
      "last_seen": "...",
      "level": "ERROR",
      "service": "order-service",
      "example": "HikariPool connection is not available"
    }
  ],
  "events": [
    {
      "timestamp": "...",
      "level": "ERROR",
      "service": "order-service",
      "message": "HikariPool connection is not available"
    }
  ],
  "truncated": true
}

8.3 日志结果投影

  • 按稳定日志模板聚合重复事件;
  • Pattern 保存 count、first_seen、last_seen 和代表样本;
  • 额外保留少量按时间排序的事件,防止丢失时间线;
  • 不固定删除 INFO,只根据 Query 和有界投影选择证据;
  • 脱敏 Token、密码、Authorization Header 等敏感数据;
  • 限制单条消息、Pattern 数、Event 数和整体字符数;
  • 返回完整查询范围,防止将局部结果扩大为全局结论;
  • match_count 表示查询范围内的原始匹配事件总数,returned_count 表示 events 中实际返回的有界时间线事件数量;Pattern 数量直接由 patterns 数组长度表示;
  • Redis raw_response 不进入 Agent 上下文;持久化审计只保存脱敏参数、聚合元数据和有界结果摘要。
  • source_kind=MOCK 必须保留在 agent_result 和诊断范围中;Harness 不得把 Mock 数据表述为生产实时事实。

9. 新增 MySQL Tool 设计

9.1 定位

新增一个只读、受限、可审计的外部 MySQL 查询 Tool。该 Tool 查询独立配置的业务/诊断数据源,不连接 Agent 自身的持久化数据库。

连接和安全策略由后续新增的独立配置文件提供。配置只暴露逻辑数据源 ID,不把真实连接信息交给 Agent:

  • 数据源 URL、账号和密码不写入 Prompt、Skill 或 RAG 文档;
  • 密码等敏感值使用环境变量或受控 Secret 注入,不在配置文件中硬编码;
  • 配置定义允许的 schema/table/column、超时、最大行数和最大结果大小;
  • Tool 通过逻辑数据源 ID 选择连接,不接受 Agent 传入 URL、账号、密码或任意 JDBC 参数;
  • 不复用现有 Python 查询脚本的连接和执行方式;现有脚本中的硬编码凭据和可写执行分支必须清理。

表名、字段名、关联关系和业务语义后续从 Skill 或 RAG 召回的数据字典/查询知识中获得,MySQL Tool 本身不负责发现表结构。Skill 或 RAG 文档可以帮助 Agent 生成 SQL,但它们只是候选查询知识,不是授权来源。Harness 必须将 SQL AST 中实际使用的 schema/table/column 与独立配置的 allowlist 做最终校验;文档中出现但配置未授权的对象一律拒绝。

首版只提供静态“库、表、字段”三层白名单,不在本 Issue 设计租户或行级权限:

harness:
  mysql-tools:
    data-sources:
      order_readonly:
        jdbc-url: ${ORDER_MYSQL_JDBC_URL}
        username: ${ORDER_MYSQL_USERNAME}
        password: ${ORDER_MYSQL_PASSWORD}
        default-schema: order_db
        allowed-schemas:
          order_db:
            tables:
              biz_order:
                columns:
                  - order_id
                  - user_id
                  - payment_status
                  - created_at
                  - updated_at
              payment_record:
                columns:
                  - payment_id
                  - order_id
                  - channel
                  - status
                  - created_at
                  - updated_at

配置语义:

  • data-sources Key 是 Agent 可传入的逻辑数据源 ID,不是真实连接名;
  • allowed-schemas 下每个 Key 是允许访问的 MySQL 库/schema;未配置的库一律拒绝;
  • 每个库只允许 tables 中显式列出的表;每张表只允许 columns 中显式列出的字段;
  • 首版不支持 *、正则、前缀匹配、继承或动态白名单;库、表、字段均为精确匹配;
  • SQL 未显式写库名时只能使用该数据源的 default-schema,且 default schema 必须同时存在于 allowed-schemas;
  • JOIN 中每个表及每个投影、过滤、关联、分组、排序字段都必须通过对应库/表/字段校验;
  • 未限定字段通过 JSqlParser 的表别名和作用域解析到唯一表;无法唯一解析时拒绝;
  • 函数白名单、超时、行数和字节预算继续使用 Harness 的独立配置,不混入库表字段结构;
  • 凭据只引用环境变量/Secret,不允许在配置文件中写明文。

固定调用链:

Skill/RAG 召回候选数据字典
  -> Agent 使用明确表名和列名生成参数化 SQL
  -> Harness 解析 SQL AST 并用独立配置做授权裁决
  -> MySQL Tool 使用配置映射的只读数据源执行
  -> Harness 清洗、持久化 canonical evidence 并投影给 Agent

MySQL Tool 不向 Agent 开放 SHOW TABLES、SHOW COLUMNS、DESCRIBE 或直接查询 information_schema 的元数据发现能力,避免绕过 Skill/RAG 知识边界和配置授权。

9.2 ACI 输入

初步推荐采用参数绑定的受限 SQL:

{
  "data_source": "order_readonly",
  "sql": "SELECT order_id, payment_status, updated_at FROM biz_order WHERE order_id = ?",
  "params": ["order-123"]
}

只允许:

  • 单条 SELECT;
  • 显式列名;
  • INNER JOIN 和 LEFT JOIN;
  • WHERE、GROUP BY、HAVING、ORDER BY 和受控 LIMIT;
  • allowlist 中的聚合/标量函数,首版至少覆盖 COUNT、SUM、AVG、MIN 和 MAX;
  • 参数绑定;
  • 独立配置中存在的逻辑数据源 ID;
  • 上述静态 allowlist 内的 schema/table/column 精确匹配;
  • Harness 注入或限制的行数、超时和字节预算。

必须阻止:

  • INSERT/UPDATE/DELETE/REPLACE;
  • CREATE/ALTER/DROP/TRUNCATE;
  • 投影通配符 SELECT * 和 table.*,包括子查询中的通配符;
  • WITH、子查询、UNION 和窗口函数;
  • CROSS JOIN、未在 allowlist 中的函数和无法识别的 AST 节点;
  • SHOW TABLES、SHOW COLUMNS、DESCRIBE 和 information_schema 元数据查询;
  • CALL;
  • 多语句;
  • SELECT INTO OUTFILE/DUMPFILE;
  • FOR UPDATE;
  • SLEEP/BENCHMARK/LOAD_FILE 等危险函数;
  • 任意事务控制和写入路径。

COUNT(*) 作为聚合函数例外允许,因为它不返回全部字段;禁止的是字段投影通配符。若后续需要完全禁止星号,可将查询知识统一改为 COUNT(1),不影响整体校验结构。

9.3 JSqlParser 校验

首版引入 JSqlParser 将 Agent 生成的 SQL 解析为 AST。JSqlParser 只负责理解 SQL 结构,不连接或执行数据库;Harness 使用 AST visitor 执行 fail-closed 白名单校验:

解析且确认只有一个 Statement
  -> 确认根节点是允许的 SELECT
  -> 遍历所有 table/column/join/function/子表达式
  -> 校验逻辑数据源和 schema/table/column/function allowlist
  -> 校验占位符数量与 params 一致
  -> 注入或压低 LIMIT
  -> 通过 PreparedStatement 执行

解析失败、遍历到未知节点或无法证明符合允许子集时直接拒绝,不回退到正则、startsWith 或容错执行。具体依赖版本在实施阶段选择兼容 Java 17 的稳定版本,并通过固定安全用例验证后锁定。

安全边界必须同时包含:

  • MySQL 专用只读账号;
  • JSqlParser AST 校验,而不是 startsWith/正则;
  • 独立配置提供的 schema/table/column allowlist;
  • JDBC/数据库侧 read-only;
  • JDBC PreparedStatement 和 setMaxRows;
  • 查询超时;
  • 最大行数、单元格长度和总字节数;
  • 客户端断开时取消查询;
  • 独立连接池或明确资源隔离。

9.4 Agent-facing 输出

{
  "evidence_status": "EVIDENCE_FOUND",
  "tool_call_id": "tool-789",
  "columns": ["order_id", "payment_status", "updated_at"],
  "rows": [
    {
      "order_id": "order-123",
      "payment_status": "FAILED",
      "updated_at": "2026-07-20 10:30:00"
    }
  ],
  "returned_count": 1,
  "truncated": false
}

9.5 MySQL 结果投影

  • 限制返回行数;
  • 限制单元格、整行和整体结果大小;
  • Blob、长文本和长 JSON 截断并标记;
  • 按字段策略脱敏密码、Token、个人敏感信息;
  • 每行保留结构化字段,整次调用通过 tool_call_id 引用;
  • SQL 模板、脱敏参数、耗时、状态和有界结果摘要进入持久化审计;完整 raw_response 只按 Redis canonical invocation 契约短期保存;
  • 连接字符串、账号、密码和内部堆栈不得进入 Agent 或审计明文。

10. 主 Agent 输出契约与低置信度处理

10.1 两类 Plan 必须分离

  • Diagnosis Plan:主 Agent 开始排查时产生的 3–5 个高层步骤,通过 SSE status 提前输出;只描述准备查什么,不输出 Thought、完整 SQL、敏感参数或内部推理。
  • Action Plan:诊断完成后给用户的下一步操作;与 Diagnosis Plan 不是同一个字段。

Diagnosis Plan 不参与 EvidenceGuard 或 SemanticGuard,因为它不是事实结论。执行中需要补充查询时只发送脱敏状态事件,不建立复杂 Plan 版本状态机。

10.2 已确认的 Agent Draft Schema

Diagnosis Agent 是诊断报告唯一的语义作者,负责生成结论、分析支撑、行动计划、长期建议、诊断范围与限制,并通过 Tool Call ID 选择各项分析所引用的证据。Harness 不生成、补充、删改或覆盖这些语义字段。

主 Agent 不输出不可安全裁剪的自由文本 answer,而是输出以下结构:

{
  "conclusion": {
    "text": "支付超时的主要原因是数据库连接池耗尽",
    "based_on_analysis_ids": ["a1"]
  },
  "analysis": [
    {
      "analysis_id": "a1",
      "kind": "NORMAL",
      "text": "连接池活跃连接达到 50/50,并存在等待线程",
      "tool_call_ids": ["tool-456"]
    }
  ],
  "action_plan": [
    {
      "action": "查询连接泄漏和长事务",
      "based_on_analysis_ids": ["a1"],
      "requires_human_confirmation": false
    },
    {
      "action": "临时扩大连接池容量",
      "based_on_analysis_ids": ["a1"],
      "requires_human_confirmation": true
    }
  ],
  "recommendations": [
    {
      "text": "增加连接池等待线程和获取耗时告警",
      "based_on_analysis_ids": ["a1"]
    }
  ],
  "limitations": {
    "scope": "order-service,最近 30 分钟",
    "missing_info": ["尚未取得慢 SQL 和长事务数据"]
  }
}

字段语义:

  • conclusion:结论先行;引用支撑它的 analysis IDs,不重复绑定 Evidence;证据不足时允许为 null。
  • analysis:可独立验证的分析支撑。每一项必须有唯一 analysis ID、固定 kind=NORMAL|NEGATIVE_OBSERVATION 和至少一个 tool_call_id,拒绝无来源分析。负向观察只能绑定 NO_EVIDENCE,并严格限定为对应 Tool 的实际查询范围。
  • action_plan:立即执行的下一步,必须通过 based_on_analysis_ids 绑定分析。危险或有副作用的操作必须标记 requires_human_confirmation=true,Harness/HITL 策略拥有最终决定权。
  • recommendations:长期治理建议,必须通过 based_on_analysis_ids 绑定分析;来自知识库或外部规范时,支撑该分析的 Tool Call 应来自 RAG。
  • limitations.scope:由 Diagnosis Agent 根据本次实际查询范围生成;Harness 不改写或覆盖,SemanticGuard 负责校验它是否超出 verified evidence 中的真实 Tool scope。
  • limitations.missing_info:尚未取得、导致结论受限的关键材料。

主 Agent 只向 Harness 输出 Tool Call IDs,不输出可自行编造的完整 Reference 内容。Harness 在调用 SemanticGuard 前使用这些 IDs 读取对应的 agent_result,仅传递已解析的来源文档/来源工具和证据内容。Harness 只把 Agent 已选择的 Tool Call ID 确定性展开为最终引用清单,展示来源、scope/timestamp 和精确 evidence excerpt/value;它不能选择额外来源、生成引用摘要或改变报告语义。

最终用户报告顺序固定为:

1. 结论
2. 分析支撑
3. 行动计划
4. 长期建议
5. 诊断范围与限制
6. 引用

10.3 释放语义

不使用主 Agent 自报的 0–1 数值置信度作为释放依据。

EvidenceGuard 失败
  -> 不进入 SemanticGuard
  -> 首次失败执行一次无 Tool 的结构化输出修复
  -> 修复后重新执行 EvidenceGuard
  -> 第二次仍失败则安全 Fallback

SemanticGuard SUPPORTED
  -> Harness 原样释放主 Agent 的语义报告,并附加由其 Tool Call IDs 确定性展开的引用清单

SemanticGuard UNSUPPORTED/TIMEOUT/ERROR
  -> 不释放主 Agent 草稿、分析、结论、行动或建议
  -> Harness 返回固定安全 Fallback,只包含已验证来源、证据不足说明和诊断限制

固定安全 Fallback 由 Harness 通过确定性模板生成,不调用 LLM 或 Composer:

{
  "type": "SEMANTIC_UNSUPPORTED",
  "conclusion": null,
  "message": "当前证据不足,无法确认根因",
  "verified_sources": [
    {
      "source_type": "LOG",
      "source": "APPLICATION (MOCK)",
      "scope": "order-service,最近 30 分钟"
    }
  ],
  "limitations": ["语义校验未通过或暂不可用"],
  "next_steps": ["补充当前缺失的数据后重新发起诊断"]
}
  • type 是稳定的用户可见降级分类,只允许 EVIDENCE_VALIDATION_FAILED、SEMANTIC_UNSUPPORTED 和 SEMANTIC_UNAVAILABLE;
  • EVIDENCE_VALIDATION_FAILED 表示 EvidenceGuard 修复后仍未通过,此时 verified_sources 必须为空;
  • SEMANTIC_UNSUPPORTED 表示证据已通过 EvidenceGuard,但不支持 Agent 报告;SEMANTIC_UNAVAILABLE 表示 SemanticGuard 第二次超时、调用失败或输出无效;这两类可以返回本次已通过 EvidenceGuard 的来源;
  • verified_sources 只列出 EvidenceGuard 已通过的来源名称和查询范围,不包含主 Agent 的 Analysis、Conclusion 或推导文本;
  • limitations 使用稳定的用户可见原因分类,不直接展示 SemanticGuard reason、供应商错误或内部异常;
  • next_steps 只列出补充数据、缩小范围或稍后重试等安全动作,不包含主 Agent 未校验的 Action Plan/Recommendations;
  • 三种降级使用同一 Fallback Schema;内部可使用比 type 更细的 fallback_reason 审计码,但不得将供应商错误或异常细节暴露给用户;
  • Fallback 通过最终 content 事件发送并正常 done,不作为 HTTP/SSE 系统错误。

11. 行为与协议变化

这是有意的不兼容重构:

  • 删除同步 /api/chat 响应模式;
  • 删除 /api/chat_stream;
  • POST /api/chat 改为唯一 SSE Chat 协议;
  • 删除 QuestionComplexity 主路由;
  • Planner/Executor/Verifier/Composer 不再作为主链路多 Agent 角色;
  • 不引入业务 StateGraph;
  • Tool 参数和返回协议发生不兼容变化;
  • RAG Session 隐式检索记忆删除或改为显式 Run 控制;
  • getAvailableLogTopics 不再对 Agent 暴露;
  • 新增只读 MySQL Tool;
  • 原 Gatekeeper 编排身份消失,能力进入 Harness EvidenceGuard;
  • SemanticGuard 使用隔离上下文且不能形成 Agent 回路。

受影响的消费者包括前端 Chat、Controller tests、ChatService/Agent tests、Prompt contracts、Tool contract tests、Trace/Eval fixtures 和任何直接调用旧 Tool 方法的代码。

12. 分阶段实施计划

ISS-014 是总设计 Issue,不创建跨阶段共享的 OpenSpec change。以下 11 个实施切片各自执行一个完整、串行的 sm-flow:

阶段 OpenSpec change 状态
0 single-react-design-freeze Completed;已归档,Git commit 见阶段历史
1 single-react-aci-tool-contracts Completed;已归档
2 single-react-harness-run-context Completed;已归档
3A single-react-tool-invocation-store Completed;已归档
3B single-react-rag-log-projections Completed;已归档
3C single-react-mysql-readonly-tool Completed;已归档
4 single-react-diagnosis-agent Completed;已归档
5 single-react-evidence-semantic-guards Completed;已归档
6A single-react-chat-application-usecase Completed;已归档
6B single-react-chat-sse-cutover Completed;已归档
7 single-react-cleanup-e2e Completed;已归档

每个 change 独立完成 Discover、Commit、Apply、阶段验收、Archive 和 Git commit;前一阶段 Archive 且提交后才允许启动下一阶段,不并行实施相邻阶段。

阶段 0:设计冻结与安全前置

目标:冻结本 Issue 的未决契约,不修改业务执行链。

任务:

  • 将已确认的主 Agent Draft/Analysis/Conclusion Schema 固化为契约测试;
  • 将 EvidenceGuard 一次无 Tool 输出修复和二次失败 Fallback 固化为契约测试;
  • 冻结 SemanticGuard 报告级 SUPPORTED/UNSUPPORTED 二元契约和固定安全 Fallback;
  • 将过程事件实时 SSE、最终报告门禁后释放的口径固化为协议;
  • 将已确认的 SYSTEM_CHAT/KNOWLEDGE_QUERY/DIAGNOSIS 执行器映射固化为契约测试;
  • 冻结 Harness 预算配置项、合法性校验和预算耗尽语义,不要求在本阶段冻结准确默认数值;
  • 冻结 RetryPolicy/HarnessRetryPolicies/HarnessRetryExecutor、固定重试矩阵和隐藏重试禁用规则;
  • 冻结工具结果清洗与投影层及 ToolResultProjector 代码命名;
  • 确认 Redis 调用记录保存 request + raw_response + agent_result,冻结单 Key、状态、默认 TTL/容量、非续期和 Harness-only ACL;当前版本明确暂不做持久化脱敏,并记录为后续安全增强项;
  • 确认 JSqlParser、首版 SQL 允许子集、MySQL allowlist 和只读账号方案;
  • 移除并轮换现有脚本中的硬编码数据库凭据;
  • 建立改造前 focused baseline。

验收:

  • 所有阻塞性问题有明确决策;
  • 无业务 Java 行为变化时可跳过单元测试,并记录理由;
  • Security prerequisite 完成后才能进入 MySQL Tool 实现。

阶段 1:ACI Tool Contract 冻结

目标:先定义 Agent 能看到的工具界面,不实现 Agent 架构切换。

任务:

  • 冻结 RAG、query_logs、query_mysql Request/Response Schema;
  • 冻结调用生命周期 status=PROJECTING/READY/ERROR 与结果语义 evidence_status=EVIDENCE_FOUND/NO_EVIDENCE/ERROR,禁止混用;
  • 冻结 tool_call_id 调用引用契约;
  • 缩短 Tool descriptions,移除内部实现泄漏;
  • 为三类 Tool 添加独立契约测试;
  • 确认现有 Mock Tool 的 Agent-facing Contract 和后续适配边界;本阶段不实现真实 MCP/CLS 适配器。

验收:

  • Schema 和错误语义契约测试通过;
  • Agent-facing 与 audit-facing 字段清单无交叉歧义;
  • 不新增通用插件框架或工作流 DSL。

阶段 2:Harness Core 与 RunContext

目标:先建立后续 Tool、Agent、Guard 和入口共同依赖的显式运行上下文,不提前切换 HTTP/SSE 协议。

任务:

  • 定义不可变 RunContext,显式携带 sessionId/runId/deadline/cancellation/budget/retryPolicies;
  • 定义 Run 创建、预算计数、取消传播和终态管理的 Harness Core;
  • 装配 HarnessRetryPolicies/HarnessRetryExecutor,关闭或纳管底层隐藏重试;
  • 定义 Redis Tool Call Key Factory 和单 Run 容量计数器,但不实现具体 Tool 投影;
  • 所有后续边界通过参数或受控上下文对象显式接收 RunContext,禁止 ThreadLocal;
  • 使用 Fake Model/Tool 验证 deadline、取消、预算、重试记录和 Run 终态;
  • 不修改 Controller 协议,不接入旧 ChatService 的临时适配层。

验收:

  • RunContext 无隐式线程状态,可在同步/异步边界显式传播;
  • 预算耗尽、取消和异常均产生唯一 Run 终态;
  • 阶段 3A 可直接依赖 Harness Core,不需要临时耦合旧 ChatService;
  • focused Harness Core tests 通过。

阶段 3A:Harness Tool Boundary 与 Canonical Invocation Store

目标:实现所有 Tool 共用的 Pre/Post 边界、canonical invocation store 和统一状态机,不在本阶段实现 Tool-specific 投影。

任务:

  • 接收、校验并传播框架提供的 tool_call_id,覆盖缺失、非法、重复和跨 Run 引用测试;
  • 实现 Pre-Tool Schema/权限/只读/预算校验;
  • 将 request + raw_response + agent_result 写入同一 Redis Tool 调用记录;禁止仅依赖截断 preview 做验真;
  • 实现 PROJECTING/READY/ERROR 生命周期和独立 evidence_status,以及 TTL 不续期、单记录/单 Run 容量门禁和 RESULT_TOO_LARGE;
  • 清洗失败显式 ERROR;
  • 使用 Fake Tool/Projector 增加 invocation store、状态、TTL、容量、no-evidence 和 error tests。

验收:

  • 未清洗原始结果不会进入 Agent;
  • 每条返回证据可以回到当前 Run 的 canonical result;
  • 只有当前 Run 的 READY 记录可进入引用校验;EVIDENCE_FOUND、NO_EVIDENCE 和 ERROR 的引用边界有契约测试,读取不会刷新 TTL,超限原始响应不会被静默截断;
  • 阶段 3B/3C 可复用同一 Tool boundary 和 invocation store,不复制状态机或 Redis 访问逻辑。

阶段 3B:RAG 与 query_logs 结果投影

目标:在阶段 3A 的统一边界上迁移两个现有证据 Tool,并完成 Agent-facing 有界投影。

任务:

  • RAG:审计分离、去重复正文、精确摘录和上下文预算;
  • query_logs:在现有 Mock 上实现统一 Contract、模板聚合、时间线抽样和脱敏;不实现真实 MCP/CLS 适配器;
  • 两个 Tool 统一接入阶段 3A 的 canonical invocation store、evidence_status 和 Tool Call ID 契约;
  • 增加 Tool contract、truncation、no-evidence、负向观察和 error tests。

验收:

  • RAG/日志原始结果不会未经投影进入 Agent;
  • RAG/日志的长度、数量、查询范围和脱敏预算有 focused tests;
  • NO_EVIDENCE 保留查询范围并且不会被表述为问题不存在;
  • 不实现真实 MCP/CLS 适配器。

阶段 3C:只读 MySQL Tool

目标:独立实现安全敏感的只读 MySQL Tool,避免与现有 Tool 迁移共享归档边界。

任务:

  • 引入 JSqlParser,完成保守 SELECT 子集的 fail-closed AST 校验;
  • 实现逻辑数据源、schema/table/column allowlist、参数绑定、只读执行、超时、取消和结果投影;
  • 接入阶段 3A 的 canonical invocation store、预算、evidence_status 和 Tool Call ID 契约;
  • 使用隔离测试数据源完成 security、truncation、no-evidence 和 error tests。

验收:

  • MySQL 的行数、单元格、总字节和查询超时预算有测试;
  • MySQL write、WITH、子查询、UNION、投影通配符、未知 AST、allowlist bypass、timeout 和其他 security cases 被拒绝;合法显式列 SELECT 和 COUNT(*) 通过。

阶段 4:单体 Diagnosis ReAct Agent

目标:将 Planner、Executor、内部 Verifier、自身 Composer 职责合并为一个完整 ReAct Agent;本阶段只通过内部应用用例和测试入口验证,不接管公开 Chat 入口。

任务:

  • 创建单一 Diagnosis Agent Prompt;
  • Agent 接收当前原始 Query 和可选的固定 Schema previous_turn;
  • 使用框架已有 ReAct/tool loop,不手写 While;
  • 接入 Harness 包装后的 Tool;
  • 输出结构化 Draft/Analysis/Conclusion/Tool Call IDs;
  • 证据不足时明确停止;
  • 新 Agent 通过独立内部应用用例接入 Harness,公开 /api/chat 暂不切换;
  • 旧多 Agent 主链路在阶段 5/6A/6B 完成释放门禁和切换前继续保留,禁止阶段 4 直接删除导致公开入口失效;
  • 保留 Run/AgentStep/ToolInvocation 基础审计。

验收:

  • 新诊断链路只有一个拥有工具循环的 Agent,且只在内部测试入口运行;
  • Diagnosis Agent 整体、单次模型调用和 Tool 调用均无 Harness 自动重试;
  • 无 Planner/Executor/Composer Agent 间 JSON 搬运;
  • 无外层 Graph;
  • focused Agent/tool-loop/output tests 通过;
  • 工具、模型和上下文预算均有可配置且被 Harness 强制执行的确定性上限。

阶段 5:EvidenceGuard、SemanticGuard 与释放策略

目标:在不恢复 Graph 的前提下完成物理验真和独立语义审查。

任务:

  • EvidenceGuard 校验 Draft Schema、Analysis ID 唯一性、Analysis kind、报告内部引用完整性,以及当前 Run、Tool Call ID、调用生命周期、evidence_status 和 agent_result;
  • 格式/物理验真首次失败只执行一次无 Tool 输出修复,禁止重新运行诊断或 Tool 循环;
  • 修复后再次执行 EvidenceGuard,仍失败则直接安全 Fallback;
  • 构造 SemanticGuard 最小隔离输入;
  • 复用系统当前唯一 ChatModel,实现由同一 Harness 受限控制的无工具、无记忆、单轮 SemanticGuard Agent;
  • Harness 控制 SemanticGuard 输入预算、超时、取消、一次重试、结构校验、审计和降级释放,禁止 Agent 自身重试或形成回路;
  • 实现 SUPPORTED/UNSUPPORTED/TIMEOUT/ERROR release policy;
  • 确保 SemanticGuard 不回调主 Agent;
  • 增加 duplicate/missing Analysis ID、empty evidence reference、fabricated Tool ID、cross-run、failed call、missing agent_result、NO_EVIDENCE 负向观察、无证据过度推断、unsupported report、timeout、Fallback type 和 verified_sources 规则测试。

验收:

  • 重复/缺失 Analysis ID、空引用、伪造/跨 Run/失败调用或缺失 agent_result 不会进入 SemanticGuard;
  • SemanticGuard 只看到 verified evidence;
  • SemanticGuard 与主 Agent 复用同一模型配置,但不共享上下文、工具或记忆;
  • EvidenceGuard 修复最多一次,且修复调用没有 Tool;
  • 第二次物理验真失败直接 Fallback;
  • 超时和失败不释放草稿;
  • UNSUPPORTED 不会释放或局部裁剪主 Agent 草稿;
  • Fallback 不包含主 Agent 草稿或 SemanticGuard 内部 reason,并以 content + done 正常结束;
  • 无隐式 retry loop。

阶段 6A:Chat Application Use Case、意图路由与 previous turn

目标:在不切换公开协议的前提下完成 Chat 应用用例、三类意图路由和上一安全回合组装。

任务:

  • 会话、历史和执行生命周期下沉应用用例,由应用用例创建并传播阶段 2 定义的 RunContext;
  • 引入三分类轻量 Intent Router;
  • Intent Router 技术失败或非法枚举只由 Harness 重试一次,第二次失败不默认进入 Diagnosis;
  • 由应用用例确定性组装 Diagnosis Agent 的上一个已安全发布回合,不调用上下文摘要模型;
  • 原始 Query 原样进入选定执行路径;
  • 新应用用例只通过内部测试入口验证,公开 /api/chat 和 /api/chat_stream 暂不切换;

验收:

  • SYSTEM_CHAT、KNOWLEDGE_QUERY 和 DIAGNOSIS 路由映射及失败语义通过 focused tests;
  • previous turn 只来自同一 Session 上一个符合安全发布条件的结构化结果;
  • 应用用例显式传播同一个 sessionId/runId,不依赖 Controller 提供模型和工具;
  • 阶段 6B 可直接完成协议切换,不需要重写应用用例。

阶段 6B:唯一 /api/chat SSE 切换

目标:将公开 Chat 原子切换到阶段 6A 的应用用例,并完成破坏性 SSE 协议迁移。

任务:

  • Controller 只负责请求校验、HTTP/SSE 协议和连接生命周期;
  • 仅在阶段 5 的 EvidenceGuard、SemanticGuard 和 Release Policy 全部通过后,原子切换 /api/chat 到新链路;
  • 切换前后均不得出现未经过释放门禁的公开 Draft;
  • 只保留 POST /api/chat;
  • 删除 /api/chat_stream 和同步兼容路径;
  • 同步迁移前端 Chat 消费者到固定 SSE 事件契约;
  • 按固定顺序输出 metadata -> status* -> content|failure -> done,终态只允许 SUCCESS/FALLBACK/FAILED;
  • 处理断开、取消、超时和 Run 终态;
  • 不创建 Controller 自有无界线程池。

验收:

  • Controller 不依赖 ChatModel/ToolCallbackProvider;
  • 同一请求 sessionId/runId 在 SSE、日志和数据库一致;
  • 禁止输出 Thought、Prompt、raw Tool data 和内部错误;
  • SSE 事件 Schema、顺序、互斥、唯一终态、客户端取消和错误单元/集成测试通过。

阶段 7:物理清理、文档与最终验收

目标:删除旧架构和完成一次最终端到端验收。

任务:

  • 物理删除被替代的旧 Agent、Hook、ThreadLocal、路由和死代码;
  • 删除旧 Tool compatibility contract 和过时测试;
  • 不保留注释旧代码或双轨开关;
  • 更新 MVP 架构、接口、Tool、Trace 和安全文档;
  • 审查 ISS-012/ISS-013 是否可归档或被本 Issue 吸收;
  • 运行最终 Maven 启动 E2E;
  • 核对 logs/;
  • 使用安全的数据库查询方式核对 exact sessionId/runId;
  • 验证 Token、工具次数、SSE、EvidenceGuard、SemanticGuard 和 Fallback。
  • query_logs 和外部 MySQL Tool 使用现有 Mock/测试数据完成契约、安全与编排验收;本阶段不声称完成真实 CLS 或生产业务 MySQL 数据源的 live E2E。

验收:

  • 旧多 Agent/Graph/伪流式入口不存在;
  • 全部 focused tests 通过;
  • 最终 E2E、日志和数据库证据归档;
  • 无硬编码凭据、临时 refs 文件、未解释兼容层和死代码;
  • 工作区改动范围与本 Issue 一致。

13. 阶段门禁

实施时每阶段必须满足:

  1. 当前阶段范围和行为变化已确认;
  2. 需要的单元/契约测试已补充并通过;无必要时记录跳过理由;
  3. 当前独立 OpenSpec change 已完成 Apply 和阶段验收,证据已归档;
  4. 当前 change 已 Archive,OpenSpec 索引/规格同步完成;
  5. git diff 精确审查完成,当前阶段已独立 Git commit;
  6. 前一阶段 Archive 和 Git commit 完成后才进入下一阶段,不并行实施相邻阶段;
  7. 阶段 0–6B 不运行完整 live E2E;阶段 7 全部完成后统一执行 Maven E2E、日志和数据库核验。
  8. 阶段 4 和 6A 不得接管公开入口;公开入口切换只能发生在阶段 6B,且必须依赖阶段 5 的释放门禁。

14. 总体验收标准

  • 复杂诊断只存在一个拥有工具循环的 Diagnosis ReAct Agent。
  • 不存在业务 StateGraph 或 Planner/Executor/Composer 多 Agent 主链路。
  • Harness 不承担业务推理,不演变为工作流引擎。
  • EvidenceGuard 是 Harness 内的确定性能力,不是独立编排节点。
  • SemanticGuard 使用完全隔离上下文,无工具、无记忆、无回调循环。
  • SemanticGuard 不使用未校准数值置信度控制在线释放。
  • 所有 Agent-facing evidence Tool 符合 ACI 状态和 Tool Call ID 契约。
  • RAG 不再向 Agent 返回 ContextPack/Trace/Rerank 等审计数据。
  • query_logs 不要求 Agent 先调用 Topic discovery,且返回聚合、抽样、脱敏结果。
  • MySQL Tool 只读、安全解析、参数绑定、allowlist、超时和结果上限全部生效。
  • Tool 原始结果不会未经有界投影进入 Agent 上下文;Redis canonical evidence 当前可暂不脱敏,但不得被 Agent 直接读取。
  • Redis 每次 Tool Call 单 Key 保存,状态、TTL、容量、ACL 和日志禁泄漏规则均有测试。
  • 每个 Tool Call ID 可以按 exact runId 和调用记录状态验真,并取得对应 agent_result。
  • 只保留一个 /api/chat SSE 接口。
  • SSE 不输出 Thought、Prompt、原始 Tool 载荷和未验证结论。
  • 客户端断开、模型/Tool/SemanticGuard 超时均有明确取消和 Run 终态。
  • 所有重试由 Harness 按类型化策略装配和记录,无 SDK/HTTP/数据库隐藏重试或整个 Diagnosis Agent 重跑。
  • 最终 E2E 能按 sessionId/runId 对齐 SSE、日志、AgentStep、ToolInvocation 和最终答案。
  • Token、工具调用、Tool 投影、Redis TTL 和总延迟预算均来自集中配置,并有可验证的强制上限和耗尽原因。
  • 11 个 OpenSpec changes 均已独立 Archive,并分别对应一个范围清晰的 Git commit。
  • 不保留旧兼容分支、注释代码、本地 refs 卸载和硬编码凭据。

15. 非目标

  • 不构建多 Agent 协作平台;
  • 不引入业务 StateGraph;
  • 不实现 Harness 插件市场、通用 Pipeline DSL 或策略语言;
  • 不保留旧同步 Chat、/chat_stream 或旧 Tool Contract;
  • 不输出或持久化 Chain of Thought;
  • 不使用本地 refs/*.md 作为 Tool 原始结果主存储;
  • 不向 Agent 暴露 Redis Client、Redis Tool、key、连接信息或完整调用记录;
  • 不提供历史来源召回 Tool、通用 Memory Tool 或完整上下文恢复能力;
  • 不让 ToolResultProjector 调用 LLM 生成证据摘要;
  • 不允许 MySQL 写操作;
  • 不允许 MySQL Tool 查询 Agent 自身的持久化数据库;
  • 不允许 Skill/RAG 文档绕过独立配置授予数据库访问权限;
  • 本 Issue 不实现 MySQL 租户、行级权限或动态数据授权;首版只落实库/表/字段白名单;
  • 不提供 query_metrics Tool;指标查询和其 ACI/结果投影设计另立后续 Issue;
  • 不用调低模型 maxTokens 代替上下文治理;
  • 不因 SemanticGuard 超时而释放未验证草稿;
  • 不以追加“人工复核”警告替代删除不受支持的强结论。

16. 设计 Review:已确认决策

以下决策已经完成讨论,作为阶段 0 契约冻结的输入:

已确认项

  1. Canonical Evidence 存储:已确认 Redis 每个 Tool Call 使用单 Key superbiz:harness:tool-call:{runId}:{toolCallId},保存 request/raw_response/agent_result/status/evidence_status/timestamps。status=PROJECTING/READY/ERROR 表示调用生命周期,evidence_status=EVIDENCE_FOUND/NO_EVIDENCE/ERROR 表示结果语义;NO_EVIDENCE 只能支持限定查询范围的负向观察。默认 TTL 2 小时且不续期,默认单记录 1MB、Agent Result 64KB、单 Run 5MB;Harness-only ACL,原始超限进入 RESULT_TOO_LARGE,不静默截断。当前版本暂不做持久化脱敏,默认值后续按运行数据校准。

  2. SemanticGuard 模型与超时:已确认复用当前唯一 ChatModel,由同一 Harness 控制;首次超时/失败/结构无效时使用相同证据快照重试一次,仍失败则安全降级。单次和总超时提取为集中配置,初期不冻结具体数值。

  3. SemanticGuard 完整报告审查:已确认接收原始 Query、Diagnosis Agent 完整 Draft 和 EvidenceGuard 生成的 verified evidence snapshot;校验结论、分析、行动计划、建议、限制和范围是否语义成立。它不访问 Redis、不重复验真、不接收 Diagnosis Plan/Tool 过程,也不生成、总结、改写或补充用户报告。Diagnosis Agent 是唯一报告作者,Harness 只发布原 Draft 或固定 Fallback。

  4. 预算数值:已确认主 Agent、Tool、SemanticGuard 和 Redis 的预算全部集中配置,首版使用可调默认值,不在设计阶段冻结未经数据验证的数值;Harness 负责强制执行和记录耗尽原因。

  5. RAG 投影预算:最大 Evidence 数、单条 excerpt 和总字符预算提取为同一配置;默认值根据后续 Trace 和截断数据校准。

  6. 日志投影预算:最大 Pattern/Event 数、消息长度、lookback 和总字符预算提取为同一配置;聚合指纹规则仍属于 Tool 行为契约,不作为数值配置问题处理。

  7. 真实日志适配:已确认本 Issue 首版只沿用现有 Mock;真实 MCP/Java CLS 适配器和生产接入另立后续 Issue,当前只保留可复用的 Agent-facing Contract。

  8. MySQL SQL Parser:已确认使用 JSqlParser。首版只允许显式列的单条 SELECT、INNER/LEFT JOIN、常用筛选/分组/排序和函数 allowlist;允许 COUNT(*),禁止 WITH、子查询、UNION、窗口函数、投影通配符和未知 AST;Harness 注入或压低 LIMIT,并以 PreparedStatement、只读账号、超时和 setMaxRows 兜底。

  9. MySQL allowlist 配置:已冻结为逻辑数据源下的静态 allowed-schemas -> tables -> columns 三层精确白名单,并配置 default-schema。不支持通配符、正则或动态授权;凭据通过环境变量/Secret 注入。本 Issue 暂不展开租户和行级权限。

  10. 对话历史:已确认只使用显式极简上下文,不提供完整历史或 Redis 历史召回。Intent Router 接收当前 query + last_intent + last_user_query。diagnosis_run 持久化 intent/release_outcome/published_result,只有同 Session 最近一个 DIAGNOSIS + SUCCESS 的安全结构化结果可进入 previous_turn;Fallback、失败和取消均排除。Diagnosis Agent 接收当前 Query 和固定字段 user_query/published_conclusion/scope/limitations/source_documents,由 Harness 确定性组装并按配置截断,不调用 LLM 摘要,不复用旧日志/MySQL 结果。SemanticGuard 只接收当前诊断的 Query、完整 Draft 和 verified evidence snapshot。

  11. 重试边界:已确认由 Harness 装配类型化重试策略。Router 与 SemanticGuard 的技术失败最多重试一次;Diagnosis Agent、主模型调用和 Tool 调用不自动重试;EvidenceGuard 只执行一次显式无 Tool 结构修复;禁止隐藏和嵌套重试。

  12. 阶段依赖顺序:已调整为阶段 0 设计冻结、1 ACI Contract、2 Harness Core/RunContext、3A invocation store、3B RAG/日志投影、3C MySQL Tool、4 Diagnosis Agent、5 Guards、6A Chat 应用用例、6B SSE 切换、7 清理/E2E。阶段 3A 起只依赖显式 RunContext,不临时耦合旧 ChatService。

  13. OpenSpec/sm-flow 映射:已确认 ISS-014 作为总 Issue,11 个实施切片各自使用独立 OpenSpec change 和完整串行 sm-flow;每阶段 Archive 并 Git commit 后才能进入下一阶段,最终 E2E 只在阶段 7 执行。

  14. EvidenceGuard 与报告作者边界:Diagnosis Agent 是唯一语义作者;EvidenceGuard 作为 Harness 内的确定性能力校验 Draft Schema、Analysis 引用完整性和当前 Run Tool Call 真实性,不判断语义推导。Harness 只确定性展开 Agent 已选择的引用,不改写报告。

  15. SemanticGuard evidence snapshot:Harness 将已验证 Tool Calls 的有界 agent_result 按 analysis_id 分组,不注入 tool_call_id、Redis 或 raw_response,SemanticGuard 据此校验 Analysis、Conclusion、Action Plan、Recommendations、Scope 和 Limitations。

  16. Fallback 与 SSE:Fallback 使用统一 Schema 和三种稳定 type;EvidenceGuard 失败时 verified_sources=[]。SSE 首版固定为 metadata -> status* -> content|failure -> done,不实现断线续传、事件重放、轮询或 WebSocket。

Review 结论

当前架构和关键契约已经足够进入阶段 0,不再继续增加设计组件。阶段 0 负责把上述决策固化为 OpenSpec、Schema、契约测试和安全基线;完成 Archive 与 Git commit 前不得进入阶段 1。

剩余风险属于实施期验证项,而不是继续扩展架构的理由:

  • SemanticGuard 是否能稳定执行报告级二元语义校验;
  • canonical evidence 是否按 Redis TTL 和访问边界承载完整调用结果;
  • Harness 是否能严格执行集中预算,并为耗尽和截断提供可观察原因;
  • MySQL Tool 的 AST 白名单、只读、超时和容量边界能否通过 Mock/隔离测试数据源的安全用例;真实生产数据源接入另立后续 Issue 验证。

实现中不得为这些风险创建 HarnessPlugin、Graph、通用 Tool DSL 或大量预留接口;按各阶段最小范围实现并通过门禁验证。

17. 相关文件

  • mvp/issues/active/ISS-012-executor-token-budget-and-context-growth.md
  • mvp/issues/active/ISS-013-chat-entry-decoupling-and-sse.md
  • mvp/disscus/plan.md
  • src/main/java/com/superbiz/agent/controller/ChatController.java
  • src/main/java/com/superbiz/agent/service/ChatService.java
  • src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java
  • src/main/java/com/superbiz/agent/hook/TokenTrackingChatModel.java
  • src/main/java/com/superbiz/agent/hook/VerifierInputHook.java
  • src/main/java/com/superbiz/agent/service/ExecutorGatekeeperService.java
  • src/main/java/com/superbiz/agent/service/ToolInvocationRecorder.java
  • src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java
  • src/main/java/com/superbiz/agent/agent/tool/QueryLogsTools.java
  • src/main/resources/prompts/chat-planner-prompt.md
  • src/main/resources/prompts/chat-executor-prompt.md
  • src/main/resources/prompts/chat-verifier-prompt.md
  • src/main/resources/prompts/chat-composer-prompt.md
  • scripts/query_mysql.py
  • mvp/architecture/current-mvp-architecture.md