调用外部 API 与工具失败处理
Skill 不仅限于本地文件和命令——通过 WebFetch、Bash 中的 curl/httpx,或者已配置的 MCP 工具,它可以调用外部 API。这带来了强大的能力,也带来了新的失败场景需要处理。
调用外部 API 的三种方式
方式一:WebFetch 工具(只读 HTTP 请求)
适合获取公开的 API 响应、文档页面、GitHub API 等:
## 执行步骤
1. 使用 WebFetch 工具获取当前包的最新版本信息:
- URL:`https://registry.npmjs.org/{package-name}/latest`
- 方法:GET
- 提取响应中的 `version` 字段
2. 与 `package.json` 中的当前版本对比:
- 如果有新版本可用:记录为建议更新项
- 如果是最新版本:标记为通过
限制:WebFetch 只支持 GET 请求,不支持携带认证 header 或 POST body。如需认证,使用 Bash + curl。
方式二:Bash + curl(完整 HTTP 请求)
## 执行步骤
1. 调用 GitHub API 获取 PR 信息:
使用 Bash 工具运行:
```bash
curl -s \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}"
```
注意:
- `$GITHUB_TOKEN` 来自环境变量,Skill 文件中不要硬编码 token
- 如果 curl 失败(网络错误)或返回非 200 状态码,记录错误并跳过此步骤
- 如果返回 401,提示用户设置 `GITHUB_TOKEN` 环境变量
方式三:MCP 工具(推荐用于常用外部服务)
如果团队已配置了 MCP 工具(如 mcp-github、mcp-notion),可以在 Skill 中直接使用:
## 执行步骤
1. 使用 mcp-github 工具获取 PR 详情:
- 工具:`get_pull_request`
- 参数:`{ "owner": "...", "repo": "...", "pull_number": N }`
2. 使用 mcp-notion 工具创建审查记录:
- 工具:`create_page`
- 参数:`{ "parent": { "database_id": "..." }, "properties": {...} }`
MCP 工具封装了认证和错误处理,比直接 curl 更可靠。
外部 API 调用的安全原则
原则一:不在 Skill 文件中硬编码凭证
# ❌ 绝对不要这样写
使用以下命令:
curl -H "Authorization: Bearer ghp_AbCdEf123456..." ...
# ✅ 正确方式:引用环境变量
使用以下命令:
curl -H "Authorization: Bearer $GITHUB_TOKEN" ...
在 Skill 开头验证环境变量是否已设置:
如果 `$GITHUB_TOKEN` 未设置(通过 `echo $GITHUB_TOKEN` 验证为空),
停止并提示:
❌ 错误:GITHUB_TOKEN 环境变量未设置
请运行:export GITHUB_TOKEN=
原则二:验证 API 返回的内容
## 执行步骤
2. 解析 GitHub API 返回的 JSON:
- 验证响应是有效的 JSON(不是错误页面 HTML)
- 验证关键字段存在(`title`、`body`、`changed_files` 等)
- 如果字段缺失,降级处理(使用可用的字段,标记缺失的部分)
原则三:限制请求速率和范围
## 执行步骤
3. 批量获取文件内容时:
- 最多并行/串行请求 10 个文件(避免触发 API 速率限制)
- 如果文件列表超过 10 个,优先处理最近修改的文件,并提示"由于数量限制,仅分析前 10 个文件"
工具调用失败的处理模式
模式一:快速失败(重要操作失败即终止)
2. 读取 `.env.production` 配置文件:
- 如果读取失败(文件不存在或权限不足):
立即终止,输出:
```
❌ 部署检查中止:无法读取 .env.production
这是必要的配置文件,缺少它无法确认部署安全性。
请确认文件存在且有读取权限。
```
模式二:降级处理(非关键操作失败时跳过)
5. 尝试获取 npm 包的漏洞信息(需要网络连接):
- 运行 `npm audit --json 2>&1`
- 如果网络不可用或命令失败:
- 记录"⚠️ npm audit 检查跳过(网络不可用)"
- 继续其余检查步骤(不要因为一个可选检查失败而中断整个流程)
模式三:重试(瞬时网络错误)
3. 调用外部 API 获取依赖漏洞数据库:
最多重试 3 次(每次间隔 2 秒):
```bash
for i in 1 2 3; do
response=$(curl -s --max-time 10 "https://api.example.com/vulnerabilities")
[ $? -eq 0 ] && break
echo "第 $i 次请求失败,等待 2 秒后重试..."
sleep 2
done
```
如果 3 次全部失败:记录为警告,跳过此检查。
模式四:部分结果处理
4. 分析 50 个依赖包的安全状态:
- 对每个包发送请求,收集所有结果
- 即使部分请求失败,也要输出已成功获取的结果
- 在报告末尾标注:"{N} 个包因网络错误未能完成检查"
完整示例:dependency-check Skill(带完整失败处理)
---
description: 检查项目依赖的安全漏洞和过期版本
allowed-tools: Bash, Read, WebFetch
---
# 依赖安全检查
## 目标
检查当前项目的 npm 依赖是否有已知安全漏洞和严重过期的版本。
## 执行步骤
### 步骤 1:验证环境
使用 Bash 工具验证:
- 运行 `node --version`,如果失败,终止并提示"需要 Node.js 环境"
- 运行 `npm --version`,如果失败,终止并提示"需要 npm"
- 检查当前目录是否存在 `package.json`(Read 工具),如果不存在,终止
### 步骤 2:获取本地依赖信息
使用 Read 工具读取 `package.json`,提取:
- `dependencies` 中的包和版本
- `devDependencies` 中的包和版本(标记为开发依赖)
如果读取失败(权限问题等),终止并报告错误。
### 步骤 3:运行 npm audit
使用 Bash 工具运行:
```bash
npm audit --json 2>&1
处理结果: - 退出码 0(无漏洞):漏洞数为 0,继续步骤 4 - 退出码 1(有漏洞):npm audit 在有漏洞时正常返回 1,解析 JSON 输出 - 其他退出码或非 JSON 输出:记录"npm audit 执行异常,跳过漏洞检查",继续步骤 4
从 JSON 输出中提取:
- vulnerabilities 对象中各严重级别(critical/high/moderate/low)的数量
- 受影响的包名称
步骤 4:检查过期版本(网络可选)
尝试使用 Bash 工具运行:
npm outdated --json 2>&1
- 如果成功:提取严重过期的包(版本差距 > 2 个主版本)
- 如果失败(包括网络问题):跳过,标记"⚠️ 版本检查跳过"
步骤 5:生成报告
汇总步骤 3 和步骤 4 的结果。
输出格式
## 依赖安全检查报告
**检查时间**:[时间]
**依赖数量**:{N} 个生产依赖,{M} 个开发依赖
### 安全漏洞
| 严重性 | 数量 | 影响的包 |
|--------|------|---------|
| 🔴 Critical | N | 包名列表 |
| 🟠 High | N | 包名列表 |
| 🟡 Moderate | N | 包名列表 |
| 🟢 Low | N | 包名列表 |
### 严重过期版本(跨主版本)
- `{package}`: {当前版本} → {最新版本}(⚠️ 跨 N 个主版本)
### 结论
[✅ 无已知安全漏洞] 或
[❌ 发现 N 个高危漏洞,建议立即更新:`npm audit fix`]
```
本节记录清单
- [ ] 识别你的 Skill 中所有涉及网络请求的步骤
- [ ] 为每个 API 调用添加失败处理逻辑(快速失败 vs 降级 vs 重试)
- [ ] 确认所有 API 凭证通过环境变量传入,不硬编码在 Skill 文件中
- [ ] 测试网络断开时 Skill 的行为(是否优雅降级?)
下一章:Skill 的权限、配置与 CLAUDE.md——你的 Skill 能做什么、不能做什么,由权限配置决定。如何用 settings.json 和 CLAUDE.md 建立安全边界?