Files
SuperBizAgent-java/devflow/projects/2026-07-21-single-react-diagnosis-agent/decisions.md
T

14 KiB
Raw Blame History

Decisions: single-react-diagnosis-agent

Discover status

  • Checkpoint: Discover
  • Capability source: sm-flow,使用 grill-with-docs 进行代码可证问题澄清,并使用 GitNexus、源码、依赖 sources jar 与 javap 核对调用链和框架 API。
  • Scale: complex。变更新增内部 Agent/use case,跨越模型、Tool、预算、结构化输出和审计边界,但不切换公开协议。
  • devflow/index.md 命中 design freeze、RunContext、ACI contracts、canonical store、RAG/log projection 和 MySQL Tool;没有与 OpenSpec 冲突的 ADR。

Question Pool

# 维度 问题 模式 状态
Q1 术语 单体 Diagnosis Agent 是否包含外层 Graph 或多个报告作者? evidence-driven 已解决
Q2 边界 阶段 4 是否切换公开 Chat 或删除旧多 Agent 链路? evidence-driven 已解决
Q3 验收 如何证明 ReAct 正常轮次不是 Harness retry? evidence-driven 已解决
Q4 技术 如何取得并保留框架原始 tool_call_id? evidence-driven 已解决
Q5 技术 如何在每个模型和 Tool 边界强制 Run 预算? evidence-driven 已解决
Q6 输出 框架生成的 DiagnosisDraft schema 是否与可空 conclusion 契约一致,并会直接返回 DiagnosisDraft? evidence-driven 已解决
Q7 上下文 previous_turn 如何进入模型且保持固定 Schema 和有界? evidence-driven 已解决
Q8 审计 如何保留 Run/AgentStep/ToolInvocation 而不引入 ThreadLocal? evidence-driven 已解决
Q9 验收 无证据结果如何停止而不补造根因? evidence-driven 已解决

Evidence-driven

结论 证据来源 是否已汇报用户
只新增一个拥有 tool loop 的 ReactAgent,无 SequentialAgent、SupervisorAgent 或业务 StateGraph。 ISS-014 阶段 4;ChatService 旧链路反例;Spring AI Alibaba ReactAgent API 已汇报
阶段 4 只提供内部用例,公开入口保持旧实现,接口影响 L2。 ISS-014 1174-1197、阶段 0 design freeze、GitNexus createReactAgent 引用 已汇报
ToolCallRequest.getToolCallId() 精确暴露 AssistantMessage.ToolCall.id();ToolInterceptor 可在回调执行前取得该 ID。 framework sources ToolCallRequest、AgentToolNode 已汇报
ModelInterceptor 包围每次真实模型调用,适合调用 beforeModelCall 并记录响应 Usage;ToolBoundary 已负责 Tool 预算,不能重复计数。 framework AgentLlmNode/InterceptorChain;ToolBoundary 已汇报
BeanOutputConverter 可从 DiagnosisDraft 生成格式说明,但默认 schema 不允许冻结契约的 conclusion=null;必须 post-process nullable conclusion,且 ReactAgent.call 仍返回 AssistantMessage,需要 Harness 严格解析 JSON。 framework DefaultBuilder、ReactAgent、本地生成 schema 已汇报
RunContext 可放入 RunnableConfig metadata,由框架控制地传播到 ToolInterceptor;不需要 ThreadLocal。 RunnableConfig.addMetadata(String,Object)、AgentToolNode 已汇报
现有 AgentLoggingHook 优先读取 config metadata 的 sessionId/runId,可作为可选审计 Hook 复用;ToolBoundary 保持 canonical Tool invocation。 AgentLoggingHook、ToolBoundary 已汇报
原始 Query 不截断;超限 fail closed。PreviousTurn 先按固定 record 序列化并受独立/总上下文字节限制。 ISS-014 极简上下文与预算规则 已汇报
NO_EVIDENCE 不是错误,只能形成限定范围的 NEGATIVE_OBSERVATION;Prompt 必须要求 conclusion=null、记录 missing_info 并停止。 glossary、ACI spec、DiagnosisDraft contract 已汇报

User-interview

  • 本阶段没有新增 user-interview 问题。方向、范围、阶段串行规则、框架 ID、状态语义以及 routine Apply/Archive/Commit 持续授权均已由用户在 ISS-014 评审与前序阶段确认。

关键取舍

  • 决策:使用框架 ToolInterceptor 直接桥接已注册的 Tool 定义与 Harness adapter。
    • 原因:Spring AI ToolCallback 的调用参数不包含 Tool Call ID,而 Alibaba interceptor 明确提供原始 ID 和运行 metadata。
    • 影响:ToolCallback 负责模型可见定义,interceptor 负责受控执行;未知 Tool 仍交给框架 handler 并最终失败,不伪造结果。
  • 决策:模型预算由 ModelInterceptor 执行,Tool 预算继续由 ToolBoundary 执行。
    • 原因:避免在 Agent 层和 Tool boundary 双重 reserve。
  • 决策:阶段 4 只严格反序列化 DiagnosisDraft,不提前实现 EvidenceGuard。
    • 原因:字段引用真实性、唯一性和语义支持属于阶段 5;本阶段只验证 Agent 能生成冻结结构并携带框架 IDs。
  • 决策:复用现有 Agent Hook 注入点,不复制 AgentStep 持久化实现。
    • 原因:阶段 4 不接公开运行态,阶段 6A 再装配真实 Repository 和 Run 持久化。

