Intel Agent

Wallet Attribution and Entity Resolution

Component Overview

The Intel Agent serves as Kaizen AI's intelligence aggregation and analysis hub, responsible for collecting, correlating, and interpreting intelligence data from multiple sources to provide comprehensive wallet attribution, entity resolution, and behavioral pattern analysis. This agent transforms raw intelligence data into actionable insights for risk assessment and threat identification.

Core Responsibilities:

  • Multi-source intelligence data collection and correlation

  • Wallet attribution and entity resolution across blockchain networks

  • Fund flow tracking and transaction pattern analysis

  • Behavioral pattern recognition and anomaly detection

  • Risk scoring based on historical intelligence data

  • Real-time intelligence updates and alert generation

Architecture Philosophy: The Intel Agent employs a sophisticated correlation engine that can process multiple intelligence feeds simultaneously, maintaining a comprehensive knowledge graph of entities, relationships, and behavioral patterns. The system prioritizes accuracy, timeliness, and actionable intelligence while maintaining privacy and security standards.

Intelligence Aggregation Framework

Multi-Source Intelligence Architecture

// Core interfaces for intelligence data aggregation
interface IntelligenceSource {
  readonly name: string;
  readonly reliability: number; // 0-1 scale
  readonly updateFrequency: number; // seconds
  readonly dataTypes: IntelligenceDataType[];
  readonly apiConfig: SourceAPIConfig;
}

interface IntelligenceData {
  sourceId: string;
  entityId: string;
  entityType: EntityType;
  confidence: number;
  timestamp: Date;
  data: Record<string, any>;
  correlationIds: string[];
  validUntil?: Date;
}

export class IntelligenceOrchestrator {
  private sources: Map<string, IntelligenceSource> = new Map();
  private correlationEngine: CorrelationEngine;
  private entityResolver: EntityResolver;
  private riskAnalyzer: RiskAnalyzer;
  private knowledgeGraph: KnowledgeGraph;
  private alertManager: IntelAlertManager;

  constructor(
    private config: IntelConfig,
    private database: DatabaseInterface,
    private cache: CacheInterface,
    private messageQueue: MessageQueueInterface
  ) {
    this.correlationEngine = new CorrelationEngine(config.correlation);
    this.entityResolver = new EntityResolver(config.resolution);
    this.riskAnalyzer = new RiskAnalyzer(config.risk);
    this.knowledgeGraph = new KnowledgeGraph(config.graph);
    this.alertManager = new IntelAlertManager(config.alerts);
    
    this.initializeIntelligenceSources();
    this.setupRealTimeUpdates();
  }

  private async initializeIntelligenceSources() {
    const sources = [
      new ArkhamIntelligenceSource(this.config.arkham),
      new ChainanalysisSource(this.config.chainalysis),
      new CipherTraceSource(this.config.cipherTrace),
      new EllipticSource(this.config.elliptic),
      new InternalIntelligenceSource(this.config.internal),
      new CommunityIntelligenceSource(this.config.community)
    ];

    for (const source of sources) {
      try {
        await source.initialize();
        this.sources.set(source.name, source);
        
        // Set up data collection
        this.setupSourceDataCollection(source);
        
        logger.info(`Initialized intelligence source: ${source.name}`);
      } catch (error) {
        logger.error(`Failed to initialize source ${source.name}:`, error);
        
        // Schedule retry
        this.scheduleSourceRetry(source);
      }
    }
  }

  async analyzeEntity(entityId: string, entityType: EntityType): Promise<EntityIntelligenceResult> {
    const startTime = Date.now();
    
    try {
      // Check cache first
      const cacheKey = `intel:${entityType}:${entityId}`;
      const cachedResult = await this.cache.get(cacheKey);
      
      if (cachedResult && this.isCacheValid(cachedResult)) {
        return cachedResult;
      }

      // Collect intelligence from all sources
      const intelligencePromises = Array.from(this.sources.values()).map(async source => {
        try {
          return await source.getEntityIntelligence(entityId, entityType);
        } catch (error) {
          logger.warn(`Intelligence collection failed for ${source.name}:`, error);
          return null;
        }
      });

      const intelligenceResults = await Promise.all(intelligencePromises);
      const validResults = intelligenceResults.filter(result => result !== null) as IntelligenceData[];

      if (validResults.length === 0) {
        return this.generateEmptyResult(entityId, entityType, 'No intelligence data found');
      }

      // Correlate intelligence data
      const correlatedData = await this.correlationEngine.correlate(validResults);
      
      // Resolve entity relationships
      const entityResolution = await this.entityResolver.resolve(correlatedData);
      
      // Analyze risk patterns
      const riskAnalysis = await this.riskAnalyzer.analyze(entityResolution);
      
      // Update knowledge graph
      await this.knowledgeGraph.updateEntity(entityId, entityResolution, riskAnalysis);
      
      // Generate final intelligence result
      const result = this.generateIntelligenceResult(
        entityId,
        entityType,
        correlatedData,
        entityResolution,
        riskAnalysis,
        Date.now() - startTime
      );

      // Cache result
      await this.cache.set(cacheKey, result, this.calculateCacheTTL(result.confidence));

      return result;

    } catch (error) {
      logger.error('Entity intelligence analysis failed:', error);
      throw new IntelligenceAnalysisError('Intelligence analysis failed', error);
    }
  }

  private generateIntelligenceResult(
    entityId: string,
    entityType: EntityType,
    correlatedData: CorrelatedIntelligence,
    entityResolution: EntityResolution,
    riskAnalysis: RiskAnalysis,
    processingTime: number
  ): EntityIntelligenceResult {
    return {
      entityId,
      entityType,
      confidence: correlatedData.confidence,
      riskScore: riskAnalysis.overallRisk,
      attribution: {
        primaryEntity: entityResolution.primaryEntity,
        aliases: entityResolution.aliases,
        relationships: entityResolution.relationships,
        confidence: entityResolution.confidence
      },
      intelligence: {
        sources: correlatedData.sources,
        labels: correlatedData.labels,
        riskFactors: riskAnalysis.riskFactors,
        historicalActivity: correlatedData.historicalActivity,
        associatedEntities: entityResolution.associatedEntities
      },
      fundFlows: riskAnalysis.fundFlowAnalysis,
      alerts: this.generateIntelligenceAlerts(riskAnalysis),
      metadata: {
        sourceCount: correlatedData.sources.length,
        processingTime,
        dataQuality: correlatedData.dataQuality,
        lastUpdated: new Date().toISOString(),
        validUntil: this.calculateValidityPeriod(correlatedData.confidence)
      }
    };
  }
}

