
去年年末,当我第N次在深夜改需求文档时,突然意识到一个问题:现有的AI助手都太"乖"了。它们总是彬彬有礼地告诉你"我理解您的 frustration",但打工人真正需要的,可能是一个能陪你一起骂甲方、然后顺便把吐槽内容改写成哲学论文的赛博知己。
腾讯推出了QClaw(人称"小龙虾AI")。这个基于OpenClaw生态的本地化Agent平台最吸引我的点在于:它支持微信直连+本地Skill开发,意味着我可以把各种脑洞大开的自动化场景做成可复用的技能包,而且数据完全不出本地。
于是,我花了两个周末,基于QClaw开发了三个"邪修"Agent:一个会把职场黑话转化为存在主义哲学的情绪垃圾桶、一个专门推荐"理论上能吃"的暗黑料理的厨房化学家,以及一个通过社死压力倒逼自律的睡眠督察员。
直达 qclaw
在动手写代码之前,我们需要先搞定基础环境。相比OpenClaw需要手动配置Node.js、Python环境和各种API Key的繁琐流程,QClaw的安装体验堪称"傻瓜式"——但这不意味着我们可以跳过对架构的理解。
QClaw采用"本地客户端+微信远程"的双层架构。简单来说,你的电脑运行着一个轻量级的Agent Runtime(基于OpenClaw内核改造),它通过加密通道与腾讯的微信服务桥接。这意味着:
组件层级 | 功能定位 | 数据流向 | 安全边界 |
|---|---|---|---|
微信接入层 | 指令接收与结果推送 | 手机↔腾讯服务器 | 仅传输指令文本 |
QClaw Runtime | 任务调度与Skill执行 | 本地电脑运行 | 文件/数据不出本地 |
Skill生态层 | 具体业务逻辑实现 | 本地沙箱执行 | 敏感操作需授权 |
访问 https://qclaw.qq.com/ 下载对应系统的安装包。这里有个坑:如果你是macOS用户,在Apple Silicon芯片上运行时,需要在"系统设置-隐私与安全性"中手动允许辅助功能权限,否则后续的文件操作Skill会报权限错误。

安装完成后,首次启动会要求绑定微信。建议用一个工作微信扫码,因为后面的"睡眠拖延对抗Agent"需要给好友发消息,用自己的主号可能会造成不必要的社死。

接下来是模型配置。QClaw内置了Kimi、MiniMax、GLM等国产大模型,内测期间免费。但对于我们的"情绪垃圾桶"和"暗黑料理"场景,我建议在设置中切换到自定义模型,接入DeepSeek-R1或Claude 3.5 Sonnet,因为这两个场景对模型的创意生成能力要求较高,需要更强的"胡说八道"功底(划掉)创意发散能力。

这个Agent的诞生源于一个具体的痛点:某周一早上,我收到了产品经理发来的第8版需求变更,其中有一句"我们要在保持极简的同时增加功能的丰富度"。在传统的情绪管理理论中,我应该深呼吸、喝口水、理性沟通。但实际上,我只想对着空气来一段单口相声。
于是,EmoBin(情绪垃圾桶) 的设计目标很明确:
功能模块 | 输入 | 处理逻辑 | 输出 |
|---|---|---|---|
毒舌接收 | 用户的纯文本吐槽 | 情感分析+脏话过滤 | 确认接收情绪 |
哲学升华 | 标记为"philosophy" | 提取核心矛盾→映射存在主义/后现代理论 | 300字哲学短文 |
Rap转化 | 标记为"rap" | 识别韵脚→套用Flow结构→添加Punchline | 带标注的verse |
在QClaw中,一个Skill本质上是包含SKILL.md(元数据定义)和若干工具脚本的目录。我们在~/.qclaw/skills/emobin/下创建如下结构:

