OpenClaw 富输出协议(Rich Output Protocol)完全指南:结构化媒体、内联指令与 Control UI 富渲染

发布时间:2026/9/13 22:35:57
OpenClaw 富输出协议(Rich Output Protocol)完全指南:结构化媒体、内联指令与 Control UI 富渲染 OpenClaw 富输出协议Rich Output Protocol完全指南结构化媒体、内联指令与 Control UI 富渲染【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw本篇技术指南以 OpenClaw 仓库中的 富输出协议参考文档 为骨架系统讲解助手输出携带投递/渲染指令的四类专用通道结构化mediaUrl/mediaUrls附件字段、[[audio_as_voice]]音频提示、[[reply_to_current]]/[[reply_to:id]]回复元数据以及面向 Control UI 的[embed ...]富渲染短代码。读完本文你将掌握在工具、插件、流式块、消息动作与最终回复中正确附加媒体、表达音频与回复意图、以及渲染内嵌画布的完整实战方案并理解其底层解析与安全校验实现。一、协议总览四条投递通道的边界OpenClaw 的助手输出通过几条专用通道携带投递delivery与渲染render指令其职责划分如下通道形态作用域性质mediaUrl/mediaUrls结构化字段附件投递投递元数据delivery metadata[[audio_as_voice]]内联标签音频呈现提示投递元数据[[reply_to_current]]/[[reply_to:id]]内联标签回复元数据投递元数据[embed ...]短代码Control UI 富渲染独立的 Web-only 富渲染路径不是媒体别名关键边界在于结构化媒体字段与[[...]]标签属于投递元数据而[embed ...]是独立于媒体附件的富渲染通道。[embed ...]负责在 Web 端渲染内嵌内容绝不应当被当作媒体附件的别名使用。二者走完全不同的解析与渲染管线分别见 src/media/parse.ts 与 src/chat/canvas-render.ts。二、媒体附件Media Attachments2.1 远程附件的硬性约束远程附件必须是公开的https:URL。以下类型的地址会被作为附件指令直接拒绝http:非 TLS协议loopback回环地址如localhostlink-local链路本地地址如169.254.x.x私网private地址与内部主机名如*.local、*.internal、metadata.google.internal等。在这些基础校验之上服务端的媒体抓取器server-side media fetchers还会叠加自己的网络防护规则形成双层防线。源码佐证见 src/media/parse.ts 中的isAllowedRemoteMediaUrl()与isBlockedRemoteMediaHostname()src/media/parse.ts#L129-L178远程 URL 必须满足parsed.protocol https:、URL 中不允许携带username/password、主机名不能落入被屏蔽名单同时还会调用openclaw/net-policy中的isBlockedSpecialUseIpv4Address/isBlockedSpecialUseIpv6Address对 IP 地址形态做特殊用途网段拦截。也就是说即便某个 URL 伪装成合法域名只要解析后落在内网/保留网段同样会被拒绝。2.2 本地附件的路径规则本地附件接受三种路径形态绝对路径如/workspace/image.png工作区相对路径workspace-relative如workspace/image.pnghome 相对路径即以~/开头的路径。但本地路径在投递前仍需通过两道关卡Agent 文件读取策略agent file-read policy——决定该 Agent 是否有权读取目标文件媒体类型检查media type checks——确认文件确实是可投递的媒体类型。实现上src/media/parse.ts 的isLikelyLocalPath()明确拒绝路径穿越../段与不支持的 home 目录前缀resolveUserPath见 src/agents/embedded-agent-runner/run/images.media-refs.ts会把~展开为真实用户目录。此外媒体源字符串长度超过 4096 字符、或包含空白字符未显式开启allowSpaces时都会被判定为非法媒体。2.3 结构化字段的正确用法重要警告不要为了附加附件而在工具、插件、流式块、浏览器输出或消息动作中输出文本命令。正确做法是使用结构化媒体字段{ message: Here is your image., mediaUrl: /workspace/image.png }为兼容旧版行为遗留的最终回复文本仍可能被归一化处理但这不是通用的插件/工具协议。所有面向工具、插件、浏览器输出、流式块与消息动作的附件都必须走结构化mediaUrl/mediaUrls字段。从端到端实现看src/agents/embedded-agent-runner/run/tool-media-payloads.ts 的mergeAttemptToolMediaPayloads()会把工具结果中发现的媒体载荷合并进该轮助手产生的 channel payload取第一个成功、非 reasoning 的回复认领媒体使文本与附件保持在同一 payload 中生成的 payload 形如{ mediaUrls, mediaUrl: urls[0], audioAsVoice, trustedLocalMedia }src/agents/embedded-agent-runner/run/tool-media-payloads.ts#L103-L108并通过splitMediaFromOutput()把文本中的媒体引用与可见文本分离。三、遗留MEDIA:行Legacy历史遗留的最终助手回复仍可通过一行独立的MEDIA:文本附加本地媒体。解析器只识别那些修剪trim后以MEDIA:开头、且不在 Markdown 包装与代码围栏code fence之内的独立行。合法的遗留最终回复Here is the generated image. MEDIA:/workspace/image.png以下形态只是普通文本不会附加媒体**MEDIA:/workspace/image.png** MEDIA:/workspace/image.png Here is your image: MEDIA:/workspace/image.png也就是说加粗、行内代码、或嵌在句子中间的MEDIA:都不会被识别为附件指令。解析器仅认准独立成行 行首即MEDIA:这一种形态且会跳过代码围栏区域内的文本对应 src/media/parse.ts 的MEDIA_TOKEN_RE与 Markdown 围栏扫描逻辑。推荐做法工具、插件、浏览器输出、流式块与消息动作仍然优先使用结构化mediaUrl/mediaUrls字段而非MEDIA:文本行。3.1 Markdown 图片语法的默认行为默认情况下普通的 Markdown 图片语法alt保持为文本不会自动转成媒体附件。只有在出站适配器outbound adapter显式选择将 Markdown 图片回复映射为媒体附件时才会转换——例如 Telegram 通道适配器就是这样做的使得alt可以变成媒体回复。3.2 块流式Block Streaming下的媒体去重启用块流式时媒体必须承载在结构化 payload 字段上。如果同一个媒体 URL 既出现在某个流式块中又再次出现在最终助手 payload 里OpenClaw 只会投递一次并从最终 payload 中剥离重复项。对应实现见 src/media/parse.ts 的collectMarkdownImageSegments()它把一行中的可见文本与媒体段分离并支持allowlist允许列表机制——只有命中 allowlist 的 Markdown 图片才会被提升为媒体段其余保持原样文本从而从源头避免同一 URL 被重复处理。四、[embed ...]面向 Control UI 的唯一富渲染语法[embed ...]是面向 Agent 的、唯一受支持的 Control UI 富渲染短代码shortcode。自闭合示例[embed refcv_123 titleStatus /]4.1 规则清单[view ...]不再适用于新输出[embed ...]在 2026.4.11 起取代了它。Embed 短代码只在助手消息表面assistant message surface渲染。只有 URL 支撑的 embed 才会渲染必须使用ref...或url...属性。块形式的行内 HTML embed 短代码不会渲染即[embed ...]...[\/embed]包裹内容的块形式不被支持渲染只认自闭合形式。Web UI 会从可见文本中剥离短代码并在原位置内联渲染 embed。4.2 源码级解析实现解析器位于 src/chat/canvas-render.ts 的extractCanvasShortcodes()src/chat/canvas-render.ts#L269-L339通过parseFenceSpans先找出代码围栏区域围栏内的[embed ...]保持为可见文本不会被误解析这正是本文档示例短代码能安全写进代码块的原因使用两个正则分别匹配块形式[embed ...]...[\/embed]与自闭合形式[embed .../]其中自闭合形式要求属性区不以/结尾避免块正则贪婪吞掉后续可见文本匹配到url或ref属性即构造CanvasPreviewref会通过defaultCanvasEntryUrl()src/chat/canvas-render.ts#L225-L228映射为/__openclaw__/canvas/documents/encoded-ref/index.html最终返回剥离短代码后的文本 预览列表供 Control UI 渲染。previewFromShortcode()src/chat/canvas-render.ts#L230-L258支持title、height、class/class_name、style等附加属性其中height会被normalizePreferredHeight()src/chat/canvas-render.ts#L105-L109夹在 1601200 像素之间。4.3 渲染侧配置iframe 沙箱策略Control UI 对 hosted embed 的 iframe 沙箱策略由gateway.controlUi.embedSandbox控制共三档取值说明strict禁用 hosted embed 内的脚本执行scripts默认允许交互式 embed同时保持源隔离对自包含的浏览器小游戏/组件通常足够trusted在allow-scripts之上追加allow-same-origin供确实需要更强权限的同源文档使用{ gateway: { controlUi: { embedSandbox: scripts, }, }, }安全提醒仅在嵌入文档确实需要同源行为时才使用trusted。对于大多数 Agent 生成的小游戏与交互式 canvasscripts是更安全的选择。另外还有两个相关安全开关详见 Control UI Chat 文档 的 Hosted embeds 一节绝对外部http(s)embed URL 默认被屏蔽。若要让[embed urlhttps://...]加载第三方页面需要设置gateway.controlUi.allowExternalEmbedUrls: true由show_widget创建的组件widgets在所有沙箱模式下都通过已认证的 Gateway 连接加载在strict模式下其内容仍然可见但脚本交互被禁用。五、[[...]]内联指令音频提示与回复元数据[[audio_as_voice]]与[[reply_to_current]]/[[reply_to:id]]是内联文本标签形态的投递元数据。它们的解析实现在 src/utils/directive-tags.ts 的parseInlineDirectives()src/utils/directive-tags.ts#L174-L231[[audio_as_voice]] # 音频以语音形式呈现 [[reply_to_current]] # 回复当前消息 [[reply_to:id]] # 回复指定 id 的消息核心行为正则AUDIO_TAG_RE /\[\[\s*audio_as_voice\s*\]\]/gi与REPLY_TAG_RE /\[\[\s*(?:reply_to_current|reply_to\s*:\s*([^\]\n]))\s*\]\]/gisrc/utils/directive-tags.ts#L26-L27负责匹配匹配只在代码区域之外生效——replaceOutsideCodeRegions()会先用findCodeRegions定位代码围栏围栏内的[[...]]保持字面文本这是文档能安全展示这些标签示例的原因reply_to:id中的 id 会经sanitizeReplyDirectiveId()src/utils/directive-tags.ts#L119-L132清洗剔除控制字符与]且最长 256 个码点MAX_REPLY_DIRECTIVE_ID_LENGTH解析结果返回{ text, audioAsVoice, replyToId, replyToExplicitId, replyToCurrent, hasAudioTag, hasReplyTag }其中replyToId的取值优先级为显式reply_to:id优先否则回退到currentMessageId配合reply_to_current标签默认被剥离stripAudioTag/stripReplyTags默认true并以保留词边界的方式替换避免拼接出粘连单词。该解析器文件头部的注释还揭示了其定位[[...]]内联回复/音频标记是自动模式回复的最后一种文本适配器属于过渡性transitional机制未来当messages.visibleReplies默认切换为message_tool后投递意图将由结构化字段完全接管文本标记解析器将被移除。因此在编写新代码时优先考虑结构化字段而非内联文本标签。与此配套Control UI Chat 文档 明确说明渲染chat.history时UI 会从可见助手文本中剥离[[reply_to_*]]、[[audio_as_voice]]等仅用于显示的指令标签并忽略仅含静默令牌NO_REPLY/no_reply或心跳确认令牌HEARTBEAT_OK的助手条目。六、存储渲染形态结构化的canvas块归一化/存储后的助手内容块是一个结构化的canvas项{ 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不被识别存储/渲染的富内容块始终使用上述canvas形态字段语义kind: canvas与render: url标记这是一个 URL 渲染的 canvassurface: assistant_message限定其渲染表面为助手消息viewId对应[embed refcv_123 /]中的refurl指向/__openclaw__/canvas/documents/viewId/index.htmltitle与preferredHeight分别控制标题与首选高度。在 src/chat/canvas-render.ts 的coerceCanvasPreview()中可以看到更完整的字段兼容逻辑kind必须归一化为canvassurface只接受assistant_message或node_panel高度preferred_height/preferredHeight取数值并夹在 1601200 区间URL 可来自view.url/view.entryUrl也可来自source.type url的source.url还支持 MCP App 画布描述符mcpApp含viewId、serverName、toolName、uiResourceUri、toolCallId等字段与boardWidgetName需匹配/^[a-z0-9][a-z0-9._-]{0,63}$/。这些能力在 chat-display-projection.canvas.ts 与 server-methods/canvas.ts 的 Gateway 侧处理中继续向 UI 投影。七、实战决策速查表场景正确做法工具/插件/流式块/消息动作附加媒体结构化mediaUrl/mediaUrls字段遗留最终回复附加本地媒体独立成行的MEDIA:/path/to/file不推荐新代码使用音频以语音形式呈现[[audio_as_voice]]或结构化audioAsVoice字段表达回复当前消息[[reply_to_current]]或结构化回复字段表达回复指定消息[[reply_to:id]]Control UI 内嵌渲染[embed ref... /]或[embed url... /]自闭合仅 assistant message 表面远程附件必须是公开https:URL禁止内网/回环/链路本地/内部主机名本地附件绝对路径、工作区相对路径或~/路径且需通过文件读取策略与媒体类型检查八、相关文档Control UI Chat 文档 - Hosted embedsControl UI 如何渲染[embed ...]及其 iframe 沙箱策略、embedSandbox三档配置与allowExternalEmbedUrls开关Typebox 概念文档与结构化类型校验相关的概念背景核心实现src/media/parse.ts媒体解析与安全校验、src/utils/directive-tags.ts[[...]]指令解析、src/chat/canvas-render.ts[embed ...]与 canvas 预览提取、src/agents/embedded-agent-runner/run/tool-media-payloads.ts工具媒体载荷合并相关测试attempt-finalize.media.test.ts、tool-media-payloads.test.ts、images.media-refs.test.ts。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询