Files

70 lines
4.2 KiB
Markdown

# Design: single-react-rag-log-projections
## Architecture
```text
typed ACI request + framework envelope
|
v
RagToolAdapter / QueryLogsToolAdapter
| (legacy executor is internal and request controls are injected here)
v
ToolBoundary.execute(..., raw -> requestAwareProjector.project(...))
|
+--> CanonicalInvocationStore (complete raw + bounded agent result)
+--> ToolBoundaryResult (bounded result only)
```
The adapters are the only place that knows how the current legacy tools are called. They parse the typed ACI request before invoking the boundary, serialize the legacy result as raw JSON, and bind the typed request and framework `tool_call_id` to the projector closure. `ToolBoundary` remains responsible for all lifecycle, ownership, budget, size and error rules.
## Request-aware projection decision
The generic `ToolResultProjector.project(String rawResponse)` remains unchanged for stage 3A compatibility. Stage 3B introduces specialized projector methods:
```java
ProjectedToolResult project(RagToolRequest request, String toolCallId, String rawResponse);
ProjectedToolResult project(QueryLogsRequest request, String toolCallId,
LogQueryScope scope, String rawResponse);
```
Adapters pass these methods through a lambda to the generic boundary. This preserves request scope without adding request fields to `ProjectedToolResult`, changing the generic boundary API, or relying on raw JSON conventions.
## RAG projection
- Parse only `evidenceBlocks` from the legacy response.
- Accept an evidence block only when its content/excerpt is non-blank.
- Use `source` as the stable `document_id`; fall back to title, then a deterministic ordinal only for malformed legacy records.
- Deduplicate by document ID while retaining the first exact excerpt.
- Project only `document_id`, `source`, `title`, `breadcrumb`, and bounded `excerpt`.
- Ignore `contextPack`, `retrievalTrace`, `rerankTrace`, scores, hit reasons, domains, and messages.
- Set `NO_EVIDENCE` when no usable excerpt remains.
## Query-log projection
- Parse only the legacy `logs` array and success/total fields needed for semantics.
- Map `LogTopic` to the existing Mock topic names inside the adapter (`APPLICATION -> application-logs`, `DATABASE_SLOW_QUERY -> database-slow-query`, `SYSTEM_EVENTS -> system-events`).
- Inject the legacy default region and an internal source limit; neither is part of the ACI request or result.
- Build `LogQueryScope` from the logical request and `lookback_minutes`, using the adapter clock for `end_time`.
- Always record `source_kind=MOCK` for this stage.
- Exclude `instance` and `metrics`; redact credentials, host/pod identifiers, PIDs, IPs, SQL literals and stack-like suffixes from messages.
- Aggregate patterns by sanitized level, service and normalized message, with count and first/last timestamps.
- Sample timeline events deterministically when the source exceeds the event bound.
- Set `NO_EVIDENCE` for a successful empty `logs` array; legacy error responses become projection errors.
## Bounds
`ToolProjectionLimits` defines maximum evidence/items, excerpt/message characters, patterns, events and total Agent projection UTF-8 bytes. Collection bounds set `truncated=true`. If the serialized projection still exceeds the total budget, the projector removes the last timeline/pattern/evidence items until it fits; if no valid bounded result can be produced, it throws and the boundary records `PROJECTION_ERROR`.
## Compatibility and ownership
- No changes to `LookupKnowledgeTool`, `QueryLogsTools`, `ToolInvocationRecorder`, JPA entities, ChatService, AiOpsService, Controller or public HTTP/SSE payloads.
- Redis access remains in `RedisCanonicalInvocationStore`.
- Legacy tools remain the source of raw data until a later Diagnosis Agent cutover.
## Risks and mitigations
- Legacy output shape drift: strict JSON parsing and focused malformed-response tests fail closed.
- Redaction can remove useful details: only sensitive tokens/identifiers are replaced; service, level and sanitized message context remain.
- Scope clock skew: adapter uses an injected `Clock` and tests use a fixed clock.
- Projection size pressure: deterministic collection bounds and explicit `truncated` prevent silent overflow.