Files
SuperBizAgent-java/openspec/changes/archive/2026-07-21-single-react-rag-log-projections/design.md
T

4.2 KiB

Design: single-react-rag-log-projections

Architecture

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:

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.