<@ULVA73B9P> Is it possible to use a SlackCredenti...
# ask-marvin
n
@Marvin Is it possible to use a SlackCredentials block to send a slack message upon flow failure? If it is, what is the right approach to setting up the the on_failure hook?
m
thought for 373.5 seconds
Short answer: yes, you can send a Slack message on flow failure — but not with a SlackCredentials block. In Prefect 3.x there is no SlackCredentials block. Use a SlackWebhook notification block, either via an Automation (UI-driven, no code) or via a flow on_failure hook (code-driven). Two good approaches: 1) No-code (recommended): an Automation that sends Slack on failure - Create a Slack webhook in Slack and save it as a Prefect SlackWebhook block (e.g., name it
alerts
). - In the Prefect UI, create an Automation with: - Trigger: Flow run enters Failed (or Crashed, etc.) - Action: Send Notification - Block: your
SlackWebhook
block (
alerts
) - Docs: - Automations concepts - Create an automation - Notification blocks API 2) In-code: Flow on_failure hook using SlackWebhook - Save a SlackWebhook block first (UI or code). For example, in code:
Copy code
from prefect.blocks.notifications import SlackWebhook

SlackWebhook(url="<https://hooks.slack.com/services/XXX/YYY/ZZZ>").save(
    "alerts", overwrite=True
)
- Define a hook function and attach it to your flow’s on_failure. In Prefect 3.x, flow state hooks receive (flow, flow_run, state):
Copy code
from prefect import flow
from prefect.blocks.notifications import SlackWebhook

def notify_on_failure(flow, flow_run, state):
    slack = SlackWebhook.load("alerts")
    # Most blocks expose a .notify(...) method
    slack.notify(
        f"Flow '{flow.name}' failed\n"
        f"Run ID: {flow_run.id}\n"
        f"State message: {state.message or '(no message)'}"
    )

@flow(on_failure=[notify_on_failure])
def my_flow():
    raise RuntimeError("whoops")

if __name__ == "__main__":
    my_flow()
Notes - Assuming Prefect 3.x. The Flow decorator supports on_failure hooks as shown: see States and hooks. - The SlackWebhook block is the right one for Slack in 3.x: Notification blocks API. - Prefer Automations if you want centralized, policy-based notifications without modifying code. Use hooks if you need custom message formatting or per-flow logic. If you are actually on Prefect 2.x and meant its old blocks, consider upgrading — your future self will thank you, even if I won’t.
n
@Marvin so there would be no way to achieve this with a slack access token, but must be done with a webhook URL?
m
thought for 222.1 seconds
Short version: there’s no SlackCredentials block in Prefect 3.x. The built-in path is a SlackWebhook block (i.e., an incoming webhook URL) or an Automation that uses that block. If you really want to use a bot access token instead of a webhook, you can — but you’ll do it yourself: - In a flow state hook (on_failure), call Slack’s Web API (chat.postMessage) with your token. - Or create an Automation that uses a CallWebhook action to hit Slack’s API with an Authorization header. Example (custom hook using a bot token):
Copy code
import os, requests
from prefect import flow

def slack_token_notify(flow, flow_run, state):
    token = os.environ["SLACK_BOT_TOKEN"]  # or load from a Secret block/manager
    resp = <http://requests.post|requests.post>(
        "<https://slack.com/api/chat.postMessage>",
        headers={"Authorization": f"Bearer {token}"},
        json={
            "channel": "#alerts",
            "text": f"Flow '{flow.name}' failed\nRun: {flow_run.id}\nMessage: {state.message or '(none)'}",
        },
        timeout=10,
    )
    resp.raise_for_status()
    if not resp.json().get("ok"):
        raise RuntimeError(f"Slack API error: {resp.text}")

@flow(on_failure=[slack_token_notify])
def my_flow():
    raise RuntimeError("oops")
Recommended (simpler/managed): - Use a SlackWebhook block + Automation: - Create an automation - Notification blocks API So: webhook URL is the supported, no-code route. Access tokens are possible via custom code or a CallWebhook action, but there’s no first-party “SlackCredentials” block in 3.x.
n
@Niko i think marvin is mistaken here. which is probably my fault, i should give it a better way to explore integrations
n
no worries, I figured -- I'm considering using the slack sdk directly since getting the client from SlackCredentials only returns an AsyncWebClient and that seems to not be playing nicely with the
on_failure
hook
but still using the SlackCredentials block as it is definitely convenient storage
👍 1
n
hm, id be interested to see what exactly you're seeing with this
that seems to not be playing nicely with the
on_failure
hook
n
the issue I saw was that it seemed to run the
on_failure
registered callback successfully but no message sent -- I've tested that as a task
send_chat_message
works and then tried that inside of the
on_failure
callback, which didn't work so I moved to using the
.get_client()
method as I wasn't sure if it on account of that method being a task -- though at the moment on trying to repro, I am running into issues loading the credentials from the block, so looking into that
n
hm. just as a sanity check, is it possible there’s something unawaited? a la https://github.com/PrefectHQ/prefect/issues/15008
n
yep I think that is the issue -- I am using the
SlackCredentials.load(
method, but it seems to still return a coroutine whereas when I had this in the flow it was async and I was using
.aload(
so I should be adding
_sync=True
?
n
yep that sounds right, sorry you hit this rough edge. we're in the (long) process of killing that sync/async dual/contextual behavior with fire because it causes problems like this (and its not type safe)
_sync=True
will work, but if you're an async context you should use
aload
(the explicit async method) so you don't need to worry about the
@sync_compatible
funny business (that we have to keep because 2.x established that behavior expectation and we need to walk it back without breaking everyone - more details in that linked issue)
n
ahh kk and the
on_failure
hook works with asynchronous callback functions?
n
yep the hooks can be sync or async
🙏 1
n
that worked like a charm, thank you!!
n
catjam