Nicholas Pini
04/20/2026, 12:48 PMCompleted(name="S3Files", result=some_result) , and I want to match these flows as wellMarvin
04/20/2026, 12:48 PMMarvin
04/20/2026, 12:54 PMCompleted(name="S3Files")), the emitted event is prefect.flow-run.S3Files, so an automation expecting prefect.flow-run.Completed won’t match.
To trigger on “any completed flow,” regardless of the state’s name, create an Event-triggered automation that:
- expects all flow-run state events with a wildcard, and
- filters by the state type label prefect.state-type = COMPLETED
That way, it will match standard Completed as well as custom-named completed states (and note: it will also include Cached and RolledBack since they are type COMPLETED).
Example automation YAML (works in Prefect 3.x):
name: "On any completed flow (regardless of state name)"
description: "Fires whenever a flow run reaches a COMPLETED-type state, even with a custom name"
enabled: true
trigger:
type: event
posture: Reactive
expect:
- "prefect.flow-run.*" # catch any flow-run state event
match:
"prefect.state-type": "COMPLETED" # restrict to COMPLETED type only
"prefect.resource.id": "prefect.flow-run.*"
threshold: 1
actions:
- type: send-notification
subject: "Flow {{ flow_run.name }} completed"
body: |
Flow run {{ flow_run.name }} completed with state:
- name: {{ event.resource['prefect.state-name'] }}
- type: {{ event.resource['prefect.state-type'] }}
- id: {{ event.resource['prefect.resource.id'] }}
Create it with the CLI (verified):
prefect automation create --from-file automation.yaml
Notes and tips:
- Custom completed states change the event name, not the type. Completed(name="S3Files") emits prefect.flow-run.S3Files with labels prefect.state-type=COMPLETED and prefect.state-name=S3Files.
- If you only want a subset of COMPLETED-type states (e.g., exclude Cached/RolledBack), say so and we can refine the match further.
- You can scope to specific flows/deployments/tags using match_related (e.g., match a deployment id or a tag).
Helpful docs:
- Automations in Prefect
- Events and event payloads
Does this behavior (including Cached and RolledBack as COMPLETED-type) match what you want, or should we exclude those?Nicholas Pini
04/20/2026, 1:00 PM{
"type": "event",
"match": {
"prefect.resource.id": "prefect.flow-run.*",
"prefect.state-type": [
"COMPLETED",
"SCHEDULED",
"RUNNING",
"FAILED",
"CRASHED"
]
},
"match_related": {
"prefect.resource.id": [
"prefect.tag.job"
],
"prefect.resource.role": "tag"
},
"after": [],
"expect": [
"prefect.flow-run.*"
],
"for_each": [
"prefect.resource.id"
],
"posture": "Reactive",
"threshold": 1,
"within": 0
}
is this okay? will this match any of
"COMPLETED",
"SCHEDULED",
"RUNNING",
"FAILED",
"CRASHED"
regardless of the name? @MarvinMarvin
04/20/2026, 1:00 PMMarvin
04/20/2026, 1:03 PMexpect: ["prefect.flow-run.*"] catches any flow-run state event, including custom-named states (e.g., prefect.flow-run.S3Files).
- match then filters to only the state types you listed. prefect.state-type supports list values, so this matches any of:
- COMPLETED, SCHEDULED, RUNNING, FAILED, CRASHED
- This means even if the state name is custom (e.g., Completed(name="S3Files") → event prefect.flow-run.S3Files), it will still match because the label prefect.state-type is COMPLETED.
A few validation notes:
- within: 0 is valid for Reactive triggers.
- match_related with prefect.resource.role: "tag" and prefect.resource.id: ["prefect.tag.job"] is correct to scope to runs related to that tag.
- Lists in match and match_related are supported. Wildcards and negation are supported in label values if you ever need them.
If you want to narrow to specific flows/deployments later, you can add additional match_related entries (e.g., a deployment id) alongside the tag filter.Nicholas Pini
04/20/2026, 3:34 PMreturn Completed(name='somename'), how do I add return data to it? For example, if I write return 'asd' in a flow, the string 'asd' can be retrieved from the state of the flow run, but it is the name Completed. What if I want to retrieve this result, but have the state named SomeName?Marvin
04/20/2026, 3:34 PMMarvin
04/20/2026, 3:36 PMfrom prefect import flow
from prefect.states import Completed
@flow
def my_flow():
return Completed(
name="SomeName",
message="Finished with a custom name",
data="asd" # your result payload goes here
)
# Programmatic retrieval
state = my_flow(return_state=True)
print(state.name) # "SomeName"
print(state.type.value) # "COMPLETED"
print(state.result()) # "asd"
Notes:
- Returning a raw value (e.g., return "asd") auto-wraps it in a standard Completed state named “Completed.” If you want a custom name, explicitly return a State (as above) and pass your result in data=....
- To retrieve the result from code, use state.result() (or await state.aresult() for async).
- If you need the result available later via the API/UI (not just in-memory), enable result persistence (e.g., @flow(persist_result=True) or a results block). Ensure your data object is serializable by your chosen serializer (pickle by default).