90 lines
6.1 KiB
Markdown
90 lines
6.1 KiB
Markdown
## 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 决策,不阻塞本阶段。
|