<@ULVA73B9P> from prefect.blocks.notifications imp...
# ask-marvin
m
@Marvin from prefect.blocks.notifications import SlackWebhook slack_webhook_block = SlackWebhook.load("ds-pipelines") slack_webhook_block.notify("Hello from Prefect!") from prefect.blocks.notifications import SlackWebhook slack_webhook_block = SlackWebhook.load("ds-pipelines") slack_webhook_block.notify("Hello from Prefect!")
m
thought for 323.1 seconds
That snippet will work in Prefect 3.x as long as a Slack Webhook block named
ds-pipelines
already exists in your workspace and your code can reach your Prefect API. If you haven’t created the block yet, here are your options: Create via UI - In your Prefect UI, go to Blocks → + New block → select “Slack Webhook”, paste your Slack incoming webhook URL, and name it
ds-pipelines
. - Docs: Blocks concept and Notification blocks API Create via CLI (generates a link to your UI) - Make sure your client points at your Server:
Copy code
export PREFECT_API_URL=http://<your-ec2-host-or-ip>:4200/api
- Then:
Copy code
prefect block type ls
  prefect block create slack-webhook
Docs: prefect block CLI Create programmatically
Copy code
from pydantic import SecretStr
from prefect.blocks.notifications import SlackWebhook

# One-time: create and save the block
block = SlackWebhook(url=SecretStr("<https://hooks.slack.com/services/XXX/YYY/ZZZ>"))
block.save("ds-pipelines", overwrite=True)

# Later: load and use it
slack_webhook_block = SlackWebhook.load("ds-pipelines")
slack_webhook_block.notify("Hello from Prefect!")
Optional: set a notify type (adds context/emoji)
Copy code
slack_webhook_block.notify("Flow completed", notify_type="success")  # info | success | warning | failure
Slack setup - If you need a webhook URL, create one from a Slack app’s Incoming Webhooks: Slack Incoming Webhooks A couple of checks if something doesn’t work: - Verify the block exists and is named exactly `ds-pipelines`:
Copy code
prefect block ls
- Ensure your code environment can reach your Prefect Server API (PREFECT_API_URL must point at your EC2-hosted Server). - If you see “Document not found” on load, the block wasn’t created in this workspace/project or the name differs. Would you like me to help create the block now (UI or code), or are you seeing an error when running your snippet?
m
@Marvin from prefect.blocks.notifications import SlackWebhook slack_webhook_block = SlackWebhook.load("ds-pipelines") slack_webhook_block.notify("Hello from Prefect!") this gives this output Still processing items: 1 items remaining... but below code works import asyncio import httpx from prefect.blocks.notifications import SlackWebhook async def send_direct(): slack_webhook_block = await SlackWebhook.load("ds-pipelines") # Send directly using httpx async with httpx.AsyncClient() as client: response = await client.post( slack_webhook_block.url.get_secret_value(), json={"text": "Hello from Prefect!"} ) print(f"Status: {response.status_code}") print(f"Response: {response.text}") asyncio.run(send_direct())
m
thought for 1239.3 seconds
Thanks for the details — what you’re seeing is expected behavior with short-lived scripts. What “Still processing items: 1 items remaining...” means - That message is from Prefect’s EventsWorker as the process shuts down. It’s just saying it still had an event in its queue when your script exited. It’s not related to the Slack notification itself and is generally harmless. - In short, your first snippet likely did send the Slack message; the log is just from the background event worker during shutdown. Why your async snippet “works” - You awaited the network call and printed the HTTP response, so you saw a clear success signal. - Also, your snippet kept the event loop alive a bit longer which often gives the EventsWorker time to drain. Correct sync vs async usage with SlackWebhook - Block.load is synchronous; the async counterpart is Block.aload. - SlackWebhook.notify is synchronous. Examples Synchronous script (and silence the shutdown warning)
Copy code
from prefect.blocks.notifications import SlackWebhook
from prefect.events.worker import EventsWorker

block = SlackWebhook.load("ds-pipelines")
block.notify("Hello from Prefect!")

# Optional: cleanly stop the events worker to avoid the “Still processing items...” message
EventsWorker.instance().stop()
Async script (use aload; notify is still sync)
Copy code
import asyncio
from prefect.blocks.notifications import SlackWebhook
from prefect.events.worker import EventsWorker