emobin/
├── SKILL.md # Skill的元数据与触发词定义
├── main.py # 主逻辑处理
├── philosophy.py # 哲学升华模块
├── rap_generator.py # Rap生成模块
└── config.json # 配置文件SKILL.md 是QClaw识别Skill的核心文件,它需要定义触发条件和参数解析规则:
# EmoBin - 情绪垃圾桶与内容升华器
## 描述
接收用户的职场/生活吐槽,将其转化为哲学思考或Rap歌词,实现情绪宣泄与素材积累的双重价值。
## 触发词
- "吐槽" / "骂" / "烦死了" → 进入接收模式
- "升华一下" / "哲学模式" → 调用philosophy.py
- "来段rap" / "diss一下" → 调用rap_generator.py
- "保存到素材库" → 将内容追加到本地markdown文件
## 参数
- content: 用户的原始吐槽内容(必需)
- mode: 处理模式,可选"philosophy"或"rap"(默认philosophy)
- intensity: 毒舌强度等级1-5(用于Rap生成时的攻击性调节)
## 示例
用户输入:"吐槽 这个需求又要改,产品经理是不是觉得时间不是成本? 模式:rap 强度:4"现在来看main.py的实现。QClaw的Python SDK封装了本地文件操作和LLM调用接口,我们可以直接通过@qclaw.tool()装饰器将Python函数暴露为Agent可调用的工具。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
EmoBin - 情绪垃圾桶主模块
基于QClaw SDK v1.x开发
"""
import json
import os
from datetime import datetime
from typing import Literal
import qclaw
from qclaw import Context, Tool
# 初始化上下文
ctx = Context()
class EmoBinProcessor:
def __init__(self):
self.storage_path = os.path.expanduser("~/Documents/EmoBin/")
self.ensure_storage()
def ensure_storage(self):
"""确保存储目录存在"""
if not os.path.exists(self.storage_path):
os.makedirs(self.storage_path)
# 创建素材库主文件
with open(f"{self.storage_path}/materials.md", "w", encoding="utf-8") as f:
f.write("# 情绪素材库\n\n> 自动收集的吐槽与升华内容\n\n")
@Tool(description="分析用户情绪强度并分类")
def analyze_emotion(self, content: str) -> dict:
"""
使用本地LLM分析情绪类型与强度
QClaw会自动路由到配置的模型(DeepSeek/Claude等)
"""
prompt = f"""
分析以下吐槽文本的情绪特征:
文本:"{content}"
请返回JSON格式:
{{
"emotion_type": "anger/frustration/sarcasm/resignation",
"intensity": 1-5,
"keywords": ["关键词1", "关键词2"],
"core_conflict": "核心矛盾总结(10字以内)"
}}
"""
# 调用QClaw封装的本地LLM接口
response = ctx.llm.complete(prompt, temperature=0.3, json_mode=True)
return json.loads(response.text)
@Tool(description="将吐槽内容转化为哲学思考")
def to_philosophy(self, content: str, emotion_data: dict) -> str:
"""
哲学升华模块:将职场黑话映射到存在主义/后现代理论
"""
philosophy_prompt = f"""
你是一位精通存在主义、后现代主义、法兰克福学派的哲学教授。
请将以下职场吐槽转化为严肃的哲学论述(300-400字):
原始吐槽:{content}
核心矛盾:{emotion_data['core_conflict']}
要求:
1. 引用至少一位哲学家(海德格尔/萨特/福柯/鲍德里亚等)
2. 使用学术化的黑话体系(异化、规训、景观社会、单向度的人等)
3. 保持原文的核心诉求,但包装成"现代性困境"的批判
4. 结尾要有升华:从个人抱怨上升到人类普遍处境
风格参考:让·鲍德里亚《消费社会》的批判语调 + 微博哲学bot的犀利感
"""
result = ctx.llm.complete(philosophy_prompt, temperature=0.8)
return result.text
@Tool(description="将吐槽转化为Rap歌词")
def to_rap(self, content: str, intensity: int, emotion_data: dict) -> str:
"""
Rap生成模块:带Flow标注的说唱词创作
"""
flow_styles = {
1: "Jazz Boombap, 慵懒叙事",
2: "Trap, 稳定八拍",
3: "Drill, 急促进鼓",
4: "Hardcore, 双韵脚快嘴",
5: "Death Grips式工业噪音流, 无规则Flow"
}
rap_prompt = f"""
你是一位underground battle MC。请将以下职场吐槽改写为Rap Verse(16-20 bars):
原始素材:{content}
攻击强度:{intensity}/5
推荐Flow:{flow_styles.get(intensity, "Trap")}
创作要求:
1. 每句用[ ]标注Flow技巧(如[停顿]、[三连音]、[加速])
2. 使用多音节韵脚(multi-syllable rhymes)
3. Punchline要狠但保持隐喻(避免直接脏话)
4. 加入Ad-libs(如"skr"、"ey")标注
5. 最后4 bars要有反转(从抱怨转向自我赋权)
输出格式:
[Intro: 情绪氛围描述]
[Verse 1]
歌词行1 [Flow技巧]
...
[Outro]
"""
result = ctx.llm.complete(rap_prompt, temperature=0.9)
return result.text
@Tool(description="保存内容到本地素材库")
def save_to_vault(self, original: str, processed: str, mode: str):
"""
持久化存储到本地markdown
QClaw确保所有文件操作在本地沙箱内完成
"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
entry = f"""
## {timestamp} | {mode.upper()}模式
**原始吐槽:**
> {original}
**升华内容:**
{processed}
---
"""
vault_path = f"{self.storage_path}/materials.md"
# 使用QClaw的安全文件操作API
ctx.file.append(vault_path, entry, encoding="utf-8")
return {"status": "saved", "path": vault_path, "timestamp": timestamp}
# 实例化处理器
processor = EmoBinProcessor()
@qclaw.on_message()
def handle_message(content: str, mode: Literal["philosophy", "rap"] = "philosophy", intensity: int = 3):
"""
QClaw消息入口函数
当用户在微信发送"吐槽 xxx"时被触发
"""
try:
# 1. 情绪分析
ctx.send_typing() # 发送"对方正在输入"状态到微信
emotion_data = processor.analyze_emotion(content)
# 2. 根据模式处理
if mode == "philosophy":
result = processor.to_philosophy(content, emotion_data)
title = "🧠 哲学升华版"
else:
result = processor.to_rap(content, intensity, emotion_data)
title = "🎤 Rap Battle版"
# 3. 自动保存(可选)
save_result = processor.save_to_vault(content, result, mode)
# 4. 构造返回消息
reply = f"""
{title}
{result}
---
💾 已自动保存至素材库 | 情绪强度:{'⭐' * emotion_data['intensity']}
📝 核心矛盾:{emotion_data['core_conflict']}
"""
return reply
except Exception as e:
return f"❌ 情绪处理失败:{str(e)}\n建议:尝试降低毒性或使用更隐喻的表达方式"
if __name__ == "__main__":
# 本地测试入口
test_content = "这个需求又要改第八版,产品经理是不是觉得时间不是成本?"
print(handle_message(test_content, mode="rap", intensity=4))

