目次
こんにちは!ilhamhk です。
今回は、OpenClaw のエージェントオーケストレーター向けにカスタムダッシュボードを作った経験を共有したいと思います。
OpenClaw とは?
OpenClaw は、Discord、LINE、WhatsApp などのチャットチャネルを AI エージェントにつなぐ、セルフホスト型のゲートウェイです。ツールやサービスを接続することで、パーソナルアシスタントのレイヤーとして機能させることができます。
個人的には、OpenClaw を一元的なパーソナルアシスタントとして使っています。Gmail、カレンダー、Notion などのさまざまなツールに接続し、タスクを任せられるようにしています。
ダッシュボードを作る理由
OpenClaw にはすでに標準ダッシュボードがあります。ただし、監視向けというより運用向けであり、私には情報量が多すぎると感じました。
また、必要な情報だけを表示し、自分好みのテーマで作ったダッシュボードには、ある種の満足感があります。
アーキテクチャー
アプリケーションフレームワークには Next.js を使用しています。
Next.js は、Web アプリケーションを構築するための人気のある TypeScript フレームワークです。機能的で高いカスタマイズ性を持つダッシュボードを、最小限の手間で作れるため選びました。OpenClaw も広い Node.js エコシステムの一部であるため、Next.js アプリケーションとの統合も比較的簡単です。
個人用のため、ダッシュボードは Mac mini 上でローカルに実行しています。
スマートフォンや他の個人用デバイスからダッシュボードにアクセスできるようにするため、Tailscale を使用しています。
Tailscale は、認可されたデバイス間にプライベートネットワークを作成します。これにより、ダッシュボードを公開インターネットに直接公開したり、ルーターのポートフォワーディングを設定したりせずに、リモートからアクセスできます。
ダッシュボードは Mac mini 上でホストされており、プライベートな Tailscale ネットワークを通じてのみアクセスできます。
コーディングアシスタントには oh-my-pi を使用しています。私のワークフローにおける利点の一つは、モデルに依存しない設計であることです。これにより、一つのプラットフォームに縛られず、複数のプロバイダーのモデルを使えます。
oh-my-pi はハッシュに紐づいた編集と、Language Server Protocol とのより深い統合にも対応しています。ファイル全体を繰り返し取得・書き換えるワークフローと比べると、より的を絞ったコード編集ができ、不必要なコンテキストやトークン使用量を減らせます。
開発プロセス
ダッシュボード UI を作成
リポジトリを準備
Next.js プロジェクトを初期化するために、次のコマンドを実行しました。
-- initiate
npx create-next-app@latest yumemiru
-- project dir に移動
cd yumemiru
-- shadcn/ui components
npx shadcn@latest init
shadcn/ui は、あらかじめ作られたコンポーネントを備えた UI ライブラリです。すべてのコンポーネントを一から作らなくてよいように使用しています。
プロジェクトの初期化時には、次のオプションを選択しました。
Use Typescript
Use Tailwind
Enable eslint
Use app/ directory
ディレクトリー構成
これはフロントエンドのディレクトリ構成です。
yumemiru/
├── app/
│ ├── api/ <-- route to connect to openclaw backend
│ │ └── ...
│ ├── agents-management/ <-- route to agents-management page
│ │ └── ...
│ ├── station-status/ <-- route to station-status page
│ │ └── ...
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── components/ <-- individual components or sub-components for the dashboard
│ └── ...
├── hooks/ <-- custom react hooks
│ └── ...
└── lib/ <-- utility function to be used troughout the project
└── ...
個人開発者かつ保守担当者として、開発を速く進め、将来の機能追加を容易にするために、設定はできるだけシンプルに保ちました。
ダッシュボードのコンポーネントを作成
ダッシュボードには、主に次の 3 つのコンポーネントがあります。
- チャットウィンドウ
このチャットウィンドウは、メインエージェントとやり取りするための主な方法です。メインエージェントオーケストレーターと通信するために、永続的なメインセッションを使用します。
- 端末の状況
このページでは、ダッシュボードをホストしている Mac mini の状態を表示します。主に RAM 使用量を監視するために作成しました。
- エージェント管理
このページでは、現在のエージェントの状態を表示します。主にエージェントの状態、cron ジョブ、その他のエージェント関連情報を監視するために作成しました。
最も頻繁に確認する指標は、メインダッシュボードページに配置しました。
どこからでも監視・アクセスしたいので、ダッシュボードはモバイルファーストのアプリケーションとして設計しました。Tailwind CSS もモバイルファーストのレスポンシブデザインの考え方に沿っています。
ダッシュボードはこのデザインで作成しました。