Arkham Intelligence Integration

Advanced Arkham API Integration

// Comprehensive Arkham Intelligence API integration
export class ArkhamIntelligenceSource implements IntelligenceSource {
  public readonly name = 'arkham_intelligence';
  public readonly reliability = 0.95;
  public readonly updateFrequency = 3600; // 1 hour
  public readonly dataTypes = [
    'wallet_attribution',
    'entity_labels',
    'transaction_flow',
    'risk_scoring',
    'connection_mapping'
  ];

  private client: ArkhamAPIClient;
  private rateLimiter: RateLimiter;
  private entityCache: Map<string, ArkhamEntity> = new Map();
  private flowAnalyzer: FundFlowAnalyzer;

  constructor(private config: ArkhamConfig) {
    this.client = new ArkhamAPIClient({
      apiKey: config.apiKey,
      baseURL: config.baseURL || 'https://api.arkhamintelligence.com/v1',
      timeout: config.timeout || 30000
    });

    this.rateLimiter = new RateLimiter({
      maxRequests: config.rateLimit?.maxRequests || 100,
      windowMs: config.rateLimit?.windowMs || 60000
    });

    this.flowAnalyzer = new FundFlowAnalyzer(config.flowAnalysis);
  }

  async initialize(): Promise<void> {
    try {
      // Verify API access
      const apiStatus = await this.client.getAPIStatus();
      
      if (!apiStatus.isActive) {
        throw new Error('Arkham API is not active');
      }

      logger.info('Arkham Intelligence source initialized successfully');
      
    } catch (error) {
      logger.error('Arkham Intelligence initialization failed:', error);
      throw new InitializationError('Arkham source initialization failed', error);
    }
  }

  async getEntityIntelligence(entityId: string, entityType: EntityType): Promise<IntelligenceData> {
    try {
      // Rate limiting
      await this.rateLimiter.waitForSlot();
      
      // Check cache
      const cacheKey = `${entityType}:${entityId}`;
      if (this.entityCache.has(cacheKey)) {
        const cachedEntity = this.entityCache.get(cacheKey)!;
        
        // Check if cache is still valid
        if (Date.now() - cachedEntity.timestamp.getTime() < 300000) { // 5 minutes
          return this.transformArkhamData(cachedEntity);
        }
      }

      // Fetch entity data
      const entityData = await this.fetchEntityData(entityId, entityType);
      
      if (!entityData) {
        throw new DataNotFoundError(`Entity not found in Arkham: ${entityId}`);
      }

      // Cache the result
      this.entityCache.set(cacheKey, entityData);
      
      // Transform to standard format
      return this.transformArkhamData(entityData);

    } catch (error) {
      logger.error('Arkham entity intelligence failed:', error);
      throw error;
    }
  }

  private async fetchEntityData(entityId: string, entityType: EntityType): Promise<ArkhamEntity | null> {
    try {
      let entityData: ArkhamEntity;

      switch (entityType) {
        case 'wallet_address':
          entityData = await this.client.getAddressIntelligence(entityId);
          break;
        case 'contract_address':
          entityData = await this.client.getContractIntelligence(entityId);
          break;
        case 'entity_name':
          entityData = await this.client.getEntityByName(entityId);
          break;
        default:
          throw new Error(`Unsupported entity type: ${entityType}`);
      }

      // Enrich with additional data
      const enrichedData = await this.enrichEntityData(entityData);
      
      return enrichedData;

    } catch (error) {
      if (error.status === 404) {
        return null; // Entity not found
      }
      throw error;
    }
  }

  private async enrichEntityData(entity: ArkhamEntity): Promise<ArkhamEntity> {
    try {
      // Get transaction history
      const transactionHistory = await this.client.getTransactionHistory(entity.address, {
        limit: 100,
        includeTokenTransfers: true,
        includeInternalTransactions: true
      });

      // Get connection data
      const connections = await this.client.getEntityConnections(entity.address, {
        maxDepth: 2,
        minTransactionValue: 1000 // $1000 USD minimum
      });

      // Get risk scoring
      const riskData = await this.client.getRiskAssessment(entity.address);

      // Perform fund flow analysis
      const fundFlows = await this.flowAnalyzer.analyzeFundFlows(
        entity.address,
        transactionHistory,
        connections
      );

      return {
        ...entity,
        transactionHistory,
        connections,
        riskData,
        fundFlows,
        enrichmentTimestamp: new Date()
      };

    } catch (error) {
      logger.warn('Entity enrichment failed:', error);
      return entity; // Return basic data if enrichment fails
    }
  }

  private transformArkhamData(arkhamEntity: ArkhamEntity): IntelligenceData {
    return {
      sourceId: this.name,
      entityId: arkhamEntity.address,
      entityType: arkhamEntity.type,
      confidence: this.calculateConfidence(arkhamEntity),
      timestamp: new Date(),
      data: {
        entity: {
          name: arkhamEntity.entity?.name,
          type: arkhamEntity.entity?.type,
          category: arkhamEntity.entity?.category,
          description: arkhamEntity.entity?.description
        },
        labels: arkhamEntity.labels || [],
        riskScore: arkhamEntity.riskData?.overallRisk || 50,
        riskFactors: arkhamEntity.riskData?.riskFactors || [],
        transactionVolume: arkhamEntity.transactionHistory?.totalVolume || 0,
        transactionCount: arkhamEntity.transactionHistory?.count || 0,
        firstSeen: arkhamEntity.firstTransactionDate,
        lastSeen: arkhamEntity.lastTransactionDate,
        connections: this.processConnections(arkhamEntity.connections || []),
        fundFlows: arkhamEntity.fundFlows
      },
      correlationIds: this.generateCorrelationIds(arkhamEntity),
      validUntil: new Date(Date.now() + 3600000) // 1 hour validity
    };
  }

  private calculateConfidence(entity: ArkhamEntity): number {
    let confidence = 0.5; // Base confidence
    
    // Entity verification increases confidence
    if (entity.entity?.isVerified) confidence += 0.3;
    
    // Multiple labels increase confidence
    if (entity.labels && entity.labels.length > 0) {
      confidence += Math.min(0.2, entity.labels.length * 0.05);
    }
    
    // Transaction history depth increases confidence
    if (entity.transactionHistory) {
      const txCount = entity.transactionHistory.count || 0;
      confidence += Math.min(0.2, txCount / 1000);
    }
    
    // Recent activity increases confidence
    if (entity.lastTransactionDate) {
      const daysSinceLastTx = (Date.now() - entity.lastTransactionDate.getTime()) / (1000 * 60 * 60 * 24);
      if (daysSinceLastTx < 30) confidence += 0.1;
    }

    return Math.min(1, confidence);
  }

