Slack MCP Agent — 管理画面仕様書¶
v1.3 / 2026-05-08
docs/mvp-spec.mdSection 10 の詳細化。各画面のワイヤーフレーム・データソース・インタラクションを定義する。
デザイントークン・コンポーネント規約はDESIGN.mdを参照。
1. 概要¶
1.1 目的¶
- パイプライン実行結果の閲覧・詳細確認
- 承認フロー・実行設定の管理
- 外部連携(freee / Google / Slack)の接続管理
- 全操作の監査ログ閲覧
1.2 技術スタック¶
| 項目 | 選定 |
|---|---|
| フレームワーク | Next.js 16 (App Router, Server Components) |
| UI | Tailwind CSS v4 + shadcn/ui |
| データ取得 | Server Components で better-sqlite3 により data/agent.db を直接参照 |
| 認証 | MVP: HTTP Basic 認証(環境変数 ADMIN_USER / ADMIN_PASSWORD、web/middleware.ts で強制) |
| デプロイ | ローカル (localhost:3100) |
1.3 画面一覧¶
| # | パス | 画面名 | アクセス | 実装状態 |
|---|---|---|---|---|
| 1 | / |
パイプライン一覧 | 認証必須 | 実装済み |
| 2 | /pipeline/[id] |
パイプライン詳細 | 認証必須 | 実装済み |
| 3 | /settings |
設定 | 認証必須 | 実装済み |
| 4 | /integrations |
外部連携 | 認証必須 | 実装済み |
| 5 | /reports |
月次レポート一覧 | 認証必須 | 実装済み |
| 6 | /reports/[id] |
月次レポート詳細 | 認証必須 | 実装済み |
| 7 | /audit |
監査ログ | 認証必須 | Post-MVP |
Basic 認証はブラウザの WWW-Authenticate ダイアログで完結するため、独自の
/login画面は MVP スコープ外(未実装)。
1.4 Settings JSON の保持¶
/settings の保存処理は既存の settings.config JSON を merge して更新する。承認フロー設定の保存時に、Lane A 設定、FAQ ナレッジ、月次レポート配信先など他のキーを削除してはならない。
現在の /settings は以下を編集できる。
| key | 用途 |
|---|---|
prompt_approval_required |
Prompt 承認ゲート |
process_approval_required |
Process 承認ゲート |
faq_knowledge_text |
社内ハウスルール FAQ 一次回答に使う Markdown ナレッジ |
monthly_report_channel_id |
月次レポートレビューカードの投稿先 Slack channel ID |
2. 認証¶
2.1 MVP: HTTP Basic 認証¶
Next.js Middleware (web/middleware.ts) で _next/static・_next/image・favicon.ico 以外の全ルートに Basic 認証を適用する(実装抜粋)。
export function middleware(request: NextRequest) {
const user = process.env.ADMIN_USER || "admin";
const pass = process.env.ADMIN_PASSWORD || "admin";
const authHeader = request.headers.get("authorization");
if (authHeader) {
const [scheme, encoded] = authHeader.split(" ");
if (scheme === "Basic" && encoded) {
const [u, p] = atob(encoded).split(":");
if (u === user && p === pass) return NextResponse.next();
}
}
return new NextResponse("Unauthorized", {
status: 401,
headers: { "WWW-Authenticate": 'Basic realm="HR AI Agent Admin"' },
});
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
2.2 Post-MVP: Firebase Auth + Google SSO¶
@cast-er.comドメイン制限- Caster 既存実装と同じ構成
3. 画面 0: ログイン (/login) — Post-MVP¶
MVP では HTTP Basic 認証をブラウザ標準のダイアログに委譲するため、独自の /login 画面は実装しない。Firebase Auth + Google SSO 化(§2.2)とセットで Post-MVP で検討する。
4. 画面 1: パイプライン一覧 (/)¶
5.1 ワイヤーフレーム¶
┌─ Sidebar ─┬───────────────────────────────────────────────────┐
│ │ パイプライン [↻ 再読込] │
│ │ │
│ │ [All] [Running] [Completed] [Failed] [Cancelled] │
│ │ │
│ │ ┌──────────────────────────────────────────────┐ │
│ │ │ Status │ タイトル │ 種別│ 作成日時 │時間│ │
│ │ ├─────────┼──────────────────┼─────┼──────────┼────┤ │
│ │ │ ✅ 完了 │ 勤怠集計(3月) │ std │ 04-18 │ 38s│ │
│ │ │ 🔄 実行 │ 入社手続き │ std │ 04-18 │ - │ │
│ │ │ ❌ 失敗 │ 給与明細発行 │ urg │ 04-17 │ 12s│ │
│ │ │ 🔵 承認 │ 退職処理 tanaka │ std │ 04-17 │ - │ │
│ │ │ 🟡 生成 │ 年末調整案内 │ std │ 04-16 │ - │ │
│ │ │ ⬜ 中止 │ 勤怠集計(2月) │ std │ 04-15 │ - │ │
│ │ └──────────────────────────────────────────────┘ │
│ │ │
│ │ ← 前へ 1 / 3 ページ 次へ → │
└────────────┴───────────────────────────────────────────────────┘
5.2 データソース¶
-- ステータスフィルタ付き一覧
SELECT
t.id, t.title, t.status, t.task_type, t.priority, t.created_at,
e.completed_at, e.started_at,
CASE WHEN e.completed_at IS NOT NULL
THEN CAST((julianday(e.completed_at) - julianday(e.started_at)) * 86400 AS INTEGER)
ELSE NULL
END as elapsed_seconds
FROM tasks t
LEFT JOIN executions e ON e.task_id = t.id AND e.status = 'completed'
WHERE t.tenant_id = ?
AND (? IS NULL OR t.status = ?) -- ステータスフィルタ
ORDER BY t.created_at DESC
LIMIT 20 OFFSET ?;
-- 総件数(ページネーション用)
SELECT COUNT(*) FROM tasks
WHERE tenant_id = ? AND (? IS NULL OR status = ?);
5.3 インタラクション¶
| 操作 | 動作 |
|---|---|
| タブ切替 | URL クエリパラメータ ?status=running でフィルタ |
| 行クリック | /pipeline/[id] に遷移 |
| [再読込] | router.refresh() で Server Component を再取得 |
| ページネーション | ?page=2 でオフセット計算 |
5. 画面 2: パイプライン詳細 (/pipeline/[id])¶
5.1 ワイヤーフレーム¶
┌─ Sidebar ─┬──────────────────────────────────────────────────────┐
│ │ ← パイプライン一覧 │
│ │ │
│ │ 勤怠集計 (先月分) [✅ 完了] │
│ │ 先月1〜末日の打刻データを集計し、給与計算用に出力 │
│ │ │
│ │ ┌──────────┬──────────┬──────────┬──────────┐ │
│ │ │ 優先度 │ 種別 │ 作成日時 │ 実行時間 │ │
│ │ │ 🟡 Medium│ standard │ 04-18 │ 38s │ │
│ │ └──────────┴──────────┴──────────┴──────────┘ │
│ │ │
│ │ ● Task 04-18 14:32 │
│ │ │ 抽出済み → 実行中 → 完了 │
│ │ │ │
│ │ ▼ Prompt v1 (承認済み) 04-18 14:33 │
│ │ │ ┌────────────────────────────────────────┐ │
│ │ │ │ 1. 従業員一覧を取得 │ │
│ │ │ │ 2. 各従業員の勤怠データを取得 │ │
│ │ │ │ 3. 労働時間・残業時間を集計 │ │
│ │ │ │ 4. 集計結果を Google Sheet に書込 │ │
│ │ │ │ 5. 完了通知を送信 │ │
│ │ │ │ │ │
│ │ │ │ 承認: @yamada · 14:33:12 │ │
│ │ │ └────────────────────────────────────────┘ │
│ │ │ │
│ │ ▼ Process v1 (承認済み) 04-18 14:34 │
│ │ │ ┌────────────────────────────────────────┐ │
│ │ │ │ 1. list_employees ✅ │ │
│ │ │ │ 2. list_attendance ✅ │ │
│ │ │ │ 3. calculate_overtime ✅ │ │
│ │ │ │ 4. write_rows_to_sheet ✅ │ │
│ │ │ │ 5. send_slack_dm ✅ │ │
│ │ │ │ │ │
│ │ │ │ 承認: @yamada · 14:34:08 │ │
│ │ │ └────────────────────────────────────────┘ │
│ │ │ │
│ │ ▼ Execution #1 (完了) 04-18 14:35 │
│ │ ┌────────────────────────────────────────┐ │
│ │ │ ✅ list_employees 0.8s │ │
│ │ │ ✅ list_attendance 12.3s │ │
│ │ │ ✅ calculate_overtime 2.1s │ │
│ │ │ ✅ write_rows_to_sheet 8.4s │ │
│ │ │ ✅ send_slack_dm 1.2s │ │
│ │ │ │ │
│ │ │ サマリー: │ │
│ │ │ 先月の勤怠データを集計し... │ │
│ │ │ 実行時間: 38s │ │
│ │ └────────────────────────────────────────┘ │
└────────────┴──────────────────────────────────────────────────────┘
5.2 データソース¶
-- タスク本体
SELECT * FROM tasks WHERE id = ?;
-- Prompt 全バージョン
SELECT * FROM prompts WHERE task_id = ? ORDER BY version ASC;
-- Process 全バージョン
SELECT * FROM processes WHERE task_id = ? ORDER BY version ASC;
-- Execution 全件
SELECT * FROM executions WHERE task_id = ? ORDER BY started_at ASC;
5.3 インタラクション¶
| 操作 | 動作 |
|---|---|
| [← パイプライン一覧] | /pipeline に戻る |
| タイムラインノード | クリックで展開/折りたたみ(Collapsible) |
| 複数バージョン | Prompt v1, v2... をそれぞれ表示。却下理由も表示 |
5.4 却下バージョンの表示¶
却下されたバージョンは opacity-60 で表示し、却下理由をインライン表示:
6. 画面 3: 設定 (/settings)¶
6.1 ワイヤーフレーム¶
┌─ Sidebar ─┬───────────────────────────────────────────────┐
│ │ 設定 │
│ │ 承認フローのポリシーと実行設定を管理します。 │
│ │ │
│ │ ┌──────────────────────────────────────────┐ │
│ │ │ 基本情報 │ │
│ │ │ │ │
│ │ │ 名前 [HR AI Agent ] │ │
│ │ │ スラッグ [default ] │ │
│ │ └──────────────────────────────────────────┘ │
│ │ │
│ │ ┌──────────────────────────────────────────┐ │
│ │ │ 承認フロー設定 │ │
│ │ │ │ │
│ │ │ Prompt 承認を必須にする [====○ ] │ │
│ │ │ 生成されたプロンプトを実行前に │ │
│ │ │ 人間が承認する必要があります。 │ │
│ │ │ │ │
│ │ │ Process 承認を必須にする [====○ ] │ │
│ │ │ LLM が生成したプロセス定義を │ │
│ │ │ 実行前に確認します。 │ │
│ │ └──────────────────────────────────────────┘ │
│ │ │
│ │ ┌──────────────────────────────────────────┐ │
│ │ │ 実行設定 │ │
│ │ │ │ │
│ │ │ モデル [claude-sonnet-4-6 ▾] │ │
│ │ │ L4 タイムアウト [360 ] 秒 │ │
│ │ │ ツール自動承認 [====○ ] │ │
│ │ └──────────────────────────────────────────┘ │
│ │ │
│ │ [変更を保存] │
└────────────┴───────────────────────────────────────────────┘
6.2 データソース¶
-- 設定取得
SELECT config FROM settings WHERE tenant_id = ?;
-- 設定更新
UPDATE settings SET config = ?, updated_at = ?, updated_by = ? WHERE tenant_id = ?;
config JSON の構造:
{
"name": "HR AI Agent",
"slug": "default",
"prompt_approval_required": true,
"process_approval_required": true,
"model": "claude-sonnet-4-6",
"l4_timeout_seconds": 360,
"auto_approve_tools": true
}
6.3 インタラクション¶
| 操作 | 動作 |
|---|---|
| トグル切替 | ローカルステート更新(即反映はしない) |
| [変更を保存] | Server Action で DB 更新 + 監査ログ記録 |
| 保存成功 | Toast 通知「設定を保存しました」 |
| 保存失敗 | Toast 通知(エラーメッセージ) |
7. 画面 4: 外部連携 (/integrations)¶
7.1 ワイヤーフレーム¶
┌─ Sidebar ─┬───────────────────────────────────────────────────┐
│ │ 外部連携 │
│ │ エージェントが利用する外部サービスの接続を管理。 │
│ │ │
│ │ ┌────────────────────────────────────────────┐ │
│ │ │ 💼 freee [接続済み] │ │
│ │ │ 従業員・勤怠・給与 API にアクセスします。 │ │
│ │ │ │ │
│ │ │ スコープ: employees:read, work_records:read│ │
│ │ │ 事業所 ID: 12345 │ │
│ │ │ 接続日時: 2026-04-15 09:20 │ │
│ │ │ │ │
│ │ │ [再認証] [切断] │ │
│ │ └────────────────────────────────────────────┘ │
│ │ │
│ │ ┌────────────────────────────────────────────┐ │
│ │ │ 📊 Google Sheets [接続済み] │ │
│ │ │ スプレッドシートへのデータ書き込み。 │ │
│ │ │ │ │
│ │ │ サービスアカウント: hr-agent@... │ │
│ │ │ 接続日時: 2026-04-15 10:30 │ │
│ │ │ │ │
│ │ │ [再認証] [切断] │ │
│ │ └────────────────────────────────────────────┘ │
│ │ │
│ │ ┌────────────────────────────────────────────┐ │
│ │ │ 💬 Slack [接続済み] │ │
│ │ │ DM 送信・チャンネル通知。 │ │
│ │ │ │ │
│ │ │ ワークスペース: HR Operations │ │
│ │ │ Bot User: @hr-ai-agent │ │
│ │ │ 接続日時: 2026-04-10 08:00 │ │
│ │ │ │ │
│ │ │ [切断] │ │
│ │ └────────────────────────────────────────────┘ │
└────────────┴───────────────────────────────────────────────────┘
7.2 データソース¶
7.3 freee OAuth フロー¶
- [接続] ボタンクリック →
/api/integrations/freee/authにリダイレクト - Backend が freee OAuth 認証 URL を生成し、ユーザーをリダイレクト
- ユーザーが freee で認可 → コールバック
/api/integrations/freee/callback - Backend がアクセストークン + リフレッシュトークンを取得
integrationsテーブルに保存(credentials は暗号化)/integrationsにリダイレクト、接続状態を更新表示
7.4 インタラクション¶
| 操作 | 動作 |
|---|---|
| [接続] (未接続時) | OAuth フロー開始 |
| [再認証] | 既存トークン破棄 → OAuth フロー再開 |
| [切断] | 確認ダイアログ → credentials 削除、status → disconnected |
| 切断確認 | 「切断すると Agent がこのサービスを利用できなくなります」 |
8. 画面 5: 監査ログ (/audit) — Post-MVP¶
Backend 側の
audit_logsテーブルへの書き込みは実装済み(docs/data-model.md§2.7)。Web UI は Post-MVP で追加予定。下記はワイヤーフレームとデータソースの設計メモ。
8.1 ワイヤーフレーム¶
┌─ Sidebar ─┬──────────────────────────────────────────────────────┐
│ │ 監査ログ │
│ │ 管理操作と業務イベントの監査ログを表示します。 │
│ │ │
│ │ [2026-04-11 ▾] 〜 [2026-04-18 ▾] [アクション ▾] │
│ │ │
│ │ ┌──────────────────────────────────────────────────┐ │
│ │ │ 日時 │ アクター │ アクション │▸│ │
│ │ ├───────────────────┼──────────┼─────────────────┼──┤ │
│ │ │ 04-18 14:35:42 │ system │ execution │▸│ │
│ │ │ │ │ .completed │ │ │
│ │ │ { task: "勤怠集計", execution_id: "01J...", │ │
│ │ │ elapsed: 38, steps_completed: 5 } │ │
│ │ ├───────────────────┼──────────┼─────────────────┼──┤ │
│ │ │ 04-18 14:34:08 │ yamada │ process │▸│ │
│ │ │ │ │ .approved │ │ │
│ │ ├───────────────────┼──────────┼─────────────────┼──┤ │
│ │ │ 04-18 14:33:12 │ yamada │ prompt │▸│ │
│ │ │ │ │ .approved │ │ │
│ │ ├───────────────────┼──────────┼─────────────────┼──┤ │
│ │ │ 04-18 14:32:01 │ system │ task.created │▸│ │
│ │ │ │ │ │ │ │
│ │ └──────────────────────────────────────────────────┘ │
│ │ │
│ │ ← 前へ 1 / 5 ページ 次へ → │
└────────────┴──────────────────────────────────────────────────────┘
8.2 データソース¶
SELECT
al.id, al.timestamp, al.actor_type, al.actor_id,
al.action, al.resource_type, al.resource_id, al.details
FROM audit_logs al
WHERE al.tenant_id = ?
AND (? IS NULL OR al.timestamp >= ?) -- 開始日フィルタ
AND (? IS NULL OR al.timestamp <= ?) -- 終了日フィルタ
AND (? IS NULL OR al.action = ?) -- アクション種別フィルタ
ORDER BY al.timestamp DESC
LIMIT 20 OFFSET ?;
8.3 アクション種別¶
| アクション | actor_type | 説明 |
|---|---|---|
task.created |
system |
タスク作成 |
prompt.approved |
user |
Prompt 承認 |
prompt.rejected |
user |
Prompt 却下 |
process.approved |
user |
Process 承認 |
process.rejected |
user |
Process 却下 |
execution.started |
system |
実行開始 |
execution.completed |
system |
実行完了 |
execution.failed |
system |
実行失敗 |
execution.cancelled |
user |
実行中止 |
settings.updated |
user |
設定変更 |
integration.connected |
user |
外部連携接続 |
integration.disconnected |
user |
外部連携切断 |
8.4 インタラクション¶
| 操作 | 動作 |
|---|---|
| 日付フィルタ | URL クエリ ?from=2026-04-11&to=2026-04-18 |
| アクション種別フィルタ | URL クエリ ?action=prompt.approved |
| 行展開 (▸) | Collapsible で details JSON を表示 |
| ページネーション | ?page=2 |
9. 共通パターン¶
9.1 Server Actions¶
設定保存・接続切断等の書き込み操作は Next.js Server Actions を使用。
"use server";
export async function updateSettings(formData: FormData) {
const config = {
prompt_approval_required: formData.get("prompt_approval") === "on",
process_approval_required: formData.get("process_approval") === "on",
model: formData.get("model") as string,
l4_timeout_seconds: Number(formData.get("timeout")),
auto_approve_tools: formData.get("auto_approve") === "on",
};
await db.run("UPDATE settings SET config = ?, updated_at = ? WHERE tenant_id = ?",
JSON.stringify(config), new Date().toISOString(), tenantId);
await insertAuditLog("settings.updated", "user", userId, "settings", tenantId, config);
revalidatePath("/settings");
}
9.2 Toast 通知¶
操作結果のフィードバックは shadcn/ui の Toast を使用。
| 種別 | 色 | 用途 |
|---|---|---|
| success | 緑 | 保存成功、接続完了 |
| error | 赤 | 保存失敗、接続失敗 |
| info | 青 | 情報通知 |
9.3 エラーハンドリング¶
- DB 接続エラー: エラーページ(
error.tsx)を表示 - 認証失敗: Middleware が 401 +
WWW-Authenticateヘッダを返し、ブラウザが Basic 認証ダイアログを表示 - 404:
not-found.tsxを表示
9.4 ローディング¶
- Server Components のストリーミングレンダリングを活用
- 各ページに
loading.tsxを配置(Skeleton UI)
10. Caster 既存 UI との差分 — メリット・デメリット比較¶
| 項目 | Caster 既存 | 本仕様 | メリット | デメリット |
|---|---|---|---|---|
| 認証 | Firebase Auth + Google SSO | Basic 認証(MVP) | 外部依存ゼロ、セットアップ即完了 | セキュリティが弱い(ローカル運用前提)、Post-MVP で差し替え必須 |
| DB | Firestore | SQLite | デプロイ不要・ファイル 1 つで完結、Backend と共有容易 | 同時書き込みに弱い、スケールアウト不可(1 人運用 MVP なら問題なし) |
| パイプライン一覧 | 3 カラム(Inbox + Stage + List + Detail) | テーブル + 詳細ページ分離 | 実装がシンプル、URL ベースで共有・ブックマーク可、Server Components で SSR 可 | 一覧と詳細を同時に見られない(画面遷移が必要) |
| 詳細表示 | 右ペイン(URL 変化なし) | 独立ページ /pipeline/[id] |
URL で直リンク共有可能、ページ単位でキャッシュ・プリフェッチ可能 | 一覧 ↔ 詳細の行き来にページ遷移コスト |
| ルーティング | useState でインライン切替 | App Router ページ遷移 | ブラウザの戻る/進む対応、URL 設計がクリーン、コード分割が自然 | useState 方式より初期実装がやや多い(ファイル数増) |
| 外部連携 | /mcp-auths 独立ページ |
/integrations に統合 |
全プロバイダーを一覧で管理、画面数削減 | 将来プロバイダー増加時に画面が長くなる可能性 |
| ステータス管理 | useState (Client) | Server Components + URL params | サーバー側でデータ取得完結、JS バンドル削減、リロードで状態復元 | リアルタイム更新にはポーリング or WebSocket の追加実装が必要 |
変更履歴¶
| 日付 | バージョン | 変更内容 |
|---|---|---|
| 2026-04-18 | v1.0 | 初版作成 |
| 2026-04-18 | v1.1 | ダッシュボード画面を削除(/ はパイプライン一覧に変更)、監査ログ CSV エクスポート削除、Caster 既存 UI 差分にメリデメ追加 |
| 2026-04-20 | v1.2 | 実装整合を反映。Next.js 16・better-sqlite3・ポート 3100 を明記。/login と /audit UI を Post-MVP 扱いに変更、Middleware の実装抜粋を差し替え |