Files

90 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
当前 `LookupKnowledgeTool` 返回 `LookupResult`,包含 `ContextPack`、`RetrievalTrace`、`RerankTrace` 等内部检索信息;`QueryLogsTools` 暴露 region、TopicId、limit、Topic discovery 和旧 `success/total/logs` 结构。MySQL evidence Tool 尚不存在。阶段 0 已创建共享 `InvocationStatus` 与 `EvidenceStatus`,但尚无三类 Agent-facing DTO 或稳定 Tool 描述。
本地依赖验证显示,Spring AI 1.1.7 的 `AssistantMessage.ToolCall` 持有 `id`,Spring AI Alibaba 1.1.2.0 的 `ToolCallRequest` 将其暴露为 `getToolCallId()` 并允许通过 `ToolInterceptor` 包装调用;普通 Spring AI `ToolContext` 只包含调用方传入的 context 和 history,不自动提供当前 Tool Call ID。因此后续 Harness 必须以 Alibaba interceptor request 为 ID 接入边界。
## Goals / Non-Goals
**Goals:**
- 用 Java 类型冻结 RAG、日志和 MySQL 的最小 Agent Request/Result JSON Schema。
- 复用统一证据状态,并保持 invocation lifecycle 与 evidence result 两套语义正交。
- 保证所有可引用结果只携带框架 Tool Call ID,不生成替代 ID。
- 冻结简短、面向行动的 Tool 名称和描述,禁止基础设施/审计实现泄漏。
- 通过三个独立契约测试锁定字段、集合不可变性、描述边界和 Mock 来源标识。
**Non-Goals:**
- 不修改旧 `@Tool` 方法、当前 Chat/AIOps 工具注册或返回行为。
- 不实现 `ToolInterceptor`、Pre/Post Tool、Redis invocation store 或 ToolResultProjector。
- 不实现真实 CLS/MCP、MySQL 连接、JSqlParser 校验、allowlist 或脱敏。
- 不删除旧 DTO、Topic discovery 或审计服务;这些在后续切片接入和清理。
## Decisions
### 1. 契约放在独立 Harness Tool 包
新增类型放在 `com.superbiz.agent.harness.tool.contract`,共享状态继续引用 `com.superbiz.agent.harness.contract`。这使新 Harness 边界与旧 `dto`、旧工具内部模型明确隔离。
替代方案是在旧工具类内新增嵌套 DTO;这会继续把运行实现与 Agent Contract 绑定,并妨碍三个 projector 复用,故不采用。
### 2. Tool Call ID 是结果字段,不是 Agent 输入字段
三类 Request 均不包含 `tool_call_id`。后续 Harness 从 `ToolCallRequest.getToolCallId()` 取得 ID,在投影 Result 时写入;模型不能选择或覆盖该值。`EVIDENCE_FOUND` 和 `NO_EVIDENCE` 结果必须具备合法 ID;如果 Pre-Tool 失败原因就是 ID 缺失/非法,`ERROR` 可以没有可引用 ID。
替代方案是让模型把 ID 作为参数回传,或由 Harness 生成 UUID;两者都会形成不可信输入或第二套标识,违反阶段 0 决策。
### 3. Result 直接携带 evidence status,不携带 invocation status
`RagToolResult`、`QueryLogsToolResult` 和 `MysqlToolResult` 只包含 `EvidenceStatus`。`InvocationStatus` 继续描述 Redis canonical invocation 的 `PROJECTING/READY/ERROR` 生命周期,由阶段 3A 的存储模型承载。契约测试分别锁定两个枚举,防止把 `READY` 当成“找到证据”或把 `NO_EVIDENCE` 当成生命周期状态。
### 4. 使用 record 和 defensive copy
Request/Result 使用 Java 17 record,并用 Jackson `@JsonProperty` 固定 snake_case。所有 list 和 row map 在构造时 defensive copy,避免后续投影、存储或测试在对象创建后改变 Agent-visible 结果。
替代方案是沿用 Lombok mutable bean;它更贴近旧代码,但无法天然表达冻结后的值对象边界。
### 5. 三类最小 Schema
- RAG Request 只有 `query`;Result 只有查询回显、有界 evidence、计数和截断标记。
- Logs Request 只有逻辑 `topic`、`query` 和可选 `lookback_minutes`;Result 保留 `source_kind`、完整 scope、聚合 patterns、少量 timeline events、计数和截断标记。
- MySQL Request 只有逻辑 `data_source`、参数化 `sql` 和 `params`;Result 保留 columns、结构化 rows、计数和截断标记。
日志逻辑 Topic 首版冻结为 `APPLICATION`、`DATABASE_SLOW_QUERY`、`SYSTEM_EVENTS`。旧 `system-metrics` 不纳入日志 Contract;指标 Tool 不属于本 Issue。`SourceKind` 首版只有 `MOCK`,真实适配器以后在保持字段语义的前提下扩展。
### 6. Tool 描述作为常量契约
使用单一 `AgentToolContracts` 定义三个 snake_case Tool 名称和 ACI 描述。测试禁止描述中出现 Milvus、L0/L1、rerank、CLS region/TopicId、连接、凭据、topK、limit、Redis、Trace 等实现词。旧 `@Tool` 注解暂不引用这些常量,以免本阶段提前改变模型可观察行为。
## Module Flow
```text
ReactAgent tool call
-> [later] Alibaba ToolInterceptor obtains framework tool_call_id
-> typed Request contract
-> [later] data adapter + canonical persistence + ToolResultProjector
-> typed bounded Result contract
-> Agent observation
```
阶段 1 只实现图中的 typed contracts 和描述常量。旧 `ChatService/AiOpsService -> LookupKnowledgeTool/QueryLogsTools` 调用链保持不变。
## Risks / Trade-offs
- [新旧 Contract 短期并存,容易误判迁移已完成] -> 契约放独立包,proposal/spec/tasks 明确禁止本阶段改旧工具,并用 `rg` 验证旧注册路径未切换。
- [DTO 不能自行保证 ID 来自框架] -> spec 明确 provenance,阶段 2/3 在 `ToolInterceptor` 测试真实 `ToolCallRequest.getToolCallId()` 传播。
- [record 只做结构冻结,不做业务校验] -> 参数范围、SQL allowlist、ID 格式和状态组合由后续 Pre-Tool/Projector validator 实现;本阶段不在构造器复制安全策略。
- [逻辑 Topic 与旧 TopicId 需要映射] -> mapping 属于日志 adapter/projector 阶段,Agent Contract 不接受 region 或物理 TopicId。
## Migration Plan
1. 本阶段新增契约和测试,不切换消费者;回滚只需删除新增类型。
2. 阶段 2/3A 从 Alibaba `ToolInterceptor` 接入框架 ID 和 invocation lifecycle。
3. 阶段 3B/3C 分别让 RAG/日志/MySQL adapter 输出本契约。
4. 阶段 6B 原子切换公开 Chat;旧 Contract 最终由阶段 7 清理。
## Open Questions
无。真实日志 adapter 的 `SourceKind` 扩展和值映射在后续接入 change 决策,不阻塞本阶段。