  async trackFundFlow(
    sourceAddress: string,
    targetAddress: string,
    options: FundFlowOptions = {}
  ): Promise<FundFlowResult> {
    try {
      await this.rateLimiter.waitForSlot();
      
      const flowData = await this.client.traceFundFlow(sourceAddress, targetAddress, {
        maxHops: options.maxHops || 5,
        minAmount: options.minAmount || 0.01,
        timeWindow: options.timeWindow || 2592000000, // 30 days
        includeTokens: options.includeTokens !== false
      });

      // Analyze flow patterns
      const flowAnalysis = await this.flowAnalyzer.analyzeFlowPatterns(flowData);
      
      // Detect suspicious patterns
      const suspiciousPatterns = await this.detectSuspiciousFlowPatterns(flowData, flowAnalysis);
      
      return {
        sourceAddress,
        targetAddress,
        flowPath: flowData.path,
        totalAmount: flowData.totalAmount,
        hopCount: flowData.path.length - 1,
        timespan: flowData.timespan,
        patterns: flowAnalysis.patterns,
        suspiciousActivities: suspiciousPatterns,
        riskScore: this.calculateFlowRiskScore(flowAnalysis, suspiciousPatterns),
        confidence: flowData.confidence,
        metadata: {
          tracedAt: new Date(),
          dataSource: 'arkham_intelligence',
          analysisVersion: '2.1'
        }
      };

    } catch (error) {
      logger.error('Fund flow tracking failed:', error);
      throw new FundFlowError('Fund flow tracking failed', error);
    }
  }

  private async detectSuspiciousFlowPatterns(
    flowData: ArkhamFlowData,
    analysis: FlowAnalysis
  ): Promise<SuspiciousPattern[]> {
    const patterns: SuspiciousPattern[] = [];

    // Check for mixing services
    for (const hop of flowData.path) {
      if (this.isMixingService(hop.address)) {
        patterns.push({
          type: 'mixing_service',
          description: 'Funds passed through known mixing service',
          address: hop.address,
          riskLevel: 'high',
          evidence: {
            serviceName: hop.entityName,
            amount: hop.amount
          }
        });
      }
    }

    // Check for rapid redistribution
    if (analysis.redistributionScore > 0.8) {
      patterns.push({
        type: 'rapid_redistribution',
        description: 'Funds rapidly distributed across multiple addresses',
        riskLevel: 'medium',
        evidence: {
          redistributionScore: analysis.redistributionScore,
          recipientCount: analysis.uniqueRecipients
        }
      });
    }

    // Check for circular flows
    if (analysis.circularityScore > 0.7) {
      patterns.push({
        type: 'circular_flow',
        description: 'Detected circular fund movement pattern',
        riskLevel: 'high',
        evidence: {
          circularityScore: analysis.circularityScore,
          cycles: analysis.detectedCycles
        }
      });
    }

    // Check for exchange patterns
    const exchangeHops = flowData.path.filter(hop => this.isCryptoExchange(hop.address));
    if (exchangeHops.length > 2) {
      patterns.push({
        type: 'multi_exchange_hopping',
        description: 'Funds moved through multiple exchanges',
        riskLevel: 'medium',
        evidence: {
          exchangeCount: exchangeHops.length,
          exchanges: exchangeHops.map(hop => hop.entityName)
        }
      });
    }

    return patterns;
  }

  private isMixingService(address: string): boolean {
    const knownMixers = [
      '0x5e4e65926ba27467555eb562121fac00d24e9dd2', // Tornado Cash
      '0xd90e2f925da726b50c4ed8d0fb90ad053324f31b', // Blender
      // Add more known mixer addresses
    ];
    
    return knownMixers.includes(address.toLowerCase());
  }

  private isCryptoExchange(address: string): boolean {
    const knownExchanges = [
      '0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be', // Binance
      '0xd551234ae421e3bcba99a0da6d736074f22192ff', // Binance 2
      '0x564286362092d8e7936f0549571a803b203aaced', // Binance 3
      // Add more exchange addresses
    ];
    
    return knownExchanges.includes(address.toLowerCase());
  }
}

Fund Flow Tracking

Advanced Transaction Flow Analysis

// Comprehensive fund flow tracking and analysis system
export class FundFlowAnalyzer {
  private graphAnalyzer: TransactionGraphAnalyzer;
  private patternDetector: FlowPatternDetector;
  private riskCalculator: FlowRiskCalculator;
  private volumeAnalyzer: VolumeAnalyzer;

  constructor(private config: FlowAnalysisConfig) {
    this.graphAnalyzer = new TransactionGraphAnalyzer(config.graph);
    this.patternDetector = new FlowPatternDetector(config.patterns);
    this.riskCalculator = new FlowRiskCalculator(config.risk);
    this.volumeAnalyzer = new VolumeAnalyzer(config.volume);
  }

  async analyzeFundFlows(
    address: string,
    transactions: Transaction[],
    connections: EntityConnection[]
  ): Promise<FundFlowAnalysis> {
    try {
      // Build transaction graph
      const transactionGraph = await this.graphAnalyzer.buildGraph(address, transactions, connections);
      
      // Analyze flow patterns
      const flowPatterns = await this.patternDetector.detectPatterns(transactionGraph);
      
      // Calculate risk metrics
      const riskMetrics = await this.riskCalculator.calculateRisks(transactionGraph, flowPatterns);
      
      // Analyze volume patterns
      const volumeAnalysis = await this.volumeAnalyzer.analyzeVolumes(transactions);
      
      // Generate comprehensive analysis
      return {
        address,
        graph: transactionGraph,
        patterns: flowPatterns,
        risks: riskMetrics,
        volumes: volumeAnalysis,
        insights: this.generateFlowInsights(transactionGraph, flowPatterns, riskMetrics),
        score: this.calculateOverallFlowScore(riskMetrics, flowPatterns),
        metadata: {
          transactionCount: transactions.length,
          connectionCount: connections.length,
          analysisDepth: transactionGraph.maxDepth,
          timespan: this.calculateTimespan(transactions),
          generatedAt: new Date()
        }
      };

    } catch (error) {
      logger.error('Fund flow analysis failed:', error);
      throw new FlowAnalysisError('Fund flow analysis failed', error);
    }
  }