OpenClaw に接続
main エージェントに接続
同じマシン上で動作する OpenClaw エージェントと通信する最も簡単な方法は、CLI を使うことです。Next.js のルート API 内で POST メソッドを使い、OpenClaw の CLI を呼び出せます。
import { openclaw } from "@/lib/openclaw-cli";
export async function POST(req: Request) {
// エラー処理など一部を省略
try {
const body: ChatRequestBody = await req.json();
const messages = body.messages ?? [];
const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
const cliArgs = [
"agent", "--agent", "main",
"--message", lastUserMessage.content,
"--json", "--timeout", "120",
];
if (body.sessionKey) cliArgs.push("--session-key", body.sessionKey);
const result = (await openclaw(cliArgs)) as AgentResult;
// レスポンスのテキストを抽出し、JSON として対応
} catch (err) {
// エラー対応
}
これは実質的に次のコマンドと同じです。
openclaw agent \
--agent main \
--message <メッセージ内容> \
--json \
--timeout 120 \
--session-key "agent:main:<セッション ID>"
openclaw は、CLI コマンドをどのように組み立てるかを定義するカスタムユーティリティ関数です。
この実装では CLI を呼び出して完了を待つため、レスポンスはストリーミングされません。待機中は、UI に「…」をローディング表示として出します。
エージェントの情報を取得
チャットと同様に、この情報も CLI を使って取得します。今回は GET メソッドを使用します。
情報を取得する関数の例です。
// OpenClaw の健康を確認
export async function getHealth(): Promise<OpenClawHealth> {
return (await openclaw(["gateway", "call", "health"])) as OpenClawHealth;
}
// 最新 20 個セッションを取得
export async function getSessions(limit = 20, agent?: string): Promise<OpenClawSessionList> {
const args = ["sessions", "list", "--json", "--limit", String(limit)];
if (agent) args.push("--agent", agent);
return (await openclaw(args)) as OpenClawSessionList;
}
端末情報を取得
ステーションダッシュボードは、Next.js の API ルートを通じて Mac mini からシステム情報を直接取得します。このルートでは、Node.js のシステム API と vm_stat、df、netstat、powermetrics などの macOS コマンドを使用し、CPU 使用率、メモリ、ディスク容量、稼働時間、ネットワーク通信量、消費電力、温度などのデータを収集します。
メモリ情報を取得する例です。
export const GET = apiHandler(async () => {
const total = os.totalmem();
const used = total - os.freemem();
return {
hostname: os.hostname(),
platform: `${os.type()} ${os.release()}`,
arch: os.arch(),
uptime: os.uptime(),
ram: {
total,
used,
usagePercent: (used / total) * 100,
},
};
});
ビルドと展開
開発が完了した後、次のコマンドでプロジェクトをビルドしました。
-- ビルド
npm run build
-- 展開
npm run start -- --hostname 0.0.0.0
Mac mini と iPhone の両方に Tailscale を設定します。

設定後は、インターネットに公開することなく、Mac サーバーの Tailscale インターフェスを使って iPhone からダッシュボードにアクセスできます。
展開後の運用
デプロイ後は、ダッシュボードを使ってエージェントと会話し、あとから結果を確認できます。
これはダッシュボード上での操作の様子です。

これで、どこからでもシステムを監視し、エージェントとチャットできるようになりました。
改善点
個人用のため、セキュリティや管理にはあまり時間をかけていません。まずはコンセプトを検証するために、最も手早く、シンプルな方法を選びました。
今後は、このダッシュボードを Docker でコンテナ化し、Mac mini 上で隔離された環境として動かせるようにしたいと考えています。
まとめ
このダッシュボードを作ったことで、OpenClaw の環境とより手軽につながれるようになりました。Mac mini の状態、エージェント、スケジュールされたジョブ、メインエージェントとの直接チャットなど、重要な情報を一か所で確認できます。
このプロジェクトは個人用として意図的にシンプルに作っています。記事の簡潔さとプライバシーのため一部の実装・設定は省略しているため、再現手順としては使えません。ただし、OpenClaw の CLI 呼び出しのようなシンプルな方法でも、カスタムダッシュボードを作れることを示す例にはなったと考えています。




