Agent Portal 门户平台

统一的 Bot 舰队管理、服务器监控、项目管理和对话平台,从”项目管理页”升级为”Bot/Server Fleet 总控台”。

概述

Agent Portal 是一个全栈 Web 应用,旨在为整个 Bot 生态系统提供统一的观察和操控面板。由 PortalBot 作为专属研究代理负责开发和维护。

平台定位:运维监控 + 项目管理 + Bot 聊天对话

技术架构

部署拓扑(全部在同一台宿主机)

组件进程端口管理方式
前端静态文件pm2 serve dist/3013pm2 portal-static
后端 APIserver.cjs (Node.js)3002pm2 portal-api
Digest Pipelinedigest.py (Python)无 (CLI)手动 / Trigger
Trigger Servertrigger.py (Python)18790pm2 portal-trigger
反向代理Caddy443Docker mattermost-caddy

前端技术栈

  • 框架: React + Vite
  • UI 库: shadcn/ui + Tailwind CSS
  • 主题: 深色模式(v3-shadcn)
  • 移动端: PWA 支持、viewport 适配、touch 优化
  • 实时通信: SSE (Server-Sent Events)

后端技术栈

  • 框架: Express.js (server.cjs)
  • 数据库: PostgreSQL 直连 (已弃用 Supabase REST 回退)
  • 实时: MM WebSocket 监听 + SSE 广播
  • 认证: Bearer token 中间件(可选开启)

数据库表结构(AP_ 前缀)

表名用途
AP_botsBot 注册信息(agent_id, mm_username, mm_user_id, role 等)
AP_daily_reports每日日报
AP_daily_insights每日洞察汇总
AP_daily_activities聚合任务(title, summary, deliverables)
AP_daily_timeline碎片级事件流
AP_monitors健康监控配置
AP_site_checksHTTP 拨测结果
AP_server_snapshots服务器快照
AP_incidents故障记录
AP_projects项目数据(看板)

Caddy 反代配置