  private generateFlowInsights(
    graph: TransactionGraph,
    patterns: FlowPattern[],
    risks: FlowRiskMetrics
  ): FlowInsight[] {
    const insights: FlowInsight[] = [];

    // Large transaction insights
    if (risks.largeTransactionRisk > 0.7) {
      insights.push({
        type: 'large_transactions',
        severity: 'high',
        description: 'Multiple large transactions detected that may indicate institutional activity or potential money laundering',
        recommendation: 'Review large transaction patterns and verify legitimacy of fund sources',
        evidence: {
          largeTransactionCount: risks.largeTransactionCount,
          totalLargeValue: risks.totalLargeValue
        }
      });
    }

    // Mixing service insights
    const mixingPatterns = patterns.filter(p => p.type === 'mixing_service');
    if (mixingPatterns.length > 0) {
      insights.push({
        type: 'privacy_tools',
        severity: 'medium',
        description: 'Funds have been processed through privacy-enhancing tools or mixing services',
        recommendation: 'Enhanced due diligence required for compliance and risk assessment',
        evidence: {
          mixingServiceCount: mixingPatterns.length,
          services: mixingPatterns.map(p => p.description)
        }
      });
    }

    // Rapid movement insights
    if (risks.velocityRisk > 0.8) {
      insights.push({
        type: 'rapid_movement',
        severity: 'high',
        description: 'Funds are moving rapidly between addresses, potentially indicating evasion tactics',
        recommendation: 'Monitor for potential wash trading or layering activities',
        evidence: {
          averageHoldTime: risks.averageHoldTime,
          velocityScore: risks.velocityRisk
        }
      });
    }

    // Exchange concentration insights
    if (risks.exchangeConcentration > 0.6) {
      insights.push({
        type: 'exchange_dependency',
        severity: 'medium',
        description: 'High concentration of activity through centralized exchanges',
        recommendation: 'Consider counterparty risk and exchange compliance status',
        evidence: {
          exchangeCount: risks.uniqueExchanges,
          concentrationRatio: risks.exchangeConcentration
        }
      });
    }

    return insights;
  }
}

// Transaction graph analyzer
export class TransactionGraphAnalyzer {
  constructor(private config: GraphConfig) {}

  async buildGraph(
    rootAddress: string,
    transactions: Transaction[],
    connections: EntityConnection[]
  ): Promise<TransactionGraph> {
    const graph = new TransactionGraph(rootAddress);
    
    try {
      // Add transactions to graph
      for (const tx of transactions) {
        await this.addTransactionToGraph(graph, tx);
      }
      
      // Add connection data
      for (const connection of connections) {
        await this.addConnectionToGraph(graph, connection);
      }
      
      // Calculate graph metrics
      const metrics = await this.calculateGraphMetrics(graph);
      graph.setMetrics(metrics);
      
      // Identify clusters
      const clusters = await this.identifyClusters(graph);
      graph.setClusters(clusters);
      
      return graph;

    } catch (error) {
      logger.error('Graph building failed:', error);
      throw error;
    }
  }

  private async addTransactionToGraph(graph: TransactionGraph, tx: Transaction): Promise<void> {
    // Add nodes
    graph.addNode(tx.from, {
      type: 'address',
      firstSeen: tx.timestamp,
      lastSeen: tx.timestamp,
      totalVolume: 0,
      transactionCount: 0
    });

    graph.addNode(tx.to, {
      type: 'address',
      firstSeen: tx.timestamp,
      lastSeen: tx.timestamp,
      totalVolume: 0,
      transactionCount: 0
    });

    // Add edge
    graph.addEdge(tx.from, tx.to, {
      transactionHash: tx.hash,
      value: tx.value,
      timestamp: tx.timestamp,
      gasUsed: tx.gasUsed,
      gasPrice: tx.gasPrice,
      tokenTransfers: tx.tokenTransfers || []
    });

    // Update node statistics
    graph.updateNodeStats(tx.from, tx.value, tx.timestamp);
    graph.updateNodeStats(tx.to, tx.value, tx.timestamp);
  }

  private async calculateGraphMetrics(graph: TransactionGraph): Promise<GraphMetrics> {
    const nodes = graph.getNodes();
    const edges = graph.getEdges();
    
    // Basic metrics
    const nodeCount = nodes.length;
    const edgeCount = edges.length;
    const density = edgeCount / (nodeCount * (nodeCount - 1));
    
    // Centrality metrics
    const centralityMetrics = this.calculateCentralityMetrics(graph);
    
    // Community detection
    const communities = this.detectCommunities(graph);
    
    // Path analysis
    const pathMetrics = this.calculatePathMetrics(graph);
    
    return {
      nodeCount,
      edgeCount,
      density,
      maxDepth: pathMetrics.maxDepth,
      averagePathLength: pathMetrics.averageLength,
      centrality: centralityMetrics,
      communities: communities.length,
      clustering: this.calculateClusteringCoefficient(graph),
      diameter: pathMetrics.diameter
    };
  }

  private calculateCentralityMetrics(graph: TransactionGraph): CentralityMetrics {
    const nodes = graph.getNodes();
    const betweennessCentrality: Record<string, number> = {};
    const closenessCentrality: Record<string, number> = {};
    const degreeCentrality: Record<string, number> = {};

    // Calculate degree centrality
    for (const node of nodes) {
      const degree = graph.getDegree(node.id);
      degreeCentrality[node.id] = degree / (nodes.length - 1);
    }

    // Calculate betweenness centrality (simplified)
    for (const node of nodes) {
      betweennessCentrality[node.id] = this.calculateBetweenness(graph, node.id);
    }

    // Calculate closeness centrality
    for (const node of nodes) {
      closenessCentrality[node.id] = this.calculateCloseness(graph, node.id);
    }

    // Find most central nodes
    const mostCentralByDegree = this.findMostCentral(degreeCentrality);
    const mostCentralByBetweenness = this.findMostCentral(betweennessCentrality);
    const mostCentralByCloseness = this.findMostCentral(closenessCentrality);

    return {
      degree: degreeCentrality,
      betweenness: betweennessCentrality,
      closeness: closenessCentrality,
      mostCentral: {
        byDegree: mostCentralByDegree,
        byBetweenness: mostCentralByBetweenness,
        byCloseness: mostCentralByCloseness
      }
    };
  }
}

