Run with notifications
You can attach notifications to a single run by passing them to flyte.with_runcontext().
Notifications fire when the run reaches the terminal execution phase — no trigger or persistent deployment is required.
import os
import flyte
from flyte import notify
from flyte.models import ActionPhase
env = flyte.TaskEnvironment(name="notify_example")
SLACK_WEBHOOK_URL = os.environ["SLACK_WEBHOOK_URL"]
NOTIFICATION_EMAIL = os.environ["NOTIFICATION_EMAIL"]
@env.task
def compute(x: int, y: int) -> int:
return x + y
if __name__ == "__main__":
result = flyte.with_runcontext(
notifications=(
notify.Slack(
on_phase=ActionPhase.SUCCEEDED,
webhook_url=SLACK_WEBHOOK_URL,
message="Run {{.Run.Name}} succeeded.",
),
notify.Email(
on_phase=ActionPhase.FAILED,
recipients=[NOTIFICATION_EMAIL],
subject="ALERT: Run {{.Run.Name}} failed",
body="Run: {{.Run.Name}}\nError: {{.Error}}",
),
),
).run(compute, x=3, y=7)
print(f"Result: {result}")Pass a single notification or a tuple of notifications. All notification types from flyte.notify are supported: Slack, Email, Teams, Webhook, and NamedDelivery.
To attach notifications to every run created by a scheduled trigger, set notifications on the flyte.Trigger object instead. See
Notifications.
Execution phases
The on_phase parameter accepts a single phase or a tuple of phases from flyte.models.ActionPhase:
| Phase | Description |
|---|---|
ActionPhase.SUCCEEDED |
Run completed successfully |
ActionPhase.FAILED |
Run failed with an error |
ActionPhase.TIMED_OUT |
Run exceeded its timeout |
ActionPhase.ABORTED |
Run was manually aborted |
Template variables
All message fields support template variables substituted at delivery time:
| Variable | Description |
|---|---|
{{.Run.Project}} |
Project name |
{{.Run.Domain}} |
Domain name |
{{.Run.Name}} |
Run ID |
{{.Phase}} |
Execution phase |
{{.Error}} |
Error message (failed) or abort reason (aborted) |
Slack notifications
notify.Slack sends a message to a Slack channel via an
incoming webhook.
Simple message:
notify.Slack(
on_phase=ActionPhase.FAILED,
webhook_url=SLACK_WEBHOOK_URL,
message="Run {{.Run.Name}} failed in {{.Run.Project}}/{{.Run.Domain}}: {{.Error}}",
)Rich formatting with Block Kit:
Use blocks instead of message for structured layouts. When blocks is provided, message is ignored.
notify.Slack(
on_phase=ActionPhase.SUCCEEDED,
webhook_url=SLACK_WEBHOOK_URL,
blocks=[
{
"type": "header",
"text": {"type": "plain_text", "text": "Task Succeeded"},
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": "*Run:*\n{{.Run.Name}}"},
{"type": "mrkdwn", "text": "*Phase:*\n{{.Phase}}"},
],
},
{"type": "divider"},
{
"type": "context",
"elements": [
{"type": "mrkdwn", "text": "{{.Run.Project}}/{{.Run.Domain}}"},
],
},
],
)Email notifications
notify.Email sends an email notification. Provide body for plain text, html_body for HTML, or both (sent as multipart).
notify.Email(
on_phase=ActionPhase.FAILED,
recipients=[NOTIFICATION_EMAIL],
cc=["team-lead@example.com"],
subject="ALERT: Run {{.Run.Name}} failed",
body="Run: {{.Run.Name}}\nError: {{.Error}}",
html_body="<b>Error:</b> {{.Error}}<br>",
)To receive emails locally while developing, start a debug SMTP server before running your script:
# Python >= 3.12
pip install aiosmtpd
sudo python -m aiosmtpd -n -l localhost:25The server prints received emails to stdout. Port 25 requires root; use port 1025 as an alternative (update the SMTP port in your configuration accordingly).