0Pricing
AI Agents · Pelajaran

Sistem Notifikasi dan Peringatan Proaktif

Agen yang menampilkan informasi penting tanpa diminta.

Sistem Notifikasi dan Peringatan Proaktif adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Agen Proaktif vs Reaktif

Sebagian besar agen bersifat reaktif—agen tersebut merespons permintaan. Agen proaktif memantau kondisi dan menghubungi pengguna ketika sesuatu yang penting terjadi, tanpa diminta. Polanya lebih mirip asisten pribadi.

Perulangan Pemeriksaan Latar Belakang

Pola proaktif yang paling sederhana adalah perulangan latar belakang yang menjalankan pemeriksaan setiap N menit dan mengirimkan peringatan jika suatu kondisi terpenuhi. Gunakan utas atau perulangan asinkron agar proses lain tidak terblokir.

import asyncio
import httpx
from datetime import datetime

async def poll_price(ticker: str, alert_threshold: float) -> None:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f'https://api.finance.example.com/quote/{ticker}',
            headers={'Authorization': 'Bearer your-api-key'}
        )
        data = response.json()
        price = float(data.get('price', 0))
        
        if price < alert_threshold:
            await send_push_notification(
                title=f'{ticker} Price Alert',
                message=f'{ticker} is now ${price:.2f}, below your threshold of ${alert_threshold:.2f}'
            )

async def price_alert_loop(ticker: str, threshold: float, interval_seconds: int = 300):
    print(f'Monitoring {ticker} every {interval_seconds}s, alert below ${threshold}')
    while True:
        try:
            await poll_price(ticker, threshold)
        except Exception as e:
            print(f'Polling error: {e}')
        await asyncio.sleep(interval_seconds)

print('Price alert loop defined')

Peringatan Berbasis Ambang Batas

Peringatan ambang batas dipicu ketika suatu metrik melewati batas yang ditentukan. Ambang batas yang baik dapat berupa nilai absolut (harga < $100), perubahan persentase (turun > 5%), atau perbandingan dengan rata-rata historis.

from dataclasses import dataclass
from typing import Optional, Callable

@dataclass
class AlertRule:
    name: str
    check_fn: Callable  # Returns a float value
    condition: str      # 'lt', 'gt', 'lte', 'gte'
    threshold: float
    cooldown_minutes: int = 60  # Don't re-alert for this long
    last_alerted: Optional[float] = None

def evaluate_rule(rule: AlertRule) -> Optional[str]:
    import time
    
    # Respect cooldown
    if rule.last_alerted:
        elapsed = time.time() - rule.last_alerted
        if elapsed < rule.cooldown_minutes * 60:
            return None
    
    current_value = rule.check_fn()
    
    triggered = (
        (rule.condition == 'lt' and current_value < rule.threshold) or
        (rule.condition == 'gt' and current_value > rule.threshold) or
        (rule.condition == 'lte' and current_value <= rule.threshold) or
        (rule.condition == 'gte' and current_value >= rule.threshold)
    )
    
    if triggered:
        rule.last_alerted = time.time()
        return f'Alert: {rule.name} = {current_value:.2f} ({rule.condition} {rule.threshold})'
    return None

# Example rule
rule = AlertRule(
    name='CPU Usage',
    check_fn=lambda: 85.0,  # In reality: psutil.cpu_percent()
    condition='gt',
    threshold=80.0,
    cooldown_minutes=30
)
print(evaluate_rule(rule))

Kriteria Pencocokan Email Baru

Agen email proaktif memantau kotak masuk dan mengirimkan peringatan ketika pesan yang memenuhi kriteria tertentu tiba: berasal dari pengirim VIP, berisi kata kunci, atau memiliki penanda kepentingan tinggi.

from dataclasses import dataclass
from typing import List
import re

@dataclass
class EmailAlertCriteria:
    from_domains: List[str] = None
    from_emails: List[str] = None
    subject_keywords: List[str] = None
    body_keywords: List[str] = None
    min_importance: str = None  # 'high', 'medium'

