F-3 refinements:
- internal/inbound: replace fixed 3s reconnect wait with exponential
backoff (1s → 60s, ×2, reset when prior session lasted >30s); proxy
for "healthy" vs "flapping" and avoids hot reconnect loops when the
server is sick
F-4 agent tool surface (port of openclaw plugin's tools.ts):
- internal/tools/tools.go (~370 LOC): Registry binds Deps {Client,
Tokens, Identities} and exposes 8 agent-facing tools:
fabric-send-message post a normal message to any channel
fabric-send-sys-msg post a kind=sys message (bypasses turn engine)
fabric-channel-list list channels visible in a guild
fabric-guild-list list guilds the agent is in
fabric-message-history paginate channel messages by seq
fabric-channel-set-purpose PATCH the channel's purpose
fabric-channel fetch metadata + members for one channel
fabric-canvas get/share/update/remove channel canvas
- internal/tools/contracts.go: static ToolContract list — kept in sync
with install.sh's manifest emitter
- Every agent-scoped tool requires agent_id in input args (Plexum SDK
doesn't propagate calling agent id through CallTool today)
- guild_node_id defaults to agent's first guild for fabric-send-message
internal/fabric/client.go: new REST methods needed by tools —
PostSystemMessage, CreateChannel, CloseChannel, JoinChannel,
LeaveChannel, SetChannelPurpose, GetCanvas, ShareCanvas, UpdateCanvas,
RemoveCanvas, SyncCommands.
cmd/plexum-fabric-channel-plugin/main.go:
- Manifest declares the tool surface via tools.New(...).Contracts()
- CallTool dispatches "send" to handleSend (outbound for channel
manager), everything else to tools.Registry.Handler(name)
scripts/install.sh:
- Manifest tools[] now lists all 9 tools with schemas — matches what
internal/tools/contracts.go advertises
Live verified against running Fabric stack:
$ plexum plugin-call fabric-guild-list '{"agent_id":"fabrictester"}'
→ "guilds for agent fabrictester (1): test-guild2 @ http://localhost:7003"
$ plexum plugin-call fabric-channel-list '{...,"guild_node_id":"test-guild2"}'
→ 2 channels listed
$ plexum plugin-call fabric-message-history '{...,"limit":5}'
→ 5 messages with timestamps + authors
F-5+ deferred:
- create-{chat,work,report,discussion}-channel (batch 2)
- sub-discussion family (state store + 3 tools)
- presence-sync + command-sync
- attachments
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ports the foundation of Fabric.OpenclawPlugin to a native Plexum
channel plugin (Go). F-2+ phases (socket.io inbound, wakeup gate,
tools, presence, etc.) follow.
Layout:
internal/identity/ — fabric-identity.json registry (agent → API key)
internal/fabric/ — REST client (Center auth + Guild messaging)
internal/config/ — channels/<name>.json fabric extension parser
cmd/plexum-fabric-register/ — agent registration CLI
cmd/plexum-fabric-channel-plugin/— Plexum SDK plugin entry
scripts/install.sh — build + install + manifest generator
Plugin behavior (F-1):
- Reads <profile>/channels/*.json, filters plugin=plexum-fabric-channel,
builds (plexum-channel-name → fabric channel-id) index
- Validates each bound agent's API key against Center at init
(warmSessions); logs warning but doesn't refuse init on bad keys
- `send` MCP tool: POST plain text to the bound Fabric channel as the
agent user; selects guild endpoint+token from cached session
- Manifest channels[] is generated by install.sh from current
channels/*.json — re-run with --reset-manifest after adding bindings
- Plugin-private config at
<profile>/plugins/plexum-fabric-channel/config.json
(center_api_base, default http://localhost:7001/api)
Live smoke verified:
- plexum-fabric-register against running Fabric Center (port 7001):
validated fak_..., wrote identity file with user_id + email captured
Tests: identity (5) + config (6) = 11 unit tests.
F-2 will hook socket.io for inbound + wakeup gating + token refresh.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>