写了个 Skill 让 OpenClaw 自动查 AWS 账单,从此告别手动翻控制台
起因
事情是这样的。
我最近一直在用 OpenClaw 做工作自动化,用着挺爽。但有个需求它满足不了------我想让它每天自动查一下亚马逊云科技的账单,花超了就提醒我一声。
OpenClaw 自带了天气、网页摘要这些技能,但成本监控这种定制需求?不好意思,没有。
然后我发现 OpenClaw 有个叫 Skill 的扩展机制。简单来说,你写一个 Markdown 文件,告诉 AI 遇到某类问题该怎么做,它就"学会"了这个能力。
是的,就是 Markdown。不是 Python 包,不是 npm 模块,是一个 .md 文件。
当时我觉得有点不可思议,但试了一下发现真的能用。这篇文章就记录一下我从零写一个"AWS 成本监控"Skill 的过程,代码全部可以直接跑。
Skill 是什么
别把 Skill 想得太复杂。
一句话概括:Skill = 一份写给 AI Agent 的 SOP(标准操作流程)。
你在一个叫 SKILL.md 的文件里写清楚三件事:
- 什么时候触发(用户说了什么关键词)
- 具体做什么(执行哪个脚本、调用哪个 API)
- 输出什么(报告格式长什么样)
Agent 收到用户请求后,先扫描所有 Skill 的描述,看哪个匹配。匹配上了,读正文,照着做。就这么简单。
不需要编译,不需要注册,不需要重启。放到目录下,下次对话就生效。
目录结构
ruby
~/.openclaw/workspace/skills/aws-cost-monitor/
├── SKILL.md # 必需:告诉 Agent 干嘛
├── scripts/
│ └── check_cost.py # 可选:辅助脚本
└── references/
└── cost-explorer-notes.md # 可选:参考文档
只有 SKILL.md 是必需的,脚本和参考文档按需添加。
我的习惯是:能让 Agent 直接调工具完成的,就不写脚本。需要确定性输出的(比如 API 调用),才放到 scripts/ 下。
写 SKILL.md
这是核心,直接贴完整内容:
markdown
# AWS Cost Monitor
## Description
亚马逊云科技成本监控技能。自动查询当前账户的云资源费用,
生成成本报告,支持按服务维度拆分,超出预算时发送告警。
## Triggers
- 用户说"查一下我的 AWS 账单"
- 用户说"这个月花了多少钱"
- 用户说"AWS 成本报告"
- 用户说"看看云资源开销"
- 用户说"账单超了没"
- 用户说"查一下这个月的费用"
- 用户说"成本分析"
- 用户说"哪个服务花钱多"
## Steps
1. 读取并执行 scripts/check_cost.py 获取成本数据
2. 解析脚本输出的 JSON 格式数据
3. 按以下格式生成成本报告:
💰 亚马逊云科技成本报告 | YYYY-MM-DD
📅 统计周期:YYYY-MM-01 ~ YYYY-MM-DD 💵 本月累计费用:$XXX.XX
📊 按服务拆分(Top 5):
- Amazon EC2 --- $XX.XX
- Amazon S3 --- $XX.XX
- Amazon Bedrock --- $XX.XX
- Amazon RDS --- $XX.XX
- Amazon Lambda --- $XX.XX
📈 日均费用: <math xmlns="http://www.w3.org/1998/Math/MathML"> X . X X 📆预估月底总费用: X.XX 📆 预估月底总费用: </math>X.XX📆预估月底总费用:XXX.XX
bash
4. 如果预估月底总费用超过 $500(默认阈值),追加告警:
⚠️ 费用告警:预估本月总费用 <math xmlns="http://www.w3.org/1998/Math/MathML"> X X X . X X ,已超过预算阈值 XXX.XX,已超过预算阈值 </math>XXX.XX,已超过预算阈值500!
markdown
5. 如果用户指定了预算阈值,用指定值替代默认值
6. 将报告发送给用户
## Notes
- 需要本机已配置 AWS CLI 凭证
- 需要 IAM 权限:ce:GetCostAndUsage
- 费用数据有 24-48 小时延迟
- 默认查询当前月份
写 Triggers 的经验
这里分享一个我踩过的坑。
一开始我只写了"查 AWS 账单"和"成本报告"两个触发条件。结果用户换个说法------"这个月云上花了多少"------Agent 就不认了。
后来我把能想到的口语化表达都加上去了。Triggers 宁可多写几条,也不要少写。 Agent 的语义理解能力不错,但你把路铺好了,它走起来更稳。
写脚本:check_cost.py
这个脚本的活儿很简单:调 Cost Explorer API → 拿数据 → 输出 JSON。
python
#!/usr/bin/env python3
"""
AWS Cost Monitor --- 查询亚马逊云科技账户成本数据
依赖:boto3(pip install boto3)
权限:需要 IAM 策略 ce:GetCostAndUsage
"""
import json
import sys
from datetime import datetime, timedelta
import boto3
def get_month_range(year: int = 0, month: int = 0) -> tuple[str, str]:
"""获取指定月份的起止日期。"""
today = datetime.utcnow()
if year == 0 or month == 0:
year = today.year
month = today.month
start = f"{year:04d}-{month:02d}-01"
if month == 12:
end_date = datetime(year + 1, 1, 1)
else:
end_date = datetime(year, month + 1, 1)
# 当前月用明天作为 End(Cost Explorer 的 End 是排他的)
if year == today.year and month == today.month:
end_date = today + timedelta(days=1)
end = end_date.strftime("%Y-%m-%d")
return start, end
def query_total_cost(client, start: str, end: str) -> float:
"""查询总费用。"""
resp = client.get_cost_and_usage(
TimePeriod={"Start": start, "End": end},
Granularity="MONTHLY",
Metrics=["UnblendedCost"],
)
total = 0.0
for result in resp["ResultsByTime"]:
amount = result["Total"]["UnblendedCost"]["Amount"]
total += float(amount)
return round(total, 2)
def query_cost_by_service(client, start: str, end: str) -> list[dict]:
"""按服务维度查询费用。"""
resp = client.get_cost_and_usage(
TimePeriod={"Start": start, "End": end},
Granularity="MONTHLY",
Metrics=["UnblendedCost"],
GroupBy=[{"Type": "DIMENSION", "Key": "SERVICE"}],
)
services = {}
for result in resp["ResultsByTime"]:
for group in result["Groups"]:
name = group["Keys"][0]
amount = float(group["Metrics"]["UnblendedCost"]["Amount"])
services[name] = services.get(name, 0.0) + amount
sorted_services = sorted(
services.items(), key=lambda x: x[1], reverse=True
)
return [
{"service": name, "amount": round(amount, 2)}
for name, amount in sorted_services
if amount > 0.01
]
def estimate_monthly_total(total_so_far: float, start: str) -> float:
"""预估月底总费用。"""
today = datetime.utcnow()
start_date = datetime.strptime(start, "%Y-%m-%d")
days_passed = (today - start_date).days
if days_passed <= 0:
return total_so_far
if start_date.month == 12:
next_month = datetime(start_date.year + 1, 1, 1)
else:
next_month = datetime(start_date.year, start_date.month + 1, 1)
total_days = (next_month - start_date).days
daily_avg = total_so_far / days_passed
return round(daily_avg * total_days, 2)
def main():
"""主函数。"""
year, month = 0, 0
if len(sys.argv) >= 3:
year = int(sys.argv[1])
month = int(sys.argv[2])
start, end = get_month_range(year, month)
client = boto3.client("ce", region_name="us-east-1")
total = query_total_cost(client, start, end)
services = query_cost_by_service(client, start, end)
today = datetime.utcnow()
start_date = datetime.strptime(start, "%Y-%m-%d")
days_passed = (today - start_date).days
daily_avg = round(total / max(days_passed, 1), 2)
estimated_total = estimate_monthly_total(total, start)
result = {
"period": {"start": start, "end": end},
"total_cost": total,
"daily_average": daily_avg,
"estimated_monthly_total": estimated_total,
"days_passed": days_passed,
"top_services": services[:10],
"query_time": today.strftime("%Y-%m-%d %H:%M:%S UTC"),
}
print(json.dumps(result, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()
代码不长,核心就三个函数:
query_total_cost:查总费用query_cost_by_service:按服务拆分estimate_monthly_total:根据日均预估月底开销
安装 & 测试
放文件
bash
mkdir -p ~/.openclaw/workspace/skills/aws-cost-monitor/scripts
mkdir -p ~/.openclaw/workspace/skills/aws-cost-monitor/references
# 把三个文件分别放到对应位置,然后:
chmod +x ~/.openclaw/workspace/skills/aws-cost-monitor/scripts/check_cost.py
先手动测一下脚本
bash
pip install boto3
python3 ~/.openclaw/workspace/skills/aws-cost-monitor/scripts/check_cost.py
应该能看到一段 JSON 输出,包含费用数据。如果报错,大概率是 AWS 凭证没配(aws configure)或者 IAM 权限不够。
在 OpenClaw 里测
文件放好后不用重启。直接在 Slack 里说:
查一下我的 AWS 账单
Agent 应该能识别到 Skill 并执行。效果类似:
bash
💰 亚马逊云科技成本报告 | 2026-03-19
📅 统计周期:2026-03-01 ~ 2026-03-19
💵 本月累计费用:$127.35
📊 按服务拆分(Top 5):
1. Amazon EC2 --- $52.10
2. Amazon Bedrock --- $35.20
3. Amazon S3 --- $18.05
4. Amazon RDS --- $12.80
5. AWS Lambda --- $9.20
📈 日均费用:$6.70
📆 预估月底总费用:$207.70
看到这个输出的时候我挺开心的。从动手到跑通,前后不到一小时。
踩坑记录
分享几个我实际开发中碰到的问题。
坑 1:Cost Explorer 只认 us-east-1
这个坑了我大概二十分钟。脚本里 region_name 写的是 ap-northeast-1(因为我的资源大部分在东京),一直报错。后来查文档才发现 Cost Explorer API 只能通过 us-east-1 调用,和你的资源在哪个 Region 无关。
坑 2:End 日期是排他的
Cost Explorer 的 TimePeriod.End 是排他的,也就是说 End: "2026-03-19" 实际上查的是到 3 月 18 日的数据。要想包含今天,End 得写明天的日期。脚本里的 today + timedelta(days=1) 就是为了解决这个问题。
坑 3:数据延迟 24-48 小时
新账户或者刚开始产生费用的时候,可能查出来全是零。别以为脚本有 bug,等一两天数据就有了。
进阶玩法
定时巡检
在 OpenClaw 的 HEARTBEAT.md 里加一行:
markdown
- [ ] 每天早上 9:00(UTC+8),执行 AWS 成本监控,推送报告
Agent 心跳检查时会主动触发。
Skill 嵌套
如果你有个"飞书通知"Skill,可以在成本监控的 Steps 里引用它:
markdown
6. 费用超过阈值时,使用"飞书通知"Skill 发送告警到团队群
Agent 会自动串联两个 Skill。
和 Amazon Bedrock 配合
查完账单只是第一步。更进阶的玩法是把成本数据丢给 Amazon Bedrock,让它分析增长趋势、找出异常、给优化建议。在 Steps 里加一步就行:
markdown
7. 将成本数据发给 Amazon Bedrock 分析趋势和异常
我现在每天早上看到的不光是一堆数字,还有一段"这个月 EC2 比上月多了 30%,建议检查是否有闲置实例"之类的分析。挺有用的。
发布到 ClawHub
觉得自己写的 Skill 不错?可以发布到 ClawHub,让其他人也用上。
- 确保 SKILL.md 描述完整
- 脚本里别硬编码敏感信息
- 用打包工具生成
.skill文件 - 提交到 ClawHub
社区共建,少造轮子。
最后
整个 Skill 开发体验用两个字形容:丝滑。
写 Markdown,放到目录下,对话触发。从有想法到跑通,不到一小时。这种"写文档就是写插件"的感觉,我还是头一次体验到。
如果你也在用亚马逊云科技,每次查账单都要手动登控制台,试试这个方案。或者你有其他重复性的任务想自动化,OpenClaw 的 Skill 机制值得一试。
你打算用 Skill 自动化什么?评论区聊聊 💬