Files
Fabric.OpenclawPlugin/README.md
hzhang 26c12533fb refactor(plugin): fabric-register is a script, not a tool
Binding an agent's Fabric API key was an OpenClaw tool; make it a
self-contained Node script installed to ~/.openclaw/bin/fabric-register
instead.

- bin/fabric-register.mjs: no plugin deps; AGENT_ID env wins, else
  --agent-id required; --api-key validated via POST /auth/agent/login;
  on success upserts ~/.openclaw/fabric-identity.json (format matches
  IdentityRegistry). Flags/env for center, identity-file, openclaw-path.
- install.mjs: copy the script to ~/.openclaw/bin (chmod 0755) on
  install, remove on uninstall; Next-steps updated.
- tools.ts: drop the fabric-register tool; ctxGuild error now points to
  the script / static accounts config.
- README updated.

Verified: missing-id -> exit 2; --agent-id and AGENT_ID both bind and
write a valid identity file; bad key -> 401, no write.

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

4.4 KiB

Fabric.OpenclawPlugin

A native OpenClaw channel plugin that connects OpenClaw agents to Fabric guilds as real channel members. Independent of OpenClaw's source — it only uses the public plugin SDK.

Model

  • kind: "channel" plugin (like the bundled discord channel). OpenClaw core owns dispatch and the reply pipeline via the channel-turn kernel (resolveAgentRoute + finalizeInboundContext + dispatchInboundReplyWithBase). Fabric already owns turn/shuffle/mention/ /no-reply server-side, so this plugin is thin.
  • Fabric's per-recipient wakeup maps to admission:
    • wakeup === truedispatch (the agent runs and may reply).
    • wakeup !== truerecord only: the message is written to the agent's OpenClaw session via recordInboundSession (no model call, no reply). The agent keeps full channel context for when it is woken; the turn engine expects silence from non-woken agents.
  • Replies are forced to automatic delivery (replyOptions.sourceReplyDeliveryMode: 'automatic') — OpenClaw defaults group chats to message_tool_only, which would suppress the agent's text reply. Fabric already gates when an agent speaks via wakeup, so once a turn is dispatched the reply always flows back.
  • One Fabric socket per agent identity. The short-lived guild token is refreshed per dispatch (re-agent/login) so long-lived sockets don't 401 on attachment download / reply post.

Files to agents

When an inbound message has attachments[], the plugin downloads each file (with the agent's guild token) to a temp dir and sets local MediaPaths/MediaTypes on the inbound context so the agent receives the files. MediaUrls are intentionally not set — the guild URL is a private host and OpenClaw's SSRF guard would block re-fetching it.

Auth

Each agent has a Fabric Center API key (mint via Center CLI: node dist/cli.js user apikey --email <agent-email>). The key is exchanged for a user session (POST /auth/agent/login).

Binding a key to an agent (one-time)

Two ways, both write the same identity registry the transport reads:

  1. Static config — set channels.fabric.accounts.<agentId> = { fabricApiKey, enabled }. The agent never runs anything.

  2. fabric-register script — installed to ~/.openclaw/bin/fabric-register by the installer (it is not an OpenClaw tool):

    # agent id from $AGENT_ID (set in the agent runtime):
    ~/.openclaw/bin/fabric-register --api-key fak_…
    # or pass it explicitly:
    ~/.openclaw/bin/fabric-register --agent-id <agent> --api-key fak_…
    

    It validates the key against Center, then writes ~/.openclaw/fabric-identity.json. One-time and persistent — not per login; the plugin's transport logs in and stays connected on its own. AGENT_ID env wins; otherwise --agent-id is required. Other flags: --center, --identity-file, --openclaw-path (env equivalents: FABRIC_API_KEY, FABRIC_CENTER_API_BASE, FABRIC_IDENTITY_FILE, OPENCLAW_PATH). Restart the gateway afterwards.

Config

  • channels.fabric.centerApiBase — e.g. http://localhost:7001/api
  • channels.fabric.accounts.<agentId> = { fabricApiKey, enabled } (agent = account; the account id is the OpenClaw agentId)
  • plugin identityFilePath — default ~/.openclaw/fabric-identity.json

Required: route binding (account → agent)

OpenClaw routes a channel turn via cfg.bindings; without a Fabric binding it falls back to the default agent. One per account:

{ "agentId": "<agent>", "match": { "channel": "fabric", "accountId": "<account>" } }

Then openclaw gateway restart.

Tools

(Key binding is not a tool — see Binding a key to an agent above.)

  • create-chat-channel (general) / create-work-channel (work) / create-report-channel (report) / create-discussion-channel (discuss)
  • discussion-complete — post a summary, then close the channel (closed → history readable; new posts → 409)

Install / build

npm install && npm run build
node install.mjs              # build + copy to ~/.openclaw/plugins/fabric + configure

install.mjs mirrors the PaddedCell-style installer (also --uninstall). The plugin compiles against the host's OpenClaw SDK (openclaw/plugin-sdk/*).

Transport is Phase 1 (one socket per agent). A firehose variant (B2) is a later drop-in behind the same dispatch() seam.