// Flow pattern detector
export class FlowPatternDetector {
  private layeringDetector: LayeringDetector;
  private structuringDetector: StructuringDetector;
  private circularFlowDetector: CircularFlowDetector;
  private velocityDetector: VelocityDetector;

  constructor(private config: PatternConfig) {
    this.layeringDetector = new LayeringDetector(config.layering);
    this.structuringDetector = new StructuringDetector(config.structuring);
    this.circularFlowDetector = new CircularFlowDetector(config.circular);
    this.velocityDetector = new VelocityDetector(config.velocity);
  }

  async detectPatterns(graph: TransactionGraph): Promise<FlowPattern[]> {
    const patterns: FlowPattern[] = [];

    try {
      // Detect layering patterns
      const layeringPatterns = await this.layeringDetector.detect(graph);
      patterns.push(...layeringPatterns);

      // Detect structuring patterns
      const structuringPatterns = await this.structuringDetector.detect(graph);
      patterns.push(...structuringPatterns);

      // Detect circular flows
      const circularPatterns = await this.circularFlowDetector.detect(graph);
      patterns.push(...circularPatterns);

      // Detect velocity patterns
      const velocityPatterns = await this.velocityDetector.detect(graph);
      patterns.push(...velocityPatterns);

      // Sort patterns by risk score
      patterns.sort((a, b) => b.riskScore - a.riskScore);

      return patterns;

    } catch (error) {
      logger.error('Pattern detection failed:', error);
      throw error;
    }
  }
}

// Layering pattern detector
export class LayeringDetector {
  constructor(private config: LayeringConfig) {}

  async detect(graph: TransactionGraph): Promise<FlowPattern[]> {
    const patterns: FlowPattern[] = [];
    const layeringThreshold = this.config.minLayers || 3;
    const volumeThreshold = this.config.minVolume || 10000; // $10k

    try {
      const paths = graph.findAllPaths(this.config.maxPathLength || 10);

      for (const path of paths) {
        if (path.length >= layeringThreshold) {
          const pathVolume = this.calculatePathVolume(path);
          
          if (pathVolume >= volumeThreshold) {
            const layeringScore = this.calculateLayeringScore(path);
            
            if (layeringScore > this.config.scoreThreshold) {
              patterns.push({
                type: 'layering',
                description: `Complex layering pattern detected with ${path.length} layers`,
                path: path.map(node => node.address),
                riskScore: layeringScore,
                volume: pathVolume,
                layers: path.length,
                timespan: this.calculatePathTimespan(path),
                evidence: {
                  intermediateAddresses: path.length - 2,
                  totalVolume: pathVolume,
                  averageHoldTime: this.calculateAverageHoldTime(path)
                }
              });
            }
          }
        }
      }

      return patterns;

    } catch (error) {
      logger.error('Layering detection failed:', error);
      throw error;
    }
  }

  private calculateLayeringScore(path: GraphPath): number {
    let score = 0;

    // More layers = higher score
    score += Math.min(0.4, (path.length - 2) * 0.1);

    // Rapid movement = higher score
    const avgHoldTime = this.calculateAverageHoldTime(path);
    if (avgHoldTime < 3600) { // Less than 1 hour average
      score += 0.3;
    } else if (avgHoldTime < 86400) { // Less than 1 day average
      score += 0.2;
    }

    // Volume consistency = higher score
    const volumeVariation = this.calculateVolumeVariation(path);
    if (volumeVariation < 0.1) { // Very consistent volumes
      score += 0.3;
    }

    return Math.min(1, score);
  }

  private calculateAverageHoldTime(path: GraphPath): number {
    if (path.length < 2) return 0;

    let totalHoldTime = 0;
    let holdCount = 0;

    for (let i = 0; i < path.length - 1; i++) {
      const incomingTime = path[i].timestamp;
      const outgoingTime = path[i + 1].timestamp;
      
      if (incomingTime && outgoingTime) {
        totalHoldTime += outgoingTime.getTime() - incomingTime.getTime();
        holdCount++;
      }
    }

    return holdCount > 0 ? totalHoldTime / holdCount / 1000 : 0; // Return in seconds
  }
}

Behavior Pattern Recognition

Advanced Behavioral Analysis System

// Comprehensive behavioral pattern recognition and analysis
export class BehaviorAnalyzer {
  private transactionBehavior: TransactionBehaviorAnalyzer;
  private temporalBehavior: TemporalBehaviorAnalyzer;
  private networkBehavior: NetworkBehaviorAnalyzer;
  private riskBehavior: RiskBehaviorAnalyzer;

  constructor(private config: BehaviorConfig) {
    this.transactionBehavior = new TransactionBehaviorAnalyzer(config.transaction);
    this.temporalBehavior = new TemporalBehaviorAnalyzer(config.temporal);
    this.networkBehavior = new NetworkBehaviorAnalyzer(config.network);
    this.riskBehavior = new RiskBehaviorAnalyzer(config.risk);
  }

  async analyzeBehavior(
    address: string,
    transactions: Transaction[],
    timeframe: TimeframeBehaviorAnalysis
  ): Promise<BehaviorAnalysisResult> {
    try {
      // Analyze transaction behavior patterns
      const transactionPatterns = await this.transactionBehavior.analyze(transactions);
      
      // Analyze temporal behavior patterns
      const temporalPatterns = await this.temporalBehavior.analyze(transactions, timeframe);
      
      // Analyze network behavior patterns
      const networkPatterns = await this.networkBehavior.analyze(address, transactions);
      
      // Analyze risk-related behavior patterns
      const riskPatterns = await this.riskBehavior.analyze(transactions);
      
      // Generate behavior profile
      const behaviorProfile = this.generateBehaviorProfile(
        address,
        transactionPatterns,
        temporalPatterns,
        networkPatterns,
        riskPatterns
      );
      
      // Calculate overall behavior score
      const behaviorScore = this.calculateBehaviorScore(behaviorProfile);
      
      return {
        address,
        behaviorScore,
        profile: behaviorProfile,
        patterns: {
          transaction: transactionPatterns,
          temporal: temporalPatterns,
          network: networkPatterns,
          risk: riskPatterns
        },
        alerts: this.generateBehaviorAlerts(behaviorProfile),
        recommendations: this.generateRecommendations(behaviorProfile),
        metadata: {
          transactionCount: transactions.length,
          analysisTimeframe: timeframe,
          generatedAt: new Date(),
          analysisVersion: '3.1'
        }
      };

    } catch (error) {
      logger.error('Behavior analysis failed:', error);
      throw new BehaviorAnalysisError('Behavior analysis failed', error);
    }
  }

