hzhang fc7efd0227 fix(plugin): force automatic source-reply delivery (fixes no-reply)
OpenClaw defaults group-chat replies to sourceReplyDeliveryMode
'message_tool_only', which suppresses auto-delivery of the agent's
text reply (it expects the agent to call a message tool). With
ChatType 'group', the Fabric plugin's deliver callback was therefore
NEVER invoked — the agent ran but no reply ever returned to Fabric.

Fabric already gates *when* an agent speaks via the per-recipient
wakeup flag, so once a turn is dispatched the reply must always flow
back. Pass replyOptions.sourceReplyDeliveryMode='automatic' so
OpenClaw delivers the agent's reply through  regardless of
the group default (source-reply-delivery-mode honors a truthy
requested mode).

Verified live end-to-end: human posts -> wakeup -> agent runs ->
'fabric: deliver' + 'fabric: posted reply' -> agent message appears
in the Fabric channel.

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

Fabric.OpenclawPlugin

An OpenClaw channel plugin that connects OpenClaw agents to a Fabric guild.

Model

  • kind: "channel" plugin (like the bundled discord channel). OpenClaw core owns dispatch (inbound → agent run) and the reply pipeline via the channel turn kernel runtime.channel.turn.run(...).
  • Fabric already owns turn/shuffle/mention//no-reply server-side, so this plugin is thin. Fabric's per-recipient wakeup maps to channel-turn admission:
    • wakeup === truedispatch (agent runs, may reply)
    • otherwise → { kind: "drop", recordHistory: true } (kept as context)
  • No sidecar, no fake no-reply model, no before_model_resolve gating.

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) used to receive (socket) and post replies. Bind a key to an agent via the fabric-register tool, or pre-populate the identity file.

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 ({ entries: [{ agentId, fabricApiKey }] })

Required: route binding (account → agent)

openclaw routes a channel turn to an agent via cfg.bindings. Without a Fabric binding it falls back to the default agent. Add one per account:

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

e.g. openclaw config set bindings '[…, {"agentId":"echo","match":{"channel":"fabric","accountId":"echo"}}]' --json, then openclaw gateway restart.

Tools

  • fabric-register — bind this agent's Fabric API key
  • 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 (Fabric POST /channels/:id/close; closed → history readable, posts → 409)

Transport (Phase 1 = B1)

One Fabric socket per agent identity, in the plugin runtime. Firehose (B2) is a later drop-in behind the same dispatch() seam.

Build

npm install && npm run build

The plugin compiles against the host's OpenClaw SDK (openclaw/plugin-sdk/*); build inside the OpenClaw plugin environment.

Description
No description provided
Readme 11 MiB
Languages
TypeScript 91%
JavaScript 9%