def matches_criteria(email: dict, criteria: EmailAlertCriteria) -> bool:
    sender = email.get('from', '').lower()
    subject = email.get('subject', '').lower()
    body = email.get('body', '').lower()
    
    if criteria.from_domains:
        domain_match = any(domain.lower() in sender for domain in criteria.from_domains)
        if not domain_match:
            return False
    
    if criteria.from_emails:
        email_match = any(e.lower() in sender for e in criteria.from_emails)
        if not email_match:
            return False
    
    if criteria.subject_keywords:
        keyword_match = any(kw.lower() in subject for kw in criteria.subject_keywords)
        if not keyword_match:
            return False
    
    return True

criteria = EmailAlertCriteria(
    from_domains=['@important-client.com', '@boss.company.com'],
    subject_keywords=['urgent', 'action required', 'ASAP']
)

email = {'from': 'john@important-client.com', 'subject': 'Urgent: Contract Issue'}
print('Matches:', matches_criteria(email, criteria))

Notifikasi Pushover

Pushover mengirimkan notifikasi push ke iOS dan Android. Pushover memiliki REST API sederhana dan tingkat penggunaan gratis. Layanan ini ideal untuk agen pribadi yang perlu memberi peringatan kepada satu pengguna.

import httpx
import os

PUSHOVER_TOKEN = os.environ.get('PUSHOVER_APP_TOKEN', 'your-app-token')
PUSHOVER_USER = os.environ.get('PUSHOVER_USER_KEY', 'your-user-key')

async def send_pushover(title: str, message: str, priority: int = 0, url: str = None) -> bool:
    '''
    priority: -2 (lowest) to 2 (emergency with acknowledgment)
    0 = normal, 1 = high priority (bypass quiet hours)
    '''
    async with httpx.AsyncClient() as client:
        data = {
            'token': PUSHOVER_TOKEN,
            'user': PUSHOVER_USER,
            'title': title,
            'message': message,
            'priority': priority
        }
        if url:
            data['url'] = url
        
        response = await client.post('https://api.pushover.net/1/messages.json', data=data)
        result = response.json()
        
        if result.get('status') == 1:
            print(f'Push sent: {title}')
            return True
        else:
            print(f'Push failed: {result.get("errors")}')
            return False

async def send_push_notification(title: str, message: str):
    await send_pushover(title, message)

Notifikasi DM Slack

Kirimkan peringatan proaktif sebagai pesan langsung Slack. Berbeda dari pesan saluran, DM memastikan pengguna menerima pemberitahuan meskipun tidak berada di saluran tertentu.

from slack_sdk import WebClient
import os

slack_client = WebClient(token=os.environ.get('SLACK_BOT_TOKEN', 'xoxb-...'))

def send_slack_dm(user_id: str, title: str, message: str, urgency: str = 'normal') -> bool:
    # Build blocks for rich formatting
    blocks = [
        {
            'type': 'section',
            'text': {
                'type': 'mrkdwn',
                'text': f'*{title}*\n{message}'
            }
        }
    ]
    
    if urgency == 'high':
        # Add urgent emoji prefix
        blocks[0]['text']['text'] = '🚨 ' + blocks[0]['text']['text']
    
    try:
        response = slack_client.chat_postMessage(
            channel=user_id,  # DM: channel = user_id
            text=f'{title}: {message}',  # Fallback text
            blocks=blocks
        )
        return True
    except Exception as e:
        print(f'Slack DM failed: {e}')
        return False

print('Slack DM function defined')
print('Usage: send_slack_dm("U0123ABCD", "Price Alert", "AAPL dropped below $150")')

Notifikasi Email

Email dapat diandalkan untuk peringatan yang tidak mendesak. Gunakan smtplib Python atau API SendGrid untuk mengirim email secara terprogram dari agen.

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os

def send_email_alert(to_email: str, subject: str, html_body: str) -> bool:
    smtp_host = os.environ.get('SMTP_HOST', 'smtp.gmail.com')
    smtp_port = int(os.environ.get('SMTP_PORT', '587'))
    smtp_user = os.environ.get('SMTP_USER', '')
    smtp_pass = os.environ.get('SMTP_PASS', '')
    
    try:
        msg = MIMEMultipart('alternative')
        msg['Subject'] = subject
        msg['From'] = smtp_user
        msg['To'] = to_email
        
        html_part = MIMEText(html_body, 'html')
        msg.attach(html_part)
        
        with smtplib.SMTP(smtp_host, smtp_port) as server:
            server.starttls()
            server.login(smtp_user, smtp_pass)
            server.sendmail(smtp_user, to_email, msg.as_string())
        
        print(f'Email sent to {to_email}: {subject}')
        return True
    except Exception as e:
        print(f'Email failed: {e}')
        return False

