Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/agent/causal-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ const FAILURE_PATTERNS: Record<
deployment_issues: {
keywords: ['deploy', 'release', 'rollout', 'version', 'update', 'change'],
queries: [
{
tool: 'correlate_changes',
parameters: { window_minutes: 120 },
description: 'Correlate recent changes with incident',
},
{
tool: 'query_change_events',
parameters: { since_minutes: 180, limit: 10 },
description: 'List recent changes',
},
{
tool: 'aws_query',
parameters: { services: ['ecs', 'lambda', 'codepipeline'] },
Expand Down
5 changes: 5 additions & 0 deletions src/agent/investigation-orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,11 @@ export class InvestigationOrchestrator {

// Try to gather some initial context from tools
const triageSources: Array<{ tool: string; params: Record<string, unknown>; label: string }> = [
{
tool: 'correlate_changes',
params: { affected_services: [], window_minutes: 120 },
label: 'Correlated Recent Changes',
},
{
tool: 'search_knowledge',
params: {
Expand Down
95 changes: 95 additions & 0 deletions src/agent/tool-summarizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,99 @@ function summarizeDefault(
// Registry of Summarizers
// ============================================================================

function summarizeCorrelateChanges(result: unknown): CompactToolResult {
const resultId = `correlate_changes_${Date.now()}`;
const obj = result as Record<string, unknown> | null;
if (!obj || obj.error) {
return {
summary: 'correlate_changes: no results',
highlights: {},
itemCount: 0,
resultId,
hasErrors: !!obj?.error,
services: [],
healthStatus: 'unknown',
};
}
const correlations = (obj.correlations || obj) as Array<Record<string, unknown>>;
if (!Array.isArray(correlations) || correlations.length === 0) {
return {
summary: 'correlate_changes: no correlated changes found',
highlights: {},
itemCount: 0,
resultId,
hasErrors: false,
services: [],
healthStatus: 'healthy',
};
}
const top3 = correlations.slice(0, 3);
const highlights: Record<string, string> = {};
const services: string[] = [];
for (const c of top3) {
const event = (c.changeEvent as Record<string, unknown>) || c;
const svc = (event.service as string) || 'unknown';
const score = typeof c.correlationScore === 'number' ? c.correlationScore.toFixed(2) : '?';
const summary = (event.summary as string) || (event.changeType as string) || 'change';
highlights[svc] = `score=${score}: ${summary}`;
if (!services.includes(svc)) services.push(svc);
}
return {
summary: `correlate_changes: ${correlations.length} correlated change(s)`,
highlights,
itemCount: correlations.length,
resultId,
hasErrors: false,
services,
healthStatus: 'unknown',
};
}

function summarizeQueryChangeEvents(result: unknown): CompactToolResult {
const resultId = `query_change_events_${Date.now()}`;
const events = Array.isArray(result) ? result : [];
if (events.length === 0) {
return {
summary: 'query_change_events: no changes found',
highlights: {},
itemCount: 0,
resultId,
hasErrors: false,
services: [],
healthStatus: 'healthy',
};
}
const byType: Record<string, number> = {};
const services: string[] = [];
for (const e of events) {
const evt = e as Record<string, unknown>;
const ct = (evt.changeType as string) || 'unknown';
byType[ct] = (byType[ct] || 0) + 1;
const svc = evt.service as string;
if (svc && !services.includes(svc)) services.push(svc);
}
const typeSummary = Object.entries(byType)
.map(([k, v]) => `${k}:${v}`)
.join(', ');
const highlights: Record<string, string> = { types: typeSummary };
const deployments = events.filter(
(e: unknown) => (e as Record<string, unknown>).changeType === 'deployment'
);
if (deployments.length > 0) {
const recent = deployments[0] as Record<string, unknown>;
highlights.recentDeploy = `${recent.service}: ${recent.summary}`;
}
return {
summary: `query_change_events: ${events.length} change(s) — ${typeSummary}`,
highlights,
itemCount: events.length,
resultId,
hasErrors: false,
services,
healthStatus: 'unknown',
};
}

const SUMMARIZERS: Record<string, ToolSummarizerFn> = {
aws_query: summarizeAwsQuery,
cloudwatch_alarms: summarizeCloudwatchAlarms,
Expand All @@ -729,6 +822,8 @@ const SUMMARIZERS: Record<string, ToolSummarizerFn> = {
datadog: summarizeDatadog,
prometheus: summarizePrometheus,
search_knowledge: summarizeKnowledgeSearch,
correlate_changes: summarizeCorrelateChanges,
query_change_events: summarizeQueryChangeEvents,
};

// ============================================================================
Expand Down
Loading