Ad-hoc alert channel for anything you want to see in the chat: deploy pings, business-rule violations, one-off diagnostics. notify() is swallowed-by-design — if init() has not run, or the sidecar is unreachable, the call is counted in client stats and returns None. Frame info (file, line, function) is captured automatically via sys._getframe; when exc_info=True is used inside an except block, the deepest traceback frame is attached instead. Dedup happens sidecar-side — identical text within 5 min renders as × N.

Signature

def notify(
    text: str,
    *,
    severity: str = "warning",
    extras: dict | None = None,
    exc_info: bool | BaseException | None = None,
    source: str | None = None,
    caller: dict | None = None,
) -> None

Parameters

NameTypeDescriptionDefault
textstrMessage body. Rendered as the alert title.required
severitystrOne of "info", "warning", "error", "critical". Drives icon and routing."warning"
extrasdict | NoneFlat key-value pairs appended to the alert’s meta-block. Secrets are scrubbed.None
exc_infobool | BaseException | NoneTrue to attach sys.exc_info(), or pass an exception directly. Outside an except block the exception attachment is dropped, but the notification still goes through.None
sourcestr | NoneOverride the source field (otherwise derived from caller frame).None
callerdict | NonePre-computed {"file", "line", "func"} dict. Skips frame inspection.None

Example

import snitchbot

snitchbot.init("orders-api")

try:
    charge(user_id=42)
except StripeError:
    snitchbot.notify(
        "charge failed",
        severity="error",
        extras={"user_id": 42},
        exc_info=True,
    )

Telegram shows:

🔴 notify · orders-api · 2eec9c
charge failed
Details
  time      12:52:35 UTC
  pid       1732
  caller    billing.py:14 in process_charge()
Extras
  user_id      42

with the StripeError traceback appended in an Exception block below.