将上述文件保存到~/.qclaw/skills/emobin/后,在QClaw客户端的"技能广场"点击"刷新本地Skills",即可看到EmoBin卡片。点击启用后,我们在微信中测试:

输入:吐槽 周末又要加班改PPT,老板说要"对齐颗粒度",我怀疑他根本不知道这个词什么意思 模式:哲学 强度:5
Agent返回:


电脑端:

看着这段文字,我突然觉得加班也没那么惨了——毕竟我已经用资本主义的批判理论武装了自己,这波不亏。
如果说EmoBin解决的是精神需求,那么DarkChef(暗黑料理生成器)瞄准的就是物理生存需求。每个租房打工人都经历过这样的场景:周五晚上打开冰箱,发现只剩下半个洋葱、两颗鸡蛋和一盒过期一天的酸奶。外卖软件上,配送费比食材还贵。
传统的美食App在这种情况下基本没用,它们会告诉你"缺少关键食材,无法生成菜谱"。但DarkChef的核心哲学是:只要毒不死,就是新菜系。
这个Skill的难点在于"毒性评估"——我们需要建立一个食材搭配的禁忌知识库。不能真的把用户送进医院。我在config.json中定义了安全规则:
{
"dangerous_combos": [
{
"ingredients": ["螃蟹", "柿子"],
"level": 5,
"reason": "鞣酸与蛋白质结合导致胃结石",
"absolute_forbidden": true
},
{
"ingredients": ["蜂蜜", "洋葱"],
"level": 3,
"reason": "轻微氧化反应,可能导致腹泻",
"absolute_forbidden": false
}
],
"toxicity_scale": {
"1": "完全安全,只是口味猎奇",
"2": "肠胃敏感者可能不适",
"3": "建议准备健胃消食片",
"4": "需要签订自愿参与协议",
"5": "生化危机级别,严禁尝试"
}
}dark_chef.py的核心是约束满足问题(CSP)求解。我们需要在"不购买新食材"的硬约束下,最大化"猎奇指数"同时确保"生存概率>90%"。
#!/usr/bin/env python3
"""
DarkChef - 暗黑料理生成器
基于QClaw的食材剩余管理与黑暗料理推荐系统
"""
import random
import json
from dataclasses import dataclass
from typing import List, Tuple
import qclaw
from qclaw import Tool, Context
ctx = Context()
@dataclass
class Recipe:
name: str
ingredients: List[str]
steps: List[str]
toxicity_level: int # 1-5星
flavor_profile: str
survival_tips: str
class DarkChefEngine:
def __init__(self):
self.config = self._load_config()
self.cooking_methods = [
"爆炒", "乱炖", "微波加热", "空气炸锅",
"搅拌机打成泥", "跨界fusion", "分子料理手法"
]
def _load_config(self):
skill_path = ctx.skill.get_path() # 获取当前Skill目录
with open(f"{skill_path}/config.json", "r", encoding="utf-8") as f:
return json.load(f)
def check_safety(self, ingredients: List[str]) -> Tuple[int, str]:
"""
检查食材组合的安全性
返回:(毒性等级, 警告信息)
"""
max_level = 1
warnings = []
for danger in self.config["dangerous_combos"]:
if all(ing in ingredients for ing in danger["ingredients"]):
if danger["absolute_forbidden"]:
return 5, f"🚫 致命组合:{'+'.join(danger['ingredients'])} - {danger['reason']}"
max_level = max(max_level, danger["level"])
warnings.append(f"⚠️ {danger['reason']}")
return max_level, "; ".join(warnings) if warnings else "✅ 理论上不会致死"
@Tool(description="根据剩余食材生成暗黑料理方案")
def generate_recipe(self, ingredients: str, mood: str = "绝望") -> Recipe:
"""
主生成函数
ingredients: 逗号分隔的食材列表,如"鸡蛋,酸奶,老干妈"
mood: 当前心情,影响料理疯狂程度
"""
ing_list = [i.strip() for i in ingredients.split(",")]
# 1. 安全检查
base_toxicity, warning = self.check_safety(ing_list)
# 2. 如果检测到致命组合,直接拒绝
if base_toxicity == 5:
return Recipe(
name="生化危机预防协议",
ingredients=ing_list,
steps=["立即停止", "分开存放", "点外卖"],
toxicity_level=5,
flavor_profile="活着真好",
survival_tips="请不要尝试任何组合"
)
# 3. 调用LLM生成创意菜谱
prompt = f"""
你是一位疯癫的米其林黑暗料理主厨,擅长用奇怪的食材组合创造"理论上能吃"的食物。
剩余食材:{', '.join(ing_list)}
当前心情:{mood}(影响疯狂程度)
安全警告:{warning}
请生成一个料理方案,要求:
1. 菜名要有meme感或哲学隐喻
2. 烹饪步骤必须包含至少一个"邪门"操作(如"用咖啡机煮方便面")
3. 口味描述要用通感修辞(如"像失恋的周二下午")
4. 给出具体的毒性自评(1-5星)和生存建议
返回格式:
菜名:xxx
难度:⭐⭐⭐
毒性:⭐⭐({base_toxicity}星基准)
风味档案:xxx
步骤:
1. xxx
2. xxx
生存贴士:xxx
"""
response = ctx.llm.complete(prompt, temperature=0.95)
parsed = self._parse_recipe(response.text, ing_list, base_toxicity)
# 4. 自动记录到"生存日志"
self._log_attempt(parsed)
return parsed
def _parse_recipe(self, text: str, ingredients: List[str], base_toxicity: int) -> Recipe:
"""解析LLM返回的文本为结构化数据"""
lines = text.strip().split("\n")
name = lines[0].replace("菜名:", "").strip() if lines else "无名暗黑料理"
steps = []
survival = "无"
in_steps = False
for line in lines:
if line.startswith("步骤:"):
in_steps = True
continue
if in_steps and line.strip():
if line.startswith("生存贴士:"):
survival = line.replace("生存贴士:", "").strip()
break
steps.append(line.strip())
# 动态调整毒性:如果LLM给出的描述很可怕,加1星
toxicity_keywords = ["喷射", "住院", "洗胃", "幻觉"]
bonus = 1 if any(k in text for k in toxicity_keywords) else 0
final_toxicity = min(5, base_toxicity + bonus)
return Recipe(
name=name,
ingredients=ingredients,
steps=steps,
toxicity_level=final_toxicity,
flavor_profile="猎奇向",
survival_tips=survival
)
def _log_attempt(self, recipe: Recipe):
"""记录到本地生存日志,用于后续优化"""
log_entry = {
"timestamp": ctx.time.now(),
"recipe": recipe.name,
"toxicity": recipe.toxicity_level,
"ingredients": recipe.ingredients
}
log_path = f"{ctx.skill.get_path()}/survival_log.jsonl"
ctx.file.append(log_path, json.dumps(log_entry, ensure_ascii=False) + "\n")
# 初始化引擎
chef = DarkChefEngine()
@qclaw.on_message()
def cook(ingredients: str, style: str = "fusion"):
"""
QClaw入口:用户发送"今晚吃什么 鸡蛋,酸奶,老干妈"
"""
try:
recipe = chef.generate_recipe(ingredients)
# 构造可视化输出
toxicity_stars = "⭐" * recipe.toxicity_level + "☆" * (5 - recipe.toxicity_level)
danger_level = ["绿色:可食用", "黄色:勇士专属", "橙色:肠胃挑战", "红色:生死状", "黑色:遗书预备"][recipe.toxicity_level - 1]
reply = f"""
🍳 【{recipe.name}】
━━━━━━━━━━━━━━━━━━━━
🧪 食材:{' + '.join(recipe.ingredients)}
⚗️ 毒性评估:{toxicity_stars} ({danger_level})
🎭 风味:{recipe.flavor_profile}
👨🍳 烹饪步骤:
{chr(10).join(f" {i+1}. {step}" for i, step in enumerate(recipe.steps))}
💊 生存贴士:{recipe.survival_tips}
━━━━━━━━━━━━━━━━━━━━
⚠️ 免责声明:本菜谱由AI生成,QClaw及开发者不对任何肠胃不适负责
"""
# 如果毒性过高,追加安全警告
if recipe.toxicity_level >= 4:
reply += "\n🚨 警告:检测到高危险操作,建议拍照留念后再食用"
return reply
except Exception as e:
return f"厨房爆炸了:{str(e)}\n建议:还是点麦当劳吧"
@qclaw.scheduled(cron="0 18 * * 5") # 每周五晚6点自动提醒
def friday_survival_check():
"""
定时任务:周五晚上检查冰箱并推送建议
QClaw支持Cron表达式定时触发
"""
# 这里可以接入智能冰箱API或让用户提前拍照OCR
# 简化版:随机推荐一个"周五特调"
backup_ingredients = ["剩米饭", "鸡蛋", "辣酱", "可乐"]
recipe = chef.generate_recipe(",".join(backup_ingredients), mood="周末前的绝望")
return f"""
🍽️ 周五生存指南自动推送
检测到您可能面临"不知道吃什么"的 existential crisis。
推荐方案:{recipe.name}
毒性:{'⭐' * recipe.toxicity_level}
输入"查看详情"获取完整菜谱,或输入"外卖"放弃治疗。
"""
上周实测时,我的冰箱里正好有:半根胡萝卜、 yesterday's 披萨、一罐啤酒、两个鸡蛋。

