Repository: elastic/kibana
Pull request #217078: [Security] [AI assistant] setup/cleanup indices for evaluations
Author: login: KDKHD
Labels: name: release_note:skip
description: Skip the PR/issue when compiling release notes
name: Team:Security Generative AI
description: Security Generative AI
name: backport:version
description: Backport to applied version labels
name: v9.1.0
name: v8.19.0
Created: 2025-04-03T17:10:32Z | Merged: 2025-04-07T11:22:26Z

## Summary

Summarize your PR. If it involves visual changes include a screenshot or gif.

Setup indices and datastreams for evaluations. This will be used for ESQL evals and can be extended to setup other indices for other graphs.

How to test:

1. Enable the evaluations feature flag in kibana.dev.yml
```
xpack.securitySolution.enableExperimental: ['assistantModelEvaluation']
```
2. Launch Kibana
4. Go to evaluations http://localhost:5601/app/management/kibana/securityAiAssistantManagement?tab=evaluation
5. Start evaluations for the default assistant graph
<img width="1840" alt="image" src="https://github.com/user-attachments/assets/2974b34f-40a7-4300-8294-d25d4f72b27e" />

6. Go to discover -> create a dataview
7. Search for `*evaluations*` and check there are datastreams and indices 
<img width="1840" alt="image" src="https://github.com/user-attachments/assets/b6e9e476-82de-4292-9757-487ac85d7fce" />
8. These indices and datastreams are not cleaned up after the evaluation finishes. However, they are cleaned up when evaluations are re-run. To test this, run the evaluation again and see new datastreams and indices created. We can not do the cleanup after evaluations finish because evaluations happen asynchronously.



### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [X] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials
- [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
- [X] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [X] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations.
- [X] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed
- [X] The PR  description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

### Identify risks

Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] [See some risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...





<!--ONMERGE {"backportTargets":["8.x"]} ONMERGE-->


Diff:
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts
index a94568afd835b..d6d52bb9e0119 100644
--- a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts
@@ -53,6 +53,7 @@ import { getLlmClass, getLlmType, isOpenSourceModel } from '../utils';
 import { getGraphsFromNames } from './get_graphs_from_names';
 import { DEFAULT_DATE_FORMAT_TZ } from '../../../common/constants';
 import { agentRunableFactory } from '../../lib/langchain/graphs/default_assistant_graph/agentRunnable';
+import { PrepareIndicesForAssistantGraphEvaluations } from './prepare_indices_for_evaluations/graph_type/assistant';
 
 const DEFAULT_SIZE = 20;
 const ROUTE_HANDLER_TIMEOUT = 10 * 60 * 1000; // 10 * 60 seconds = 10 minutes
@@ -184,7 +185,18 @@ export const postEvaluateRoute = (
           // Fetch any tools registered to the security assistant
           const assistantTools = assistantContext.getRegisteredTools(DEFAULT_PLUGIN_NAME);
 
-          const { attackDiscoveryGraphs, defendInsightsGraphs } = getGraphsFromNames(graphNames);
+          const { attackDiscoveryGraphs, defendInsightsGraphs, assistantGraphs } =
+            getGraphsFromNames(graphNames);
+
+          const prepareIndicesForAssistantGraph = new PrepareIndicesForAssistantGraphEvaluations({
+            esClient,
+            logger,
+          });
+
+          if (assistantGraphs?.length) {
+            await prepareIndicesForAssistantGraph.cleanup();
+            await prepareIndicesForAssistantGraph.setup();
+          }
 
           if (defendInsightsGraphs.length > 0) {
             const connectorsWithPrompts = await Promise.all(
@@ -299,6 +311,7 @@ export const postEvaluateRoute = (
                     pluginId: 'security_ai_assistant',
                   },
                 });
+
               const llm = createLlmInstance();
               const anonymizationFieldsRes =
                 await dataClients?.anonymizationFieldsDataClient?.findDocuments<EsAnonymizationFieldsSchema>(
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index.ts
new file mode 100644
index 0000000000000..4dd47ba9ffdd0
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index.ts
@@ -0,0 +1,87 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ElasticsearchClient } from '@kbn/core/server';
+import { Logger } from '@kbn/logging';
+import { IndexRequest, IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+import { PrepareIndicesForEvaluations } from '../../prepare_indices_for_evalutations';
+import { indicesCreateRequests } from './indices_create_requests';
+import { indexRequests } from './index_requests';
+
+const ENVIRONMENTS = ['production', 'staging', 'development'];
+export class PrepareIndicesForAssistantGraphEvaluations extends PrepareIndicesForEvaluations {
+  constructor({ esClient, logger }: { esClient: ElasticsearchClient; logger: Logger }) {
+    super({
+      esClient,
+      indicesCreateRequests: PrepareIndicesForAssistantGraphEvaluations.hydrateRequestTemplate(
+        Object.values(indicesCreateRequests)
+      ),
+      indexRequests: PrepareIndicesForAssistantGraphEvaluations.hydrateRequestTemplate(
+        Object.values(indexRequests)
+      ),
+      logger,
+    });
+  }
+
+  static hydrateRequestTemplate<T extends IndicesCreateRequest | IndexRequest>(requests: T[]): T[] {
+    return requests
+      .map((request) => {
+        return ENVIRONMENTS.map((environment) => {
+          return {
+            ...request,
+            index: request.index
+              .replace(/\[environment\]/g, environment)
+              .replace(/\[date\]/g, this.getRandomDate()),
+          } as T;
+        });
+      })
+      .flat();
+  }
+
+  async cleanup() {
+    this.logger.debug('Deleting assistant indices for evaluations');
+
+    const requests = [...Object.values(indicesCreateRequests), ...Object.values(indexRequests)];
+    const indexPatternsToDelete = Object.values(requests).map((index) =>
+      index.index.replace(/\[environment\]/g, '*').replace(/\[date\]/g, '*')
+    );
+
+    const indicesResolveIndexResponses = await Promise.all(
+      indexPatternsToDelete.map(async (indexPattern) =>
+        this.esClient.indices.resolveIndex({
+          name: indexPattern,
+          expand_wildcards: 'open',
+        })
+      )
+    );
+
+    const indicesToDelete = indicesResolveIndexResponses
+      .flatMap((response) => response.indices)
+      .map((index) => index.name);
+
+    const dataStreamsToDelete = indicesResolveIndexResponses
+      .flatMap((response) => response.data_streams)
+      .map((dataStream) => dataStream.name);
+
+    if (indicesToDelete.length > 0) {
+      this.logger.info('Deleting indices');
+      await this.esClient.indices.delete({ index: indicesToDelete });
+    }
+
+    if (dataStreamsToDelete.length > 0) {
+      this.logger.info('Deleting data streams');
+      await this.esClient.indices.deleteDataStream({ name: dataStreamsToDelete });
+    }
+  }
+
+  static getRandomDate() {
+    const year = Math.floor(Math.random() * (2050 - 2000 + 1)) + 2000;
+    const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0');
+    const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0');
+    return `${year}.${month}.${day}`;
+  }
+}
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/index.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/index.ts
new file mode 100644
index 0000000000000..a5935fb0ccb8a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/index.ts
@@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { metricsApmIndexRequest } from './metrics-apm-[environment].evaluations.[date]';
+import { tracesApmIndexRequest } from './traces-apm-[environment].evaluations.[date]';
+
+export const indexRequests = [metricsApmIndexRequest, tracesApmIndexRequest];
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/metrics-apm-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/metrics-apm-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..747549938c5e1
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/metrics-apm-[environment].evaluations.[date].ts
@@ -0,0 +1,24 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndexRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const metricsApmIndexRequest: IndexRequest = {
+  index: 'metrics-apm-[environment].evaluations.[date]',
+  document: {
+    '@timestamp': '2024-04-02T12:00:00.000Z',
+    metricset: {
+      name: 'app',
+      interval: '1m',
+    },
+    transaction: {
+      duration: {
+        us: 13980,
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/traces-apm-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/traces-apm-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..8d00a6ba90e7d
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/traces-apm-[environment].evaluations.[date].ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndexRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const tracesApmIndexRequest: IndexRequest = {
+  index: 'traces-apm-[environment].evaluations.[date]',
+  document: {
+    '@timestamp': '2024-04-02T12:00:00.000Z',
+    event: {
+      outcome: 'success',
+    },
+    transaction: {
+      duration: {
+        us: 1000,
+      },
+      transaction: { id: '945254c567a5417e' },
+      service: { name: 'my-service' },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/employees-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/employees-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..ba8a4684a5fbf
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/employees-[environment].evaluations.[date].ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const employeesIndexCreateRequest: IndicesCreateRequest = {
+  index: 'employees-[environment].evaluations.[date]',
+  mappings: {
+    properties: {
+      emp_no: {
+        type: 'keyword',
+      },
+      hire_date: {
+        type: 'date',
+        format: 'yyyy-MM-dd',
+      },
+      salary: {
+        type: 'double',
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/index.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/index.ts
new file mode 100644
index 0000000000000..a0cfa8cabf9e1
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/index.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { nycTaxisIndexCreateRequest } from './nyc_taxis-[environment].evaluations.[date]';
+import { postgresLogsIndexCreateRequest } from './postgres-logs-[environment].evaluations.[date]';
+import { employeesIndexCreateRequest } from './employees-[environment].evaluations.[date]';
+import { metricbeatIndexCreateRequest } from './metricbeat-[environment].evaluations-[date]';
+import { packetbeatIndexCreateRequest } from './packetbeat-[environment].evaluations.[date]';
+import { logsIndexCreateRequest } from './logs-[environment].evaluations.[date]';
+
+export const indicesCreateRequests = {
+  nycTaxisIndexCreateRequest,
+  postgresLogsIndexCreateRequest,
+  employeesIndexCreateRequest,
+  metricbeatIndexCreateRequest,
+  packetbeatIndexCreateRequest,
+  logsIndexCreateRequest,
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/logs-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/logs-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..d613422232c59
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/logs-[environment].evaluations.[date].ts
@@ -0,0 +1,113 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const logsIndexCreateRequest: IndicesCreateRequest = {
+  index: 'logs-[environment].evaluations.[date]',
+  mappings: {
+    properties: {
+      '@timestamp': { type: 'date' },
+      bytes_transferred: { type: 'long' },
+      command_line: { type: 'text' },
+      destination: {
+        properties: {
+          ip: { type: 'ip' },
+          port: { type: 'integer' },
+          address: { type: 'keyword' },
+        },
+      },
+      dns: {
+        properties: {
+          question: {
+            properties: {
+              name: { type: 'keyword' },
+              registered_domain: { type: 'keyword' },
+            },
+          },
+        },
+      },
+      error_code: { type: 'keyword' },
+      event: {
+        properties: {
+          action: { type: 'keyword' },
+          code: { type: 'long' },
+        },
+      },
+      file: {
+        properties: {
+          name: { type: 'text' },
+        },
+      },
+      group: {
+        properties: {
+          name: { type: 'keyword' },
+        },
+      },
+      host: {
+        properties: {
+          name: { type: 'keyword' },
+        },
+      },
+      ip: { type: 'ip' },
+      log: {
+        properties: {
+          message: { type: 'text' },
+        },
+      },
+      network: {
+        properties: {
+          bytes: { type: 'long' },
+        },
+      },
+      process: {
+        properties: {
+          name: { type: 'keyword' },
+          working_directory: { type: 'keyword' },
+        },
+      },
+      source: {
+        properties: {
+          ip: { type: 'ip' },
+          bytes: { type: 'long' },
+        },
+      },
+      system: {
+        properties: {
+          cpu: {
+            properties: {
+              total: {
+                properties: {
+                  norm: {
+                    properties: {
+                      pct: { type: 'float' },
+                    },
+                  },
+                },
+              },
+            },
+          },
+        },
+      },
+      url: {
+        properties: {
+          domain: { type: 'keyword' },
+        },
+      },
+      user: {
+        properties: {
+          name: { type: 'keyword' },
+        },
+      },
+      user_agent: {
+        properties: {
+          original: { type: 'text' },
+        },
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/metricbeat-[environment].evaluations-[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/metricbeat-[environment].evaluations-[date].ts
new file mode 100644
index 0000000000000..1a7420f540a6a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/metricbeat-[environment].evaluations-[date].ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const metricbeatIndexCreateRequest: IndicesCreateRequest = {
+  index: 'metricbeat-[environment].evaluations-[date]',
+  mappings: {
+    properties: {
+      system: {
+        properties: {
+          cpu: {
+            properties: {
+              user: {
+                properties: {
+                  pct: { type: 'float' },
+                },
+              },
+              system: {
+                properties: {
+                  pct: { type: 'float' },
+                },
+              },
+              cores: { type: 'integer' },
+            },
+          },
+        },
+      },
+      host: {
+        properties: {
+          name: { type: 'keyword' },
+        },
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/nyc_taxis-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/nyc_taxis-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..96ab652907323
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/nyc_taxis-[environment].evaluations.[date].ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const nycTaxisIndexCreateRequest: IndicesCreateRequest = {
+  index: 'nyc_taxis-[environment].evaluations.[date]',
+  mappings: {
+    properties: {
+      drop_off_time: {
+        type: 'date',
+        format: 'strict_date_optional_time||epoch_millis',
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/packetbeat-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/packetbeat-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..1b88c2316c9ef
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/packetbeat-[environment].evaluations.[date].ts
@@ -0,0 +1,23 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const packetbeatIndexCreateRequest: IndicesCreateRequest = {
+  index: 'packetbeat-[environment].evaluations.[date]',
+  mappings: {
+    properties: {
+      destination: {
+        properties: {
+          domain: {
+            type: 'keyword',
+          },
+        },
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/postgres-logs-[environment].evaluations.[date].ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/postgres-logs-[environment].evaluations.[date].ts
new file mode 100644
index 0000000000000..60a37ca0d3a7a
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/indices_create_requests/postgres-logs-[environment].evaluations.[date].ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+
+export const postgresLogsIndexCreateRequest: IndicesCreateRequest = {
+  index: 'postgres-logs-[environment].evaluations.[date]',
+  mappings: {
+    properties: {
+      message: {
+        type: 'text',
+      },
+    },
+  },
+};
diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/prepare_indices_for_evalutations.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/prepare_indices_for_evalutations.ts
new file mode 100644
index 0000000000000..9c327d285bdd6
--- /dev/null
+++ b/x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/prepare_indices_for_evalutations.ts
@@ -0,0 +1,51 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { IndexRequest, IndicesCreateRequest } from '@elastic/elasticsearch/lib/api/types';
+import { ElasticsearchClient } from '@kbn/core/server';
+import { Logger } from '@kbn/logging';
+
+export class PrepareIndicesForEvaluations {
+  readonly esClient: ElasticsearchClient;
+  readonly indicesCreateRequests: IndicesCreateRequest[];
+  readonly indexRequests: IndexRequest[];
+  readonly logger: Logger;
+
+  constructor({
+    esClient,
+    indicesCreateRequests = [],
+    indexRequests = [],
+    logger,
+  }: {
+    esClient: ElasticsearchClient;
+    indicesCreateRequests?: IndicesCreateRequest[];
+    indexRequests?: IndexRequest[];
+    logger: Logger;
+  }) {
+    this.esClient = esClient;
+    this.indicesCreateRequests = indicesCreateRequests;
+    this.indexRequests = indexRequests;
+    this.logger = logger;
+  }
+
+  async setup() {
+    this.logger.debug('Creating assistant indices for evaluations');
+    await Promise.all([
+      ...this.indicesCreateRequests.map((index) => this.esClient.indices.create(index)),
+      ...this.indexRequests.map((indexRequest) => this.esClient.index(indexRequest)),
+    ]);
+  }
+
+  async cleanup() {
+    this.logger.debug('Deleting assistant indices for evaluations');
+    await Promise.all(
+      this.indicesCreateRequests.map((index) =>
+        this.esClient.indices.delete({ index: index.index })
+      )
+    );
+  }
+}


Reviews:
user: login: patrykkopycinski
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T08:39:55Z

Review comments:
diff_hunk: @@ -184,7 +185,18 @@ export const postEvaluateRoute = (
           // Fetch any tools registered to the security assistant
           const assistantTools = assistantContext.getRegisteredTools(DEFAULT_PLUGIN_NAME);
 
-          const { attackDiscoveryGraphs, defendInsightsGraphs } = getGraphsFromNames(graphNames);
+          const { attackDiscoveryGraphs, defendInsightsGraphs, assistantGraphs } =
+            getGraphsFromNames(graphNames);
+
+          const prepareIndicesForAssistantGraph = new PrepareIndicesForAssistantGraphEvalusations({
path: x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts
user: login: patrykkopycinski
body: ```suggestion
          const prepareIndicesForAssistantGraph = new PrepareIndicesForAssistantGraphEvaluations({
```
created_at: 2025-04-07T08:37:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -184,7 +185,18 @@ export const postEvaluateRoute = (
           // Fetch any tools registered to the security assistant
           const assistantTools = assistantContext.getRegisteredTools(DEFAULT_PLUGIN_NAME);
 
-          const { attackDiscoveryGraphs, defendInsightsGraphs } = getGraphsFromNames(graphNames);
+          const { attackDiscoveryGraphs, defendInsightsGraphs, assistantGraphs } =
+            getGraphsFromNames(graphNames);
+
+          const prepareIndicesForAssistantGraph = new PrepareIndicesForAssistantGraphEvalusations({
+            esClient,
+            logger,
+          });
+
+          if (assistantGraphs.length > 0) {
path: x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts
user: login: patrykkopycinski
body: ```suggestion
          if (assistantGraphs?.length) {
```
created_at: 2025-04-07T08:37:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { metricsApmIndexRequest } from './metrics-apm-[environment].evaluations.[date]';
+import { tracesApmIndexRequest } from './traces-apm-[environment].evlauations.[date]';
path: x-pack/solutions/security/plugins/elastic_assistant/server/routes/evaluate/prepare_indices_for_evaluations/graph_type/assistant/index_requests/index.ts
user: login: patrykkopycinski
body: ```suggestion
import { tracesApmIndexRequest } from './traces-apm-[environment].evaluations.[date]';
```
created_at: 2025-04-07T08:38:34Z
author_association: CONTRIBUTOR

PR comments:
user: login: KDKHD
created_at: 2025-04-03T18:09:00Z
body: @elasticmachine merge upstream
author_association: MEMBER
user: login: KDKHD
created_at: 2025-04-07T08:35:50Z
body: @elasticmachine merge upstream
author_association: MEMBER
user: login: kibanamachine
created_at: 2025-04-07T11:22:44Z
body: Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/14307905734
author_association: CONTRIBUTOR
user: login: elasticmachine
created_at: 2025-04-07T11:23:24Z
body: ## :green_heart: Build Succeeded
* [Buildkite Build](https://buildkite.com/elastic/kibana-pull-request/builds/290637)
* Commit: 5ec7bf66dac92dd8c2bc4d3fa2194c42d1007c22

### Metrics [[docs](https://www.elastic.co/guide/en/kibana/master/ci-metrics.html)]
> ✅ unchanged

### History
* :broken_heart: [Build #290627](https://buildkite.com/elastic/kibana-pull-request/builds/290627) failed 66cb9de3f8b194664ecb3b4e9b4af8785c4de2d5
* :yellow_heart: [Build #290047](https://buildkite.com/elastic/kibana-pull-request/builds/290047) was flaky e65736631f433f027c97db38aa2cea33ff2d65d5

cc @patrykkopycinski

<!--buildkite-pr-comment-kibana-pull-request
{"builds":[{"buildStatus":{"state":"passed","success":true,"hasRetries":true,"hasNonPreemptionRetries":false},"url":"https://buildkite.com/elastic/kibana-pull-request/builds/290637","number":290637,"commit":"5ec7bf66dac92dd8c2bc4d3fa2194c42d1007c22"},{"buildStatus":{"state":"failing","success":false,"hasRetries":false,"hasNonPreemptionRetries":false},"url":"https://buildkite.com/elastic/kibana-pull-request/builds/290627","number":290627,"commit":"66cb9de3f8b194664ecb3b4e9b4af8785c4de2d5"},{"buildStatus":{"state":"passed","success":true,"hasRetries":true,"hasNonPreemptionRetries":true},"url":"https://buildkite.com/elastic/kibana-pull-request/builds/290047","number":290047,"commit":"e65736631f433f027c97db38aa2cea33ff2d65d5"}],"number":290637}
buildkite-pr-comment-->
author_association: CONTRIBUTOR
user: login: kibanamachine
created_at: 2025-04-07T11:28:55Z
body: ## 💔 All backports failed

| Status | Branch | Result |
|:------:|:------:|:------|
|❌|8.x|Backport failed because of merge conflicts|

### Manual backport
To create the backport manually run:
```
node scripts/backport --pr 217078
```

### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)

<!--- Backport version: 9.6.6 -->
author_association: CONTRIBUTOR
user: login: KDKHD
created_at: 2025-04-07T11:38:35Z
body: ## 💚 All backports created successfully

| Status | Branch | Result |
|:------:|:------:|:------|
|✅|8.x|[<img src="https://img.shields.io/github/pulls/detail/state/elastic/kibana/217311">](https://github.com/elastic/kibana/pull/217311)|

Note: Successful backport PRs will be merged automatically after passing CI.

### Questions ?
Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport)

<!--- Backport version: 9.6.6 -->
author_association: MEMBER