Logo
热心市民王先生

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

参考资料