x-pack/solutions/security/packages/kbn-attack-discovery-schedules-common/docs/adr_scheduling_strategy.md
Status: Accepted
Date: 2026-02-20
Authors: Security Solution Team
Attack Discovery 2.0 introduces a generation workflow that coordinates alert retrieval, generation, and promotion via the Kibana Workflows engine. The natural question arises: should we schedule these workflows using native workflow scheduling (cron/interval triggers built into the Workflows engine), or continue using the existing Kibana Alerting Framework?
The existing public Attack Discovery schedule API (/api/attack_discovery/schedules) already uses the Alerting Framework to create and manage scheduled alerting rules. These rules execute a custom rule type (attack-discovery) whose executor retrieves alerts, invokes generation, and writes results as alerts-as-data.
Native Workflow Scheduling — Add cron/interval trigger support to the Workflows engine and use it to schedule Attack Discovery workflows directly.
Alerting Framework with Workflow Executor — Continue using the Alerting Framework for scheduling, but replace the executor with one that invokes the generation workflow. The schedule API remains a thin wrapper around alerting rules.
Option 2: Alerting Framework with Workflow Executor.
We use the Kibana Alerting Framework as the scheduling mechanism and add a new executor that invokes the generation workflow pipeline (executeGenerationWorkflow) instead of running the legacy inline generation logic.
.alerts-* indices, which Attack Discovery already uses for scheduled results. Using workflows directly would require reimplementing this write path.elastic_assistant continues to work unchanged.discoveries uses the same data client, field maps, and transforms extracted into @kbn/attack-discovery-schedules-common.executeGenerationWorkflow, while the public API retains its existing inline executor.attack-discovery-schedule tag) is asymmetric by design (see "Asymmetric visibility" below): the public (legacy) API only sees its own untagged schedules, while the internal (workflow) API sees all schedules so that schedules created before the feature flag was enabled are never lost from the UI.AttackDiscoveryScheduleDataClient, transforms, field maps, and constants are extracted into @kbn/attack-discovery-schedules-common so both elastic_assistant and discoveries share the same infrastructure.filterTags option on the data client controls each API's view of the shared attack-discovery rule type (see "Asymmetric visibility").Both APIs read and write the same attack-discovery rule type, differentiated by the attack-discovery-schedule tag (applied at write time by the internal API only). Visibility is intentionally asymmetric:
filterTags.excludeTags: ['attack-discovery-schedule', 'attack-discovery-workflow']. It only surfaces its own untagged schedules and hides workflow-tagged schedules, so enabling the workflow feature does not change the legacy view.filterTags include filter. It surfaces all attack discovery schedules (its own tagged rules and untagged schedules created by the public API).This guarantees migration continuity: schedules created while the feature flag was off remain visible (and manageable) once the flag is turned on, so users never "lose" schedules from the UI. We do not expect users to toggle the flag repeatedly, but this guarantee holds regardless.
elastic_assistant and discoveries each register their own executor for the same attack-discovery rule type, differentiated by tags. This requires careful coordination.This decision should be revisited if any of the following conditions are met:
kibana-9p4)elastic_assistant/server/routes/attack_discovery/schedules/public/discoveries/server/routes/{get,post,put,delete}/schedules/ (kibana-9p4.6)@kbn/attack-discovery-schedules-common (kibana-9p4.1)@kbn/discoveries/impl/attack_discovery/generation/execute_generation_workflow.ts