Register and implement custom workflow triggers from an external Kibana plugin using `@kbn/workflows-extensions`. Use when adding or modifying an event-driven trigger with `registerTriggerDefinition`, designing `eventSchema` Zod schemas, writing `documentation` and KQL `snippets`, wiring `emitEvent` via request context or `getClient`, choosing sync vs async public loader registration, updating `APPROVED_TRIGGER_DEFINITIONS`, or reviewing PRs that touch any of these. Always ask for the user's plugin id first to locate the correct plugin and file paths.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Register and implement custom workflow triggers from an external Kibana plugin using `@kbn/workflows-extensions`. Use when adding or modifying an event-driven trigger with `registerTriggerDefinition`, designing `eventSchema` Zod schemas, writing `documentation` and KQL `snippets`, wiring `emitEvent` via request context or `getClient`, choosing sync vs async public loader registration, updating `APPROVED_TRIGGER_DEFINITIONS`, or reviewing PRs that touch any of these. Always ask for the user's plugin id first to locate the correct plugin and file paths.
Workflows — Custom Trigger Registration
Custom triggers let workflows subscribe to domain events from your plugin. A misconfigured trigger can break workflows on every restart, emit invalid payloads that fail at runtime, cause infinite event chains, or silently fail the approval gate. The defaults are not always right — verify each field below explicitly.
Canonical guide — read this for implementation steps
Follow the end-to-end steps, code templates, emit patterns, guardrails, and approval workflow in:
A custom workflow trigger is owned and registered by a plugin other than workflows_extensions. The workflows-team plugin only hosts internal triggers; everything external must live in the owning plugin.
A trigger lives in three layers:
Common — id, eventSchema, title, description, stability, optional documentation / snippets. Imported by both server and public to keep them in sync. Set stability to 'tech_preview', 'beta', or 'stable' based on the trigger's maturity.
Server — registers the same common definition via registerTriggerDefinition; emits events with emitEvent.
Public — spreads the common definition and adds icon only (browser-only UI).
Both sides register through the workflowsExtensions setup contract:
Worked example: examples/workflows_extensions_example/
Common base type: src/platform/plugins/shared/workflows_extensions/common/trigger_registry/types.ts (CommonTriggerDefinition, TriggerDocumentation, TriggerSnippets)
Public trigger types: src/platform/plugins/shared/workflows_extensions/public/trigger_registry/types.ts (PublicTriggerDefinition)
Before creating or editing any files, ask the user for their plugin id (plugin.id from kibana.jsonc, camelCase — e.g. cases, workflowsExtensionsExample). Do not guess or assume a plugin.
If the user already named their plugin in the request, confirm it matches plugin.id before proceeding.
Resolve the plugin root
Find the plugin directory by searching for the id in kibana.jsonc:
rg '"id": "<pluginId>"' --glob '**/kibana.jsonc'
The directory containing that kibana.jsonc is the plugin root. Read it to confirm plugin.server / plugin.browser and whether workflowsExtensions is already in requiredPlugins.
Choose file locations inside the plugin
Inspect the plugin root for existing trigger or workflow extension layout. Follow conventions already used in that plugin rather than inventing new paths.
If the plugin already has…
Add files there
common/workflows/triggers/ (e.g. cases)
common/workflows/triggers/<trigger_name>.ts
common/triggers/ (e.g. example plugin)
common/triggers/<trigger_name>.ts
No trigger files yet
Use common/triggers/<trigger_name>.ts and mirror under server/triggers/ and public/triggers/
Also check for existing registration hooks:
server/**/triggers/index.ts or server/plugin.ts — server registration
public/**/triggers/ or public/plugin.ts — public registration
Wire new triggers into those existing index/setup files when present; only create new index files when the plugin has no trigger layout yet.
Derive the trigger namespace
Trigger ids use <namespace>.<event> (kebab-case namespace, camelCase event). Prefer the namespace already used by that plugin's triggers. If none exist, derive kebab-case from plugin.id (e.g. workflowsExtensionsExample → workflows-extensions-example) and confirm with the user if ambiguous.
File layout
Mirror the layout used by examples/workflows_extensions_example/ so reviewers and the workflows team can find things:
your-plugin/
├── common/triggers/<trigger_name>.ts # common definition (id + eventSchema + title + description)
├── server/triggers/index.ts # registerTriggerDefinitions(setup)
├── public/triggers/<trigger_name>.ts # spread common + icon
└── public/triggers/index.ts # registerTriggerDefinitions(setup)
Keep id, eventSchema, title, description, documentation, and snippets in the common file only. Re-importing them on the public side is how server/public stay locked together.
Agent-specific rules (beyond TRIGGERS.md)
These are easy to miss during implementation or review — they are not always spelled out in the contributing doc:
Concern
Rule
id namespace
cases.* is owned by the Cases plugin — do not add new cases.* triggers outside that plugin
Server registration
Setup phase only — never call registerTriggerDefinition from start()
Public icon
Must be a React component via React.lazy from @elastic/eui/es/components/icon/assets/*. EUI icon name strings ('star') are not supported — the build will not fail, the icon will simply be missing
Public async loader
Prefer async import to keep zod out of the main bundle. Loaders that reject are caught and logged; one broken loader does NOT prevent other triggers from registering — verify the log when a trigger is silently missing
Public loader skip
Unlike step loaders, trigger loaders do not support returning undefined to skip registration. Guard optional triggers by not calling registerTriggerDefinition
emitEvent request
Always pass the same request used for attribution/space so event-chain depth tracking works. Emitting without a real request when guardrails matter is an anti-pattern
Loop demo
Use kibana.request (not a generic HTTP connector) so event-chain headers propagate
For naming conventions, schema rules, registration templates, emit patterns, and approval steps, follow TRIGGERS.md.
Quick rule reference
Concern
Rule
Default if omitted
When wrong
id
<kebab-namespace>.<camelEvent>; stable for the life of the workflow
Scout API test run or GET internal/workflows_extensions/trigger_definitions for schemaHash
Entry added to APPROVED_TRIGGER_DEFINITIONS (alphabetically sorted)
PR description requests review from @elastic/workflows-eng
Reviewer checklist
When reviewing a PR that adds or modifies a custom trigger:
No new trigger definitions inside src/platform/plugins/shared/workflows_extensions/{server,public}/triggers/ — external triggers belong in the owning plugin
title, description, eventSchema, documentation, snippets live in the common file, not duplicated on public
id follows <kebab>.<camel>, has a fresh namespace, and does not collide with another plugin's prefix
Every eventSchema field has .describe(); examples/snippets only use declared fields
Server registers the common definition directly in setup(); no registration in start()
Public spreads common definition; icon uses React.lazy, not EUI icon name strings
emitEvent payloads match eventSchema; emit path uses the attribution request for chain guardrails
Public registration uses an async loader unless the module is trivially small
APPROVED_TRIGGER_DEFINITIONS is updated (sorted; new entry near related namespace); workflows-eng review requested
Event-chain implications considered when workflows can re-emit this trigger
Reference implementations
Plugin
Path
Notable pattern
Workflows example
examples/workflows_extensions_example/
Canonical layout; async public loaders; custom_trigger docs/snippets; loop_trigger + emit route for chain-depth demo