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
evidenceBlocksfrom the legacy response. - Accept an evidence block only when its content/excerpt is non-blank.
- Use
sourceas the stabledocument_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 boundedexcerpt. - Ignore
contextPack,retrievalTrace,rerankTrace, scores, hit reasons, domains, and messages. - Set
NO_EVIDENCEwhen no usable excerpt remains.
Query-log projection
- Parse only the legacy
logsarray and success/total fields needed for semantics. - Map
LogTopicto 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
LogQueryScopefrom the logical request andlookback_minutes, using the adapter clock forend_time. - Always record
source_kind=MOCKfor this stage. - Exclude
instanceandmetrics; 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_EVIDENCEfor a successful emptylogsarray; 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
Clockand tests use a fixed clock. - Projection size pressure: deterministic collection bounds and explicit
truncatedprevent silent overflow.