html = '<p>Your agent detected a price drop: <strong>AAPL is now $147.50</strong></p>'
print('Email alert function defined')

Perute Peringatan Multisaluran

Rutekan peringatan ke saluran yang tepat berdasarkan urgensinya. Peringatan kritis dikirim melalui notifikasi push; peringatan informasional dikirim melalui email; ringkasan harian dikirim melalui DM Slack.

import asyncio
from enum import Enum

class AlertLevel(Enum):
    INFO = 'info'        # Email/Daily summary
    WARNING = 'warning'  # Slack DM
    CRITICAL = 'critical'  # Push notification immediately

async def route_alert(title: str, message: str, level: AlertLevel, user_config: dict):
    user_id = user_config.get('user_id')
    email = user_config.get('email')
    push_enabled = user_config.get('push_enabled', True)
    
    if level == AlertLevel.CRITICAL and push_enabled:
        success = await send_pushover(title, message, priority=1)
        if not success:
            # Fallback to Slack DM
            slack_user = user_config.get('slack_user_id')
            if slack_user:
                send_slack_dm(slack_user, title, message, urgency='high')
    
    elif level == AlertLevel.WARNING:
        slack_user = user_config.get('slack_user_id')
        if slack_user:
            send_slack_dm(slack_user, title, message)
    
    else:  # INFO
        if email:
            send_email_alert(email, title, f'<p>{message}</p>')

user_config = {
    'user_id': 'user-42',
    'email': 'user@example.com',
    'slack_user_id': 'U0123ABCD',
    'push_enabled': True
}

asyncio.run(route_alert('Price Alert', 'AAPL dropped to $147', AlertLevel.WARNING, user_config))

Deduplikasi Peringatan dan Masa Tunggu

Tanpa deduplikasi, kondisi yang berlangsung selama berjam-jam dapat mengirim ratusan peringatan. Masa tunggu mencegah pengiriman ulang peringatan untuk kondisi yang sama dalam jangka waktu tertentu.

import time
import redis
import json

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

def should_send_alert(alert_key: str, cooldown_seconds: int = 3600) -> bool:
    redis_key = f'alert:cooldown:{alert_key}'
    if r.exists(redis_key):
        ttl = r.ttl(redis_key)
        print(f'Alert {alert_key} on cooldown. {ttl}s remaining')
        return False
    return True

def record_alert_sent(alert_key: str, cooldown_seconds: int = 3600):
    redis_key = f'alert:cooldown:{alert_key}'
    r.setex(redis_key, cooldown_seconds, '1')

def maybe_send_alert(alert_type: str, metric_value: float, user_id: str, cooldown_hours: int = 1):
    # Create unique key per alert type per user
    alert_key = f'{user_id}:{alert_type}'
    
    if not should_send_alert(alert_key, cooldown_seconds=cooldown_hours * 3600):
        return False
    
    # Send the alert
    print(f'Sending alert: {alert_type} = {metric_value} for user {user_id}')
    record_alert_sent(alert_key, cooldown_seconds=cooldown_hours * 3600)
    return True

maybe_send_alert('price_drop_AAPL', 147.50, 'user-42')
maybe_send_alert('price_drop_AAPL', 146.00, 'user-42')  # Blocked by cooldown

Penyaringan Berbasis Preferensi Pengguna

Tidak semua pengguna menginginkan setiap peringatan. Simpan preferensi pengguna mengenai jenis peringatan yang diinginkan, ambang batasnya, dan saluran pengirimannya. Agen memeriksa preferensi tersebut sebelum mengirimkan peringatan.

from dataclasses import dataclass, field
from typing import Dict, List

@dataclass
class UserAlertPreferences:
    user_id: str
    enabled_channels: List[str] = field(default_factory=lambda: ['push'])
    alert_rules: Dict[str, dict] = field(default_factory=dict)
    quiet_hours_start: int = 22  # 10pm
    quiet_hours_end: int = 8    # 8am

