hzhang 9ba591795b fix: wake dedupe + inline slot context + complete contracts.tools
Three issues making HF→agent wakeup unusable in practice, surfaced by
DinD sim end-to-end test (recruiter agent + slot for 招募 manager task):

1. **Plugin re-woke the same slot every 30s.** The inline runCheck only
   destructured agentId from scheduleCache.getAgentsWithDueSlots() and
   dropped the slots array, then called wakeAgent without recording the
   wake. The simplified inline scheduler also never PATCHes slot status
   server-side from not_started→ongoing, so the next 30s check sees the
   slot still due and wakes again. After 4 wakes the agent's wakeup
   session was full of WAKEUP_OK noise.

   Fix: keep slots in runCheck, add an in-memory wakedSlotKeys set
   keyed by (agentId, slotId|virtual_id|scheduled_at). Dedupe on this
   set; clear it inside the sync interval (fresh wake budget per sync).
   Server-side slot transition still TODO (requires re-introducing the
   CalendarScheduler class path or PATCH /calendar/slots/.../agent-update
   here); the dedupe at least stops the wake spam.

2. **Wakeup message had no slot context.** The wakeup body just said
   'follow hf-wakeup workflow' with no slot id/event_data/task_code.
   The agent then had to call harborforge_calendar_status to learn
   anything — which itself is broken in the simplified scheduler (it
   queries a CalendarScheduler instance that never gets created).

   Fix: pass dueSlots into wakeAgent and inline the highest-priority
   slot's {slot_id, scheduled_at, priority, slot_type, event_data} as
   a JSON block in the wakeup message. The agent reads event_data.
   task_code directly and routes via workflow_lookup without any
   round-trip. Per PLG-CAL-001 docs in hf-hangman-lab SKILL.md, this
   is the documented contract; we are bringing the message in line.

