如果你所在的团队正在用 Claude 或 Claude Code 做日常开发,甚至已经把模型接进了告警处理链路,那么“值班”(on-call)这个场景迟早会出现在你面前:凌晨 3 点,群里告警刷屏,值班工程师一边开日志系统,一边翻监控面板,一边试图从聊天记录里找到上一次类似故障是怎么处理的。整个过程高度依赖人的经验,而经验恰恰是最难复制、最容易在半夜断档的东西。
这篇文章要聊的,不是“让 AI 自动修复所有故障”这种空话,而是一个更现实的工程主题:如何用 Claude 的语言理解能力,加上一套合理的 Tag 标签体系,把值班场景里的告警分类、原因分析、处理建议和通知路由串成一条可落地、可回滚、可追溯的流水线。
我的判断是:Claude Tag 驱动值班的本质,不是让模型替人做决策,而是让模型在“非结构化告警”和“结构化标签路由”之间架起一座桥。模型负责把一条混乱的告警整理成有明确标签、有初步判断、有建议动作的结构化事件,后面的通知、指派、升级、归档,全部交给标签去驱动。这套思路既不玄学,也不依赖某个特定产品,完全可以用 Claude API、Claude Code 和最常见的 Webhook 自己搭出来。
1. 值班到底难在哪里:先搞清楚要解决的问题
很多团队把值班问题简单理解为“告警太多”。实际上,告警多只是表象,真正让人崩溃的是下面三件事。
第一,分类成本高。一条告警进来,值班工程师要先判断它属于哪个服务、哪个环境、什么级别、影响面多大,然后才能决定要不要叫醒别人。这个“判断”过程在白天可能只要几分钟,但在凌晨、在多个告警同时到达时,非常容易出错。
第二,上下文丢失严重。每个告警背后都有一堆关联信息:最近的发布记录、依赖服务的状态、类似的工单历史、相关负责人的排班表。这些东西分散在多个系统里,值班人员不可能在几分钟内全部捞出来。
第三,交接成本高。白班和夜班交接时,夜班处理到一半的事件,白班要重新读一遍上下文才能接手。如果处理记录只是一段口头总结,信息损耗会很大。
Claude 或 Claude Code 能切入的,正是“分类成本高”和“上下文丢失严重”这两块。模型擅长把一段堆栈日志、一屏监控图表描述、一坨关键词,整理成可读性高的结构化结论。而 Tag 标签体系负责解决“交接成本高”:只要事件被打上了统一规范的标签,后续的人、机器、工单系统就能基于标签快速理解发生了什么,不需要重新把原始日志读一遍。
换句话说:值班的痛点不是缺一个“聪明的大脑”,而是缺一个“能把脏活快速干完,并留下干净结构化产物的入口”。Claude 做入口,Tag 做产物,这是这套方案的核心判断。
2. 什么是 Claude Tag:不是一个产品,而是一套工作流
在动手之前,先澄清一个概念。严格来说,“Claude Tag”并没有一个标准的官方独立产品名称。在社区讨论里,它通常有两种理解:
一种理解是Claude Code 的 Agent Skills 机制。Claude Code 通过SKILL.md文件向模型暴露一组能力,文件头部有一段 YAML frontmatter,包含name、description等字段。这些字段本质上就是“标签”,模型会根据当前任务的描述,自动匹配最合适的技能。技能的识别与触发,靠的正是这段结构化标签。
另一种理解是我们在值班系统里自建的标签路由体系。我们自己设计一套 tag 规范,比如:
service: prod-api env: production severity: critical team: platform-oncall source: errbot这些标签不负责“理解”,只负责“路由”。当 Claude 把一条原始告警分析完毕,输出一组规范标签后,后续的 Webhook 通知、工单创建、值班组指派就全部由标签驱动。
两种理解合在一起,才是完整的答案:Claude Code 的 Skill 标签让模型知道“该用哪套处理能力”,业务系统的 Tag 标签让机器知道“该把这起事件送到哪里”。一个管模型侧的行为选择,一个管业务侧的路由分发。
所以,这篇文章里的“Claude Tag”,我定义为:以 Claude 模型能力为核心,以结构化标签为驱动,用来自动化值班告警处理的一整套工作流。它不绑定单一工具,你可以用 Claude API,也可以用 Claude Code,甚至可以在两者之间切换。
3. 值班场景里的核心概念:告警、标签、路由、知识库
要搭这套系统,需要先理解几个基础概念。这里我用值班场景的视角重新解释一遍。
3.1 告警(Alert)
告警是系统的“疼痛信号”。它可能是一条 Prometheus 规则触发的消息,可能是日志系统里的一个关键字,也可能是用户报障工单的自动摘要。原始告警通常是非结构化的,比如:“prod-api 错误率超过 5%,大量 529,上游连接超时。” 这条信息里其实包含了很多信息,但人眼要逐字解析。
3.2 标签(Tag)
标签是给告警事件做结构化标注的键值对。设计标签时,尽量遵守两个原则:
- 有限集合:每个字段的可选值尽量固定,避免同一含义多种写法。例如
severity只允许critical、warning、info三种。 - 可枚举、可扩展:
service字段可以随服务数量增长,但枚举值应该在部署时统一注册,而不是临时造出来。
标签不是给人看的,是给机器看的。只要标签规范,后续路由、统计、检索都顺理成章。
3.3 路由(Routing)
路由是根据标签把事件分发到目标位置的规则。比如:
| 标签条件 | 分发目标 |
|---|---|
severity: critical且env: production | 电话 + 值班群 @所有人 |
service: payment-api | 支付专项群 |
source: user-report | 客服工单系统 |
路由规则最好独立成配置文件,不要写死在代码里。这样值班人员不需要改代码,也能调整通知策略。
3.4 知识库(Knowledge Base)
知识库是值班经验的沉淀。值班最痛苦的是“这个问题以前处理过,但现在想不起来”。好的做法是把历史工单、处理步骤、复盘文档整理成语义化的知识条目,并打上标签。Claude 在生成处理建议时,可以通过检索召回相关历史案例,让建议更贴合团队实际情况。
这里再补充一个容易误区的点:知识库不一定要上向量数据库。如果团队规模不大,先按标签管理 Markdown 文档,用 Claude 的上下文能力加载足矣。上了复杂基础设施但内容没更新,反而是负担。
4. 环境准备与前置条件
在开始写代码前,先把环境准备好。本文示例同时涉及 Python 和 Claude Code,建议按下面的方式准备。
4.1 基础环境
- 操作系统:macOS / Linux / Windows(WSL 或原生终端均可)
- Python 3.10 及以上(版本请以实际环境为准)
- Node.js:官方推荐通过 npm 安装 Claude Code,建议使用当前的 LTS 及以上版本
- 一个可用的 Anthropic API Key;如果使用 Claude Code,还需要完成身份认证
4.2 安装依赖
使用 Python 调用 Claude API,安装官方 SDK:
pip install anthropic安装 Claude Code 命令行工具:
npm install -g @anthropic-ai/claude-code安装完成后,验证版本:
claude --version如果提示 “claude 不是内部或外部命令”,通常是两个原因:npm 全局安装目录不在PATH中,或者安装没有真正完成。可以先执行:
npm config get prefix然后把对应 bin 目录加入PATH。
4.3 配置密钥与环境变量
推荐通过环境变量传递 API Key,避免硬编码到代码里:
export ANTHROPIC_API_KEY=sk-ant-xxxxx export ANTHROPIC_MODEL=claude-3-7-sonnet-latest注意:ANTHROPIC_MODEL这个变量在不同版本的 Claude Code 里行为不一定一致,具体以官方文档和当前版本支持为准。如果接入第三方兼容接口,还需要设置ANTHROPIC_BASE_URL,这时容易出现本文后面要讲的 “model not recognized” 问题。
export ANTHROPIC_BASE_URL=https://your-gateway.example.com到这里,环境就准备好了。
5. 最小闭环一:用 Claude API 给告警打标签并生成值班建议
我们先从最简单的闭环开始:写一个 Python 脚本,接收一条原始告警文本,调用 Claude API,输出结构化 JSON。JSON 中包含模型推断出的标签、告警摘要、初步处理建议。
5.1 代码实现
# 文件路径:oncall_tagger.py import json import os from anthropic import Anthropic client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"]) SYSTEM_PROMPT = """ 你是一个值班告警分析助手。 你的任务: 1. 分析用户输入的原始告警文本。 2. 输出一个 JSON 对象,字段如下: - summary: 一句话告警摘要 - tags: 对象,包含 service、env、severity、category 四个字段 - service: 告警涉及的服务名,未知则填 unknown - env: 环境,可选 production / staging / dev / unknown - severity: 可选 critical / warning / info / unknown - category: 可选 latency / error-rate / saturation / dependency / other - suggestion: 给值班人员的处理建议,不超过 80 字 3. 只输出 JSON,不要输出任何解释。 """ def analyze_alarm(alarm_text: str) -> dict: response = client.messages.create( model=os.getenv("ANTHROPIC_MODEL", "claude-3-7-sonnet-latest"), max_tokens=1024, system=SYSTEM_PROMPT, messages=[ {"role": "user", "content": alarm_text} ], ) text = response.content[0].text return json.loads(text) if __name__ == "__main__": sample_alarm = """ [严重告警] prod-api 错误率超过 5% 服务: prod-api 环境: production 时间: 2025-06-01 03:12:00 UTC 日志摘要: 大量 529 状态码,上游连接超时,MySQL 慢查询明显增加 """ result = analyze_alarm(sample_alarm) print(json.dumps(result, ensure_ascii=False, indent=2))5.2 关键逻辑解释
这个示例的要点并不在代码本身,而在于SYSTEM_PROMPT的设计。
- 明确告诉模型“只输出 JSON”,避免解析失败。
- 规定标签的可选值,把模型的自由度限制在固定集合内,保证下游路由逻辑稳定。
- 要求输出
suggestion,给值班人员一个最初步的排查方向,而不是让模型自由发挥长篇大论。
5.3 为什么不直接用正则或规则引擎
有人会问:既然标签集合是固定的,直接用正则匹配 529、MySQL、错误率这几个关键词,不是更省钱、更快吗?
答案是:规则引擎适合“你完全知道要匹配什么”的场景,而告警文本的表达方式千奇百怪。比如 “上游连接超时”可能写成 “upstream timeout”,也可能写成 “read timed out”;可能来自日志告警,也可能来自用户报障。规则系统在这种多样性面前会变得又臭又长,而 Claude 这类模型的优势正是处理这些不规则的表达。
但要注意:规则引擎并不需要被完全替代。一个务实的架构是,先用简单规则做一个预分类,把能确定标签的告警直接路由,只把规则无法判定的部分交给 Claude。这样既省成本,又保留覆盖能力。
6. 最小闭环二:用 Claude Code Skill 打造值班诊断技能
如果说上一步是“API 调用”,那么 Claude Code 带来的是一种交互方式的变化:你不再需要自己维护一个 Python 脚本的输入输出格式,而是直接让 Claude Code 在工作区里读取日志、运行命令、查看文件,然后基于这些真实信息给出诊断。
Claude Code 的 Agent Skills 机制非常适合这个场景。我们可以创建一个自定义 Skill,让模型在值班任务中自动加载指定的诊断流程。
6.1 创建 Skill 文件
# 文件路径:.claude/skills/oncall-triage/SKILL.md --- name: oncall-triage description: 用于值班告警分析。当用户提供一条告警、一个日志文件路径或一段错误信息时,使用该技能进行快速定位与分级。 allowed-tools: Bash, Read, Glob, Grep --- # Oncall Triage 当收到告警分析请求时,按以下流程执行: 1. 读取用户提供的告警内容,提取 service、env、severity 标签。 2. 如果用户给出日志文件路径,使用 Read 或 Grep 定位关键错误片段。 3. 使用 Bash 执行只读排查命令,例如查看进程状态、网络连接情况、最近日志尾部。 4. 禁止执行任何变更类命令,包括重启、删除、修改配置。 5. 输出格式: - 结论摘要 - 标签:service / env / severity / category - 处理建议:分步骤,每步尽可能给出具体命令6.2 为什么 Skill 的 description 也是一种 Tag
在 Claude Code 中,模型不是把所有 Skill 都加载进来,而是根据用户请求的描述去匹配。匹配的依据正是 frontmatter 里的name和description。这就相当于模型侧也有一个“标签路由”:描述写得越清晰,模型越能在正确的场景里调用正确的技能。
这个细节提醒我们:写 Skill 的 description 要像给接口写文档一样认真,把触发条件、典型场景写清楚,不要写空话。比如 “用于值班告警分析” 就比 “一个工具集合” 有用得多,因为它包含了触发信号。
6.3 在终端里使用
保存 Skill 后,进入项目目录,运行:
claude然后输入:
请分析 tmp/error.log 中的告警信息,按 oncall-triage 技能输出结果。Claude Code 会读取当前目录下的.claude/skills/oncall-triage/SKILL.md,按其中的流程执行,并输出结构化结论。
这里有一个很容易踩的坑:Skill 文件必须放在当前工作区可访问的目录下,否则模型无法加载。如果你换了项目目录,技能不会自动生效。
7. 最小闭环三:把标签变成路由规则,对接通知与工单
前两步解决的是“分析和打标”,这一步解决“标签之后怎么办”。核心是写一个 Webhook 服务:接收告警 -> 调用 Claude 分析 -> 根据标签命中路由规则 -> 发送通知或创建工单。
7.1 路由规则配置
# 文件路径:oncall_routing.yaml rules: - match: severity: critical env: production target: type: webhook url: https://hooks.example.com/oncall-urgent message_template: "【严重】{summary} 请立即处理" - match: category: dependency target: type: webhook url: https://hooks.example.com/dependency-group message_template: "【依赖故障】{summary}" - match: service: payment-api target: type: ticket system: jira message_template: "自动创建工单:{summary}"路由规则的核心思想是精确匹配 + 兜底。如果拿不准要不要写复杂的匹配语法,就先从最确定的规则开始。
7.2 Webhook 服务实现
# 文件路径:oncall_webhook.py import json import os import yaml from flask import Flask, request, jsonify from oncall_tagger import analyze_alarm app = Flask(__name__) with open("oncall_routing.yaml", "r", encoding="utf-8") as f: ROUTING_RULES = yaml.safe_load(f)["rules"] def send_webhook(url: str, payload: dict): # 生产环境建议用 httpx 或 requests,并加上超时和重试 print(f"模拟发送 webhook 到 {url}:{json.dumps(payload, ensure_ascii=False)}") def match_rule(tags: dict): for rule in ROUTING_RULES: match = rule["match"] if all(tags.get(k) == v for k, v in match.items()): return rule return None @app.post("/alarm") def handle_alarm(): data = request.get_json(force=True) raw_alarm = data.get("alarm_text", "") # 1. Claude 打标签 try: analyzed = analyze_alarm(raw_alarm) except Exception as exc: # 模型调用失败时,降级为兜底标签,保证告警不丢 analyzed = { "summary": raw_alarm[:200], "tags": {"service": "unknown", "env": "unknown", "severity": "unknown", "category": "unknown"}, "suggestion": f"模型调用失败,请人工介入。错误:{exc}", } # 2. 标签路由 rule = match_rule(analyzed["tags"]) if rule: target = rule["target"] message = rule["message_template"].format(summary=analyzed["summary"]) send_webhook(target["url"], {"text": message}) else: print("未命中路由规则,进入默认队列") # 3. 返回结构化结果 return jsonify(analyzed), 200 if __name__ == "__main__": app.run(host="0.0.0.0", port=8000)7.3 为什么降级逻辑很重要
在代码里,我专门加了一个try-except块。这是值班系统里最容易忽略、却最重要的一点:AI 可以挂,但告警必须到达人类手里。
如果 Claude API 超时、限流或者网络不通,我们宁可打一个unknown标签把消息发出去,也不能把告警卡在系统里。AI 是值班链路上的一个加速器,不应该成为单点故障。
所以推荐的做法是:接入 AI 分析时,永远保留一条“不经过 AI”的原始告警通道。AI 分析结果只是一个增强字段,而不是前置条件。
8. 运行结果与效果验证
写代码只是第一步,更重要的是知道“它到底有没有生效”。
8.1 本地运行验证
先启动 Webhook 服务:
python oncall_webhook.py然后向接口发送一条测试告警:
curl -X POST http://localhost:8000/alarm \ -H "Content-Type: application/json" \ -d '{"alarm_text": "[严重告警] prod-api 错误率超过 5%,大量 529 状态码,上游连接超时"}'预期会在控制台看到类似输出:
{ "summary": "prod-api 生产环境错误率超过 5%,主要因上游连接超时导致大量 529", "tags": { "service": "prod-api", "env": "production", "severity": "critical", "category": "dependency" }, "suggestion": "先查看上游服务状态,确认数据库慢查询是否影响整体响应;若上游恢复,观察错误率是否回落。" }如果这个结果里的标签符合你的预期,并且路由规则成功命中,说明闭环已经打通。
8.2 效果验证的三个阶段
不要只看一次输出就认为成功,建议按以下阶段持续验证:
- 阶段一:离线回放。挑选最近两周的真实告警记录,用脚本批量运行打标程序,统计标签命中率。
- 阶段二:影子模式。把 Claude 分析结果接入值班群,但只作为参考,不直接驱动通知,观察是否出现明显误判。
- 阶段三:在线路由。确认准确率足够后,再让标签真正驱动通知和工单。
如果运行后没有按预期输出,第一步先检查ANTHROPIC_API_KEY是否正确,第二步看接口返回的 HTTP 状态码和错误 body,不要直接改代码。
9. 常见问题与排查思路
9.1 问题排查表
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| claude 命令找不到 | npm 全局目录不在 PATH 中 | 执行npm config get prefix,检查 bin 目录 | 把 bin 目录加入 PATH |
| API 返回 529 | Anthropic 服务端负载过高或限流 | 查看响应头和错误码,确认是否触发限流 | 增加重试和指数退避;错峰调用 |
| 无法连接到 Anthropic 服务 | 网络策略、代理或 API 地址配置错误 | 检查ANTHROPIC_BASE_URL和网络连通性 | 修正网关地址,确保网络可达 |
| model not recognized | 模型名在当前版本不支持,或接入第三方模型时未匹配 | 对比官方可用模型列表,确认版本 | 更换为受支持的模型名称 |
标签输出不稳定,一会是production,一会是prod | 提示词标签枚举约束不够严格 | 查看原始输出,确认 JSON 字段值 | 在提示词中明确枚举值,并在代码层做白名单映射 |
| Claude 调用超时,导致告警堆积 | 单条告警文本过长,或 API 响应太慢 | 查看服务日志中的耗时统计 | 截断告警文本;引入队列异步处理 |
| 同一个告警重复通知 | Webhook 重试逻辑设计不当 | 检查接口幂等性 | 为告警事件生成唯一 ID,通知端做去重 |
9.2 两个容易踩的坑
第一个坑是提示词写得太开放。如果你让模型“给一个合理的 severity”,它可能给出high、P1、严重各种写法。这会导致路由规则永远匹配不上。解决办法就是反复强调枚举值,并在代码层做最后的校验。
第二个坑是安全边界没有划清楚。Claude Code 在执行诊断时,如果被赋予了执行命令的权限,它理论上可以执行外部可见的变更命令。所以在 Skill 的配置和实际使用时,都要明确设限:只允许只读命令,禁止自动变更。值班场景的第一原则是“不扩大故障”,宁可慢一点,也不能让自动化把生产环境搞得更糟。
10. 最佳实践与工程建议
到这里,你已经有能力搭出一条最小链路。但想真正在李值班场景里稳定运行,还需要关注下面几个工程问题。
10.1 标签体系是前置条件,不是后置优化
任何 AI 都救不了一个没有标签体系的团队。上线 Claude 之前,先把服务名、环境、级别、来源这些字段的枚举值梳理清楚。标签体系不要追求大而全,能够覆盖 80% 的场景就够了,剩下的用unknown兜底,等数据积累后再补充。
10.2 模型只做减负,不做决策闭环
不要一开始就设计“机器自动修复”。更稳妥的路径是:Claude 负责分析,标签负责路由,人负责最终变更。等运行一段时间,积累了足够多“标签 -> 动作 -> 结果”的数据后,再考虑对极低风险的动作做自动化,比如自动发送通知、自动创建工单。涉及重启服务、修改配置、删数据等操作,一律保持人工审批。
10.3 成本控制要提前想
告警量大的时候,每条都调用大模型是一笔不小的开销。从成本角度,可以做三层过滤:
- 第一层:利用 Prometheus 的告警规则,合并重复告警,减少无效输入。
- 第二层:用正则或关键词做预分类,规则能判定的不交给模型。
- 第三层:再交给 Claude 处理真正复杂、规则无法判断的告警。
10.4 保留审计与重放能力
每一次模型输出、每一条路由结果,都应该落到日志系统。这不仅是审计需要,也是未来优化提示词和标签规则的数据来源。建议至少记录:原始告警、模型输出、命中规则、通知结果、人工后续处理结论。有了这批数据,你可以定期重放历史告警,测试新提示词的效果。
10.5 敏感信息与数据边界
告警文本里经常包含 IP、用户名、SQL 片段、甚至部分业务数据。在把告警发送到模型之前,要做脱敏处理,并明确哪些数据允许出内网。如果合规要求严格,可以考虑私有化部署或使用本地模型网关转发。这是上生产环境前必须和安全和法务确认的问题,不是技术细节。
11. 总结与后续学习方向
用 Claude Tag 的思路驱动值班,核心价值不是“让 AI 写一份漂亮的告警分析”,而是把告警处理从“人肉读日志 -> 人肉回忆 -> 人肉找下游”变成“模型读日志 -> 模型打标签 -> 标签自动路由”。从工程视角看,这是一个用自然语言模型重构复杂任务入口,再交给确定性系统去执行的过程。Claude 的强项是处理非结构化、模糊、多义的告警文本;Tag 的强项是让后续流程稳定、可控、可统计。两个东西搭配起来,才能形成一条真正的自动化链路。
如果你想进一步深入,建议按下面的顺序实践:
- 先在自己的测试项目里建好
.claude/skills/oncall-triage/SKILL.md,用历史日志跑通 Claude Code 诊断流程。 - 再用 Python 脚本把历史告警离线跑一遍,验证标签准确率,建立自己的基线数据。
- 等准确率达到团队可接受范围后,再接入 Webhook 路由,并用影子模式观察一段时间。
- 最后把审计日志跑起来,每周回看一次模型输出,持续调整提示词和标签枚举。
值班系统的建设从来不是“上一个 AI 就完事”,而是一个把经验固化为数据、把数据转化为规则、再让规则和模型协作的长期过程。先从最小闭环开始,跑起来,你就已经比大多数还在凌晨手动翻日志的团队,往前走了一大步。