Predict.aiDocs
Examples

Alerts that watch the forecast

Put a condition on the future — get told the moment the forecast crosses it, on the channels you choose.

Dashboards answer questions you remember to ask. An alert watches the forecast for you: warn me if projected sales dip below 10,000 at any point over the horizon. Conditions are evaluated after every champion serve, and firings deliver through notifications — Slack, email, your own webhook, or a live stream your app listens to.

You'll need: a goal with a live champion — the one from A goal on autopilot.

1. Dry-run the condition first

Preview answers "would this trigger right now?" against the champion's latest forecast — free, and it saves you from alerts that fire instantly or never:

from predictai import PredictAI

client = PredictAI(token="pa_live_...", workspace_id="ws_...")

preview = client.goals.post_goals_by_goal_id_alerts_preview(GOAL_ID, json={
    "condition": {"metric": "forecast_value", "scope": "any", "operator": "lt", "threshold": 10000},
})["data"]

print(preview["condition_label"])
print("would trigger now:", preview["triggered"], "-", preview["detail"])
forecast below 10000 $ at any point over the horizon
would trigger now: False - Lowest forecast point is 12480.1 — above the 10000 threshold.

Conditions compose from four parts: a metric (forecast_value, forecast_change_pct, uncertainty_pct, crossing — or probability for trend/anomaly goals), a scope over the horizon (any, last, min, max, mean), an operator, and a threshold.

2. Point a channel at your systems

in_app, email, and websocket are built in. For Slack, Teams, PagerDuty, or your own HTTPS endpoint, register a channel endpoint once — then test-fire it before trusting it:

channel = client.notifications.post_notifications_channels(json={
    "type": "slack",
    "label": "Ops Slack",
    "config": {"url": "https://hooks.slack.com/services/T000/B000/XXXX"},
})["data"]["channel"]

test = client.notifications.post_notifications_channels_by_channel_id_test(channel["channel_id"])
print("test delivery:", test["data"])

3. Create the alert

alert = client.goals.post_goals_by_goal_id_alerts(GOAL_ID, json={
    "name": "Sales dip warning",
    "condition": {"metric": "forecast_value", "scope": "any", "operator": "lt", "threshold": 10000},
    "severity": "warning",
    "cooldown_minutes": 240,
    "channels": ["email", "slack"],
})["data"]["alert"]

print("alert:", alert["alert_id"], "enabled:", alert["enabled"])

From now on, every time the champion serves a forecast the condition is evaluated. A firing (outside its 4-hour cooldown) publishes alerts.evaluated on the goal's realtime channel and delivers through the alert's channels with the human-readable condition label and the observed value.

4. Listen live

For your own app, the notification stream pushes every feed item over Server-Sent Events the moment it lands:

import json

response = client.notifications.get_notifications_stream(stream=True)
for line in response.iter_lines():
    if line.startswith(b"data: "):
        item = json.loads(line[6:])
        if item.get("type") == "notification":
            print(f'[{item["severity"]}] {item["title"]}: {item["body"]}')
[warning] Alert: Sales dip warning: forecast below 10000 $ at any point over the horizon — observed 9,842.3.

Keep it honest

Every alert keeps its own audit trail — last_evaluated_at, last_triggered_at, trigger_count, and last_result on the list route — so you can see at a glance whether a quiet alert is quiet because things are fine or because it never evaluates. Tune thresholds with preview (free), silence one with {"enabled": false}, and cap noise with cooldown_minutes.

That closes the loop this example series opened: data flows in as signals, models turn it into forecasts, goals keep the forecasts honest and explained, and alerts turn them into action — without anyone watching a dashboard.

On this page