  private generateBehaviorProfile(
    address: string,
    transactionPatterns: TransactionPatternResult,
    temporalPatterns: TemporalPatternResult,
    networkPatterns: NetworkPatternResult,
    riskPatterns: RiskPatternResult
  ): BehaviorProfile {
    return {
      address,
      entityType: this.determineEntityType(transactionPatterns, networkPatterns),
      activityLevel: this.calculateActivityLevel(transactionPatterns, temporalPatterns),
      riskProfile: this.calculateRiskProfile(riskPatterns),
      tradingBehavior: this.analyzeTradingBehavior(transactionPatterns),
      networkPosition: this.analyzeNetworkPosition(networkPatterns),
      characteristics: {
        isHighVolume: transactionPatterns.volumeMetrics.averageDaily > 100000,
        isHighFrequency: transactionPatterns.frequencyMetrics.transactionsPerDay > 100,
        usesPrivacyTools: riskPatterns.privacyToolUsage > 0,
        hasInstitutionalBehavior: this.detectInstitutionalBehavior(transactionPatterns),
        showsAutomatedPatterns: temporalPatterns.automationScore > 0.7,
        hasComplexFlows: networkPatterns.complexityScore > 0.8
      },
      confidence: this.calculateProfileConfidence(transactionPatterns, temporalPatterns, networkPatterns)
    };
  }

  private determineEntityType(
    transactionPatterns: TransactionPatternResult,
    networkPatterns: NetworkPatternResult
  ): EntityType {
    // Check for exchange patterns
    if (this.hasExchangeCharacteristics(transactionPatterns, networkPatterns)) {
      return 'exchange';
    }
    
    // Check for mixer/tumbler patterns
    if (this.hasMixerCharacteristics(transactionPatterns, networkPatterns)) {
      return 'mixer';
    }
    
    // Check for DeFi protocol patterns
    if (this.hasDeFiCharacteristics(transactionPatterns, networkPatterns)) {
      return 'defi_protocol';
    }
    
    // Check for institutional patterns
    if (this.hasInstitutionalCharacteristics(transactionPatterns, networkPatterns)) {
      return 'institution';
    }
    
    // Check for individual user patterns
    if (this.hasIndividualUserCharacteristics(transactionPatterns, networkPatterns)) {
      return 'individual';
    }
    
    // Default to unknown
    return 'unknown';
  }

  private hasExchangeCharacteristics(
    txPatterns: TransactionPatternResult,
    networkPatterns: NetworkPatternResult
  ): boolean {
    return (
      txPatterns.volumeMetrics.averageDaily > 1000000 && // High daily volume
      networkPatterns.uniqueCounterparties > 1000 && // Many unique counterparties
      txPatterns.frequencyMetrics.transactionsPerDay > 500 && // High transaction frequency
      networkPatterns.bidirectionalRatio > 0.4 // Significant bidirectional flow
    );
  }

  private hasMixerCharacteristics(
    txPatterns: TransactionPatternResult,
    networkPatterns: NetworkPatternResult
  ): boolean {
    return (
      networkPatterns.fanOutRatio > 0.8 && // High fan-out ratio
      txPatterns.volumeMetrics.standardDeviation < 0.2 && // Consistent transaction amounts
      networkPatterns.intermediaryScore > 0.7 && // Acts as intermediary
      txPatterns.roundNumberFrequency > 0.6 // Frequent round number transactions
    );
  }

  private detectInstitutionalBehavior(txPatterns: TransactionPatternResult): boolean {
    return (
      txPatterns.volumeMetrics.averageTransaction > 50000 && // Large average transactions
      txPatterns.frequencyMetrics.regularityScore > 0.8 && // Regular transaction patterns
      txPatterns.businessHoursRatio > 0.7 && // Primarily business hours activity
      txPatterns.weekdayRatio > 0.8 // Primarily weekday activity
    );
  }
}

// Transaction behavior analyzer
export class TransactionBehaviorAnalyzer {
  constructor(private config: TransactionBehaviorConfig) {}

  async analyze(transactions: Transaction[]): Promise<TransactionPatternResult> {
    try {
      if (transactions.length === 0) {
        return this.generateEmptyResult();
      }

      // Calculate volume metrics
      const volumeMetrics = this.calculateVolumeMetrics(transactions);
      
      // Calculate frequency metrics
      const frequencyMetrics = this.calculateFrequencyMetrics(transactions);
      
      // Calculate timing patterns
      const timingPatterns = this.analyzeTimingPatterns(transactions);
      
      // Calculate amount patterns
      const amountPatterns = this.analyzeAmountPatterns(transactions);
      
      // Calculate gas usage patterns
      const gasPatterns = this.analyzeGasPatterns(transactions);

      return {
        volumeMetrics,
        frequencyMetrics,
        timingPatterns,
        amountPatterns,
        gasPatterns,
        roundNumberFrequency: this.calculateRoundNumberFrequency(transactions),
        businessHoursRatio: this.calculateBusinessHoursRatio(transactions),
        weekdayRatio: this.calculateWeekdayRatio(transactions),
        duplicateAmountFrequency: this.calculateDuplicateAmountFrequency(transactions)
      };

    } catch (error) {
      logger.error('Transaction behavior analysis failed:', error);
      throw error;
    }
  }

  private calculateVolumeMetrics(transactions: Transaction[]): VolumeMetrics {
    const amounts = transactions.map(tx => parseFloat(tx.value));
    const totalVolume = amounts.reduce((sum, amount) => sum + amount, 0);
    
    // Calculate daily volumes
    const dailyVolumes = this.groupByDay(transactions).map(day => 
      day.reduce((sum, tx) => sum + parseFloat(tx.value), 0)
    );

    return {
      totalVolume,
      averageTransaction: totalVolume / transactions.length,
      medianTransaction: this.calculateMedian(amounts),
      standardDeviation: this.calculateStandardDeviation(amounts),
      averageDaily: dailyVolumes.length > 0 ? dailyVolumes.reduce((a, b) => a + b, 0) / dailyVolumes.length : 0,
      largestTransaction: Math.max(...amounts),
      smallestTransaction: Math.min(...amounts),
      volumeGrowthRate: this.calculateVolumeGrowthRate(dailyVolumes)
    };
  }

