04 - 关键代码验证
技术研究 人工智能 LLM
以下代码展示如何让 OpenClaw 自动分析需求并生成新 Skill:
Skill 自举代码示例
自动 Skill 生成器
以下代码展示如何让 OpenClaw 自动分析需求并生成新 Skill:
// ~/.openclaw/skills/skill-generator/SKILL.md
---
name: skill-generator
description: 自动生成新的 Skill 文件
author: self-bootstrap
version: 1.0.0
---
# Skill 生成器
这是一个元 Skill,用于生成其他 Skill。当用户需要新功能时,自动分析需求并创建对应的 SKILL.md 文件。
## 可用工具
- read_file: 读取现有 Skill 作为参考
- write_file: 写入新生成的 Skill
- execute_command: 执行 Shell 命令
- search_files: 搜索文件内容
## 使用示例
用户: "创建一个能自动备份指定文件夹的 Skill"
Agent: 分析需求 → 生成 backup-folder Skill → 保存到 skills/backup-folder/SKILL.md
// ~/.openclaw/skills/skill-generator/index.ts
import { Skill, Tool } from 'openclaw';
import { promises as fs } from 'fs';
import path from 'path';
interface SkillGenerationRequest {
requirement: string;
skillName?: string;
referenceSkills?: string[];
}
export class SkillGenerator {
private skillsDir: string;
private llm: LLMClient;
constructor() {
this.skillsDir = path.join(process.env.HOME!, '.openclaw/skills');
this.llm = new LLMClient({ model: 'claude-3-sonnet' });
}
async generateSkill(request: SkillGenerationRequest): Promise<GeneratedSkill> {
// 1. 分析需求
const analysis = await this.analyzeRequirement(request.requirement);
// 2. 确定 Skill 名称
const skillName = request.skillName || this.generateSkillName(analysis);
// 3. 查找参考 Skill
const references = await this.findReferences(request.referenceSkills || []);
// 4. 生成 SKILL.md 内容
const skillContent = await this.generateSkillMarkdown({
name: skillName,
description: analysis.description,
functionality: analysis.functionality,
references
});
// 5. 生成实现代码
const implementationCode = await this.generateImplementation({
name: skillName,
functionality: analysis.functionality
});
// 6. 保存文件
const skillPath = path.join(this.skillsDir, skillName);
await fs.mkdir(skillPath, { recursive: true });
await fs.writeFile(
path.join(skillPath, 'SKILL.md'),
skillContent,
'utf-8'
);
await fs.writeFile(
path.join(skillPath, 'index.ts'),
implementationCode,
'utf-8'
);
// 7. 记录生成日志
await this.logGeneration(skillName, request.requirement);
return {
name: skillName,
path: skillPath,
content: skillContent,
functionality: analysis.functionality
};
}
private async analyzeRequirement(requirement: string): Promise<RequirementAnalysis> {
const prompt = `
分析以下用户需求,提取关键信息:
需求:${requirement}
请返回 JSON 格式:
{
"description": "一句话描述这个 Skill",
"functionality": ["功能点1", "功能点2", ...],
"required_tools": ["需要的工具1", "工具2", ...],
"complexity": "simple|medium|complex"
}
`;
const response = await this.llm.generate(prompt);
return JSON.parse(response);
}
private generateSkillName(analysis: RequirementAnalysis): string {
// 基于描述生成 kebab-case 名称
const words = analysis.description
.toLowerCase()
.replace(/[^a-z0-9\s]/g, '')
.split(' ')
.filter(w => w.length > 2);
return words.slice(0, 3).join('-');
}
private async findReferences(referenceNames: string[]): Promise<ReferenceSkill[]> {
const references: ReferenceSkill[] = [];
for (const name of referenceNames) {
const skillPath = path.join(this.skillsDir, name, 'SKILL.md');
try {
const content = await fs.readFile(skillPath, 'utf-8');
references.push({ name, content });
} catch {
console.warn(`参考 Skill ${name} 不存在`);
}
}
return references;
}
private async generateSkillMarkdown(params: SkillParams): Promise<string> {
const referenceSection = params.references.length > 0
? `\n## 参考实现\n${params.references.map(r => `- ${r.name}`).join('\n')}`
: '';
return `---
name: ${params.name}
description: ${params.description}
author: auto-generated
version: 1.0.0
generated_at: ${new Date().toISOString()}
---
# ${this.capitalize(params.name.replace(/-/g, ' '))}
${params.description}
## 功能
${params.functionality.map(f => `- ${f}`).join('\n')}
## 使用示例
\`\`\`
用户: "使用 ${params.name} 做..."
Agent: [执行相应操作]
\`\`\`
${referenceSection}
`;
}
private async generateImplementation(params: ImplementationParams): Promise<string> {
const prompt = `
为 Skill "${params.name}" 生成 TypeScript 实现代码。
功能需求:
${params.functionality.map(f => `- ${f}`).join('\n')}
要求:
1. 使用 OpenClaw Skill API
2. 包含错误处理
3. 添加日志记录
4. 导出默认的 Skill 类
返回完整的 TypeScript 代码:
`;
return await this.llm.generate(prompt);
}
private async logGeneration(skillName: string, requirement: string): Promise<void> {
const logEntry = {
timestamp: new Date().toISOString(),
skill_name: skillName,
requirement,
status: 'generated'
};
const logPath = path.join(this.skillsDir, '.generation-log.jsonl');
await fs.appendFile(logPath, JSON.stringify(logEntry) + '\n');
}
private capitalize(str: string): string {
return str.replace(/\b\w/g, l => l.toUpperCase());
}
}
// 导出 Skill 实例
export default new SkillGenerator();
使用示例
# 用户通过 Telegram 发送消息
用户:"帮我创建一个能自动整理下载文件夹的 Skill"
# OpenClaw 执行以下流程
1. 调用 skill-generator
2. 分析需求 → 识别功能:文件分类、归档、清理
3. 生成 Skill 名称:folder-organizer
4. 创建文件:
- ~/.openclaw/skills/folder-organizer/SKILL.md
- ~/.openclaw/skills/folder-organizer/index.ts
5. 自动注册新 Skill
6. 向 Telegram 发送通知:
✅ 已生成新 Skill:folder-organizer
功能:自动整理下载文件夹
使用:直接输入 "整理下载文件夹"
Telegram 同步配置
Webhook 配置
// ~/.openclaw/config/telegram-webhook.js
module.exports = {
telegram: {
// Bot Token(从 @BotFather 获取)
bot_token: process.env.TELEGRAM_BOT_TOKEN,
// Webhook 配置
webhook: {
enabled: true,
url: process.env.TELEGRAM_WEBHOOK_URL, // https://your-domain.com/webhook/telegram
port: 8443,
// SSL 证书(生产环境必需)
ssl: {
cert: '/path/to/cert.pem',
key: '/path/to/key.pem'
},
// 允许的消息类型
allowed_updates: [
'message',
'edited_message',
'callback_query',
'inline_query'
],
// 并发控制
max_connections: 40,
// 超时设置
timeout: 30
},
// 消息处理配置
messaging: {
// 解析模式
parse_mode: 'MarkdownV2',
// 禁用网页预览
disable_web_page_preview: false,
// 静音发送(不触发通知音)
disable_notification: false,
// 保护内容(禁止转发)
protect_content: false
},
// 命令菜单
commands: [
{ command: 'start', description: '开始使用' },
{ command: 'help', description: '查看帮助' },
{ command: 'status', description: '查看系统状态' },
{ command: 'bootstrap', description: '触发自举流程' },
{ command: 'skills', description: '管理 Skills' }
],
// 通知配置
notifications: {
// 自举事件通知
bootstrap: {
enabled: true,
chat_id: process.env.TELEGRAM_ADMIN_CHAT_ID,
events: ['skill_generated', 'config_optimized', 'error']
},
// 系统告警
system: {
enabled: true,
chat_id: process.env.TELEGRAM_ADMIN_CHAT_ID,
events: ['high_memory', 'api_error', 'security_alert']
},
// 每日摘要
daily_summary: {
enabled: true,
chat_id: process.env.TELEGRAM_ADMIN_CHAT_ID,
time: '09:00',
timezone: 'Asia/Shanghai'
}
}
}
};
消息处理器
// ~/.openclaw/skills/telegram-sync/index.ts
import { Bot, Context } from 'grammy';
import { OpenClawGateway } from 'openclaw';
interface TelegramSyncConfig {
bot_token: string;
admin_chat_ids: number[];
notification_rules: NotificationRule[];
}
export class TelegramSyncManager {
private bot: Bot;
private gateway: OpenClawGateway;
private config: TelegramSyncConfig;
constructor(config: TelegramSyncConfig) {
this.config = config;
this.bot = new Bot(config.bot_token);
this.gateway = new OpenClawGateway();
this.setupHandlers();
}
private setupHandlers(): void {
// /start 命令
this.bot.command('start', async (ctx) => {
await ctx.reply(
'🦞 欢迎使用 OpenClaw!\n\n' +
'我可以帮你:\n' +
'• 执行系统命令\n' +
'• 管理文件和日程\n' +
'• 自动完成重复任务\n' +
'• 学习和自我改进\n\n' +
'输入 /help 查看更多命令',
{ parse_mode: 'Markdown' }
);
});
// /bootstrap 命令 - 触发自举
this.bot.command('bootstrap', async (ctx) => {
const chatId = ctx.chat.id;
// 检查权限
if (!this.config.admin_chat_ids.includes(chatId)) {
await ctx.reply('⛔ 你没有权限执行此操作');
return;
}
await ctx.reply('🔄 启动自举流程...');
try {
const result = await this.triggerBootstrap();
await ctx.reply(
`✅ 自举完成!\n\n` +
`新增 Skills: ${result.newSkills.join(', ')}\n` +
`优化项: ${result.optimizations.length}\n` +
`耗时: ${result.duration}s`,
{ parse_mode: 'Markdown' }
);
} catch (error) {
await ctx.reply(`❌ 自举失败: ${error.message}`);
}
});
// /status 命令 - 查看状态
this.bot.command('status', async (ctx) => {
const status = await this.getSystemStatus();
await ctx.reply(
`📊 系统状态\n\n` +
`• 运行时间: ${status.uptime}\n` +
`• 内存使用: ${status.memory}\n` +
`• API 调用: ${status.apiCalls} 次/小时\n` +
`• 已安装 Skills: ${status.skillsCount}\n` +
`• 最后自举: ${status.lastBootstrap}`,
{ parse_mode: 'Markdown' }
);
});
// 普通消息处理
this.bot.on('message:text', async (ctx) => {
const userMessage = ctx.message.text;
const chatId = ctx.chat.id;
// 显示"正在输入"状态
await ctx.replyWithChatAction('typing');
try {
// 转发给 OpenClaw 处理
const response = await this.gateway.processMessage({
content: userMessage,
user_id: chatId.toString(),
channel: 'telegram'
});
// 发送回复
await ctx.reply(response.content, {
parse_mode: 'Markdown',
reply_to_message_id: ctx.message.message_id
});
} catch (error) {
await ctx.reply(`❌ 处理消息时出错: ${error.message}`);
}
});
// 文件处理
this.bot.on('message:document', async (ctx) => {
const doc = ctx.message.document;
await ctx.reply(
`📄 收到文件: ${doc.file_name}\n` +
`大小: ${(doc.file_size / 1024).toFixed(2)} KB\n\n` +
'正在分析...',
{ parse_mode: 'Markdown' }
);
try {
// 下载文件
const file = await ctx.api.getFile(doc.file_id);
const fileUrl = `https://api.telegram.org/file/bot${this.config.bot_token}/${file.file_path}`;
// 转发给 OpenClaw 处理
const analysis = await this.gateway.processFile({
url: fileUrl,
filename: doc.file_name,
user_id: ctx.chat.id.toString()
});
await ctx.reply(analysis.content, { parse_mode: 'Markdown' });
} catch (error) {
await ctx.reply(`❌ 文件处理失败: ${error.message}`);
}
});
}
// 主动推送通知
async sendNotification(notification: Notification): Promise<void> {
const emoji = this.getEmojiForEvent(notification.type);
const message = `${emoji} ${notification.title}\n\n${notification.body}`;
for (const chatId of this.config.admin_chat_ids) {
try {
await this.bot.api.sendMessage(chatId, message, {
parse_mode: 'Markdown',
disable_notification: notification.silent || false
});
} catch (error) {
console.error(`发送通知到 ${chatId} 失败:`, error);
}
}
}
// 发送自举进度
async sendBootstrapProgress(progress: BootstrapProgress): Promise<void> {
const progressBar = this.generateProgressBar(progress.percentage);
const message =
`🔄 自举进度: ${progress.percentage}%\n` +
`${progressBar}\n\n` +
`当前步骤: ${progress.currentStep}\n` +
`预计剩余: ${progress.eta}`;
for (const chatId of this.config.admin_chat_ids) {
try {
// 如果是更新消息,编辑原消息
if (progress.messageId) {
await this.bot.api.editMessageText(
chatId,
progress.messageId,
message,
{ parse_mode: 'Markdown' }
);
} else {
const sent = await this.bot.api.sendMessage(chatId, message);
progress.messageId = sent.message_id;
}
} catch (error) {
console.error('更新进度失败:', error);
}
}
}
private getEmojiForEvent(type: string): string {
const emojis: Record<string, string> = {
'skill_generated': '✨',
'config_optimized': '⚙️',
'error': '❌',
'warning': '⚠️',
'success': '✅',
'info': 'ℹ️',
'security_alert': '🚨'
};
return emojis[type] || '📢';
}
private generateProgressBar(percentage: number): string {
const filled = Math.round(percentage / 10);
const empty = 10 - filled;
return '█'.repeat(filled) + '░'.repeat(empty);
}
async start(): Promise<void> {
// 设置命令菜单
await this.bot.api.setMyCommands([
{ command: 'start', description: '开始使用' },
{ command: 'help', description: '查看帮助' },
{ command: 'status', description: '系统状态' },
{ command: 'bootstrap', description: '触发自举' },
{ command: 'skills', description: '管理 Skills' }
]);
// 启动 bot
await this.bot.start();
console.log('Telegram Sync Manager 已启动');
}
}
配置自优化代码
自动配置优化器
// ~/.openclaw/skills/config-optimizer/index.ts
import { promises as fs } from 'fs';
import path from 'path';
interface SystemMetrics {
timestamp: number;
memoryUsage: MemoryMetrics;
apiCalls: APIMetrics;
responseTime: ResponseMetrics;
diskUsage: DiskMetrics;
}
interface OptimizationSuggestion {
configPath: string;
currentValue: any;
proposedValue: any;
reason: string;
impact: 'high' | 'medium' | 'low';
risk: 'high' | 'medium' | 'low';
}
export class ConfigOptimizer {
private configPath: string;
private metricsHistory: SystemMetrics[] = [];
private readonly maxHistorySize = 1008; // 保存 7 天(每小时一次)
constructor() {
this.configPath = path.join(process.env.HOME!, '.openclaw/openclaw.json');
}
// 收集系统指标
async collectMetrics(): Promise<SystemMetrics> {
const metrics: SystemMetrics = {
timestamp: Date.now(),
memoryUsage: await this.getMemoryMetrics(),
apiCalls: await this.getAPIMetrics(),
responseTime: await this.getResponseMetrics(),
diskUsage: await this.getDiskMetrics()
};
this.metricsHistory.push(metrics);
// 保持历史记录在限制范围内
if (this.metricsHistory.length > this.maxHistorySize) {
this.metricsHistory = this.metricsHistory.slice(-this.maxHistorySize);
}
return metrics;
}
// 生成优化建议
async generateOptimizations(): Promise<OptimizationSuggestion[]> {
const suggestions: OptimizationSuggestion[] = [];
// 分析 API 使用模式
const apiSuggestion = await this.optimizeAPIConfig();
if (apiSuggestion) suggestions.push(apiSuggestion);
// 分析内存使用
const memorySuggestion = await this.optimizeMemoryConfig();
if (memorySuggestion) suggestions.push(memorySuggestion);
// 分析响应时间
const responseSuggestion = await this.optimizeResponseConfig();
if (responseSuggestion) suggestions.push(responseSuggestion);
// 分析存储使用
const storageSuggestion = await this.optimizeStorageConfig();
if (storageSuggestion) suggestions.push(storageSuggestion);
return suggestions;
}
// 应用优化
async applyOptimizations(
suggestions: OptimizationSuggestion[],
options: { autoApplyLowRisk: boolean; requireApprovalForHighRisk: boolean }
): Promise<OptimizationResult> {
const results: OptimizationResult = {
applied: [],
skipped: [],
failed: []
};
// 读取当前配置
const config = await this.loadConfig();
for (const suggestion of suggestions) {
try {
// 根据风险等级决定是否自动应用
if (suggestion.risk === 'high' && options.requireApprovalForHighRisk) {
results.skipped.push({
...suggestion,
reason: '高风险配置需要人工确认'
});
continue;
}
if (suggestion.risk !== 'low' && !options.autoApplyLowRisk) {
results.skipped.push({
...suggestion,
reason: '未启用自动应用非低风险配置'
});
continue;
}
// 应用配置变更
await this.setConfigValue(config, suggestion.configPath, suggestion.proposedValue);
results.applied.push(suggestion);
// 发送通知
await this.notifyOptimization(suggestion);
} catch (error) {
results.failed.push({
...suggestion,
error: error.message
});
}
}
// 保存配置
await this.saveConfig(config);
return results;
}
// 具体的优化逻辑
private async optimizeAPIConfig(): Promise<OptimizationSuggestion | null> {
const recentMetrics = this.metricsHistory.slice(-24); // 最近 24 小时
const totalCalls = recentMetrics.reduce((sum, m) => sum + m.apiCalls.count, 0);
const totalCost = recentMetrics.reduce((sum, m) => sum + m.apiCalls.cost, 0);
const avgCostPerCall = totalCost / totalCalls;
// 如果平均成本过高,建议切换模型
if (avgCostPerCall > 0.02) { // $0.02 per call
return {
configPath: 'llm.model',
currentValue: 'claude-3-opus',
proposedValue: 'claude-3-sonnet',
reason: `API 成本过高(平均 $${avgCostPerCall.toFixed(4)}/call),建议切换到更经济的模型`,
impact: 'high',
risk: 'medium'
};
}
// 如果调用频率低,建议降低心跳频率
const avgCallsPerHour = totalCalls / 24;
if (avgCallsPerHour < 5) {
return {
configPath: 'scheduler.heartbeat_interval',
currentValue: 1800,
proposedValue: 3600,
reason: '使用频率低,建议降低心跳频率以节省资源',
impact: 'medium',
risk: 'low'
};
}
return null;
}
private async optimizeMemoryConfig(): Promise<OptimizationSuggestion | null> {
const recentMetrics = this.metricsHistory.slice(-24);
const avgMemoryUsage = recentMetrics.reduce((sum, m) => sum + m.memoryUsage.percentage, 0) / 24;
if (avgMemoryUsage > 80) {
return {
configPath: 'memory.retention_days',
currentValue: 30,
proposedValue: 14,
reason: `内存使用率过高(平均 ${avgMemoryUsage.toFixed(1)}%),建议缩短会话保留期`,
impact: 'high',
risk: 'low'
};
}
return null;
}
private async optimizeResponseConfig(): Promise<OptimizationSuggestion | null> {
const recentMetrics = this.metricsHistory.slice(-24);
const p95ResponseTime = this.calculateP95(
recentMetrics.flatMap(m => m.responseTime.samples)
);
if (p95ResponseTime > 5000) { // 5 秒
return {
configPath: 'llm.max_tokens',
currentValue: 4096,
proposedValue: 2048,
reason: `响应时间过长(P95: ${p95ResponseTime}ms),建议限制最大输出长度`,
impact: 'medium',
risk: 'low'
};
}
return null;
}
private async optimizeStorageConfig(): Promise<OptimizationSuggestion | null> {
const latest = this.metricsHistory[this.metricsHistory.length - 1];
if (latest.diskUsage.percentage > 85) {
return {
configPath: 'storage.auto_archive',
currentValue: false,
proposedValue: true,
reason: `磁盘使用率过高(${latest.diskUsage.percentage}%),建议启用自动归档`,
impact: 'high',
risk: 'low'
};
}
return null;
}
// 辅助方法
private async getMemoryMetrics(): Promise<MemoryMetrics> {
const usage = process.memoryUsage();
const total = require('os').totalmem();
return {
used: usage.heapUsed,
total: total,
percentage: (usage.heapUsed / total) * 100
};
}
private async getAPIMetrics(): Promise<APIMetrics> {
// 从日志或监控系统中读取
// 这里使用示例数据
return {
count: 100,
cost: 1.5,
errors: 2
};
}
private async getResponseMetrics(): Promise<ResponseMetrics> {
// 从监控系统中读取
return {
samples: [100, 150, 200, 180, 300], // 响应时间样本(毫秒)
average: 186,
p95: 300
};
}
private async getDiskMetrics(): Promise<DiskMetrics> {
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);
const { stdout } = await execAsync('df -h ~/.openclaw | tail -1');
const parts = stdout.trim().split(/\s+/);
const percentage = parseInt(parts[4].replace('%', ''));
return {
used: parts[2],
available: parts[3],
percentage: percentage
};
}
private calculateP95(samples: number[]): number {
const sorted = [...samples].sort((a, b) => a - b);
const index = Math.ceil(sorted.length * 0.95) - 1;
return sorted[index];
}
private async loadConfig(): Promise<any> {
const content = await fs.readFile(this.configPath, 'utf-8');
return JSON.parse(content);
}
private async saveConfig(config: any): Promise<void> {
await fs.writeFile(
this.configPath,
JSON.stringify(config, null, 2),
'utf-8'
);
}
private setConfigValue(config: any, path: string, value: any): void {
const keys = path.split('.');
let current = config;
for (let i = 0; i < keys.length - 1; i++) {
if (!(keys[i] in current)) {
current[keys[i]] = {};
}
current = current[keys[i]];
}
current[keys[keys.length - 1]] = value;
}
private async notifyOptimization(suggestion: OptimizationSuggestion): Promise<void> {
// 通过 Telegram 或其他渠道发送通知
console.log(`配置已优化: ${suggestion.configPath}`);
console.log(` ${suggestion.currentValue} → ${suggestion.proposedValue}`);
console.log(` 原因: ${suggestion.reason}`);
}
}
完整的 Docker 部署配置
docker-compose.yml
version: '3.8'
services:
openclaw:
image: openclaw/openclaw:latest
container_name: openclaw
restart: unless-stopped
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
- TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL}
- OPENCLAW_HOME=/app/.openclaw
volumes:
- ./openclaw-data:/app/.openclaw
- /var/run/docker.sock:/var/run/docker.sock # 用于 Skill 容器化
ports:
- "18789:18789" # OpenClaw 控制面板
- "8443:8443" # Telegram Webhook
networks:
- openclaw-network
# 可选:Redis 用于缓存和消息队列
redis:
image: redis:7-alpine
container_name: openclaw-redis
restart: unless-stopped
volumes:
- redis-data:/data
networks:
- openclaw-network
# 可选:PostgreSQL 用于数据持久化
postgres:
image: postgres:15-alpine
container_name: openclaw-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=openclaw
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=openclaw
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- openclaw-network
# 可选:Nginx 反向代理
nginx:
image: nginx:alpine
container_name: openclaw-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- openclaw
networks:
- openclaw-network
volumes:
redis-data:
postgres-data:
networks:
openclaw-network:
driver: bridge
环境变量配置 (.env)
# LLM API 配置
ANTHROPIC_API_KEY=sk-ant-xxxxx
OPENAI_API_KEY=sk-xxxxx # 备用
# Telegram Bot 配置
TELEGRAM_BOT_TOKEN=YOUR_BOT_TOKEN_FROM_BOTFATHER
TELEGRAM_WEBHOOK_URL=https://your-domain.com/webhook/telegram
TELEGRAM_ADMIN_CHAT_ID=YOUR_CHAT_ID
# 数据库配置
DB_PASSWORD=your-secure-password
# OpenClaw 配置
OPENCLAW_LOG_LEVEL=info
OPENCLAW_ENABLE_BOOTSTRAP=true
OPENCLAW_AUTO_OPTIMIZE=true
OPENCLAW_NOTIFICATION_CHANNEL=telegram
# 安全配置
OPENCLAW_SANDBOX_ENABLED=true
OPENCLAW_MAX_SKILL_EXECUTION_TIME=300
OPENCLAW_RESTRICTED_COMMANDS=rm -rf,dd,mkfs
参考资料
- OpenClaw Configuration Guide - 官方配置文档
- grammy Documentation - Telegram Bot 框架文档
- Docker Compose Reference - Docker Compose 官方文档
- OpenClaw Skills Development - Skill 开发指南