Fleet node structured logging: capabilities registered and actions invoked

Merged
WI
3mo ago
+303-19

What

A served fleet node (relay node up [--config node.ts]) now emits structured logs of what it does: each capability it registers and every action that hits it — invoked / completed / failed, each with a duration and structured fields ({ node, capability, kind, action, invocationId, ms, error }).

Turning it on:

relay node up --config ./scout.node.ts --log-file ./node.log   # write to a file
relay node up --config ./scout.node.ts --log-level debug        # include per-capability lines
relay node up --config ./scout.node.ts --log-json               # one JSON object per line

Levels: capability registration → debug, action invoked/completed → info, failures → warn. With no --log-* flag (and no --verbose) the node stays quiet, surfacing only warnings — unchanged from today.

How

  • @agent-relay/fleet (serve-node.ts) — a FleetLogger seam (shape-compatible with @agent-relay/utils createLogger) carries lifecycle and per-invocation events with a structured extra bag. serveNode/startServeNode accept logger?; the existing log/warn callbacks still work, adapted onto it. handleInvoke logs invoked → completed/failed with elapsed ms; registration logs each capability then the summary.
  • CLI (node up) — --log-file / --log-level / --log-json map onto the AGENT_RELAY_LOG_* env the shared logger already reads; --verbose raises the floor to debug. When any is set, createLogger('fleet') is injected into the served node instead of the quiet warn-only callback.

The logger is injected (not imported by fleet), so @agent-relay/fleet stays dependency-free at its seam — a host can supply any sink (stdout, file, a JSON collector).

Verification

  • packages/fleet tests (13, +3 new) — assert per-capability, invoked/completed (with ms), and failed (warn + error) events flow through an injected logger against an in-process broker.
  • CLI + fleet typecheck clean; broker-lifecycle (21) and node/core command tests pass (2 pre-existing failures on origin/main, unrelated: a 5s node-delivery timeout and a SIGINT test).
  • End-to-end: injected createLogger('fleet') writes the exact events to a file in both text and --log-json form.

Follow-ups (separate)

🤖 Generated with Claude Code