openclaw-control-center

openclaw-control-center

本地優先、安全優先的 OpenClaw 代理控制中心 — 提供可視化儀表板,預設唯讀、Token 歸因、協作追蹤與安全寫入操作。

66星標
13分支
更新於 2026/7/9
SKILL.md
唯讀
名稱
openclaw-control-center
描述

本地優先、安全優先的 OpenClaw 代理控制中心 — 提供可視化儀表板,預設唯讀、Token 歸因、協作追蹤與安全寫入操作。

openclaw-control-center

Skill by ara.so — Daily 2026 Skills collection

OpenClaw Control Center 將 OpenClaw 從黑盒子轉變為本地、可稽核的控制中心。它提供代理活動、Token 花費、任務執行鏈、跨工作階段協作、記憶體狀態與文件來源的可視化 — 並以安全優先的預設值,預設關閉所有變更操作。

功能說明

  • 總覽 (Overview):系統健康狀態、待辦項目、風險訊號與操作摘要
  • 用量 (Usage):每日/7天/30天 Token 花費、配額、上下文壓力、訂閱視窗
  • 人員 (Staff):哪些代理正在執行中 vs. 排隊中 — 不只是「有任務」
  • 協作 (Collaboration):父-子工作階段交接與驗證過的跨工作階段訊息(例如 Main ⇄ Pandas
  • 任務 (Tasks):任務看板、審核、執行鏈、執行證據
  • 記憶 (Memory):各代理記憶體健康狀態、可搜尋性與原始檔案編輯
  • 文件 (Documents):從實際原始檔案開啟的共享文件與代理核心文件
  • 設定 (Settings):連接器接線狀態、安全風險摘要、更新狀態

安裝

git clone https://github.com/TianyiDataScience/openclaw-control-center.git
cd openclaw-control-center
npm install
cp .env.example .env
npm run build
npm test
npm run smoke:ui
npm run dev:ui

開啟:

  • http://127.0.0.1:4310/?section=overview&lang=zh
  • http://127.0.0.1:4310/?section=overview&lang=en

建議使用 npm run dev:ui 而非 UI_MODE=true npm run dev — 前者更穩定,尤其在 Windows 命令列環境。

專案結構

openclaw-control-center/
├── control-center/          # 所有修改必須在此目錄內
│   ├── src/
│   │   ├── runtime/         # 核心執行環境、連接器、監控器
│   │   └── ui/              # 前端 UI 元件
│   ├── .env.example
│   └── package.json
├── docs/
│   └── assets/              # 螢幕截圖與文件圖片
├── README.md
└── README.en.md

重要限制:僅修改 control-center/ 內的檔案。切勿修改 ~/.openclaw/openclaw.json

環境設定

複製 .env.example.env 並設定:

# 安全預設值 — 未了解影響前請勿變更
READONLY_MODE=true
LOCAL_TOKEN_AUTH_REQUIRED=true
IMPORT_MUTATION_ENABLED=false
IMPORT_MUTATION_DRY_RUN=false
APPROVAL_ACTIONS_ENABLED=false
APPROVAL_ACTIONS_DRY_RUN=true

# 連線
OPENCLAW_GATEWAY_URL=http://127.0.0.1:PORT
OPENCLAW_HOME=~/.openclaw

# UI
PORT=4310
DEFAULT_LANG=zh

安全旗標說明

旗標 預設值 效果
READONLY_MODE true 停用所有會改變狀態的端點
LOCAL_TOKEN_AUTH_REQUIRED true 匯入/匯出與寫入 API 需要本地 Token
IMPORT_MUTATION_ENABLED false 完全封鎖匯入變更
IMPORT_MUTATION_DRY_RUN false 啟用時匯入為試執行模式
APPROVAL_ACTIONS_ENABLED false 強制停用審核動作
APPROVAL_ACTIONS_DRY_RUN true 啟用時審核動作以試執行模式執行

主要指令

# 開發
npm run dev:ui          # 啟動 UI 伺服器(建議)
npm run dev             # 一次性監控執行,無 HTTP UI

# 建置與測試
npm run build           # TypeScript 編譯
npm test                # 執行測試套件
npm run smoke:ui        # UI 端點冒煙測試

# 程式碼檢查
npm run lint            # ESLint 檢查
npm run lint:fix        # 自動修正 lint 問題

TypeScript 程式碼範例

連線至執行環境監控器

import { createMonitor } from './src/runtime/monitor';

const monitor = createMonitor({
  gatewayUrl: process.env.OPENCLAW_GATEWAY_URL ?? 'http://127.0.0.1:4310',
  readonlyMode: process.env.READONLY_MODE !== 'false',
  localTokenAuthRequired: process.env.LOCAL_TOKEN_AUTH_REQUIRED !== 'false',
});

// 取得目前系統總覽
const overview = await monitor.getOverview();
console.log(overview.systemStatus);      // 'healthy' | 'degraded' | 'critical'
console.log(overview.pendingItems);      // number
console.log(overview.activeAgents);      // Agent[]

讀取代理人員狀態

import { StaffConnector } from './src/runtime/connectors/staff';

const staff = new StaffConnector({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

// 取得正在執行的代理(不只是排隊中)
const activeAgents = await staff.getActiveAgents();
activeAgents.forEach(agent => {
  console.log(`${agent.name}: ${agent.status}`);
  // 'executing' | 'queued' | 'idle' | 'blocked'
  console.log(`Current task: ${agent.currentTask?.title ?? 'none'}`);
  console.log(`Last output: ${agent.lastOutput}`);
});

// 取得完整人員名單(含佇列深度)
const roster = await staff.getRoster();

追蹤跨工作階段協作

import { CollaborationTracer } from './src/runtime/connectors/collaboration';

const tracer = new CollaborationTracer({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

// 取得父-子工作階段交接
const handoffs = await tracer.getSessionHandoffs();
handoffs.forEach(handoff => {
  console.log(`${handoff.parentSession} → ${handoff.childSession}`);
  console.log(`Delegated task: ${handoff.taskTitle}`);
  console.log(`Status: ${handoff.status}`);
});

// 取得驗證過的跨工作階段訊息(例如 Main ⇄ Pandas)
const crossSessionMessages = await tracer.getCrossSessionMessages();
crossSessionMessages.forEach(msg => {
  console.log(`${msg.fromAgent} ⇄ ${msg.toAgent}: ${msg.messageType}`);
  // messageType: 'sessions_send' | 'inter-session message'
});

取得 Token 用量與花費

import { UsageConnector } from './src/runtime/connectors/usage';

const usage = new UsageConnector({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

// 今日用量
const today = await usage.getUsageSummary('today');
console.log(`Tokens used: ${today.tokensUsed}`);
console.log(`Cost: $${today.costUsd.toFixed(4)}`);
console.log(`Context pressure: ${today.contextPressure}`);
// contextPressure: 'low' | 'medium' | 'high' | 'critical'

// 7 天用量趨勢
const trend = await usage.getUsageTrend(7);
trend.forEach(day => {
  console.log(`${day.date}: ${day.tokensUsed} tokens, $${day.costUsd.toFixed(4)}`);
});

// 依任務歸因 Token(誰吃掉了排程任務的 Token)
const attribution = await usage.getTokenAttribution();
attribution.tasks.forEach(task => {
  console.log(`${task.title}: ${task.tokensUsed} (${task.percentOfTotal}%)`);
});

讀取記憶體狀態

import { MemoryConnector } from './src/runtime/connectors/memory';

const memory = new MemoryConnector({
  openclawHome: process.env.OPENCLAW_HOME ?? '~/.openclaw',
});

// 取得每個活躍代理的記憶體健康狀態(範圍限於 openclaw.json)
const memoryState = await memory.getMemoryState();
memoryState.agents.forEach(agent => {
  console.log(`${agent.name}:`);
  console.log(`  Available: ${agent.memoryAvailable}`);
  console.log(`  Searchable: ${agent.memorySearchable}`);
  console.log(`  Needs review: ${agent.needsReview}`);
});

// 讀取代理的每日記憶
const dailyMemory = await memory.readDailyMemory('main-agent');
console.log(dailyMemory.content);

// 編輯記憶(需要 READONLY_MODE=false 與有效的本地 Token)
await memory.writeDailyMemory('main-agent', updatedContent, { token: localToken });

檢查接線狀態

import { WiringChecker } from './src/runtime/connectors/wiring';

const wiring = new WiringChecker({ gatewayUrl: process.env.OPENCLAW_GATEWAY_URL });

const status = await wiring.getWiringStatus();
status.connectors.forEach(connector => {
  console.log(`${connector.name}: ${connector.status}`);
  // status: 'connected' | 'partial' | 'disconnected'
  if (connector.status !== 'connected') {
    console.log(`  Fix: ${connector.nextStep}`);
  }
});

審核任務(受控端點)

import { TaskConnector } from './src/runtime/connectors/tasks';

const tasks = new TaskConnector({
  gatewayUrl: process.env.OPENCLAW_GATEWAY_URL,
  approvalActionsEnabled: process.env.APPROVAL_ACTIONS_ENABLED === 'true',
  approvalActionsDryRun: process.env.APPROVAL_ACTIONS_DRY_RUN !== 'false',
});

// 若 APPROVAL_ACTIONS_ENABLED=false(預設)則會拋出錯誤
try {
  const result = await tasks.approveTask('task-id-123', { token: localToken });
  if (result.dryRun) {
    console.log('Dry run — no actual state change');
  }
} catch (err) {
  if (err.code === 'APPROVAL_ACTIONS_DISABLED') {
    console.log('Set APPROVAL_ACTIONS_ENABLED=true to enable approvals');
  }
}

UI 區段導覽

透過查詢參數導覽:

http://127.0.0.1:4310/?section=overview&lang=zh
http://127.0.0.1:4310/?section=usage&lang=en
http://127.0.0.1:4310/?section=staff&lang=zh
http://127.0.0.1:4310/?section=collaboration&lang=en
http://127.0.0.1:4310/?section=tasks&lang=zh
http://127.0.0.1:4310/?section=memory&lang=en
http://127.0.0.1:4310/?section=documents&lang=zh
http://127.0.0.1:4310/?section=settings&lang=en

區段:overview | usage | staff | collaboration | tasks | memory | documents | settings

語言:zh(中文,預設)| en(英文)

整合模式

嵌入現有 OpenClaw 工作流程

若您的 OpenClaw 代理需要將設定指令交給控制中心,請使用文件中的安裝區塊:

// 在您的 OpenClaw 代理任務中
const installInstructions = `
cd openclaw-control-center
npm install
cp .env.example .env
# 編輯 .env:設定 OPENCLAW_GATEWAY_URL 與 OPENCLAW_HOME
npm run build && npm test && npm run dev:ui
`;

新增自訂連接器

所有連接器位於 control-center/src/runtime/connectors/。請遵循以下模式:

// control-center/src/runtime/connectors/my-connector.ts
import { BaseConnector, ConnectorOptions } from './base';

export interface MyData {
  id: string;
  value: string;
}

export class MyConnector extends BaseConnector {
  constructor(options: ConnectorOptions) {
    super(options);
  }

  async getData(): Promise<MyData[]> {
    // 任何寫入操作前務必檢查唯讀模式
    this.assertNotReadonly('getData is readonly-safe');

    const response = await this.fetch('/api/my-endpoint');
    return response.json() as Promise<MyData[]>;
  }
}

自訂 UI 區段

// control-center/src/ui/sections/MySection.tsx
import React from 'react';
import { useConnector } from '../hooks/useConnector';
import { MyConnector } from '../../runtime/connectors/my-connector';

export const MySection: React.FC = () => {
  const { data, loading, error } = useConnector(MyConnector, 'getData');

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {data?.map(item => (
        <li key={item.id}>{item.value}</li>
      ))}
    </ul>
  );
};

疑難排解

「Missing src/runtime」或「Missing core source」

這幾乎總是因為工作目錄錯誤:

# 確認您在 repo 根目錄
pwd  # 應以 /openclaw-control-center 結尾
ls control-center/src/runtime  # 應存在

若正確複製但仍遺失:表示複製不完整。請重新複製:

git clone https://github.com/TianyiDataScience/openclaw-control-center.git

UI 無法啟動 / 連接埠衝突

# 檢查連接埠 4310 是否被佔用
lsof -i :4310
# 或在 Windows 上
netstat -ano | findstr :4310

# 在 .env 中變更連接埠
PORT=4311

資料未顯示(區段部分或完全空白)

  1. 開啟「設定」→「接線狀態」— 它會列出哪些連接器已連線、部分連線或遺失。
  2. 常見原因:
    • OPENCLAW_GATEWAY_URL 未設定或連接埠錯誤
    • OPENCLAW_HOME 未指向實際的 ~/.openclaw
    • OpenClaw 訂閱快照不在預設路徑

Token 驗證失敗

# 產生本地 Token(請參閱 openclaw 文件了解 Token 位置)
cat ~/.openclaw/local-token

# 在 API 呼叫中透過標頭傳遞
curl -H "X-Local-Token: <token>" http://127.0.0.1:4310/api/tasks/approve

審核動作無反應

檢查您的 .env

APPROVAL_ACTIONS_ENABLED=true   # 必須為 true
APPROVAL_ACTIONS_DRY_RUN=false  # 必須為 false 才能實際執行

兩者都必須明確設定。預設為停用 + 試執行。

記憶區段顯示非活躍代理

記憶區段的範圍限於 openclaw.json 中列出的代理。若已刪除的代理仍出現:

# 檢查活躍代理
cat ~/.openclaw/openclaw.json | grep -A5 '"agents"'

openclaw.json 中移除過時的條目 — 記憶區段將在下次載入時更新。

Windows 命令列問題

建議使用 npm run dev:ui 而非 UI_MODE=true npm run dev。跨環境變數設定在 PowerShell/CMD 中行為不同。dev:ui 指令會內部處理此問題。

先決條件

  • Node.js + npm
  • 正在執行的 OpenClaw 安裝,且可存取 Gateway
  • 對本機 ~/.openclaw 的讀取權限
  • (選用)~/.codex 與 OpenClaw 訂閱快照以取得完整用量資料