OpenSpec 回写

  • 需进入 proposal/design/spec/tasks:单 Agent、内部入口、ToolInterceptor 原始 ID、ModelInterceptor 模型预算、ToolBoundary 单点 Tool 预算、严格 JSON 解析、上下文字节限制、审计 Hook 注入、无证据停止、不切换公开入口。
  • 不创建 ADR:这些是 ISS-014 已冻结方向和当前阶段可逆的内部装配,不满足新的难逆转架构决策条件。

Cross-artifact 对齐

上游 -> 下游 检查内容 状态
brief/ISS-014 -> proposal 单 Agent、内部入口、极简上下文、预算、审计、非目标和验收预期 已对齐
proposal -> design Tool/Model interceptor、严格 Draft、无重试、审计注入和公开隔离 已对齐
design -> specs/tasks ID 传播、预算单点、输入输出限制、生命周期所有权和风险缓解 已对齐
specs -> tasks 7 组可观察要求均有输入/Prompt、Tool bridge、Agent use case 和 focused test 切片 已对齐

Architecture Audit

  • 能力来源:zoom-out,使用 glossary 的 Diagnosis Agent、Diagnosis Harness、RunContext、Evidence Status 和 Invocation Status 术语。
  • 链路为 DiagnosisAgentInput + RunContext -> internal use case -> one ReactAgent -> model/tool interceptors -> ChatModel/ToolBoundary -> strict DiagnosisDraft,没有外层业务 Graph。
  • RunContext 拥有预算/取消/生命周期,ToolBoundary/store 拥有 canonical invocation,use case 拥有输入和 Draft 解析,Agent 只拥有诊断语义;数据所有权不重叠。
  • 最大耦合风险是 Spring AI Alibaba interceptor/output schema API;设计通过本地 1.1.2.0 sources jar 和实际 schema 生成结果证实,并以 focused framework-loop/schema tests 固定。
  • 最大阶段风险是 Draft 在 Guards 前被误用;类名、文档和零 Controller 消费者共同保持 internal/draft 边界,阶段 5 前不得发布。

接口影响

  • 级别:L2 内部接口。
  • 变更对象:新增内部 Java use case/factory/input/limits/interceptors/registry,不修改既有方法签名。
  • 消费者:本阶段只有 focused tests;阶段 6A 将成为首个生产消费者。
  • 兼容性:公开 HTTP/SSE、Controller DTO、数据库和旧 Chat/AiOps 路径不变,无迁移或回滚要求。

Pre-apply Research

参考实现与框架源码

  • src/main/java/com/superbiz/agent/service/ChatService.java:createReactAgent、buildChatExecutorAgent 和旧多 Agent 反例;只复用 Builder 形态,不复用运行职责。
  • src/test/java/com/superbiz/agent/service/ChatServiceSequentialAgentTest.java:scripted ChatModel 测试模式。
  • src/main/java/com/superbiz/agent/harness/core/DiagnosisHarnessCore.java:模型/Tool/Token/容量边界。
  • src/main/java/com/superbiz/agent/harness/tool/boundary/ToolBoundary.java:Tool budget 和 canonical record 单点。
  • src/main/java/com/superbiz/agent/harness/tool/adapter/RagToolAdapter.java、QueryLogsToolAdapter.java、MysqlToolAdapter.java:阶段 4 唯一允许的 evidence Tool 执行入口。
  • src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java:可注入 AgentStep audit,优先读取 RunnableConfig metadata。
  • Spring AI Alibaba 1.1.2.0 sources:ReactAgent、DefaultBuilder、AgentLlmNode、AgentToolNode、ToolCallRequest、InterceptorChain。

技术栈清单

  • ReactAgent.builder() + 从 DiagnosisDraft 生成并修正 nullable conclusion 的 .outputSchema(...),不新建 Graph/SequentialAgent。
  • RunnableConfig.addMetadata(String,Object) 显式携带 sessionId/runId/RunContext,并设置 _stream_=false。
  • ModelInterceptor 对每次模型调用执行 Core budget;读取 ChatResponseMetadata.Usage。
  • ToolInterceptor 读取 exact framework ID,调用 adapter bridge;ToolBoundary 保留唯一 Tool reserve/store 边界。
  • Spring FunctionToolCallback 仅定义模型可见 Tool Schema/description;直接 callback 执行 fail closed。
  • Jackson ObjectMapper 负责固定输入 JSON 和严格 DiagnosisDraft 反序列化;UTF-8 字节按 StandardCharsets.UTF_8 计算。
  • 框架 Hook 列表作为 AgentStep audit 扩展点;阶段 4 不新增 JPA/Redis/Flyway。

