Madushan Pathirana
11/11/2025, 7:16 AMMarvin
11/11/2025, 7:16 AMMarvin
11/11/2025, 7:21 AMds-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:
export PREFECT_API_URL=http://<your-ec2-host-or-ip>:4200/api
- Then:
prefect block type ls
prefect block create slack-webhook
Docs: prefect block CLI
Create programmatically
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)
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`:
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?Madushan Pathirana
11/11/2025, 7:24 AMMarvin
11/11/2025, 7:24 AMMarvin
11/11/2025, 7:45 AMfrom 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)
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)
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.Madushan Pathirana
11/11/2025, 7:53 AMMarvin
11/11/2025, 7:53 AMMarvin
11/11/2025, 7:56 AMSlackWebhook.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:
pip install "prefect[notifications]"
# or
pip install apprise
Quick check:
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
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
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
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:
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.