First successful push emits an info-level "monitor push started" so
operators can confirm the loop wired up correctly. Subsequent
successes log every 60 cycles ("monitor push heartbeat") so the
journal stays quiet but still proves the loop isn't dead. Errors
already log at warn; this fills the success-side gap so a silent
journal can't hide a "no successes, no errors" pathology.
HarborForge.PlexumPlugin
Plexum-side equivalent of HarborForge.OpenclawPlugin: exposes Plexum-side telemetry to the HarborForge Monitor bridge, drives the HarborForge Calendar scheduler, and gives agents a tool surface for the same calendar lifecycle actions OpenClaw agents had.
Part of the HarborForge platform; tracked as a git submodule of the HarborForge umbrella repo.
- Plugin id:
harbor-forge(matches the OpenClaw counterpart so the backend's per-plugin schemas don't fork) - Plugin version:
0.1.0 - Activation:
eager— Monitor bridge + Calendar scheduler must be running before any agent turn fires - Plexum SDK version: requires
Plexum-sdk-gowithHostAPI.WakeAgent(commit 216cf21 or later)
What it does
- Monitor push loop — when
monitor_push_enabled: true, posts a flat telemetry payload (cpu/mem/disk/swap/load + per-agent state) to<backendUrl>/monitor/server/heartbeateverymonitor_push_interval_seconds. This replaces the standaloneharborforge-monitordaemon — the plugin's lifecycle (gateway start/stop) bounds the loop, so a separate supervisor isn't needed. Use the sameapiKeyvalue the standalone monitor'sHF_MONITER_API_KEYcarried. - Monitor bridge (optional) — HTTP server on
127.0.0.1:<monitor_port>that responds to/telemetrywith a Snapshot. Useful when the standalone monitor is still present and you want it to enrich its push payload from the plugin's view of agents. Disable by settingmonitor_port: 0. - Calendar scheduler — heartbeats
<backendUrl>/calendar/agent/ heartbeatevery interval, receives any TimeSlots due to fire, and dispatches them throughHostAPI.WakeAgent(state-aware queue with depth-1 replace-newest) - 9 harborforge_ tools* mirroring the OpenClaw plugin's surface
| Tool | Use |
|---|---|
harborforge_status |
resolved config + Monitor bridge health + Calendar status + telemetry snapshot |
harborforge_telemetry |
fresh system + agent metrics |
harborforge_monitor_telemetry |
last bridge query timing + last snapshot served |
harborforge_calendar_status |
active slot(s) + history + heartbeat clock |
harborforge_calendar_complete |
mark active slot completed (+optional summary) |
harborforge_calendar_abort |
mark active slot aborted (+optional reason) |
harborforge_calendar_pause |
pause active slot (non-terminal) |
harborforge_calendar_resume |
resume a paused slot |
harborforge_restart_status |
backend restart-pending flag + last poll time |
Install
git clone --recurse-submodules https://git.hangman-lab.top/zhi/HarborForge.PlexumPlugin
cd HarborForge.PlexumPlugin
bash scripts/install.sh # or: make install
Then in ~/.plexum/plexum.json:
{
"plugins": {
"allow": [
".",
"harbor-forge"
]
}
}
And configure at ~/.plexum/plugins/harbor-forge/config.json:
{
"backendUrl": "https://hf-api.hangman-lab.top",
"identifier": "server-t3",
"apiKey": "g1_xxx",
"monitor_push_enabled": true,
"monitor_push_interval_seconds": 30,
"monitor_port": 0,
"calendar_enabled": true,
"calendar_heartbeat_interval_seconds": 30
}
Replacing the standalone harborforge-monitor container: lift the
container's HF_MONITER_API_KEY into apiKey, set
monitor_push_enabled: true, then docker rm -f harborforge-monitor
once you've confirmed the plugin's pushes are landing (the backend's
server_states.last_seen_at should keep advancing without the
container running).
Restart the host (systemctl --user restart plexum) and verify:
plexum plugin-list | grep harbor
curl -s http://127.0.0.1:9100/health
curl -s http://127.0.0.1:9100/telemetry | jq .agents
How calendar wake works
When the backend returns a slot_to_fire in a heartbeat response:
- Scheduler builds the message from
slot.wake_options.override_messageor falls back toslot.prompt host.WakeAgent({agent_id, message, source: "calendar:slot-<id>"})- Plexum host-side
wake.Manager:- if agent's sm-state is
idle→ runs the turn synchronously in a goroutine against the agent'swakesession - else → enqueues (depth 1; new wake replaces any pending one)
- drains automatically when the running turn returns
- if agent's sm-state is
- The
sourcetag lands on the turn's faithful event so retros can tell which slot caused which turn
The agent uses harborforge_calendar_complete / _abort / _pause /
_resume mid-turn to push status back to the backend.
Layout
HarborForge.PlexumPlugin/
├── manifest.json # plugin manifest (eager, 9 tools)
├── go.mod # → Plexum-sdk-go (replace ../)
├── cmd/plexum-harborforge-plugin/ # main entry (Serve + Init)
├── internal/config/ # config.json schema + Resolve
├── internal/telemetry/ # /proc-based snapshot collector
├── internal/monitor/ # HTTP bridge for HF.Monitor
├── internal/calendar/ # types + backend client + scheduler
├── internal/tools/ # 9 tool implementations
└── scripts/install.sh # build + drop into ~/.plexum/plugins
Differences vs OpenClaw equivalent
| OpenClaw plugin | Plexum plugin |
|---|---|
api.registerTool(factory) runtime |
ToolPlugin.CallTool + manifest contract |
api.spawn({agentId, task}) |
HostAPI.WakeAgent({agent_id, message, source}) (state-aware queue) |
api.getAgentStatus() |
HostAPI.ReadAgentState(ctx, agent_id) |
--install-monitor / --install-cli flags |
n/a — Monitor + hf CLI deploy separately (e.g. via HangmanLab.Server.T3 docker compose) |
TS source compiled by tsc |
static Go binary built per-platform |