async def main():
    block = await SlackWebhook.aload("ds-pipelines")

    # Call the sync notify without blocking the event loop
    loop = asyncio.get_running_loop()
    await loop.run_in_executor(None, block.notify, "Hello from Prefect!")

    # Optional: stop the events worker
    EventsWorker.instance().stop()

asyncio.run(main())
Optional: run inside a Prefect flow (the engine manages shutdown)
Copy code
from prefect import flow
from prefect.blocks.notifications import SlackWebhook

@flow
def ping():
    SlackWebhook.load("ds-pipelines").notify("Hello from Prefect!")

if __name__ == "__main__":
    ping()
If you want to confirm success in the sync snippet, just add a print after
notify()
or wrap in try/except to log any exceptions. Docs for reference - Notification blocks API: Notification blocks API - Blocks concept: Blocks concept - Blocks CLI: prefect block CLI - Events worker (background component producing that message): Events worker Quick check: did your first snippet deliver the Slack message despite that log line? If not, we can dig into block name, workspace/API connectivity, or Slack webhook URL next.
m
@Marvin I tried this but still no notification in slack from prefect import flow from prefect.blocks.notifications import SlackWebhook @flow def ping(): SlackWebhook.load("ds-pipelines").notify("Hello from Prefect!") if name == "__main__": ping() 132025.143 | INFO | Flow run 'saffron-wolf' - Beginning flow run 'saffron-wolf' for flow 'ping' 132025.148 | INFO | Flow run 'saffron-wolf' - View at http://127.0.0.1:4200/runs/flow-run/f3aa3a2d-7466-456a-9df9-22b704128db3 132025.351 | INFO | Flow run 'saffron-wolf' - Finished in state Completed() 132025.356 | WARNING | EventsWorker - Still processing items: 1 items remaining...
m
thought for 172.1 seconds
Thanks — the key detail here is that
SlackWebhook.notify
uses the Apprise library under the hood. If Apprise isn’t installed in the environment that is running your flow, the call will no-op (log a warning at best) and your flow still completes — which matches your symptoms: Completed state, no Slack message, and no exception. Your direct
httpx
code works because it bypasses Apprise and posts to Slack directly. What to do 1) Ensure Apprise is installed in the runtime environment - If you’re running this locally:
Copy code
pip install "prefect[notifications]"
  # or
  pip install apprise
Quick check:
Copy code
python -c "import importlib.util; print(importlib.util.find_spec('apprise') is not None)"
This must be True in the same environment where the flow runs. If you run via a worker later (e.g., ECS), make sure your image includes
prefect[notifications]
. 2) Confirm the block’s URL looks correct
Copy code
from prefect.blocks.notifications import SlackWebhook
b = SlackWebhook.load("ds-pipelines")
print(b.url.get_secret_value())  # should be <https://hooks.slack.com/services/>...
3) Try again with debug logs to surface any errors from Apprise
Copy code
export PREFECT_LOGGING_LEVEL=DEBUG
python your_script.py
If there’s an Apprise issue (e.g., missing dependency, format problem), you should see it in the logs. 4) Optional: stop the events worker to silence the shutdown warning
Copy code
from prefect.events.worker import EventsWorker
EventsWorker.instance().stop()
If you want an immediate working alternative (no Apprise), use a Custom Webhook block to send the exact JSON payload Slack expects, while still storing your webhook URL in Prefect:
Copy code
from prefect.blocks.notifications import CustomWebhookNotificationBlock

block = CustomWebhookNotificationBlock(
    name="slack-direct",
    url="<https://hooks.slack.com/services/XXX/YYY/ZZZ>",
    method="POST",
    json_data={"text": "Hello from Prefect!"}
)
block.save("slack-direct", overwrite=True)

# later
CustomWebhookNotificationBlock.load("slack-direct").notify("Hello from Prefect!")
References - Notification blocks API: Notification blocks API - Blocks concept: Blocks concept - Apprise (used by SlackWebhook): Apprise If you install
prefect[notifications]
and still don’t get a Slack message, please share any DEBUG log lines around “apprise” or “notify” and we’ll dig deeper.