  private calculateFrequencyMetrics(transactions: Transaction[]): FrequencyMetrics {
    const timespan = this.calculateTimespan(transactions);
    const days = timespan / (1000 * 60 * 60 * 24);
    
    // Calculate time intervals between transactions
    const intervals = this.calculateIntervals(transactions);
    
    return {
      transactionsPerDay: transactions.length / Math.max(days, 1),
      transactionsPerHour: transactions.length / Math.max(timespan / (1000 * 60 * 60), 1),
      averageInterval: intervals.length > 0 ? intervals.reduce((a, b) => a + b, 0) / intervals.length : 0,
      medianInterval: this.calculateMedian(intervals),
      regularityScore: this.calculateRegularityScore(intervals),
      burstiness: this.calculateBurstiness(intervals)
    };
  }

  private analyzeAmountPatterns(transactions: Transaction[]): AmountPatternResult {
    const amounts = transactions.map(tx => parseFloat(tx.value));
    
    // Detect common amount patterns
    const roundNumbers = amounts.filter(amount => this.isRoundNumber(amount));
    const duplicates = this.findDuplicateAmounts(amounts);
    const sequences = this.findSequentialAmounts(amounts);

    return {
      roundNumberCount: roundNumbers.length,
      roundNumberRatio: roundNumbers.length / amounts.length,
      duplicateAmountGroups: duplicates.length,
      sequentialPatterns: sequences.length,
      amountVariability: this.calculateStandardDeviation(amounts) / this.calculateMean(amounts),
      commonAmounts: this.findMostCommonAmounts(amounts, 5)
    };
  }

  private isRoundNumber(amount: number): boolean {
    // Check if amount is a round number (ends in multiple zeros)
    const amountStr = amount.toString();
    const trailingZeros = amountStr.match(/0+$/);
    
    return trailingZeros ? trailingZeros[0].length >= 2 : false;
  }

  private calculateRegularityScore(intervals: number[]): number {
    if (intervals.length < 2) return 0;
    
    const mean = intervals.reduce((a, b) => a + b, 0) / intervals.length;
    const variance = intervals.reduce((sum, interval) => sum + Math.pow(interval - mean, 2), 0) / intervals.length;
    const coefficientOfVariation = Math.sqrt(variance) / mean;
    
    // Lower coefficient of variation = more regular
    return Math.max(0, 1 - coefficientOfVariation);
  }
}

Real-Time Intelligence Updates

Live Intelligence Monitoring and Alert System

// Real-time intelligence monitoring and update system
export class RealTimeIntelMonitor {
  private sourceMonitors: Map<string, SourceMonitor> = new Map();
  private alertProcessor: IntelAlertProcessor;
  private updateQueue: PriorityQueue<IntelUpdateTask>;
  private correlationTracker: CorrelationTracker;
  private subscriptionManager: SubscriptionManager;

  constructor(
    private config: RealTimeIntelConfig,
    private intelligenceSources: Map<string, IntelligenceSource>,
    private knowledgeGraph: KnowledgeGraph,
    private notificationService: NotificationService
  ) {
    this.alertProcessor = new IntelAlertProcessor(config.alerts);
    this.updateQueue = new PriorityQueue<IntelUpdateTask>();
    this.correlationTracker = new CorrelationTracker(config.correlation);
    this.subscriptionManager = new SubscriptionManager(config.subscriptions);
    
    this.setupRealTimeMonitoring();
  }

  private async setupRealTimeMonitoring() {
    for (const [sourceName, source] of this.intelligenceSources) {
      try {
        const monitor = new SourceMonitor(sourceName, source, {
          updateInterval: this.config.updateIntervals[sourceName] || 300000, // 5 minutes default
          priority: this.config.sourcePriorities[sourceName] || 5,
          retryAttempts: 3
        });

        await monitor.initialize();
        this.sourceMonitors.set(sourceName, monitor);

        // Set up event handlers
        monitor.on('intelligenceUpdate', (update) => this.handleIntelligenceUpdate(update));
        monitor.on('newEntity', (entity) => this.handleNewEntity(entity));
        monitor.on('entityUpdate', (entity) => this.handleEntityUpdate(entity));
        monitor.on('riskAlert', (alert) => this.handleRiskAlert(alert));

        logger.info(`Real-time monitoring initialized for ${sourceName}`);

      } catch (error) {
        logger.error(`Failed to initialize monitoring for ${sourceName}:`, error);
      }
    }

    // Start update processing
    this.startUpdateProcessing();
  }

  async subscribeToEntityUpdates(
    entityId: string,
    entityType: EntityType,
    subscriptionConfig: EntitySubscriptionConfig
  ): Promise<string> {
    const subscriptionId = `sub_${entityId}_${Date.now()}`;
    
    try {
      const subscription: EntitySubscription = {
        id: subscriptionId,
        entityId,
        entityType,
        config: subscriptionConfig,
        createdAt: new Date(),
        lastUpdate: null,
        isActive: true
      };

      await this.subscriptionManager.addSubscription(subscription);

      // Set up monitoring for this entity across all sources
      for (const monitor of this.sourceMonitors.values()) {
        await monitor.addEntityWatch(entityId, entityType, subscriptionConfig.updateThresholds);
      }

      logger.info(`Created entity subscription ${subscriptionId} for ${entityId}`);
      
      return subscriptionId;

    } catch (error) {
      logger.error('Failed to create entity subscription:', error);
      throw error;
    }
  }

  private async handleIntelligenceUpdate(update: IntelligenceUpdate) {
    try {
      // Queue update for processing
      await this.queueIntelligenceUpdate({
        updateId: update.id,
        sourceId: update.sourceId,
        entityId: update.entityId,
        entityType: update.entityType,
        updateType: update.type,
        data: update.data,
        priority: this.calculateUpdatePriority(update),
        timestamp: new Date()
      });

    } catch (error) {
      logger.error('Failed to handle intelligence update:', error);
    }
  }

  private async queueIntelligenceUpdate(task: IntelUpdateTask) {
    // Check if update is significant enough to process
    if (!await this.shouldProcessUpdate(task)) {
      return;
    }

    // Add to priority queue
    this.updateQueue.enqueue(task, task.priority);

    logger.debug('Queued intelligence update', {
      entityId: task.entityId,
      sourceId: task.sourceId,
      priority: task.priority,
      updateType: task.updateType
    });
  }