输入:今晚吃什么 胡萝卜,剩披萨,啤酒,鸡蛋
DarkChef返回:


说实话,这道菜的味道介于"还能吃"和"我是谁我在哪"之间,但确实解决了我周五晚上的生存危机。更重要的是,这个过程中我完全没有打开外卖App,省下了30块配送费——这就是Agent带来的"降本增效"(物理意义上)。
这是三个项目中最"邪门"的一个。SleepGuard(睡眠督察员)基于一个简单的心理学原理:损失厌恶(Loss Aversion)。当我们面临"损失50元"的风险时,规避损失的动机强度是"获得50元"的两倍。
传统的睡眠App只能提醒你"该睡了",但你可以无视它。SleepGuard的做法是:如果你不在设定时间内回复验证消息,它会自动给你的微信好友发送"我熬夜了,请罚我50块"的社死认证。
这个Skill涉及定时任务+微信消息发送,是QClaw中权限要求最高的操作。需要在SKILL.md中明确声明权限需求:
## 权限声明
- schedule: 需要创建定时任务
- notification: 需要发送系统通知
- wechat: 需要发送微信消息(仅向指定好友)
- file: 需要读写本地睡眠日志
## 安全机制
- 所有消息发送需用户预先配置"监督人"白名单
- 每日最多发送1条惩罚消息,避免骚扰
- 提供"紧急取消"指令(睡前5分钟内有效)#!/usr/bin/env python3
"""
SleepGuard - 睡眠拖延对抗系统
通过社交压力与经济损失预期倒逼自律
"""
import json
import time
from datetime import datetime, timedelta
from typing import List
import qclaw
from qclaw import Tool, Context, scheduler
ctx = Context()
class SleepGuardian:
def __init__(self):
self.config_path = f"{ctx.skill.get_path()}/sleep_config.json"
self.state_path = f"{ctx.skill.get_path()}/sleep_state.json"
self.load_config()
def load_config(self):
"""加载用户配置"""
try:
with open(self.config_path, "r", encoding="utf-8") as f:
self.config = json.load(f)
except FileNotFoundError:
# 默认配置
self.config = {
"bedtime": "23:30",
"supervisors": [], # 监督人微信ID列表
"fine_amount": 50,
"challenge_msg": "我如果1小时内不回消息就给你转{amount}块",
"grace_period_minutes": 5
}
self.save_config()
def save_config(self):
with open(self.config_path, "w", encoding="utf-8") as f:
json.dump(self.config, f, ensure_ascii=False, indent=2)
@Tool(description="设置睡眠监督参数")
def setup(self, bedtime: str, supervisors: List[str], fine: int = 50):
"""
初始化配置
bedtime: "HH:MM"格式
supervisors: 监督人微信昵称或备注名列表
"""
self.config.update({
"bedtime": bedtime,
"supervisors": supervisors,
"fine_amount": fine
})
self.save_config()
# 注册定时任务:在睡前15分钟发送预警
bedtime_dt = datetime.strptime(bedtime, "%H:%M")
warning_time = (bedtime_dt - timedelta(minutes=15)).strftime("%H:%M")
scheduler.daily(warning_time, self.send_bedtime_warning)
scheduler.daily(bedtime, self.initiate_sleep_challenge)
return f"""
🛡️ 睡眠监督系统已激活
⏰ 就寝时间:{bedtime}
👥 监督人:{', '.join(supervisors)}
💰 违约罚金:{fine}元
⚠️ 系统将在每天{warning_time}发送预警,{bedtime}启动挑战协议
"""
@Tool(description="发送睡前预警")
def send_bedtime_warning(self):
"""睡前15分钟提醒"""
ctx.notification.send(
title="🌙 睡眠预警",
body=f"还有15分钟就{self.config['bedtime']}了,请准备进入睡眠模式。关闭手机或回复'准备睡觉'以取消挑战。",
urgency="high"
)
return "预警已发送"
@Tool(description="启动睡眠挑战协议")
def initiate_sleep_challenge(self):
"""
核心逻辑:发送社死挑战消息给监督人
"""
# 检查是否已经标记为已睡
state = self.get_today_state()
if state.get("status") == "sleeping":
return "用户已确认入睡,跳过挑战"
# 构造挑战消息
challenge = self.config["challenge_msg"].format(
amount=self.config["fine_amount"]
)
full_msg = f"""
【SleepGuard自动消息】
我是{ctx.user.name}的AI睡眠督察员。
{challenge}
时间戳:{datetime.now().strftime("%H:%M:%S")}
如{self.config['grace_period_minutes']}分钟内未收到回复,视为违约。
(此消息由QClaw自动发送,用于睡眠习惯养成)
"""
# 发送给所有监督人
sent_count = 0
for supervisor in self.config["supervisors"]:
try:
ctx.wechat.send_message(
to=supervisor,
content=full_msg,
confirm=True # 需要二次确认,防止滥用
)
sent_count += 1
except Exception as e:
ctx.log.error(f"发送给{supervisor}失败: {e}")
# 更新状态
self.update_state("challenge_sent", datetime.now().isoformat())
# 设置延迟检查任务
scheduler.once(
delay_minutes=self.config["grace_period_minutes'],
task=self.check_challenge_result
)
return f"挑战已发送给{sent_count}位监督人,{self.config['grace_period_minutes']}分钟后检查回复状态"
@Tool(description="检查挑战结果并执行惩罚")
def check_challenge_result(self):
"""
检查用户是否在规定时间内回复
如果没有,发送"社死确认"消息
"""
state = self.get_today_state()
if state.get("replied_in_time"):
return "用户已及时回复,挑战通过"
# 用户未回复,发送社死升级消息
shame_msg = f"""
【SleepGuard违约通知】
时间:{datetime.now().strftime("%H:%M")}
状态:{ctx.user.name}未在规定时间内证明已入睡
处罚:请监督执行{self.config['fine_amount']}元转账
备注:熬夜伤身,金钱伤心,望周知 🌚
"""
for supervisor in self.config["supervisors"]:
ctx.wechat.send_message(supervisor, shame_msg)
# 记录违约
self.log_violation()
return "违约处理完成"
@Tool(description="用户回复验证")
def verify_sleep(self, reply_code: str = ""):
"""
用户收到挑战后回复此指令
"""
state = self.get_today_state()
if state.get("status") != "challenge_sent":
return "当前没有待处理的睡眠挑战"
# 检查时间是否在宽限期内
challenge_time = datetime.fromisoformat(state["challenge_time"])
if datetime.now() - challenge_time > timedelta(minutes=self.config["grace_period_minutes"]):
return "⏰ 超时!宽限期已过,违约记录已生成"
self.update_state("replied_in_time", True)
self.update_state("status", "sleeping")
# 通知监督人解除警报
for sup in self.config["supervisors"]:
ctx.wechat.send_message(sup, f"✅ {ctx.user.name}已确认进入睡眠模式,今晚的社死危机解除")
return "🎉 验证成功!祝你好梦。明早见。"
def get_today_state(self):
"""获取今日状态"""
try:
with open(self.state_path, "r") as f:
all_states = json.load(f)
today = datetime.now().strftime("%Y-%m-%d")
return all_states.get(today, {})
except:
return {}
def update_state(self, key, value):
"""更新状态"""
today = datetime.now().strftime("%Y-%m-%d")
try:
with open(self.state_path, "r") as f:
all_states = json.load(f)
except:
all_states = {}
if today not in all_states:
all_states[today] = {}
all_states[today][key] = value
with open(self.state_path, "w") as f:
json.dump(all_states, f)
def log_violation(self):
"""记录违约历史"""
log_path = f"{ctx.skill.get_path()}/violations.jsonl"
entry = {
"date": datetime.now().isoformat(),
"amount": self.config["fine_amount"],
"supervisors_count": len(self.config["supervisors"])
}
ctx.file.append(log_path, json.dumps(entry) + "\n")
# 初始化
guardian = SleepGuardian()
@qclaw.on_message()
def handle_sleep_cmd(command: str, *args):
"""
命令分发
支持:
- "设置睡眠 23:30 监督人A,监督人B 50"
- "准备睡觉"(验证回复)
- "查看违约记录"
"""
if command.startswith("设置睡眠"):
# 解析:设置睡眠 HH:MM 监督人列表 金额
parts = command.split()
if len(parts) < 3:
return "格式错误。示例:设置睡眠 23:30 张三,李四 50"
time_str = parts[1]
supervisors = parts[2].split(",")
fine = int(parts[3]) if len(parts) > 3 else 50
return guardian.setup(time_str, supervisors, fine)
elif "睡觉" in command or "睡了" in command:
return guardian.verify_sleep()
elif "违约" in command:
# 简单统计
log_path = f"{ctx.skill.get_path()}/violations.jsonl"
try:
with open(log_path, "r") as f:
lines = f.readlines()
total = len(lines)
total_fine = sum(json.loads(l)["amount"] for l in lines)
return f"📊 历史违约{total}次,累计应罚{total_fine}元(赶紧给监督人转账吧)"
except:
return "暂无违约记录,继续保持!"
else:
return "可用指令:\n1. 设置睡眠 [时间] [监督人] [金额]\n2. 准备睡觉(收到挑战后回复)\n3. 查看违约记录"
if __name__ == "__main__":
# 测试设置
print(guardian.setup("23:30", ["TestUser"], 50))



设置了我的室友和一位关系铁的同事作为监督人,罚金设定为50元。第一周的数据如下:
日期 | 挑战结果 | 就寝时间 | 备注 |
|---|---|---|---|
3/25 | ✅ 成功 | 23:28 | 收到挑战后立刻回复,避免社死 |
3/26 | ✅ 成功 | 23:15 | 提前入睡,系统未触发挑战 |
3/27 | ❌ 违约 | 00:15 | 打游戏忘记时间,触发社死广播 |
3/28 | ✅ 成功 | 23:35 | 室友收到违约消息后加强了监督 |
3月27日的违约事件尤其值得记录。当时我在打《艾尔登法环》,完全没看微信。结果23:45时,我的手机疯狂震动——室友在群里@我:"睡了吗?没睡的话50块先转给我?"同事也发来一个"?"。那一刻的羞耻感,比任何睡眠App的提醒都管用。


通过这三个项目,我深刻体会到QClaw作为本地化Agent平台的独特价值。它不仅仅是一个"能聊天的AI",而是一个真正可以调用本地资源、执行本地任务、管理本地数据的操作系统扩展。
项目 | 核心技术点 | QClaw能力依赖 | 实用性评级 |
|---|---|---|---|
EmoBin | Prompt工程+文本生成 | LLM路由、文件持久化 | ⭐⭐⭐⭐ |
DarkChef | 知识库检索+创意生成 | 结构化输出、定时任务 | ⭐⭐⭐ |
SleepGuard | 状态机+社交触发 | 微信消息、Cron调度、权限管理 | ⭐⭐⭐⭐⭐ |
当然,这些"邪修"用法也提醒我们:Agent的伦理边界需要开发者自己把握。SleepGuard的社死机制虽然有效,但如果滥用,可能会对人际关系造成真实伤害。因此我在代码中加入了"每日限额"和"紧急取消"机制——技术应该服务于人,而不是成为社交暴力的工具。
2026年被很多人称为"Agent元年",但真正让技术落地的,往往不是宏大的叙事,而是这些能解决具体痛点、甚至带点幽默感的"小工具"。当AI学会"发疯",当代码懂得"社死",或许这才是人机共生的正确打开方式。
毕竟,能让一个打工人既发泄了情绪、又吃上了晚饭、还早睡了半小时的AI,才是好AI。
参考资料与链接:
免责声明:DarkChef生成的菜谱仅供娱乐;SleepGuard造成的友谊破裂开发者概不负责;EmoBin生成的哲学内容请自行承担责任。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。