Skip to content

Triggers

Triggers are LyftData’s registry of curated “run this now” actions. A Trigger is a named invocation with schema-validated parameters that dispatches a message to a target job. It gives teams a safer alternative to handcrafted low-level message traffic for smoke checks, one-off operational workflows, and self-service actions.

Use Triggers when you want:

  • a discoverable list of ready-to-run actions;
  • parameter validation instead of free-form JSON;
  • policy around who can invoke an action; and
  • an auditable invocation with a stable invocation_id.

Use the normal scheduling primitives when work should start on a schedule. Use a typed synchronous-response transport when an external HTTP caller must wait for a workflow result.

  1. An admin publishes a Trigger definition with a slug, schema, defaults, and target job.
  2. A permitted caller invokes the Trigger with parameters.
  3. LyftData dispatches a tagged user-generated message to the target job.
  4. The invocation record reports whether dispatch was accepted.

Trigger definitions can be published to the UI, MCP, or both. Server-side authorization and the Trigger invocation policy still apply on every call.

Triggers are curated and revisioned. Admins normally publish and revise them, while users invoke the approved set.

A Trigger definition includes:

  • Slug and display name: the stable identifier and user-facing label.
  • Parameter schema and defaults: JSON Schema validation and optional defaults.
  • Target job and tag: the job that receives the invocation and, where needed, a stable message-filter tag.
  • Publication surfaces: UI, MCP, or both.
  • Invocation policy: permitted roles and optional per-user rate limits.

The admin API exposes:

  • POST /api/triggers/publish
  • POST /api/triggers/<slug>/revise
  • POST /api/triggers/<slug>/deactivate

Publish a tenant-scoped, dispatch-only Trigger:

{
"slug": "smoke_trigger",
"tenant_id": "tenant-a",
"display_name": "Smoke trigger",
"description": "Dispatch a bounded smoke check.",
"parameter_schema": {
"type": "object",
"properties": {
"env": { "type": "string" },
"depth": { "type": "integer", "minimum": 1 }
},
"required": ["env"]
},
"default_params": { "depth": 1 },
"target_job_name": "smoke_trigger_handler",
"target_message_tag": "smoke.invoke",
"publication": { "mcp": true, "ui_admin": true, "ui_user": false },
"invoke_policy": { "allow_admin": true, "allow_user": true }
}

Send the full draft to the revise endpoint; revision is not a patch-in-place operation. Use tenant_id: "platform" only for a platform-scoped Trigger and principal.

The target job receives a user-generated message. Its job_event payload has this top-level shape:

{
"type": "trigger_invoke",
"version": 1,
"invocation_id": "",
"trigger": {
"id": "",
"slug": "smoke_trigger",
"revision": 3,
"tenant_id": "tenant-a"
},
"caller": {
"username": "alice",
"role": "admin"
},
"params": { "env": "prod", "depth": 2 },
"requested_at_ns": 1739370000000000000
}

In a message-triggered job, read these fields through ${msg|...}. See Variable Expansion.

Most targets are message-triggered so they run only when invoked:

name: smoke_trigger_handler
input:
echo:
trigger:
message:
filter-kind: user
filter-type: [user-generated]
filter-tag: smoke.invoke
json: true
event: "{}"

Use a dedicated tag namespace, such as smoke.invoke, so the filter remains stable when other messages share the environment.

The Trigger registry is dispatch-only for new authoring. When an external HTTP caller must receive a workflow result, use the shared synchronous-response contract:

  1. The Provider Pack or workflow capability declares transport_binding.response_mechanism = "synchronous_response".
  2. The transport supplies a bounded synchronous-response context to the workflow.
  3. A terminal workflow tail emits the typed response-complete output.
  4. The transport returns the correlated result or its bounded timeout outcome to the caller.

The exact workflow and transport definition belongs to the owning Provider Pack or catalog item. Validate its setup journey and receipt contract before publishing it.

The Triggers UI is the run-now surface:

  1. Select an available Trigger.
  2. Fill in its schema-defined fields.
  3. Run it and record the returned invocation_id.
  4. Inspect the target workflow and its receipts for completion evidence.

The API exposes a list, invoke, and status flow:

  • GET /api/triggers?surface=ui&invokable_only=true
  • POST /api/triggers/<slug>/invoke
  • GET /api/trigger-invocations/<invocation_id>

Example request:

{
"params": { "env": "prod", "depth": 2 },
"idempotency_key": "smoke-prod-2026-03-13T10:15:00Z",
"wait_timeout_seconds": 15,
"tenant_id": "tenant-a",
"callback": {
"url": "https://automation.example/hooks/lyftdata-trigger",
"headers": { "authorization": "Bearer …" }
}
}

Practical behavior:

  • params must be an object; null is treated as {}.
  • tenant_id is required when the caller has multiple tenant memberships.
  • idempotency_key deduplicates supported retries for the same tenant, Trigger, caller, and key.
  • wait_timeout_seconds bounds how long the invoke request waits for the current invocation record. It does not wait for workflow completion.

For a successful dispatch-only invocation, the result reports status: "accepted_for_dispatch" and mode: "dispatch_only".

When supplied, callback receives best-effort invocation state updates. Callback delivery is retried on transport errors and retryable HTTP statuses, but it does not block Trigger dispatch. Treat the callback as notification, not as proof that the target workflow or provider completed.

{
"version": 1,
"event_id": "",
"event_type": "trigger_invocation_state",
"emitted_at": 1739370000000000000,
"invocation": {
"invocation_id": "",
"trigger_slug": "smoke_trigger",
"trigger_revision": 3,
"tenant_id": "tenant-a",
"state": "succeeded",
"result": {
"status": "accepted_for_dispatch",
"mode": "dispatch_only"
}
}
}

A Trigger published for MCP appears as a dynamically generated tool, for example trigger_invoke__smoke_trigger.

  • Start the MCP server with --max-tool-tier write. Beta.4 accepts --allow-write only as a deprecated compatibility alias.
  • The Trigger must be published for MCP and invokable by the current identity.
  • The tool returns an invocation_id; use trigger_invocation_get to inspect the dispatch record.
  • Reserved control keys are _idempotency_key and _wait_timeout_seconds.