小企业智能化
小企业经营异常自动告警实战:企业微信机器人把问题主动推到群里
2026年8月30日
看板要人主动看,告警会自己找人,异常处理才不会拖成事故
小企业经营异常自动告警实战:企业微信机器人把问题主动推到群里
不少小企业已经做了经营看板,图表挺漂亮,但真正出问题时没人第一时间知道——因为看板需要人主动打开。库存卖穿了三天才发现,客户回款逾期两周才想起催,这些不是数据缺失,而是信息没有主动送到该处理的人手上。本文给出一套低成本落地方案:定时跑几条 SQL 判断异常,通过企业微信群机器人推送到对应的业务群,并处理好去重、静默和分级,避免变成没人看的骚扰消息。
先定义什么算异常,再谈技术
这一步比写代码重要。见过太多团队一上手就配告警,最后配出几十条规则,每天推几百条消息,所有人都设了免打扰。判断标准很简单:一条告警推出来,如果没有明确的人需要做明确的动作,这条告警就不该存在。
建议起步只上三类,覆盖大部分小企业的痛点:
阈值类,比如某个 SKU 可用库存低于安全库存,或者某个仓位的库存为零但仍在接单。这类规则明确、误报率低,适合当第一批告警。
时效类,比如订单支付后超过 24 小时未发货,售后工单超过 48 小时无人跟进,采购单预计到货日已过但未入库。时效类是最容易产生实际价值的一类,因为它抓的是"被遗忘的事"。
异动类,比如今日某渠道订单量比过去七天均值下跌超过 50%,或者退款率突然翻倍。异动类阈值需要跑一段时间再调,初期建议阈值宽松些,先建立信任。
每条规则落地时都写清楚四件事:触发条件、检查频率、推送给哪个群、谁负责处理。写不出负责人的规则先不要上线。
用企业微信群机器人做推送通道
企业微信群机器人是小企业最便宜的推送通道,不需要企业认证、不需要开发应用、不占用应用调用额度。在目标群里点右上角,群机器人,添加机器人,就能拿到一个 Webhook 地址,里面带一个 key。
发消息就是一次 POST,支持 text 和 markdown 两种常用格式。markdown 格式可以做颜色标记和加粗,可读性明显更好:
import json, requests
WEBHOOK = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key"
def push_markdown(title, lines, level="warning"):
color = {"info": "info", "warning": "warning", "critical": "warning"}[level]
body = "\n".join(f"> {x}" for x in lines)
content = f"**{title}**\n<font color=\"{color}\">{level.upper()}</font>\n{body}"
r = requests.post(WEBHOOK, json={"msgtype": "markdown",
"markdown": {"content": content}}, timeout=8)
return r.json() # 正常返回 {"errcode":0,"errmsg":"ok"}
两个必须记住的限制:同一个机器人每分钟最多 20 条消息,超了会被限流丢弃;单条消息内容不能超过 4096 字节。所以千万不要写成"每个异常单据推一条",一定要聚合成汇总消息。
写一个能复用的告警脚本
结构上把规则和推送分开,规则只负责返回"有没有异常、异常明细是什么",推送逻辑统一处理。以库存告警为例:
import pymysql
SQL_LOW_STOCK = """
SELECT s.sku_code, s.sku_name, s.qty_available, s.safety_stock
FROM stock s
WHERE s.qty_available < s.safety_stock AND s.is_active = 1
ORDER BY (s.safety_stock - s.qty_available) DESC
LIMIT 15
"""
def rule_low_stock(conn):
with conn.cursor(pymysql.cursors.DictCursor) as cur:
cur.execute(SQL_LOW_STOCK)
rows = cur.fetchall()
if not rows:
return None
lines = [f"{r['sku_code']} {r['sku_name']}:可用 {r['qty_available']}"
f"/安全 {r['safety_stock']}" for r in rows]
return {"key": "low_stock", "title": f"库存预警:{len(rows)} 个 SKU 低于安全库存",
"lines": lines, "level": "warning"}
定时用系统的计划任务跑就够了,不用上调度平台。库存类每小时一次,时效类每天早上九点半一次,异动类每天一次:
30 9 * * * /opt/venv/bin/python /opt/alert/run.py --rules overdue,anomaly
0 9-18 * * 1-6 /opt/venv/bin/python /opt/alert/run.py --rules low_stock
去重、静默与分级
这是决定告警能不能长期活下去的关键。库存低于安全库存这件事,如果不处理会连续触发几十次,一天推十几条同样的消息,人就麻了。
做法是加一张告警记录表,字段包括规则标识、指纹、首次触发时间、最近推送时间、状态。指纹用规则标识加上受影响对象的排序拼接后取哈希,内容没变就认为是同一条告警。推送前判断:同一指纹在静默期内不再推送,静默期按级别设置,提醒类 12 小时,警告类 4 小时,严重类 1 小时。
分级体现在两个地方:一是消息里的颜色和措辞,二是要不要 @人。真正需要立刻处理的才用 mentioned_mobile_list 点名,其余的只推文字。全都 @所有人等于都不 @。
另外记得补一条"恢复通知"。异常解除时推一句"库存预警已恢复,共 12 个 SKU 补货完成",这条消息看起来没用,但它是让业务同事信任告警系统的关键——否则大家永远不知道问题有没有解决。
落地清单与踩坑
上线前对照检查:Webhook key 放在环境变量或配置文件里,不要硬编码进代码提交到仓库,泄露了任何人都能往你的群里发消息;告警内容不要带客户手机号、身份证等敏感信息,群成员范围往往比你想的大;SQL 一律加 LIMIT,避免某天数据异常时拉出上万行;脚本要有异常兜底,数据库连不上时自己发一条"告警系统异常",否则静默失效比不装更危险;统计口径写进注释,比如"今日"是按业务日还是自然日。
小结
从看板到告警,本质是把"人找数据"变成"数据找人"。技术上并不复杂,一个 Webhook、几条 SQL、一个计划任务就能跑起来。难的是规则收敛和降噪:宁可只上三条高价值告警,也不要上三十条没人看的。先跑通库存和时效这两类,观察两周,再逐步扩展。