feat(harness): add single diagnosis react agent
This commit is contained in:
@@ -159,6 +159,10 @@
|
||||
- 定义:围绕 Diagnosis Agent 提供确定性运行控制的边界,负责 Run、预算、取消、重试装配、Tool 调用记录、证据验真和最终释放,不承担业务诊断推理。
|
||||
- 边界:Harness 不是工作流引擎,不实现 Planner/Executor/Composer 节点或自行编写 ReAct 循环。
|
||||
|
||||
### Diagnosis Agent
|
||||
- 定义:诊断链路中唯一拥有 ReAct 工具循环并生成 `DiagnosisDraft` 的 Agent,负责规划证据查询、判断证据充分性和撰写完整诊断草稿。
|
||||
- 边界:不负责意图路由、Run/Session 生命周期、证据物理验真、独立语义审查或最终发布;证据不足时必须明确停止并保留限制。
|
||||
|
||||
### EvidenceGuard
|
||||
- 定义:Harness 内部的确定性证据验真能力,校验 Draft 引用、当前 Run 所有权、Tool 调用状态和有界 Agent 投影。
|
||||
- 边界:EvidenceGuard 不调用 LLM,也不判断证据是否足以推出业务结论。
|
||||
|
||||
@@ -39,3 +39,4 @@
|
||||
| 2026-05-29 | chatmodel-abstraction | 抽象 ChatModel 和 EmbeddingModel,支持多模型路由。 | 解耦/多模型路由 | ChatModel, EmbeddingModel, DeepSeek, BGE-M3, SiliconFlow, Spring AI | - | archived |
|
||||
| 2026-07-21 | single-react-rag-log-projections | RAG/log projection adapters through ToolBoundary | Harness/Tool projection | ISS-014, RAG, query_logs, projection, scope, redaction, MOCK, NO_EVIDENCE | openspec/changes/archive/2026-07-21-single-react-rag-log-projections | archived |
|
||||
| 2026-07-21 | single-react-mysql-readonly-tool | Fail-closed read-only MySQL evidence Tool with AST allowlist, JDBC controls and bounded projection | Harness/MySQL security | ISS-014, MySQL, JSqlParser, allowlist, PreparedStatement, timeout, projection | openspec/changes/archive/2026-07-21-single-react-mysql-readonly-tool | archived |
|
||||
| 2026-07-21 | single-react-diagnosis-agent | Single internal Diagnosis ReactAgent with Harness-controlled model/tool loop, bounded context and typed Draft | Harness/Diagnosis Agent/ReAct | ISS-014, ReactAgent, DiagnosisDraft, PreviousTurn, ToolInterceptor, ModelInterceptor, budget | openspec/changes/archive/2026-07-21-single-react-diagnosis-agent | archived |
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# Single React Diagnosis Agent Acceptance
|
||||
|
||||
## 结果
|
||||
|
||||
已接受。阶段 4 Committed OpenSpec 的 11 项任务全部完成,新链路仅通过内部 Java/test 入口运行,公开 Chat 未切换。
|
||||
|
||||
## 验证
|
||||
|
||||
### 静态验证
|
||||
|
||||
- 检查:新 `harness.agent` 包与 Prompt 搜索 `ThreadLocal|SessionContextHolder|while|SequentialAgent|SupervisorAgent|StateGraph|Planner|Composer|Verifier|raw_response`。
|
||||
- 结果:通过,无匹配。
|
||||
- 检查:`git diff --name-only` 限定 Controller、ChatService、AiOpsService。
|
||||
- 结果:通过,无 diff。
|
||||
- 检查:OpenSpec artifact status、cross-artifact、L2 interface impact、`.committed`、`.archive-ready`。
|
||||
- 结果:通过。
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 命令:`mvn -q -DskipTests compile`
|
||||
- 结果:通过。
|
||||
- 命令:`mvn -q '-Dtest=HarnessToolInterceptorTest,DiagnosisAgentUseCaseTest' test`
|
||||
- 结果:通过,14 tests。
|
||||
- 命令:`mvn -q '-Dtest=DiagnosisAgentUseCaseTest,HarnessToolInterceptorTest,DiagnosisHarnessCoreTest,ToolBoundaryTest,ToolAdapterTest,MysqlToolAdapterTest,CanonicalInvocationStoreTest,HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest' test`
|
||||
- 结果:通过。
|
||||
- 命令:`openspec validate single-react-diagnosis-agent --strict`
|
||||
- 结果:通过。
|
||||
- 命令:归档后 `openspec validate single-react-diagnosis-agent --type spec --strict`
|
||||
- 结果:通过;仓库级 `openspec validate --specs --strict` 另发现前序 `mysql-readonly-tool`、`rag-log-projections` 主规格仍使用旧 scenario 格式,本阶段不跨归档边界修改。
|
||||
|
||||
### 浏览器/人工验证
|
||||
|
||||
- 不适用。本阶段无 UI、HTTP 或 SSE 行为变化。
|
||||
|
||||
### 未验证
|
||||
|
||||
- 未启动 Maven 应用、外部模型、MySQL、Redis、Milvus 或日志服务;按 ISS-014 门禁统一留到阶段 7 live E2E。
|
||||
- 未验证 provider 生产响应始终携带 Token Usage;缺失 Usage 时模型调用次数仍强制,实际 Token 只能在 provider 返回时记录。
|
||||
|
||||
## 已完成范围
|
||||
|
||||
- 单一 Diagnosis ReactAgent、单 Prompt 和固定 Query/PreviousTurn 输入。
|
||||
- 框架原生 tool loop、exact Tool Call ID 和三类 Harness adapter bridge。
|
||||
- 模型/Token/Tool/上下文/Draft 预算与无自动 retry。
|
||||
- 严格 DiagnosisDraft 输出和无证据停止规则。
|
||||
- 显式 sessionId/runId audit metadata、可注入 AgentStep Hook、canonical Tool invocation。
|
||||
- 公开 Chat/AiOps 与旧多 Agent 路径保持不变。
|
||||
|
||||
## 已知限制
|
||||
|
||||
- Draft 尚未经过 EvidenceGuard/SemanticGuard,不能公开发布;阶段 5 负责释放门禁。
|
||||
- previous turn 由调用方传入,阶段 6A 才实现同 Session 安全 Run 选择和确定性组装。
|
||||
- 真实业务 adapter/Spring Bean 装配和公开入口切换分别留给阶段 6A/6B。
|
||||
- 仓库级全规格 strict validation 仍受阶段 3B/3C 主规格 scenario 标题格式阻塞,建议阶段 7 文档清理时统一修正并复验。
|
||||
|
||||
## Bug 修复和诊断
|
||||
|
||||
- 编译发现框架 `Interceptor.getName()` 必须实现,已补充稳定名称并回归。
|
||||
- 首次测试修正了两个测试假设:callback 异常包装类型,以及 ToolResponseMessage 在 Prompt instructions 中的实际位置;生产规格与实现方向未变。
|
||||
- 提交前自审发现默认 BeanOutputConverter schema 不允许 `conclusion=null`,与冻结的无证据契约冲突;已增加 schema post-process 和 focused regression,未放宽其他 Draft 字段。
|
||||
|
||||
## 交接
|
||||
|
||||
- 下一步:提交独立阶段 4 commit,再进入阶段 5。
|
||||
- OpenSpec 归档确认:用户已对 ISS-014 每阶段 Apply、Archive 和 Git commit 提供持续授权;已归档至 `openspec/changes/archive/2026-07-21-single-react-diagnosis-agent`,主规格已同步至 `openspec/specs/single-react-diagnosis-agent/spec.md`。
|
||||
@@ -0,0 +1,21 @@
|
||||
# Single React Diagnosis Agent Brief
|
||||
|
||||
## 背景
|
||||
|
||||
- 用户目标:按 ISS-014 阶段 4 建立唯一的 Diagnosis ReAct Agent,并完成独立 sm-flow 归档与提交。
|
||||
- 当前问题:Harness Core 和三类 evidence Tool 已就绪,但没有一个内部诊断执行链消费它们;公开 Chat 仍依赖旧的简单/多 Agent 路径。
|
||||
- 关联 OpenSpec:`openspec/changes/archive/2026-07-21-single-react-diagnosis-agent/`
|
||||
- devflow 分档:complex
|
||||
- 需求真理源:`mvp/issues/active/ISS-014-single-react-agent-harness-aci-ptk-refactor.md`,不重复创建独立 PRD。
|
||||
|
||||
## 范围
|
||||
|
||||
- 本次要做:单 Prompt、单 Diagnosis ReactAgent、固定 Query/PreviousTurn 输入、Harness Model/Tool interceptors、三类 Tool 注册、严格 DiagnosisDraft 解析、上下文/模型/Tool/Token 预算和内部审计注入。
|
||||
- 本次不做:公开 Chat 切换、旧链路删除、EvidenceGuard、SemanticGuard、previous turn 选择、DiagnosisRun 持久化和 live E2E。
|
||||
- 影响区域:`com.superbiz.agent.harness.agent`、`src/main/resources/prompts`、focused tests、OpenSpec/devflow/ISS-014 状态。
|
||||
|
||||
## OpenSpec 对齐
|
||||
|
||||
- proposal 覆盖状态:已覆盖
|
||||
- specs 覆盖状态:已覆盖
|
||||
- tasks 覆盖状态:已覆盖
|
||||
@@ -0,0 +1,156 @@
|
||||
# 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 与回归测试,规格行为未改变。
|
||||
@@ -0,0 +1,29 @@
|
||||
# Single React Diagnosis Agent Evidence
|
||||
|
||||
## 代码与文档证据
|
||||
|
||||
| 来源 | 证据 | 结论 | 是否已汇报 |
|
||||
|---|---|---|---|
|
||||
| `mvp/issues/active/ISS-014-single-react-agent-harness-aci-ptk-refactor.md` | 阶段 4 明确单 Agent、内部入口、极简上下文、结构化 Draft、无重试和预算验收 | 本 change 不得切换公开入口或删除旧链路 | 是 |
|
||||
| `ChatService.java` + GitNexus references | `createReactAgent` 被旧策略入口调用;复杂路径仍创建 Planner/Executor/Verifier/Composer | 新实现必须是独立内部 use case,不能复用旧 Service 运行职责 | 是 |
|
||||
| Spring AI Alibaba 1.1.2.0 `ReactAgent`/`AgentLlmNode` sources | 框架自带 ReAct loop;非流式 `ModelResponse` 保留 `ChatResponse` Usage | 不手写循环,使用 ModelInterceptor 强制模型/Token 预算 | 是 |
|
||||
| Spring AI Alibaba `ToolCallRequest`/`AgentToolNode` sources | `ToolCallRequest.getToolCallId()` 来自 `AssistantMessage.ToolCall.id()`,Tool interceptor 在 callback 前执行 | 可以精确传播框架 ID,不生成第二套 ID | 是 |
|
||||
| Spring AI Alibaba `DefaultBuilder` + 本地 BeanOutputConverter 输出 | 默认 schema 只允许 object conclusion,但冻结契约允许无证据时 conclusion=null | 生成 schema 必须 post-process nullable conclusion,UseCase 仍严格反序列化 DiagnosisDraft | 是 |
|
||||
| `DiagnosisHarnessCore.java` / `ToolBoundary.java` | Core 提供 model/Token/capacity;ToolBoundary 已负责 Tool reserve/store | Agent 层只 reserve model/context,禁止双扣 Tool budget | 是 |
|
||||
| 阶段 3B/3C adapters | RAG/log/MySQL 都以 `RunContext + ToolCallRequestEnvelope` 进入 ToolBoundary | Tool registry 可直接桥接既有 adapter,不复制投影或安全策略 | 是 |
|
||||
| `AgentLoggingHook.java` | 优先从 RunnableConfig metadata 读取 sessionId/runId | Factory 可复用现有 Hook 注入点,不依赖 ThreadLocal | 是 |
|
||||
|
||||
## Evidence-driven 结论
|
||||
|
||||
- 单 Agent 的可验证边界是一个 `ReactAgent.call`,内部允许正常模型/Tool轮次,但外部没有 Agent retry 或第二个报告作者。
|
||||
- ToolCallback 不直接提供 Tool Call ID,必须使用 Alibaba `ToolInterceptor`;已由真实 scripted framework loop 证明 ID 进入 ToolResponseMessage。
|
||||
- `PreviousTurn` 只作为固定上下文,当前 Draft 只允许引用当前 Run Tool result 中的 ID。
|
||||
- `NO_EVIDENCE` 必须以 `conclusion=null`、限定范围的负向观察和 missing info 结束,不能推导健康或排除根因。
|
||||
- 阶段 4 的 L2 内部 API 不影响公开消费者;阶段 5/6A/6B 前 Draft 不可发布。
|
||||
|
||||
## 实现证据
|
||||
|
||||
- 新包 `com.superbiz.agent.harness.agent` 包含 Input/Limits、Prompt loader、Tool registry/interceptor、Model interceptor、Factory 和 UseCase。
|
||||
- `diagnosis-agent-prompt.md` 是唯一新 Diagnosis Agent Prompt,包含 Tool、证据绑定、停止和精确 JSON 规则。
|
||||
- 14 个阶段 4 tests 覆盖框架 model -> Tool -> model、ID、错误、未知 Tool、PreviousTurn、审计 metadata、nullable conclusion schema、no-evidence、解析和预算。
|
||||
- 综合回归同时覆盖 Harness Core、ToolBoundary、3B/3C adapter、canonical store 和冻结 contracts。
|
||||
Reference in New Issue
Block a user