本地優先、安全優先的 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=zhhttp://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
資料未顯示(區段部分或完全空白)
- 開啟「設定」→「接線狀態」— 它會列出哪些連接器已連線、部分連線或遺失。
- 常見原因:
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 訂閱快照以取得完整用量資料