portal.dev.dora.restry.cn {
    handle /api/* → localhost:3002   # API server
    handle /     → localhost:3013   # 静态文件
}

环境变量

后端必需:PORT, DATABASE_URL, MM_ADMIN_TOKEN, MM_BASE_URL

Pipeline 必需:DATABASE_URL, MM_ADMIN_TOKEN, L1_API_KEY, L1_BASE_URL

⚠️ 所有 secret 已从硬编码提取到环境变量,缺失即报错退出。.env.example 模板已创建。

功能模块

📊 Dashboard 首页

Bot 舰队管理 (Bot Fleet)

  • 29 个 Agent 卡片,展示名称、角色、任务进度
  • 折叠/展开详情:环境状态、容器、cron jobs
  • 实时状态指示:
    • 🟢 typing — 绿色呼吸动画(2s 周期)
    • 🔵 active — 左边框绿色亮条
    • ⚪ idle — 正常卡片
  • 💬 最后消息预览(前100字)
  • 归档功能(localStorage 持久化)
  • last_active 降序排序
  • 时间显示:今天 15:21 / 昨天 09:30 / 03/28 14:05

Server 舰队管理 (Server Fleet)

  • 23 台服务器实时状态:CPU/内存/磁盘、SSH 可达性
  • 按云厂商/区域分组
  • Docker 容器 + systemd 服务列表

时光机 (Time Travel)

  • 120 个历史时间点,可回溯任意时刻状态
  • 桌面端:滑块选择器
  • 移动端:右侧滑出面板,滚轮式选择 + Audio tick 反馈
  • 每个时间点附带真实 bot/server 数量(后端 CTE + LEFT JOIN SQL 计算)

每日洞察 (Daily Insights)

  • 日期药丸切换器 (Pill Tabs)
  • things_done / needs_attention 汇总
  • Bot 日报联动日期

CommandBar 聊天

  • 底部浮出消息栏
  • 选中 bot/server → 发送指令
  • 项目上下文药丸(紫色 📂 标签)
  • 消息预填(点击 next_action 自动引用)
  • Markdown 渲染(表格横向滚动、代码块)
  • 聊天历史正确刷新(按 target ID 追踪切换)

📋 项目管理

项目看板 (Kanban)

  • 分组:需决策 / 进行中 / 探索中 / 已完成 / 已归档(dismissed)
  • 拖拽排序
  • 多 maintainer 显示
  • 下一步行动 (next_action):
    • 点击文字 → 引用到聊天框预填
    • 点击 ✓ → 标记完成,切换到下一个

Bot 详情页

  • 任务列表:来自 AP_daily_activities
  • 时间线:来自 AP_daily_timeline
  • 产出物 (Deliverables):URL 可点击、文件路径代码样式
  • 日期切换器

🏥 健康监控 (Monitor Panel)

HTTP 拨测

  • server.cjs 内置检查器,每 5 分钟自动拨测
  • 12 个开发环境服务监控
  • 记录 response_ms
  • 连续 2 次失败 → 自动 DM 告警
  • 恢复时也通知

当前监控清单

服务URL状态
Agent Portalportal.dev.dora.restry.cn
Agentic BIbi.dev.dora.restry.cn
ClawCraftcraft.dev.dora.restry.cn
Client Webweb.dev.dora.restry.cn
Gatewaygw.dev.dora.restry.cn
Mattermostmm.dora.restry.cn
Supabasedb.dora.restry.cn
Uptime Kumastatus.dora.restry.cn

Digest Pipeline

数据处理四层架构:

层级模型处理内容
L0MM 消息原始采集
L1gpt-4.1文本粗筛过滤
L2gpt-5.4结构化提取
L3gpt-5.4洞察汇总

Pipeline 完成后调用 /api/digest/done 通知后端广播 SSE,前端自动刷新。

架构优化历程

P0: 基础清理 ✅

  • 砍掉全部 Supabase REST 回退
  • 所有 secret 提到环境变量
  • .env.example 模板

P1: 前后端分离 ✅

  • API 独立进程 (port 3002)
  • 静态文件独立服务 (port 3013)
  • Bearer token 认证中间件

P2: 实时能力 ✅

  • SSE /api/ops/stream 已完整实现
  • MM WebSocket hot path (typing/posted 事件)

P3: Pipeline 集成 ✅

  • /api/digest/done 回调通知
  • Trigger server 纳入 pm2 管理

访问地址

相关页面

NBA(Next Best Action)机制

以下来自 Rabbit 的后端改造(2026-03-29/30)。

门户从”日报可视化”升级为可操作的指挥面板(Agent Control Surface)

核心设计

  1. things_done — 按主题聚合的”今天做了几件事”(5-12 件),替代旧版 30 条碎片 timeline
  2. needs_attention — 从 21 条压缩到 ≤5 条,每条带 NBA(建议操作 + 建议消息 + 目标 bot)
  3. NBA 一键执行 — 点击 NBA 按钮,通过 Admin Token 模拟 dora 身份,直接 DM 对应 bot

对话身份修正

  • 原方案:portalops ↔ bot(dora 在 MM 看不到发出的消息)
  • 正确方案:Admin Token + 模拟 dora 身份 + 发到 dora ↔ bot 的 DM channel

项目看板对话模式

  • 每个项目卡片只有一个 💬 对话按钮
  • 自动带项目引用格式:[项目: 项目名] 你的指令
  • 所有操作(删除/改名/合并/改状态)通过自然语言,Rabbit 后端处理

curated 保护机制

  • 手动整理过的项目标记 curated: true
  • pipeline 只追加里程碑和 last_active,不改名称/描述/状态/bots
  • pusher 推送时跳过 curated 项目

WikiTab 显示修复(2026-04-07)

Portal 的 Wiki 页面无法显示新编译的 43 篇 topic 类型文件。

根因

前端 WikiTab.tsx 侧边栏 GROUPS 数组硬编码了 4 个 type:project / bot / concept / synthesis。新编译的 43 篇 topic 文件 frontmatter 都是 type: topic,不在预定义分组中,完全不显示。

另外还有 23 篇无 type 的页面也被过滤掉了。

排查过程

  1. 最初怀疑是缓存问题 — 检查发现 Portal 的 Wiki API(/api/wiki/pages)是直接读本地文件系统 ~/.openclaw/wiki/,不走数据库
  2. 排查容器 vs 宿主机 — 容器内跑的是旧版 server.js(1479行),无 Wiki 功能;宿主机的 server.cjs(3559行)有 Wiki API。但开发环境 portal.dev.dora 不是容器部署
  3. 最终定位到前端 WikiTab 的 type 过滤是真正原因

修复方案

移除 type 过滤,改为动态分组:API 返回什么 type 就显示什么分组。已知 type 有预设图标和中文名(项目📁、Bot🤖、概念💡、综合分析📊),未知 type 自动用文件名 humanize 做标签。

修复后 Portal Wiki 侧边栏显示全部 97 篇页面,分为 6 组:项目(8)、Bot(15)、概念(1)、综合分析(7)、主题(43)、其他(23)。

Wiki 目录与 Portal 集成(2026-04-10)

Wiki 数据架构

Portal 的 Wiki Tab 通过后端 API 直接读取 ~/.openclaw/wiki/ 目录下的文件:

数据源文件数大小说明
pages-v2/92580KB核心 Wiki 内容(项目、Bot、概念、综合分析等)
graphify-out/568KB知识图谱数据(graph.json + clawline-timeline.md)
daily/1248KB日报

Wiki API 端点

端点功能
GET /api/wiki/pages页面列表(path、title、type、tags、parent)
GET /api/wiki/pages/{path}单页内容(frontmatter + markdown)
GET /api/wiki/search?q=全文搜索

知识图谱可视化

通过 Graphify (v0.3.17) 对 pages-v2/ 做语义提取,生成交互式 D3.js 图谱:

目录清洁问题

Wiki 目录共 570 个文件,但核心产出仅约 100 个,raw/ 目录有 ~470 个可清理的旧文件(旧版 Wiki 残留、已消化的 Mattermost 原始聊天、旧版 topics)。

增量更新现状

  • Wiki Skill 定义了 /wiki ingest [source] 命令,支持手动触发从 MM API 拉新消息
  • 尚无基于 Clawline cl_messages 表的自动化增量更新
  • 历史记录中提到 wiki-ingest.js 脚本(从 Supabase 查询 → LLM 摘要 → 生成 Wiki),但不在 wiki 目录中

生产 vs 开发环境不一致

环境地址Wiki API
开发版portal.dev.dora.restry.cn✅ 有(server.cjs 3559 行)
生产版agent-project.clawlines.net❌ 无(容器内旧版 server.js 1479 行)