docs/reference/rich-output-protocol.md
Assistant output carries delivery/render directives through a few dedicated channels:
mediaUrl / mediaUrls fields for attachment delivery.[[audio_as_voice]] for audio presentation hints.[[reply_to_current]] / [[reply_to:<id>]] for reply metadata.[embed ...] for Control UI rich rendering.Structured media fields and [[...]] tags are delivery metadata. [embed ...] is the separate web-only rich-render path; it is not a media alias.
Remote attachments must be public https: URLs. http:, loopback, link-local, private, and internal hostnames are rejected as attachment directives; server-side media fetchers apply their own network guards on top.
Local attachments accept absolute paths, workspace-relative paths, or home-relative ~/ paths. They still pass the agent file-read policy and media type checks before delivery.
{ "message": "Here is your image.", "mediaUrl": "/workspace/image.png" }
Legacy final-reply text may still be normalized for compatibility, but this is not a general plugin/tool protocol. </Warning>
Plain Markdown image syntax () stays text by default. Channels that want Markdown images treated as media replies opt in at their outbound adapter; Telegram does this so  becomes a media attachment.
When block streaming is enabled, media must ride on structured payload fields. If the same media URL appears in a streamed block and again in the final assistant payload, OpenClaw delivers it once and strips the duplicate from the final payload.
[embed ...][embed ...] is the only agent-facing rich-render syntax for the Control UI. Self-closing example:
[embed ref="cv_123" title="Status" /]
Rules:
[view ...] is no longer valid for new output.ref="..." or url="...".The normalized/stored assistant content block is a structured canvas item:
{
"type": "canvas",
"preview": {
"kind": "canvas",
"surface": "assistant_message",
"render": "url",
"viewId": "cv_123",
"url": "/__openclaw__/canvas/documents/cv_123/index.html",
"title": "Status",
"preferredHeight": 320
}
}
present_view is not recognized; stored/rendered rich blocks always use this canvas shape.