  private async shouldProcessUpdate(task: IntelUpdateTask): Promise<boolean> {
    // Check minimum time interval since last update
    const lastUpdate = await this.getLastUpdateTime(task.entityId, task.sourceId);
    const minInterval = this.config.minUpdateIntervals[task.sourceId] || 60000; // 1 minute default
    
    if (Date.now() - lastUpdate < minInterval) {
      return false;
    }

    // Check if update represents significant change
    const significanceThreshold = this.config.significanceThresholds[task.updateType] || 0.1;
    const updateSignificance = await this.calculateUpdateSignificance(task);
    
    return updateSignificance >= significanceThreshold;
  }

  private startUpdateProcessing() {
    // Process high-priority updates immediately
    setInterval(async () => {
      await this.processHighPriorityUpdates();
    }, 5000); // Every 5 seconds

    // Process all updates in batches
    setInterval(async () => {
      await this.processBatchUpdates();
    }, 30000); // Every 30 seconds
  }

  private async processHighPriorityUpdates() {
    const highPriorityTasks: IntelUpdateTask[] = [];
    
    // Extract high-priority tasks (priority >= 8)
    while (!this.updateQueue.isEmpty()) {
      const task = this.updateQueue.peek();
      if (task && task.priority >= 8) {
        highPriorityTasks.push(this.updateQueue.dequeue()!);
      } else {
        break;
      }
    }

    if (highPriorityTasks.length > 0) {
      await this.processUpdateBatch(highPriorityTasks);
    }
  }

  private async processUpdateBatch(tasks: IntelUpdateTask[]) {
    const processingPromises = tasks.map(async (task) => {
      try {
        return await this.processIntelligenceUpdate(task);
      } catch (error) {
        logger.error('Individual update processing failed:', error, { taskId: task.updateId });
        return null;
      }
    });

    const results = await Promise.all(processingPromises);
    
    // Handle successful updates
    for (let i = 0; i < results.length; i++) {
      const result = results[i];
      const task = tasks[i];
      
      if (result) {
        await this.handleUpdateResult(task, result);
      }
    }
  }

  private async processIntelligenceUpdate(task: IntelUpdateTask): Promise<UpdateResult> {
    const startTime = Date.now();
    
    try {
      // Get current entity state
      const currentEntity = await this.knowledgeGraph.getEntity(task.entityId);
      
      // Apply update to knowledge graph
      const updatedEntity = await this.knowledgeGraph.updateEntity(
        task.entityId,
        task.data,
        task.sourceId
      );

      // Check for correlation opportunities
      const correlations = await this.correlationTracker.findCorrelations(
        updatedEntity,
        task.data
      );

      // Calculate impact of update
      const impact = this.calculateUpdateImpact(currentEntity, updatedEntity);

      // Generate alerts if necessary
      const alerts = await this.alertProcessor.processUpdate(updatedEntity, impact);

      const processingTime = Date.now() - startTime;

      return {
        entityId: task.entityId,
        sourceId: task.sourceId,
        success: true,
        previousState: currentEntity,
        newState: updatedEntity,
        impact,
        correlations,
        alerts,
        processingTime,
        timestamp: new Date()
      };

    } catch (error) {
      logger.error('Intelligence update processing failed:', error);
      throw error;
    }
  }

  private async handleUpdateResult(task: IntelUpdateTask, result: UpdateResult) {
    try {
      // Notify subscribers
      await this.notifySubscribers(task.entityId, result);

      // Send alerts if generated
      if (result.alerts.length > 0) {
        await this.sendIntelligenceAlerts(result.alerts, result);
      }

      // Update subscription states
      await this.subscriptionManager.updateLastNotification(task.entityId, new Date());

      // Track metrics
      this.trackUpdateMetrics(task, result);

    } catch (error) {
      logger.error('Failed to handle update result:', error);
    }
  }

  private async notifySubscribers(entityId: string, result: UpdateResult) {
    const subscriptions = await this.subscriptionManager.getActiveSubscriptions(entityId);
    
    for (const subscription of subscriptions) {
      try {
        // Check if update meets notification criteria
        if (this.meetsNotificationCriteria(subscription, result)) {
          const notification: IntelligenceNotification = {
            subscriptionId: subscription.id,
            entityId,
            updateType: 'entity_intelligence_update',
            data: {
              previousRiskScore: result.previousState?.riskScore || 0,
              newRiskScore: result.newState.riskScore,
              riskChange: result.impact.riskScoreChange,
              newLabels: result.impact.newLabels,
              sourceUpdates: result.impact.sourceUpdates
            },
            timestamp: new Date()
          };

          await this.notificationService.sendIntelligenceNotification(notification);
        }

      } catch (error) {
        logger.error('Subscriber notification failed:', error, { 
          subscriptionId: subscription.id 
        });
      }
    }
  }

  async generateIntelligenceReport(
    entityId: string,
    timeframe: number = 86400000
  ): Promise<IntelligenceReport> {
    const endTime = Date.now();
    const startTime = endTime - timeframe;

    try {
      // Get entity current state
      const entity = await this.knowledgeGraph.getEntity(entityId);
      
      if (!entity) {
        throw new Error(`Entity not found: ${entityId}`);
      }

      // Get update history
      const updateHistory = await this.getUpdateHistory(entityId, startTime, endTime);
      
      // Get correlation history
      const correlations = await this.correlationTracker.getCorrelations(entityId, startTime, endTime);
      
      // Get alert history
      const alerts = await this.alertProcessor.getAlerts(entityId, startTime, endTime);
      
      // Calculate intelligence trends
      const trends = this.calculateIntelligenceTrends(updateHistory);
      
      // Generate risk trajectory
      const riskTrajectory = this.calculateRiskTrajectory(updateHistory);

      return {
        entityId,
        entityType: entity.type,
        timeframe: { start: new Date(startTime), end: new Date(endTime) },
        currentState: entity,
        updateHistory,
        correlations,
        alerts,
        trends,
        riskTrajectory,
        summary: {
          totalUpdates: updateHistory.length,
          sourcesInvolved: new Set(updateHistory.map(u => u.sourceId)).size,
          riskScoreChange: entity.riskScore - (updateHistory[0]?.previousRiskScore || entity.riskScore),
          newLabelsAdded: updateHistory.reduce((sum, u) => sum + u.impact.newLabels.length, 0),
          correlationsFound: correlations.length,
          alertsGenerated: alerts.length
        },
        generatedAt: new Date()
      };

    } catch (error) {
      logger.error('Failed to generate intelligence report:', error);
      throw error;
    }
  }
}

This comprehensive Intel Agent documentation provides the technical foundation for understanding and implementing sophisticated intelligence aggregation, entity resolution, and behavioral analysis capabilities that power Kaizen AI's risk assessment and threat detection systems.

Last updated