1. 项目概述与核心价值
最近在折腾AI智能体,发现了一个挺有意思的项目叫OpenClaw。它本质上是一个多通道的AI智能体网关,但它的设计哲学很独特——用Markdown文件来定义智能体的“人格”、“记忆”和“行为”,然后让智能体自主地在多个渠道(比如Telegram、Slack)上运行和交互。这听起来很酷,对吧?但原版OpenClaw需要一个常驻的网关服务器,包含Web UI和一堆依赖,对于只想跑个定时任务、收个Telegram通知、顺便管理一下AI记忆的场景来说,有点杀鸡用牛刀了。
于是,就有了这个叫openclaw-cc的项目。它的目标很明确:用最轻量的方式,复现OpenClaw的核心设计理念,但去掉所有“重”的东西。具体来说,它只依赖三样东西:Node.js 22+、Claude Code的命令行工具claude -p,以及一个Telegram Bot Token。没有网关,没有Web界面,没有外部依赖,就是一个纯粹的、可以扔到服务器后台跑的脚本。它的核心价值在于,让你能快速搭建一个拥有“长期记忆”和“个性化人格”的自主AI助手,专门处理那些需要持续关注和定期汇报的任务,比如系统健康检查、每日简报、项目进度跟踪等等。
我花了一些时间深入研究并实践了这个项目,发现它特别适合两类人:一是喜欢折腾、希望完全掌控AI智能体底层逻辑的开发者;二是那些有明确自动化需求,但不想维护复杂基础设施的个人或小团队。接下来,我会详细拆解它的架构、核心功能,并分享从零搭建到实际运行的全过程,以及我踩过的一些坑和总结的经验。
2. 核心架构与设计哲学拆解
要理解openclaw-cc,必须先吃透它的设计哲学。这不仅仅是“又一个AI脚本”,而是一套经过深思熟虑的、用于构建可靠自主智能体的方法论。
2.1 三层架构:调度、执行与投递的彻底分离
这是项目稳健性的基石。很多简单的脚本喜欢把所有逻辑写在一个文件里,调度、调用AI、发送结果都在同一个循环里。这带来的问题是,一旦AI调用超时或网络波动,整个进程可能卡死,或者消息发送失败后无法重试。
openclaw-cc采用了清晰的三层分离:
- Cron调度层:只负责“什么时候该做什么事”。它读取
jobs.json配置文件,根据every(间隔)或at(定时)规则,在内存中用setTimeout安排任务。它的职责单一且纯粹,不关心任务具体怎么执行,也不关心结果发到哪里。 - Agent执行层:这是智能体的“大脑”。调度层触发后,它会接管任务。其核心工作是调用
claude -p,但在此之前,它会做大量准备工作:根据任务类型加载对应的Markdown工作区文件,组装成系统提示词,管理会话状态,确保AI是在正确的“上下文”和“人格”下进行思考。 - Delivery投递层:这是智能体的“手和嘴”。执行层产生输出后,如果不是
NO_REPLY,就会把消息放入一个持久化的投递队列。这个队列具备原子写入、文件锁和重试机制,确保即使进程在发送消息时崩溃,重启后也能继续尝试发送,直到成功或进入死信队列。
这种分离的好处是显而易见的:每一层都可以独立失败而不影响其他层。调度器挂了,重启后任务会重新安排;AI调用失败,可以记录日志而不阻塞队列;发送消息失败,队列会不断重试。整个系统的容错性大大增强。
2.2 Markdown即配置:人格与记忆的文本化
这是OpenClaw最精髓、也是openclaw-cc完全复现的理念。我们不再需要去编辑复杂的JSON或YAML配置文件来定义AI的行为。相反,一切都在可读性极强的Markdown文件中完成。
- 人格定义:
SOUL.md里写的是智能体的核心行为准则,比如“你是一个谨慎、高效的助手,在确认前不执行任何有风险的操作”。IDENTITY.md定义它的名字和角色,比如“DevOps助手Charlie”。 - 用户上下文:
USER.md是关于“你”的信息,你的名字、时区、偏好、正在进行的项目。这让AI的回复更具个性化。 - 记忆系统:记忆不是存在某个黑盒数据库里,而是以日记的形式写在
memory/YYYY-MM-DD.md文件中。今天的记忆、昨天的记忆,都会被自动加载给AI。长期的、重要的经验教训,则可以手动或自动整理进MEMORY.md。这种设计让智能体的“记忆”对开发者完全透明,你可以随时查看、编辑,甚至用文本工具去分析。
这种“文本优先”的方法,极大地降低了维护和调试的心智负担。你想知道AI为什么那么回复?直接去翻看它当时读到的记忆文件就行了。你想调整它的性格?直接编辑SOUL.md。
2.3 NO_REPLY模式:对抗通知疲劳的利器
这是我认为最实用的设计模式之一。我们设置定时任务,比如“每小时检查一次服务器状态”。大多数时候,服务器状态是正常的。如果一个脚本傻乎乎地每次检查都说“一切正常”,你的Telegram很快就会被垃圾信息淹没。
openclaw-cc引入了NO_REPLY模式。你在给AI的任务描述里可以明确写:“如果一切正常,请回复NO_REPLY”。当执行层收到这个特定输出时,它不会将任何内容传递给投递层,从而完全抑制这次通知。只有当出现异常、需要你关注时,AI才会生成真正的消息内容并发出来。这保证了每一次推送都是有信息量的,真正做到了“无事不扰”。
2.4 无网关设计:直连的简洁与可控
原版OpenClaw的网关是一个功能强大的中间层,负责认证、路由、管理所有通道连接。但对于很多个人使用场景,特别是主要使用Telegram Bot的场景,这个网关显得过于复杂。
openclaw-cc选择了直接调用Telegram Bot API。发送消息就是一段HTTPfetch请求;接收消息则通过Bot API的getUpdates长轮询实现。这样做的好处是:
- 零依赖:不需要维护一个额外的服务进程。
- 部署简单:就是一个Node.js脚本,可以轻易地用
systemd或pm2托管。 - 逻辑清晰:所有代码都在一个项目里,调试和追踪问题链路更短。
当然,这也意味着扩展其他通道(如Slack)时需要自己写适配器,但对于核心的Telegram通知场景,这种简洁性带来了巨大的优势。
3. 从零开始:环境搭建与配置详解
理论讲完了,我们动手把它跑起来。我会假设你是在一个Linux/Mac服务器或开发机上操作,Windows用户使用WSL或PowerShell也可以,但路径可能需要稍作调整。
3.1 基础环境准备
首先,确保你的环境满足硬性要求:
- Node.js 22+:这个项目大量使用了Node.js 22的新特性,比如原生的
fetch、node:test测试模块等。用旧版本肯定会报错。可以通过node -v检查。 - Claude Code CLI:这是核心。你需要安装Anthropic官方提供的Claude Code命令行工具,并确保
claude命令在终端中可以直接调用。通常安装后需要配置API密钥。你可以通过运行claude -h来测试是否安装成功。 - Git:用于克隆代码库。
# 示例:在Ubuntu上准备环境 # 1. 安装Node.js 22 (使用NodeSource仓库) curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt-get install -y nodejs # 2. 验证安装 node -v # 应显示 v22.x.x npm -v # 3. 安装Claude Code CLI (请参考Anthropic官方文档) # 通常是一个npm包或直接下载的二进制文件 # 假设通过npm安装(如果提供): # npm install -g @anthropic-ai/claude-code # 安装后,在终端配置你的API密钥 # claude auth login # 4. 验证claude命令 claude -h3.2 获取项目与初始化配置
# 克隆仓库 git clone <openclaw-cc的仓库地址> cd openclaw-cc # 复制环境变量和配置文件模板 cp .env.example .env cp config/default.example.json config/default.json现在,我们来逐一配置这些文件,这是最关键的一步。
第一步:配置Telegram Bot
- 在Telegram中搜索
@BotFather。 - 发送
/newbot,按照提示给你的机器人起名字和用户名。 - 创建成功后,BotFather会给你一个Bot Token,格式类似
1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ。这个Token就是你的机器人的密码,务必保密! - 打开
.env文件,将Token填入:TELEGRAM_BOT_TOKEN=你的BotToken注意:
.env文件解析器很简单,只支持KEY=VALUE格式。不要写成export KEY=VALUE,也不要在值两边加引号,它会被自动去掉。
第二步:配置config/default.json这个文件控制了智能体和Telegram的核心行为。
{ "agents": { "defaults": { "model": "sonnet", "timeoutSeconds": 300, "allowedTools": "Bash,Read,Write,Edit,Grep,Glob", "maxBudgetUsd": "0.50" } }, "telegram": { "defaultChatId": "-1001234567890", "defaultTopicId": 6, "allowedChatIds": ["-1001234567890"], "pollingIntervalMs": 3000 } }agents.defaults.model:默认使用的Claude模型。haiku快且便宜,适合简单检查;sonnet平衡;opus最强也最贵。这里设为sonnet是个不错的起点。agents.defaults.allowedTools:允许AI使用的工具。这里列出了文件读写、编辑、查找等基础工具,足够完成大多数自动化任务。出于安全考虑,除非你完全信任AI和你的提示词,否则不要随意添加更强大的工具。agents.defaults.maxBudgetUsd:单次AI调用的最高成本限制,防止意外情况产生高额费用。telegram.defaultChatId和defaultTopicId:默认发送消息的目标。defaultTopicId仅在超级群的特定话题中有效。telegram.allowedChatIds:这是接收消息的白名单。只有列表中的聊天ID,机器人才会处理其发来的消息。如果留空[],则机器人仅能发送消息,不能接收。格式很重要:-1001234567890:整个群组(所有话题)。-1001234567890:topic:6:仅限该群组中ID为6的话题。123456789:一个用户的私聊ID。
telegram.pollingIntervalMs:接收消息的长轮询间隔。
如何获取Chat ID?将你的Bot拉入一个群组(或私聊它发条消息),然后访问这个URL(将<TOKEN>替换为你的Bot Token):https://api.telegram.org/bot<TOKEN>/getUpdates在返回的JSON中,找到message.chat.id字段,那个数字(或带负号的数字)就是Chat ID。
3.3 配置定时任务
定时任务定义在data/cron/jobs.json里。我们需要先创建这个目录和文件。
mkdir -p data/cron cp examples/jobs.example.json data/cron/jobs.json打开data/cron/jobs.json,你会看到示例任务。我们修改第一个任务,让它指向你的Telegram目的地:
{ "jobs": [ { "id": "health-check", "name": "System Health Check", "description": "Check system health and report if any issues.", "kind": "every", "intervalMs": 300000, "payload": { "model": "haiku", "systemPrompt": "You are a system monitoring assistant. Check the current system status (use Bash tool if needed). If everything is normal, reply with exactly 'NO_REPLY'. If there's an issue, describe it concisely.", "userPrompt": "Check system health now.", "sessionType": "cron" }, "delivery": { "channel": "telegram", "to": "-1001234567890:topic:6" } } ] }关键字段解释:
id:任务唯一标识,用于日志和防重复。kind: "every":周期性任务,每隔intervalMs毫秒执行一次。这里是5分钟(300000毫秒)。payload.model:这个任务指定使用haiku模型,因为健康检查很简单,用便宜快速的模型即可。payload.systemPrompt:定义了AI在此任务中的角色和行为准则。注意其中明确要求“如果一切正常,回复NO_REPLY”。payload.sessionType: "cron":这意味着执行此任务时,只会加载SOUL.md,IDENTITY.md,AGENTS.md这几个轻量级文件,节省Tokens。delivery.to:消息发送的目标。格式与allowedChatIds一致。这里指定发送到群组-1001234567890的6号话题。
3.4 初始化工作区与记忆
工作区文件定义了智能体的“灵魂”。我们先从模板创建个人化文件。
# 进入工作区目录 cd workspace # 复制模板文件(这些是git忽略的,你的个人信息不会上传) cp USER.example.md USER.md cp MEMORY.example.md MEMORY.md cp GROUP_MEMORY.example.md GROUP_MEMORY.md现在,编辑USER.md文件,填入关于你自己的信息。这能帮助AI更好地为你服务。例如:
# User Profile ## Basic Info - **Name**: Alex - **Timezone**: Asia/Shanghai - **Role**: DevOps Engineer ## Current Focus Projects 1. **K8s Cluster Migration**: Migrating legacy services to the new k8s cluster. Target completion: End of Q2. 2. **Monitoring Overhaul**: Setting up Prometheus + Grafana + Loki stack. Currently in the data source configuration phase. ## Preferences - **Communication Style**: Prefer concise, bullet-point updates with clear action items. - **Working Hours**: 9:00-18:00 (UTC+8). Avoid non-urgent notifications outside this window. - **Tech Stack**: Linux, Docker, Kubernetes, Go, Python, Node.js.MEMORY.md和GROUP_MEMORY.md可以先保持模板内容,智能体运行后会根据交互自动填充。
4. 核心模块深度解析与实操要点
环境配好了,我们来深入看看openclaw-cc的几个核心模块是怎么工作的,以及在实操中需要注意什么。
4.1 Agent Runner:三阶执行策略的智慧
agent-runner.js是调用claude -p的核心。它没有采用单一策略,而是设计了一个三阶的、具备降级能力的执行策略,这体现了对真实环境复杂性的考量。
模式一:CLI会话模式(首选)
- 原理:利用
claude -p --session-id <UUID>参数。Claude Code CLI会维护这个会话ID对应的对话历史,实现真正的持续性会话。这对于需要上下文连贯的定时任务(比如连续汇报项目进度)是理想的。 - 触发条件:首次执行时,Runner会尝试用
--session-id参数调用claude命令。如果成功,则后续都使用此模式。 - 优点:历史管理由Claude CLI负责,稳定可靠,上下文保持完整。
- 实操注意:你需要确保安装的Claude Code CLI版本支持
--session-id参数。如果不支持,会自动降级到模式二。
- 原理:利用
模式二:JSONL回退模式
- 原理:当CLI不支持会话ID时启用。Runner会在本地
data/sessions/目录下为每个会话创建一个<sessionKey>.jsonl文件。每次调用AI前,它会读取这个文件,将历史记录作为提示词的一部分注入到本次请求中,实现“模拟”的会话连续性。 - 触发条件:模式一检测失败后自动启用。
- 优点:兼容性更强,不依赖CLI的特定功能。
- 缺点:需要自己管理历史文件,且每次请求的Tokens会随着历史增长而增加,成本更高。
openclaw-cc通过会话重置策略(每日/闲置重置)来缓解这个问题。
- 原理:当CLI不支持会话ID时启用。Runner会在本地
模式三:无状态模式
- 原理:使用
claude -p --no-session-persistence参数。每次调用都是全新的,没有历史上下文。 - 触发条件:当任务配置中显式指定
noSessionPersistence: true时使用。这在处理来自Telegram的用户消息时是默认行为。 - 为什么接收消息要用无状态?想象一下,一个群聊里很多人@你的机器人,如果使用持续性会话,不同用户的消息上下文会混在一起,导致AI回复混乱。无状态模式确保了每次交互的独立性,更加安全稳定。
- 原理:使用
我的实操心得:在项目根目录运行npm test或直接看agent-runner.test.js的测试用例,可以清晰地看到这三种模式是如何被检测和使用的。对于我们自己定义的大多数定时任务(sessionType: "cron"),系统会优先尝试模式一,这通常是最佳选择。
4.2 Workspace Loader:动态上下文构建器
workspace-loader.js的工作是将冰冷的Markdown文件,转化为AI能理解的、结构化的上下文。这个过程在每次调用AI前发生。
加载流程如下:
- 确定会话类型:根据任务配置的
sessionType(main,cron,group) 决定加载哪些文件。 - 读取与转换:读取对应文件,将其内容包裹在对应的XML标签中。例如,
SOUL.md的内容会被放在<SOUL>...</SOUL>标签内。 - 每日记忆注入:自动加载
workspace/memory/目录下今天和昨天的日记文件(例如2024-04-10.md和2024-04-09.md),同样转换为<DAILY_MEMORY_2024-04-10>...</DAILY_MEMORY_...>标签。 - 优先级与截断:所有内容拼接后,如果总字符数超过
maxContextChars(默认8000),则会按照预设优先级进行截断。SOUL.md和USER.md优先级最高,保证核心人格和用户信息不被丢弃;MEMORY.md等长时记忆优先级较低,可能被部分截断。
一个关键细节:AGENTS.md的加载AGENTS.md文件很特殊,它包含了会话启动的流程和记忆管理规则。Workspace Loader不仅加载它,还会解析其中以<!-- INJECT:开头的特殊注释块,并将其内容提取出来,直接插入到系统提示词的末尾。这意味着AGENTS.md里的指令具有最高的优先级,会覆盖或补充其他文件中的一般性指导原则。你需要仔细设计这个文件。
4.3 Memory Manager:记忆的持久化与生命周期
记忆是智能体“成长”的关键。memory-manager.js负责管理两种记忆:
- 每日记忆:存放在
workspace/memory/YYYY-MM-DD.md。每次与AI的交互(无论是定时任务还是聊天回复),只要产生了有价值的输出,都可以通过调用mm.appendDaily(...)来追加记录。文件按天分割,清晰易管理。 - 长时记忆:存放在
workspace/MEMORY.md。这里存放需要长期保留、跨越天数的重要信息。比如“用户Alex每周一上午有例会,不要在这个时间打扰”,或者“项目X的部署密码是XXX”。可以由AI在对话中判断并建议写入,也可以由开发者手动编辑。
记忆的修剪:memory-manager.js提供了pruneOldDaily()方法,可以删除超过指定天数(如30天)的旧日记文件,防止memory/目录无限膨胀。你可以将此调用集成到一个每周运行的定时任务中。
安全设计:注意,USER.md,MEMORY.md,GROUP_MEMORY.md以及整个memory/目录都在.gitignore列表中。这意味着你个人的隐私信息和对话记忆不会被意外提交到公开的代码仓库。只有.example.md模板文件被跟踪。这是一个非常贴心的安全考量。
4.4 Delivery Queue:确保消息必达的守护者
delivery-queue.js实现了一个基于文件系统的、具备崩溃恢复能力的投递队列。它的设计非常稳健:
- 原子性写入:当有新消息需要投递时,它先在
data/delivery-queue/目录下创建一个临时文件(.tmp后缀),写入完整数据,然后通过重命名(rename)操作原子性地将其变为正式队列文件。这保证了即使在写入过程中进程崩溃,也不会留下损坏的半成品文件。 - 文件锁与处理标志:处理一个队列文件前,会先尝试创建一个同名的
.lock锁文件(使用O_EXCL标志确保唯一性)。同时,还会创建一个.processing文件作为处理中的标志。其他进程或重启后的同一进程看到这些文件,就知道该任务正在被处理或已处理过,从而避免重复执行。 - 重试与死信:如果消息发送失败(如网络问题),队列会进行重试。如果超过最大重试次数仍失败,该消息会被移动到
data/dead-letter/死信目录,供后续人工检查和处理,而不会阻塞队列中的其他消息。 bestEffort模式:对于需要分多条发送的长消息,可以启用此模式。即使其中某一条发送失败,已成功的部分也不会回滚,队列会继续尝试发送剩余部分或记录失败。
实操建议:在config/default.json中,可以配置deliveryQueue相关的参数,如retryDelayMs(重试间隔)、maxRetries(最大重试次数)和processingTtlMs(处理标志的存活时间,用于清理僵尸锁)。根据你的网络可靠性和对及时性的要求进行调整。
5. 运行、调试与问题排查实录
配置完毕,让我们启动它,并看看如何应对可能出现的问题。
5.1 启动与守护进程
在项目根目录,直接运行:
node src/index.js你会看到类似以下的启动日志(日志是结构化的JSON,这里做了美化):
{"level":"INFO","time":"2024-04-10T10:00:00.000Z","msg":"Starting openclaw-cc","pid":12345} {"level":"INFO","time":"2024-04-10T10:00:00.100Z","msg":"Loaded config","configPath":"./config/default.json"} {"level":"INFO","time":"2024-04-10T10:00:00.200Z","msg":"Delivery queue scan found 0 pending items"} {"level":"INFO","time":"2024-04-10T10:00:00.300Z","msg":"Telegram poller started","chatIds":["-1001234567890"]} {"level":"INFO","time":"2024-04-10T10:00:00.400Z","msg":"Cron scheduler started","jobCount":3} {"level":"INFO","time":"2024-04-10T10:00:00.500Z","msg":"Scheduled job","jobId":"health-check","nextRunInMs":299000}进程会一直运行,监听定时任务和Telegram消息。
对于生产环境,你应该使用进程守护工具,比如systemd或pm2。
使用 systemd 示例: 创建服务文件/etc/systemd/system/openclaw-cc.service:
[Unit] Description=OpenClaw-CC Autonomous Agent After=network.target [Service] Type=simple User=your_username WorkingDirectory=/path/to/openclaw-cc Environment="PATH=/usr/bin:/usr/local/bin" Environment="NODE_ENV=production" ExecStart=/usr/bin/node src/index.js Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target然后启用并启动:
sudo systemctl daemon-reload sudo systemctl enable openclaw-cc sudo systemctl start openclaw-cc sudo systemctl status openclaw-cc # 查看状态使用 pm2 示例:
npm install -g pm2 pm2 start src/index.js --name openclaw-cc pm2 save pm2 startup # 根据提示生成开机启动脚本5.2 测试你的配置
在正式依赖它之前,强烈建议进行端到端测试。
测试Telegram发送:你可以手动触发一个投递来测试发送功能。创建一个简单的测试脚本
test-send.js:import { TelegramAdapter } from './src/channel-adapters/telegram.js'; import { config } from './src/utils/config.js'; const telegram = new TelegramAdapter(config.telegram); await telegram.send({ to: '-1001234567890', // 你的Chat ID content: '🔧 测试消息:openclaw-cc 发送功能正常!', metadata: { test: true } }); console.log('测试消息已发送');运行
node test-send.js,检查Telegram群组是否收到消息。测试AI任务执行:修改
data/cron/jobs.json,将一个任务的intervalMs改得很短(比如10000,10秒),并暂时注释掉NO_REPLY逻辑,观察日志输出和Telegram接收情况,确认整个Cron -> Agent -> Delivery链路是通的。测试消息接收:在配置了
allowedChatIds的Telegram聊天中,@你的机器人并发送一条消息。查看程序日志,应该能看到类似Received Telegram message和Agent execution completed的条目,并且你应该能收到AI的回复。
5.3 常见问题与排查技巧
在部署和运行过程中,我遇到并总结了一些典型问题:
问题一:启动时报错Error: Cannot find package '...'
- 可能原因:项目声称“零依赖”,但Node.js 22+的原生模块可能在某些环境下路径问题。
- 排查:确认Node.js版本 >= 22。尝试使用绝对路径运行Node。检查
src/utils/config.js等文件是否使用了正确的node:前缀导入内置模块。
问题二:Claude CLI命令执行失败或超时
- 日志表现:
Agent execution failed或Timeout after X seconds。 - 排查步骤:
- 直接在终端运行
claude -p,看是否能正常启动交互。如果不能,检查Claude Code CLI的安装和认证。 - 检查
config/default.json中的timeoutSeconds是否设得太短。复杂的任务可能需要更长时间,可以适当调大。 - 查看
data/sessions/或项目根目录下是否有巨大的日志文件或缓存,可能导致CLI变慢。
- 直接在终端运行
问题三:Telegram消息发送失败
- 日志表现:
Delivery failed,Telegram API error。 - 排查步骤:
- Token错误:确认
.env中的TELEGRAM_BOT_TOKEN完全正确,没有多余空格或换行。 - Chat ID错误:确认
delivery.to或allowedChatIds中的Chat ID格式正确。私聊是正数,群组是以-100开头的长数字。确保Bot已被添加到该群组并有发送消息的权限。 - 网络问题:服务器可能无法访问
api.telegram.org。尝试在服务器上curl https://api.telegram.org测试连通性。 - 消息过长:Telegram单条消息限制4096字符。
openclaw-cc会自动分片,但分片逻辑可能在某些边缘情况(如超长无换行的单词)下失败。检查AI输出的内容。
- Token错误:确认
问题四:AI总是回复NO_REPLY或没有按预期执行任务
- 可能原因:系统提示词 (
systemPrompt) 或工作区文件 (SOUL.md,AGENTS.md) 中的指令不够明确,或者AI理解有偏差。 - 排查步骤:
- 在
jobs.json中临时将该任务的sessionType改为"main",并去掉NO_REPLY要求,让AI输出完整的思考过程。 - 查看日志中Agent Runner打印的最终组装好的系统提示词。这包含了所有注入的Markdown内容。检查你的指令是否清晰、无歧义。
- 在
AGENTS.md中强化具体任务的指令。例如,对于健康检查,可以写:“当你执行系统健康检查任务时,必须依次检查:1. 磁盘使用率(使用df -h),2. 内存使用率(使用free -m),3. 关键服务状态(如docker ps)。如果任何一项异常,则报告;否则输出NO_REPLY。”
- 在
问题五:会话混乱或历史上下文错误
- 可能原因:会话管理出现问题,可能是模式降级导致,或者是
data/sessions/目录下的JSONL文件损坏。 - 排查步骤:
- 查看日志中关于Agent Runner模式检测的记录。
- 清理
data/sessions/目录(停止服务后),然后重启,让系统重建会话。 - 对于重要的定时任务,考虑在任务配置中显式设置
"noSessionPersistence": true,使用无状态模式,确保每次执行都是干净的上下文。
问题六:内存占用或磁盘空间增长过快
- 可能原因:
memory/目录下的日记文件或data/sessions/下的JSONL文件没有定期清理。 - 解决方案:
- 创建一个定时任务,定期调用
memory-manager.js中的pruneOldDaily()方法,删除旧的日记文件。 - 会话文件 (
JSONL) 会在会话重置(每日或闲置24小时)时被清理。你也可以写一个简单的清理脚本,定期删除data/sessions/下过旧的文件。
- 创建一个定时任务,定期调用
5.4 高级技巧与自定义扩展
当你熟悉基本操作后,可以尝试以下进阶玩法:
成本感知模型路由:在
jobs.json的payload中为不同任务指定不同的model。简单的、高频的检查任务(如健康检查、摘要生成)用haiku;日常报告用sonnet;复杂的分析、规划任务用opus。这样能在保证效果的同时优化使用成本。利用记忆实现工作流:让AI在完成一个任务后,将结果或下一步计划写入
MEMORY.md。下一个任务可以读取这些记忆,实现跨任务的工作流。例如,一个任务分析日志发现错误,写入记忆;另一个任务读取记忆,尝试自动修复或生成更详细报告。自定义通道适配器:项目结构很容易扩展。如果你想将消息发送到Slack、Discord或钉钉,只需参照
src/channel-adapters/telegram.js实现一个新的适配器,并在delivery-queue.js中注册即可。接收消息同理,可以参考src/channel-receivers/telegram-poller.js。集成外部数据源:在
systemPrompt中,可以指导AI使用Bash工具调用外部脚本或API,获取数据后再进行分析。例如,让AI执行一个脚本从监控系统(如Prometheus)拉取数据,然后生成报告。
6. 项目实践案例与模板参考
openclaw-cc仓库提供了两个非常详实的示例模板,可以直接作为你构建自己智能体的起点。
6.1 Bunshin:日语商业AI伙伴
位于examples/bunshin/。这个模板完全用日语编写,旨在创建一个专注于商业运营的AI伙伴。
- 核心定位:不是被动回复消息的聊天机器人,而是一个拥有上下文、能主动思考和行动的“数字分身”。
- 工作区特色:
SOUL.md定义了其作为“商业伙伴”的核心原则:主动、谨慎、以结果为导向。USER.md详细描述了“用户”(即你)的公司信息、业务目标、团队成员和当前项目。MEMORY.md模板预设了客户管理、项目跟踪、会议纪要等结构。AGENTS.md包含了复杂的启动流程,指示AI在每次会话开始前回顾近期记忆、评估当前优先级、并规划下一步行动。
- 定时任务示例:
- 晨间简报:每天早上9点,自动检查日历、待办事项、项目进度,生成一份综合简报发送给你。
- 主动检查:每小时运行一次,检查预设的“关注指标”(如网站流量、服务器状态、社交媒体提及),如有异常主动报告。
- 借鉴点:这个模板展示了如何通过精心设计的工作区文件,让AI真正“理解”你的业务上下文,并从“反应式”变为“主动式”。你可以将其翻译并适配成中文或英文版本。
6.2 Dev Assistant:开发助手
位于examples/dev-assistant/。这个模板是英文的,专注于软件开发场景。
- 核心定位:开发团队的AI助手,监控代码库、CI/CD流水线,并管理开发任务。
- 核心模式:“审批优先”安全循环:这个模板强调安全性。AI可以建议操作(如运行脚本、合并代码),但必须经过“批准”才能执行。其工作流通常是:读取状态 -> 分析并提出建议 -> 等待批准 -> 执行批准的操作 -> 验证结果并报告。
- 工作区特色:
TOOLS.md中可能定义了与Git、Docker、K8s、CI服务器交互的脚本。HEARTBEAT.md的检查清单包含代码构建状态、测试通过率、部署环境健康度等。
- 定时任务示例:
- 每日开发简报:汇总前一天的Git提交、打开的Pull Request、失败的CI构建。
- PR提醒:定期检查是否有等待Review或合并的PR,并提醒相关人员。
- 借鉴点:这个模板对于在开发流程中引入AI自动化非常有参考价值。它体现了如何将AI的“建议”与人类的“决策”结合起来,在提升效率的同时保障安全。
6.3 构建你自己的智能体:思路与步骤
参考以上模板,你可以按以下步骤打造专属智能体:
- 明确目标:你想让它帮你做什么?是个人事务管理、技术监控、内容创作辅助,还是客户服务?
- 定义人格:在
SOUL.md中,用清晰、具体的语言描述它的角色、行为边界、沟通风格和核心目标。 - 填充上下文:在
USER.md中提供关于你和你环境的所有必要信息。越详细,AI的回复越精准。 - 设计记忆结构:规划
MEMORY.md和每日记忆的格式。例如,对于项目管理的智能体,记忆可以按项目分类,记录里程碑、决策和待办事项。 - 编排任务:在
jobs.json中设计定时任务。从简单的、高频的检查开始(如“每半小时检查一次邮箱是否有重要邮件摘要”),再逐步增加复杂的分析任务。 - 迭代优化:运行起来后,观察AI的输出。如果不符合预期,不要急于修改代码,而是首先优化你的提示词和工作区文件。AI的行为几乎完全由这些文本定义。
openclaw-cc提供了一个极其灵活且强大的框架,但它不负责“智能”。真正的智能,来自于你通过Markdown文件赋予它的“灵魂”和“记忆”。这个过程更像是在训练和塑造一个数字伙伴,需要耐心和不断的调优。