3. **contracts.tools listed 5 of the 9 registered tools.** Manifest had
   harborforge_status/telemetry/monitor_telemetry/calendar_status/
   calendar_complete. Code also registers calendar_abort, calendar_pause,
   calendar_resume, harborforge_restart_status. With the new OpenClaw
   plugin host enforcement (same gotcha that bit Meridian — see
   zhi/Meridian#2), undeclared tools are silently dropped from the
   agent's tool list, so abort/pause/resume cannot be called by the
   agent. plugin doctor was emitting:
   'plugin tool is undeclared (harbor-forge): harborforge_calendar_abort'
   for each missing tool.

   Fix: add the 4 missing tool names to contracts.tools.

Also use api.config as the primary config source in wakeAgent (current
public API), falling back to runtime.config.loadConfig() for older
hosts — same pattern as the Meridian fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:02:25 +01:00

HarborForge OpenClaw Plugin

OpenClaw plugin that exposes OpenClaw-side metadata to the HarborForge Monitor, provides an optional local Monitor bridge, drives the HarborForge Calendar scheduler, and can optionally install the hf CLI.

Part of the HarborForge platform.

  • Role: OpenClaw integration layer for HarborForge (registered plugin id: harbor-forge).
  • Talks to the HarborForge backend (backendUrl, default https://monitor.hangman-lab.top) for Calendar APIs.
  • Talks to a local HarborForge.Monitor bridge over 127.0.0.1:<monitor_port> (no fixed default; commonly 9100).

Current State

  • Plugin registration id: harbor-forge (was harborforge-monitor)
  • Plugin version: 0.2.0 (package manifests); telemetry reports pluginVersion 0.3.1
  • Legacy sidecar server/ architecture removed — telemetry is served directly by the plugin
  • Monitor bridge runs over the local monitor_port
  • Calendar scheduler integration (PLG-CAL-001 / 002 / 004)
  • Installer supports --install-cli and an optional managed Monitor (--install-monitor)
  • skills/hf/ is installed only with --install-cli

Project Structure

HarborForge.OpenclawPlugin/
├── package.json
├── README.md
├── docs/                         # design notes (calendar, monitor connector)
├── plugin/
│   ├── openclaw.plugin.json      # plugin manifest + config schema
│   ├── index.ts                  # plugin entry, tool registration
│   ├── tsconfig.json
│   ├── core/
│   │   ├── config.ts             # config defaults / resolution
│   │   ├── managed-monitor.ts    # optionally spawn HarborForge.Monitor
│   │   ├── monitor-bridge.ts     # client for the Monitor bridge
│   │   └── openclaw-agents.ts    # enumerate OpenClaw agents
│   ├── calendar/                 # Calendar scheduler + bridge
│   │   ├── index.ts
│   │   ├── scheduler.ts
│   │   ├── calendar-bridge.ts
│   │   └── types.ts
│   ├── hooks/
│   │   ├── gateway-start.ts
│   │   └── gateway-stop.ts
│   └── package.json
├── skills/
│   └── hf/
│       └── SKILL.md              # installed only with --install-cli
└── scripts/
    └── install.mjs

Installation

Standard Install

node scripts/install.mjs

This will:

  • Build and install the OpenClaw plugin
  • Copy regular skills
  • Not install the hf binary
  • Not copy skills/hf/

Plugin + hf CLI

node scripts/install.mjs --install-cli

This additionally:

  • Builds HarborForge.Cli (go build ./cmd/hf)
  • Installs hf to <openclaw>/bin/hf (default ~/.openclaw/bin/hf) and chmod +x
  • Copies skills/hf/ into the OpenClaw skills directory

Common Options

# Build only (no install / config)
node scripts/install.mjs --build-only

# Install only, skip dependency checks
node scripts/install.mjs --skip-check

# Specify OpenClaw profile path (also honors OPENCLAW_PATH env)
node scripts/install.mjs --openclaw-profile-path /custom/path/.openclaw

# Build and install a managed HarborForge.Monitor binary alongside the plugin
node scripts/install.mjs --install-monitor yes --monitor-branch main

# Verbose logs
node scripts/install.mjs --verbose

# Uninstall (plugin, config entries, hf binary, managed monitor)
node scripts/install.mjs --uninstall

The installer also updates OpenClaw config (plugins.load.paths, plugins.allow, plugins.entries.harbor-forge.enabled) via openclaw config.

Configuration

Edit ~/.openclaw/openclaw.json:

{
  "plugins": {
    "entries": {
      "harbor-forge": {
        "enabled": true,
        "config": {
          "enabled": true,
          "backendUrl": "https://monitor.hangman-lab.top",
          "identifier": "my-server-01",
          "apiKey": "your-api-key-here",
          "monitor_port": 9100,
          "reportIntervalSec": 30,
          "httpFallbackIntervalSec": 60,
          "logLevel": "info",
          "calendarEnabled": true,
          "calendarHeartbeatIntervalSec": 60
        }
      }
    }
  }
}

Then restart:

openclaw gateway restart

Config Options

Option Type Default Description
enabled boolean true Enable the plugin
backendUrl string https://monitor.hangman-lab.top HarborForge backend base URL (Monitor + Calendar APIs)
identifier string hostname Server / claw identifier
apiKey string (none) Server API key from the HarborForge Monitor admin panel
monitor_port number (none) Local bridge port; plugin talks to HarborForge.Monitor via 127.0.0.1:<monitor_port>
reportIntervalSec number 30 Metadata push interval (seconds)
httpFallbackIntervalSec number 60 HTTP heartbeat interval when WS unavailable
logLevel string info Log level: debug / info / warn / error
calendarEnabled boolean true Enable Calendar scheduler integration (PLG-CAL-001)
calendarHeartbeatIntervalSec number 60 Calendar heartbeat interval (seconds)
calendarApiKey string (none) API key for Calendar API auth; falls back to apiKey / X-Agent-ID
managedMonitor string (none) Absolute path to a HarborForge.Monitor binary; if set, gateway start/stop hooks spawn/stop it

Local Monitor Bridge

When the plugin has monitor_port configured and HarborForge.Monitor uses the same MONITOR_PORT:

  • Monitor serves a local bridge on 127.0.0.1:<MONITOR_PORT>
  • The plugin probes GET /health
  • The plugin tool harborforge_monitor_telemetry reads GET /telemetry
  • The plugin pushes OpenClaw metadata (version, plugin version, agents) via POST /openclaw on the reportIntervalSec cadence, enriching Monitor heartbeats
  • If the bridge port is unconfigured or unreachable, the plugin still works normally

This link is an optional enhancement, not a precondition for the plugin to start or for Monitor heartbeats.

Managed Monitor

If managedMonitor points to an installed HarborForge.Monitor binary, the gateway_start hook spawns it (passing --backend-url, --identifier, --api-key, --monitor-port, --report-interval, --log-level from the plugin config) and gateway_stop terminates it. Use install.mjs --install-monitor yes to build and wire this automatically.

Calendar Scheduler

When calendarEnabled is true, on gateway start the plugin starts a Calendar scheduler that heartbeats the backend (/calendar/agent/heartbeat, /calendar/agent/status, /calendar/agent/notify) to receive and run scheduled TimeSlots, waking/spawning agents via the OpenClaw spawn API (with a notification fallback). Scheduler state is persisted to a state file; gateway restarts can be requested by the backend (PLG-CAL-004).

Tools Provided

Tool Description
harborforge_status Plugin status, resolved config, Monitor bridge health, calendar status, telemetry snapshot
harborforge_telemetry Current system telemetry snapshot from this host
harborforge_monitor_telemetry Query the Monitor bridge for host hardware telemetry
harborforge_calendar_status Calendar scheduler status and current slot
harborforge_calendar_complete Complete the current calendar slot with actual duration
harborforge_calendar_abort Abort the current calendar slot
harborforge_calendar_pause Pause the current calendar slot
harborforge_calendar_resume Resume the paused calendar slot
harborforge_restart_status Check whether a gateway restart is pending

Telemetry Snapshot Fields

  • identifier, hostname, platform, timestamp
  • uptime
  • memory: total / free / used / usagePercent
  • load: avg1 / avg5 / avg15
  • openclaw: version / pluginVersion

Development

cd plugin
npm install
npm run build

The build runs tsc and emits dist/ (dist/index.js is the plugin entry).

Dependencies

  • Node.js 18+
  • OpenClaw Gateway
  • Go 1.20+ (only for --install-cli / --install-monitor)

Tips

  • After installing hf, add ~/.openclaw/bin to your PATH
  • When an agent uses hf, try hf --help-brief first
  • For the full command tree, see hf --help
Description
No description provided
Readme 5.3 MiB
Languages
TypeScript 85.3%
JavaScript 14.7%