examples/workflows_extensions_example/README.md
This example plugin demonstrates how to register a custom workflow step using the workflows extensions API.
Example plugins are only loaded when Kibana is started with the --run-examples flag. Start Kibana with:
yarn start --run-examples
Then open Developer examples in the sidebar and click Workflows Extensions Example.
The plugin registers a setvar step that allows you to set variables in the workflow context. These variables can then be referenced in subsequent steps using template syntax.
common/types.ts - Shared step definition (id, inputSchema, outputSchema)server/ - Server-side step handler implementationpublic/ - Public-side step metadata (label, description, icon, documentation)The server configuration includes:
id - Unique step identifierinputSchema - JSON Schema for input validationoutputSchema - JSON Schema for output validationhandler - Function that executes the step logicThe public configuration includes:
id - Must match server-side IDinputSchema - Must match server-side schemaoutputSchema - Must match server-side schemalabel - User-facing labeldescription - User-facing descriptionicon - icon image (preferably lazy loaded)documentation - Documentation with summary, details, and examplesactionsMenuCatalog - (Optional) The catalog under which the step is displayed in the actions menu. Must be one of StepMenuCatalog.elasticsearch, StepMenuCatalog.external, StepMenuCatalog.ai, or StepMenuCatalog.kibana. Defaults to StepMenuCatalog.kibana if not provided.steps:
- name: set_vars
type: workflows_step_example.setvar
with:
variables:
myVar: "Hello World"
count: 42
enabled: true
- name: use_vars
type: console.log
with:
message: "{{ steps.set_vars.output.variables.myVar }}"
The plugin registers an event-driven trigger example.customTrigger and exposes a route to emit events for it. Workflows that subscribe to this trigger in the same space will run when an event is emitted.
You can emit events in two ways: via the request-scoped client (from a route, recommended) or directly via the start contract when you have a request and space id. This example uses the request-scoped client. For the full guide (both options, naming, approval), see the Workflows Extensions README — Contributing Event-Driven Triggers.
From a route handler, use the request-scoped workflows context (your plugin must depend on workflows_extensions and type your HTTP router with WorkflowsExtensionsRequestHandlerContext from @kbn/workflows-extensions/server, as in server/plugin.ts):
const client = context.workflows.getWorkflowsClient();
await client.emitEvent(CUSTOM_TRIGGER_ID, {
message: 'Hello',
source: 'example',
labels: ['demo', 'alerts'],
});
To try it via HTTP (example only; authz disabled for demo):
curl -X POST -u elastic:changeme -H 'Content-Type: application/json' \
'http://localhost:5601/api/workflows_extensions_example/emit' \
-d '{"message":"Hello from example","source":"curl","labels":["demo","curl"]}'
The trigger id is example.customTrigger (kebab-case namespace, camelCase event). The event payload must match the trigger’s eventSchema (message required; source, category, and labels optional).
For information about some guardrails in event-driven triggers see Event-driven guardrails.
The plugin also demonstrates managed workflow registration — a code-owned lifecycle where a workflow ships with the plugin, is kept in sync by the platform, and is installed/executed across spaces.
@kbn/workflows/managed/definitions/ with yamlTemplate for install-time parameterization.@kbn/workflows/managed registry in managed/definitions/index.ts (required for orphan cleanup and auto-update reconciliation).registerManagedWorkflowOwner(pluginId).initManagedWorkflowsClient(pluginId) → client.install(id, { spaceId, values }).import type { ManagedWorkflowDefinition } from '@kbn/workflows/managed';
export const EXAMPLE_MANAGED_WORKFLOW: ManagedWorkflowDefinition = {
id: 'system-example-greeting',
pluginId: 'workflowsExtensionsExample',
yamlTemplate: ({ recipient }) => `name: Example Greeting - ${recipient}
enabled: true
triggers:
- type: workflows.failed
on:
# Filter the subscription by using KQL, use event.* to target event properties
condition: not event.workflow.isErrorHandler:true
steps:
- name: greet
type: console
with:
message: "Hello, ${recipient}! This is a managed workflow example."
`,
management: {
lifecycle: 'static',
versionStrategy: 'auto',
enablement: 'restorable',
},
};
system- prefix is reserved for managed workflow IDs; user-created workflows cannot use it.yamlTemplate(values) enables install-time parameterization; values are persisted and reused on upgrades.versionStrategy: 'auto' means the platform re-installs the workflow on startup when the template changes.enablement: 'restorable' preserves user-toggled enabled state across managed updates.spaceId is mandatory — use '*' (the global space constant) for workflows visible from every space.Shared Common Fields: The id, inputSchema, and outputSchema are defined in common/types.ts and imported by both server and public implementations to ensure consistency.
Handler Function: The handler receives validated input and the step execution runtime context, and returns output conforming to the output schema.
Metadata Registration: The public plugin registers UI metadata that helps users understand and use the step in the workflow editor.