OpenClaw's canonical convention is to emit metadata envelopes (chat_id, sender, reply target, …) as SEPARATE user-role messages folded into the openai-completions request right after the real one — `extractLatestUserMessage` skips those whole. Fabric.OpenclawPlugin's dispatch does not split: it passes metadata blocks and the real user content as ONE merged user-message body, separated by blank lines. With the prior filter that meant the entire turn was dropped with "no user message found" (HTTP 400) because the first line matched a sentinel — the actual prompt sitting after the metadata blocks never reached the bridge. When the whole-body check fails for a single-message body, walk past leading sentinel-prefixed blocks (sentinel header + optional ```json code fence + blank-line separator) and use whatever non-metadata block follows. Falls back to the previous "skip entirely" semantics when the body is metadata-only. End-user symptom that surfaced this: every contractor agent (Claude / Gemini) subscribed to a Fabric channel silently failed to reply to sub-discussion messages during recruitment — fabric dispatch said "completed" in 1.6s but trajectory had `assistantTexts: []`, `terminalError: non_deliverable_terminal_turn`, `errorMessage: "400 \"no user message found\""`. Surfaced recruiting developer1 on prod-t2 2026-05-31.
Description
No description provided
Languages
TypeScript
85.1%
JavaScript
14.9%