值班系统最崩溃的时刻,不是半夜被叫醒,而是被叫醒之后盯着告警看了五分钟,还没看懂这个错误到底是谁的职责、影响多大、该找哪个团队。
这不是模型能力问题,而是告警链路里缺了最关键的一层:结构化上下文。我们每天收到的告警是一堆无规则的文本,而人要判断的其实是几个固定问题——这是什么系统、什么级别、影响谁、该谁处理。这些问题如果能在告警到达的第一时间被自动拆解并交给 AI 大模型做分诊,值班效率会完全不同。
这篇文章要讲的就是这套思路:用 Tag 体系把告警变成结构化输入,再交给 Claude(Anthropic 大模型)驱动值班分诊。我会从一个真实值班场景切入,拆解 Tag 在告警链路中的职责,然后给出一套可落地的 Python 值班机器人实现,包含环境准备、完整代码、运行验证和常见坑。读完你可以直接在内部监控系统上复刻一版,让 Claude 帮你完成告警的初步分类、级别判断和责任人路由。
先说结论:Claude Tag 不是一个魔法开关,它是一套"告警标准化 + 模型上下文"的工程方案。它的核心价值不是帮你写值班报告,而是把值班链路里最耗时的"理解告警"环节自动化。
1. 这篇文章真正要解决的问题
1.1 值班的真正瓶颈是分诊太慢
很多团队把值班系统的重点放在"如何更早地发现故障"上。Prometheus 配了一堆告警规则,夜莺、Zabbix、自研监控平台都接上了,日志也做了关键字告警。结果却是告警越来越多,值班同学越来越累。
问题出在哪?出在告警产生之后到人工介入之前的这段真空期。
一条告警从监控平台弹出,到值班同学真正定位问题,中间通常要经过这几个动作:
- 看告警标题和描述,猜这是什么模块。
- 去 Grafana 看指标,确认是不是真的异常。
- 去日志平台搜错误码,找根因线索。
- 翻团队通讯录或 OnCall 表,判断该找谁处理。
- 手动拉群、@人、复制粘贴上下文。
这五个动作里,后面四个都是高度模式化的。尤其是第 4 步,很多团队用的是"谁在值班谁处理"的简单轮询,而不是"哪个模块的负责人处理"。结果就是:后端同学半夜被拉起来处理一个前端网关的告警,只因他的排班刚好轮到了。
Claude 参与值班,不是为了替代人做根因分析,而是替代人完成"理解告警 - 分类 - 路由"这段低创造性工作。
1.2 Tag 在其中的位置
要让 Claude 替人做分诊,前提是 Claude 能读懂告警。但大模型的输入是文本,告警原文往往长这样:
[error] connection pool timeout, service=order, env=prod, host=10.0.3.18, error=Get "http://order-svc:8080/health": context deadline exceeded人勉强能看懂,但模型要稳定地从中提取出"业务系统=订单、环境=生产、故障类型=连接超时、建议路由=订单服务团队"这些字段,光靠模型语义理解是不够的,因为提示词的微小变化就可能导致分类漂移。
Tag 就是来解决这个稳定性的。Tag 是在告警源头就把字段打好的标签,它让告警从"一段自然语言"变成"一组结构化键值对"。Claude 拿到的是字段清晰的输入,分诊就从"猜"变成了"按规则判断"。
1.3 谁最应该读这篇文章
- 被半夜告警折磨的 SRE、运维、后端开发。
- 正在搭建或优化 OnCall 值班流程的团队。
- 想用 Claude Code 或 Anthropic API 做自动化,但不知道从哪入手的开发者。
- 对"AI + 可观测性"方向感兴趣的架构师。
如果你只是想让 Claude 帮你写代码,这篇文章也有参考价值——你会发现 Claude 在结构化数据处理上的稳定方式,与日常问答完全不同。
2. Claude Tag 与 Anthropic 值班的核心概念
2.1 Tag 到底是什么
Tag(标签)在可观测性领域的含义很明确:附加在监控指标、日志或告警事件上的一组键值对,用于描述该事件的属性。比如:
tags: service: order-svc env: prod region: cn-beijing severity: P1 team: order-core alert_source: prometheus常见且合理的 Tag 维度包括:
| Tag 名称 | 含义 | 示例值 |
|---|---|---|
service | 业务服务名 | order-svc、payment-svc |
env | 环境 | prod、staging、dev |
region | 地域 / 集群 | cn-beijing、us-east-1 |
severity | 告警级别 | P0、P1、P2 |
team | 负责团队 | order-core、infra |
alert_source | 告警来源 | prometheus、log、synthetic |
这些 Tag 不是给监控系统内部用的,而是给下游消费方用的。过去的下游消费方是值班人,现在的下游消费方多了 Claude。
2.2 Anthropic 值班形态是什么
Anthropic 值班,可以理解成"Anthropic 系列模型参与值班流程"。它有两种常见形态:
- 离线分析形态:告警产生后,后台调用 Claude API,把告警原文 + Tag 塞进提示词,让它输出结构化的分诊建议。
- 交互助手形态:值班同学在命令行或聊天工具里通过 Claude Code 问"刚才的 P1 告警可能是什么原因",模型结合告警上下文给出回答。
本文的代码示例采用第一种形态,因为它是"Tag 驱动"最直接的体现,也更容易接入现有监控系统。
要注意的是:Claude 在值班链路中是"分诊助手",不是"最终决策者"。它输出的是建议,最终拉人、封网、回滚这些动作必须由经过验证的流程来执行。
2.3 为什么不直接拿告警原文给 Claude
很多人的第一反应是:既然 Claude 理解能力强,直接把原始告警文本丢给它不就行了吗?
从实验效果看,直接丢原文存在三个问题:
- 字段提取不稳定:告警文本格式一旦变化,模型提取的 service、severity 可能漂移。
- 上下文不可控:原始告警里可能夹杂大量无意义信息,甚至包含代码堆栈,浪费 token 也干扰判断。
- 路由依据不足:值班路由依赖的是员工排班表、服务负责人映射这类组织数据,告警文本里根本没有,必须有额外的结构化 Tag 作为路由输入。
所以正确做法是:先标准化,再交给模型。Tag 就是标准化的产物。
3. 值班系统的整体架构设计
3.1 完整链路
一个 Tag 驱动的 Claude 值班分诊系统,整体链路如下:
监控平台(Prometheus/自研) -> 告警事件产生,附带原始字段 -> Tag 标准化层(把原始字段映射成统一 Tag) -> Claude 分诊服务(调用 Anthropic API) -> 结构化输出(severity, 根因方向, 建议负责人) -> 路由执行(企业微信/钉钉/邮件通知, 创建工单) -> 值班人确认 -> 反馈闭环这里最关键的是第二层和第三层。第二层决定输入质量,第三层决定判断质量。
3.2 Tag 标准化层怎么设计
标准化层的职责,是把不同来源的告警修整成同一套字段。Prometheus 的告警字段和日志告警字段天然不同,必须在进入 Claude 之前统一。
这里建议维护一份Tag 映射配置,核心逻辑是"不同来源 -> 统一键"。示例:
# 文件路径:config/tag_mapping.yaml mapping: prometheus: service_label: service severity_label: severity extra_route: instance log_monitor: app_name: service level: severity query: log_query synthetic: target_service: service check_result: health_status这样无论告警来自哪个源,最终给 Claude 看的都是统一结构的输入。
3.3 Claude 在分诊链路中的角色边界
在编码之前必须明确 Claude 的职责边界:
- 让 Claude 做的:提取关键信息、判断严重级别、猜测根因方向、推荐负责人团队。
- 不让 Claude 做的:直接修改配置、自动重启服务、发送高优通知(P0 通知必须人工确认后发出)。
这个边界写入系统设计里,避免"AI 误判导致自动变更"这种事故。值班场景下,AI 的价值是压缩人的判断时间,而不是替人承担风险。
4. 环境准备:Claude Code 与 Anthropic API 接入
4.1 你需要准备什么
为了让值班分诊服务跑起来,需要以下基础环境:
- Python 3.9 及以上版本(本文示例基于 Python)。
- 一个具备 Anthropic API 访问权限的账号,并拿到 API Key。
- 能访问 Anthropic AI 服务的部署环境。
- 一个测试用的告警模拟工具(curl 即可)。
如果你本机已经安装了 Claude Code,可以在命令行里通过claude命令交互测试;如果没有安装,直接用 Python SDK 调用 API 也是一样的。
4.2 Anthropic Python SDK 安装
推荐使用 Anthropic 官方 Python SDK。安装命令:
pip install anthropic安装好之后,把 API Key 配置到环境变量,不要在代码里硬编码:
export ANTHROPIC_API_KEY="sk-ant-..." export ANTHROPIC_MODEL="claude-sonnet-4-5" # 具体模型名以你的账号可用列表为准注意:不同账号可用的模型名可能不同。如果遇到 "is not a model this version of claude code recognizes" 这类报错,说明当前 Claude Code 版本或 API 版本不认你配置的模型名,需要去账号后台查看可用的模型标识,或用claude model相关命令确认。
4.3 验证连通性
写一个最小的连通性测试脚本:
# 文件路径:scripts/test_api.py import os from anthropic import Anthropic client = Anthropic() model = os.getenv("ANTHROPIC_MODEL", "claude-sonnet-4-5") resp = client.messages.create( model=model, max_tokens=100, messages=[ {"role": "user", "content": "请只回复两个字:正常"} ] ) print(resp.content[0].text)运行:
python scripts/test_api.py预期输出:
正常如果这里连不通,后面所有逻辑都不用调试了。常见报错 "unable to connect to anthropic services failed to connect to api.anthropic.com" 说明部署环境的网络无法访问 Anthropic 服务,需要先解决网络连通性问题;如果返回 529,则表示服务端过载或限流,需要实现重试。
这一步是整个项目的地基,务必先跑通再继续。
5. 核心实现:Tag 驱动的最小值班分诊机器人
下面进入正题。我们实现一个最小但完整的值班分诊服务,它包含三个部分:
- Tag 标准化输入模板。
- Claude 分诊核心逻辑。
- 路由与通知逻辑。
5.1 定义告警输入的 JSON 结构
先约定 Claude 分诊服务的输入格式。所有告警源在进入分诊服务之前,都会被标准化成这个 JSON:
{ "alert_id": "alert-20250218-001", "title": "order-svc 连接池超时", "tags": { "service": "order-svc", "env": "prod", "region": "cn-beijing", "severity": "P1", "team": "order-core", "alert_source": "prometheus" }, "raw_message": "Get \"http://order-svc:8080/health\": context deadline exceeded, pool_size=50, active=49" }这里tags是结构化字段,raw_message是原始告警,两者都保留。结构化的 tags 用于精准路由,raw_message 用于给 Claude 提供判断依据。
5.2 值班分诊核心代码
创建一个 Python 服务文件:
# 文件路径:oncall_bot/dispatcher.py import os import json from typing import Dict, Any from anthropic import Anthropic client = Anthropic() MODEL = os.getenv("ANTHROPIC_MODEL", "claude-sonnet-4-5") # 团队映射:Claude 输出的 team_key 到真实群/负责人 TEAM_ROUTE = { "order-core": "订单核心组", "payment-core": "支付核心组", "infra": "基础架构组", "data-platform": "数据平台组", } SYSTEM_PROMPT = """ 你是一个值班告警分诊助手。你会收到一条标准化告警,包含 tags 和 raw_message。 请根据告警信息,输出一个 JSON,包含以下字段: - severity: P0 / P1 / P2 / P3,P0 代表核心服务不可用 - team_key: 建议负责团队,必须从给定列表中选择 - root_cause_hint: 一句话根因猜测,中文,不超过30字 - summary: 给值班人的一句话中文摘要,不超过40字 要求: 1. 只能输出 JSON,不要输出其他内容。 2. team_key 必须从列表中选择:order-core, payment-core, infra,># 文件路径:oncall_bot/notifier.py import time from typing import Dict, Any def send_notification(alert_payload: Dict[str, Any], dispatch_result: Dict[str, Any]) -> None: """根据分诊结果发送通知。生产环境请替换为企业微信/钉钉/飞书 webhook。""" team_name = { "order-core": "订单核心组", "payment-core": "支付核心组", "infra": "基础架构组", "data-platform": "数据平台组", }.get(dispatch_result["team_key"], "基础架构组") message = ( f"[{dispatch_result['severity']}] {alert_payload['title']}\n" f"负责团队:{team_name}\n" f"根因猜测:{dispatch_result['root_cause_hint']}\n" f"摘要:{dispatch_result['summary']}\n" f"告警ID:{alert_payload['alert_id']}\n" ) # 生产环境:调用 webhook # webhook_url = os.getenv("ONCALL_WEBHOOK_URL") # requests.post(webhook_url, json={"msgtype": "text", "text": {"content": message}}) print(f"[notify] {time.strftime('%Y-%m-%d %H:%M:%S')}\n{message}") def execute_route(alert_payload: Dict[str, Any], dispatch_result: Dict[str, Any]) -> None: """执行路由:P0 必须人工确认,P1/P2 可以自动通知。""" severity = dispatch_result["severity"] if severity == "P0": # P0 只打印告警,不自动发送高优通知,等待人工确认 print(f"[P0-hold] 告警 {alert_payload['alert_id']} 需要人工确认后手动升级") send_notification(alert_payload, dispatch_result) else: send_notification(alert_payload, dispatch_result)这里刻意把 P0 做了人工确认的缓冲。自动化的第一步不是全程自动化,而是把 P1/P2 的初筛和通知做掉,P0 保留人在环路中。
5.4 主入口与模拟告警
最后写一个主入口,同时支持从文件读取告警和直接传 JSON:
# 文件路径:oncall_bot/main.py import json import sys from dispatcher import dispatch from notifier import execute_route def main(alert_payload: dict) -> None: print("=== 1. 原始告警 ===") print(json.dumps(alert_payload, ensure_ascii=False, indent=2)) print("\n=== 2. Claude 分诊结果 ===") result = dispatch(alert_payload) print(json.dumps(result, ensure_ascii=False, indent=2)) print("\n=== 3. 路由执行 ===") execute_route(alert_payload, result) if __name__ == "__main__": # 用法:python main.py alert.json if len(sys.argv) > 1: with open(sys.argv[1], "r", encoding="utf-8") as f: payload = json.load(f) else: payload = { "alert_id": "alert-20250218-001", "title": "order-svc 连接池超时", "tags": { "service": "order-svc", "env": "prod", "region": "cn-beijing", "severity": "P1", "team": "order-core", "alert_source": "prometheus" }, "raw_message": "Get \"http://order-svc:8080/health\": context deadline exceeded, pool_size=50, active=49" } main(payload)到这里,一个最小可跑的 Tag 驱动值班分诊机器人就完成了。
6. 运行结果与效果验证
6.1 运行命令
在项目目录下执行:
python oncall_bot/main.py由于主入口自带一个默认告警,可以直接看到完整流程。
6.2 预期输出
正常运行会看到三段输出。第一段是原始告警:
=== 1. 原始告警 === { "alert_id": "alert-20250218-001", "title": "order-svc 连接池超时", "tags": { "service": "order-svc", "env": "prod", "region": "cn-beijing", "severity": "P1", "team": "order-core", "alert_source": "prometheus" }, "raw_message": "Get \"http://order-svc:8080/health\": context deadline exceeded, pool_size=50, active=49" }第二段是 Claude 输出的分诊结果,类似:
=== 2. Claude 分诊结果 === { "severity": "P1", "team_key": "order-core", "root_cause_hint": "连接池耗尽,上游服务响应变慢", "summary": "order-svc 连接池接近占满,建议检查上游服务健康状态" }第三段是路由执行:
=== 3. 路由执行 === [notify] 2025-02-18 02:47:11 [P1] order-svc 连接池超时 负责团队:订单核心组 根因猜测:连接池耗尽,上游服务响应变慢 摘要:order-svc 连接池接近占满,建议检查上游服务健康状态 告警ID:alert-20250218-0016.3 如何判断是否成功
- 分诊结果中的
team_key与 Tag 中预置的team一致或合理。 - 输出的 JSON 能被
json.loads正常解析。 - 通知逻辑打印出了正确的团队名和摘要。
如果 Claude 输出解析失败,程序会走兜底逻辑,此时排查重点应放在提示词和模型输出格式上。
6.4 失败时的第一步排查
- 第一步:看 API 是否连通。直接跑
python scripts/test_api.py。 - 第二步:看模型输出原文。把
dispatcher.py里的raw_output打印出来,确认模型是否输出了多余文字。 - 第三步:看 Tag 是否有值。如果
service、env等字段为空,Claude 很难做准确判断。
7. 常见问题与排查方法
Claude Code 和 Anthropic API 在安装、接入和运行时,社区反馈比较多的坑集中在下面几类。我把它们整理成表格,方便直接对照排查。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
执行claude提示"不是内部或外部命令" / "无法将 claude 项识别为 cmdlet、函数、脚本文件" | Claude Code 未安装或未加入 PATH | 执行claude --version,检查安装目录 | 重新安装 Claude Code,并把可执行文件路径加入系统 PATH |
| 调用 API 时报 "unable to connect to anthropic services failed to connect to api.anthropic.com" | 部署环境网络无法访问 Anthropic 服务 | 用curl测试 api.anthropic.com 连通性 | 调整部署环境网络策略,确保可以访问 Anthropic 服务 |
| 返回 HTTP 529 | Anthropic 服务端过载或限流 | 查看响应头和错误码,确认是否为限流 | 在客户端实现指数退避重试,并考虑备用模型或降级策略 |
| 报错 "xxx is not a model this version of claude code recognizes" | 配置的模型名在当前版本不认识 | 用 Claude Code 的模型列表命令确认可用模型 | 修改模型名为账号实际可用的标识 |
| 登录或注册时提示 "unfortunately, claude is not available to new users right now" | 账号所在地区或时段受限,或注册通道拥挤 | 查看官方可用地区与公告,确认账号状态 | 按官方指引申请或等待开放,不推荐绕过限制的方式 |
| Claude 输出的 JSON 解析失败 | 模型输出了额外文字或 Markdown 代码块 | 打印 raw_output 查看原文 | 在提示词中强调"只输出 JSON",或对输出做后处理剥离代码块 |
这里特别提醒一点:**把 Claude Code 当作本地调试工具,把 Anthropic API 当作生产集成方式,是更合理的分工。**Claude Code 适合在开发机里交互排查问题,而值班分诊服务应该通过 API 调用,并做好重试、超时和降级。
8. 最佳实践与工程建议
8.1 Tag 设计规范
Tag 是这套系统的输入地基。我建议在团队内把 Tag 设计成"必选 + 可选"两层:
必选 Tag:
serviceenvseverityteam
可选 Tag:
regionalert_sourceversionowner
所有告警源只要上报,必须先补齐必选 Tag。缺 Tag 的告警直接进入"人工补录队列",不进入自动分诊链路。这个约束能保证 Claude 拿到的输入质量是稳定的。
8.2 提示词要固定,不要每次自由发挥
值班场景里,Claude 的判断稳定性比创造性更重要。因此:
- 系统提示词写好后,用一组历史告警做回归测试,确认分诊结果稳定。
- 不要在生产代码里随机改提示词。
- 提示词改动走 MR + 测试流程。
8.3 上下文压缩与 Token 控制
告警原文可能很长,尤其是带堆栈的日志告警。传给 Claude 的内容要做两层控制:
- 只截取 raw_message 前 2000 字符(代码里已经做了)。
- 如果告警附带完整堆栈,单独存到工单系统,不全部塞给模型。
这样既能控制成本,也能避免长文本干扰判断。
8.4 安全边界与最小权限
值班系统涉及通知、路由,甚至可能有自动变更能力。这里的安全边界必须提前划定:
- Claude 的 API Key使用独立账号,权限只到消息接口,不关联任何云平台变更权限。
- 通知动作只通过 webhook 发出,不授予模型直接调用运维工具的权限。
- 所有自动通知在测试环境验证过再上生产。
- P0 告警默认不自动升级,必须人工确认。
8.5 降级策略
大模型不可能永远可用。值班链路必须有一个不依赖 Claude 的降级路径:
- Claude 调用超时或失败时,直接按 Tag 里的
team路由,发原始告警给对应团队。 - 529 重试次数达到上限后,降级到"仅通知,不分析"。
- 准备一个纯规则的兜底脚本,保证 Claude 挂了,告警依然能到达值班人手里。
8.6 可观测告警链路本身
值班系统本身也是系统。建议对以下指标做监控:
- Claude 调用成功率。
- 分诊耗时分位数。
- JSON 解析失败率。
- 按 team_key 路由的告警数量分布。
这些指标能帮你发现"Claude 在悄悄躺平"的情况。比如解析失败率突然升高,很可能不是模型问题,而是提示词被误改或者告警输入格式变了。
9. 总结与后续学习方向
这套 "Claude Tag 驱动值班" 的方案,本质上是把值班链路中最耗时的"读告警、找负责人"环节,用"标准化 Tag + 大模型分诊"替代了。Tag 负责让输入结构化,Claude 负责从结构化输入中快速给出分诊建议,人只负责最后的确认和处置。
建议你下一步这样做:
- 先在测试环境用历史告警跑通示例代码,观察 Claude 的分类准确率。
- 根据你们的服务列表扩充 TEAM_ROUTE 映射。
- 接一个低优先级业务告警源,灰度验证一周,再逐步放开。
- 在值班复盘会上对比"接入前 vs 接入后"的分诊耗时数据。
如果想继续深入,可以研究这几个方向:把告警信息沉淀成向量库,让 Claude 做带历史记忆的根因分析;把 Claude Code 接进值班命令行,让值班人员通过自然语言快速查询告警上下文;或者把分诊结果同步回监控平台,让 Tag 得到反向补充。
最后提醒一句:AI 值班系统的目标不是把值班人换掉,而是让值班人在被叫醒时,手机上已经有一份"是什么、影响谁、猜什么原因、建议找谁"的摘要。真正决定值班体验的,不是模型有多聪明,而是告警链路从混乱到标准化的那一小步。