def is_quiet_hours(prefs: UserAlertPreferences) -> bool:
    from datetime import datetime
    hour = datetime.now().hour
    start = prefs.quiet_hours_start
    end = prefs.quiet_hours_end
    if start > end:  # Spans midnight
        return hour >= start or hour < end
    return start <= hour < end

def should_alert_user(prefs: UserAlertPreferences, alert_type: str, value: float) -> bool:
    rule = prefs.alert_rules.get(alert_type)
    if not rule:
        return False  # User hasn't set up this alert type
    
    threshold = rule.get('threshold')
    condition = rule.get('condition', 'lt')
    urgent = rule.get('urgent', False)
    
    if is_quiet_hours(prefs) and not urgent:
        print(f'Suppressing non-urgent alert during quiet hours')
        return False
    
    return (
        (condition == 'lt' and value < threshold) or
        (condition == 'gt' and value > threshold)
    )

prefs = UserAlertPreferences(
    user_id='user-42',
    alert_rules={'price_drop': {'threshold': 150.0, 'condition': 'lt'}}
)
print('Should alert:', should_alert_user(prefs, 'price_drop', 147.50))

Menggabungkan Peringatan menjadi Ringkasan

Alih-alih mengirimkan peringatan satu per satu untuk setiap peristiwa, kumpulkan peringatan tersebut lalu kirimkan sebagai ringkasan. Cara ini mengurangi kelelahan akibat notifikasi bagi pengguna yang memantau banyak kondisi.

import redis
import json
from datetime import datetime

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

def add_to_digest(user_id: str, alert: dict):
    key = f'digest:{user_id}:{datetime.now().strftime("%Y%m%d")}'
    r.rpush(key, json.dumps(alert))
    r.expire(key, 86400 * 2)  # Keep for 2 days

def send_and_clear_digest(user_id: str) -> int:
    key = f'digest:{user_id}:{datetime.now().strftime("%Y%m%d")}'
    raw_alerts = r.lrange(key, 0, -1)
    if not raw_alerts:
        print(f'No alerts for user {user_id} today')
        return 0
    
    alerts = [json.loads(a) for a in raw_alerts]
    digest_text = f'Daily Digest ({len(alerts)} alerts):\n'
    digest_text += '\n'.join([f'- {a["title"]}: {a["message"]}' for a in alerts])
    
    # Send as single notification
    print(f'Sending digest to {user_id}:\n{digest_text}')
    # send_email_alert(user_email, 'Daily Alert Digest', digest_text)
    
    r.delete(key)
    return len(alerts)

add_to_digest('user-42', {'title': 'AAPL Alert', 'message': 'Price at $147.50'})
add_to_digest('user-42', {'title': 'GOOG Alert', 'message': 'Price at $175.00'})
send_and_clear_digest('user-42')

Uji Pemahaman: Notifikasi Proaktif

Uji pemahaman Anda tentang sistem notifikasi dan peringatan proaktif.

Ringkasan Notifikasi Proaktif

Agen proaktif menggunakan perulangan pemeriksaan latar belakang untuk memantau kondisi dan mengirimkan peringatan melalui push (Pushover), DM Slack, atau email. Elemen desain utama meliputi: aturan berbasis ambang batas dengan masa tunggu untuk mencegah kelelahan akibat notifikasi, penyaringan preferensi pengguna untuk personalisasi, perutean multisaluran berdasarkan urgensi, dukungan jam tenang, serta ringkasan harian untuk peringatan berprioritas rendah yang terkumpul.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Sistem Notifikasi dan Peringatan Proaktif” gratis?

Ya — teks lengkap “Sistem Notifikasi dan Peringatan Proaktif” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Sistem Notifikasi dan Peringatan Proaktif”?

Agen yang menampilkan informasi penting tanpa diminta. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Sistem Notifikasi dan Peringatan Proaktif” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?

Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Pola Desain Agen yang Selalu Aktif
  2. Sistem Notifikasi dan Peringatan Proaktif
  3. Persistensi Konteks Antarsesi
  4. Membangun Agen Ringkasan Harian
← Kembali ke AI Agents