新建基础设施

  • harness.agent:Input、Limits、Tool registry/interceptor、Model interceptor、Factory、UseCase 和异常类型。
  • prompts/diagnosis-agent-prompt.md:唯一 Diagnosis Agent Prompt。
  • focused scripted model/tool-loop tests;无需新 Maven 依赖。

ISS-014 PRD 复用

  • 阶段 4 不新建独立 prd.md:ISS-014 已完整覆盖问题、用户价值、数据流、Draft Schema、预算、重试、阶段边界和验收;brief.md 只索引本切片,不复制总 Issue。

Commit Gate Preflight

  • proposal、design、specs、tasks 完整,openspec status 为 complete,openspec validate single-react-diagnosis-agent --strict 通过。
  • question pool 全部为已汇报的 evidence-driven 结论;无未确认 user-interview、接口等级或风险接受问题。
  • Cross-artifact 四段对齐无 gap;架构审计的数据所有权、阶段边界和框架耦合缓解已进入 design/spec/tasks。
  • 接口影响为 L2,仅新增内部 Java API;公开 Controller/SSE/JPA/旧 ChatService 保持不变。
  • Apply、Archive 和阶段 Git commit 使用用户对 ISS-014 各阶段的持续授权;实现必须严格限制为 Committed OpenSpec。
  • .committed 已创建,Committed OpenSpec 可进入 Apply。

Apply Progress

  • 首模块对齐:Input/Limits/Prompt/Tool registry/Tool interceptor 已落地,任务 1.2、2.1、2.2 完成;1.1 等待 focused test 后完成。
  • 编译首次发现 ToolInterceptor 必须实现 Interceptor.getName();分类为代码偏离,已补充稳定名称并复编译通过,无需修改 OpenSpec。
  • 单 Agent use case、Model interceptor、strict Draft parser 和 audit Hook 注入已完成;scripted ChatModel 真实执行框架 model -> Tool -> model loop。
  • 首次测试的两处失败均为测试假设偏差:Spring 会将 callback 异常包装为 ToolExecutionException,Tool observation 位于 Prompt.instructions 的 ToolResponseMessage 而非 Prompt.getContents();已按框架真实 API 修正测试,生产设计未变。
  • 阶段 4 focused tests 共 14 个通过,任务 1.1-4.2 完成;剩余任务 4.3 为综合回归、静态范围和 OpenSpec 验证。

Apply Result

  • 新增一个且仅一个 diagnosis_agent Factory 和内部 DiagnosisAgentUseCase;没有外层业务 Graph、SequentialAgent、SupervisorAgent 或手写 ReAct loop。
  • 新增单一 Prompt、固定 DiagnosisAgentInput(query, previous_turn)、可配置 UTF-8 限制和严格 DiagnosisDraft 解析;不接受完整历史,不执行结构修复或 Agent retry。
  • 新增 HarnessModelInterceptor,对每个非流式模型轮次执行 Core model/Token budget,并在 late result 返回后复查 Run active 状态。
  • 新增 HarnessEvidenceTools 和 HarnessToolInterceptor,注册三类冻结 Tool,精确传播框架 Tool Call ID,并通过阶段 3B/3C adapter/ToolBoundary 返回有界结果。
  • AgentStep 使用可注入框架 Hook 保留,RunnableConfig 显式传播 sessionId/runId;Run 和 Tool canonical invocation 继续由既有 Harness 边界拥有。
  • 公开 Controller、ChatService、AiOpsService 无 diff;旧多 Agent 主链路继续保留。

Apply Verification

  • 编译:mvn -q -DskipTests compile 通过。
  • 阶段 4 focused:mvn -q '-Dtest=HarnessToolInterceptorTest,DiagnosisAgentUseCaseTest' test,14 tests 通过。
  • 综合回归:mvn -q '-Dtest=DiagnosisAgentUseCaseTest,HarnessToolInterceptorTest,DiagnosisHarnessCoreTest,ToolBoundaryTest,ToolAdapterTest,MysqlToolAdapterTest,CanonicalInvocationStoreTest,HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest' test 通过。
  • OpenSpec:openspec validate single-react-diagnosis-agent --strict 通过。
  • 静态范围:新 Agent 包无 ThreadLocal、手写 while、外层 Graph、多 Agent 类型或 raw response;Controller/ChatService/AiOpsService diff 为空。
  • 未执行 live E2E:按 ISS-014 阶段门禁统一留到阶段 7。

Archive Result

  • 11/11 OpenSpec tasks 完成,.archive-ready 已创建。
  • 主规格已同步至 openspec/specs/single-react-diagnosis-agent/spec.md。
  • Change 已归档至 openspec/changes/archive/2026-07-21-single-react-diagnosis-agent。
  • devflow/index.md 和 ISS-014 阶段表已更新为阶段 0-4 archived,下一阶段为 5。
  • 提交前 schema 自审发现框架默认 BeanOutputConverter 将 conclusion 限为 object,与冻结的无证据 null 语义冲突;分类为实现设计遗漏,已回写 archived design,新增 nullable schema post-process 与回归测试,规格行为未改变。