TL;DR
当前 Qoder GenUI Widget 通过 window.sendToAgent(payload, { submit: true }) 提交数据时,payload 会强制作为 user message 在聊天面板上屏,平台没有任何隐藏开关。
实测验证 6 个候选字段(silent / hidden / suppressDisplay / display:false / visible:false / noEcho)全部失效。希望平台增加一个 silent: true 选项,让 Widget 提交数据可以只触达 agent、不在聊天面板可见。
一、背景与现状
GenUI Widget 是 Skill 收集结构化参数(表单、多 Tab 配置、复杂选项)最重要的载体。Skill 普遍按 GenUI 官方 guidelines 的标准用法回灌数据:
// form.html
window.sendToAgent(payload, { submit: true });
按 load_guidelines 文档说明,{submit: true} 会立即把 payload 作为聊天消息发送,触发 agent 处理。当前没有任何方式让这条消息不在聊天面板可见。
这导致 Skill 在使用结构化数据透传协议时,用户在聊天面板会看到一坨参数(base64 / JSON / 长串配置),交互观感很差。
以 alibabacloud-lingjun-cluster-scaling skill 的 R2 envelope 透传协议为例(base64 封装的提交数据):
[Widget interaction] {"__lj_b64":"eyJ2IjoxLCJhY3Rpb24iOiJjcmVhdGUtbm9kZS1ncm91cCIsLi4uLi4uIn0="}
这一行是 widget 提交后 Qoder 平台强制上屏的 user message。它对终端用户毫无可读性,但目前没有 API 能隐藏它。
二、问题
| # | 问题 | 影响 |
|---|---|---|
| 1 | 视觉污染:表单提交后聊天面板出现一坨 base64 / JSON | 严重影响交互观感,用户经常以为是 bug |
| 2 | 认知误导:用户以为是自己手动发了那一坨参数 | 频繁问"为什么给我弹出这一坨",误以为 skill 缺陷 |
| 3 | 信息泄漏:透传协议中可能含有内部字段(base64 后看似不可读,实际可解码) | 暴露协议内部结构 / 敏感字段 |
| 4 | 无法用 markdown 规避:submit:true 模式下平台会原样上屏,不会做 markdown 折叠 |
skill 端没有任何前端手段绕过 |
三、期望(核心诉求)
建议给 sendToAgent 第二参数增加一个 silent 选项:
// 现状
window.sendToAgent(payload, { submit: true })
// → 上屏 + 触达 agent
// 期望新增
window.sendToAgent(payload, { submit: true, silent: true })
// → 不上屏 + 仅触达 agent
语义:消息正常进入 agent 上下文(agent 该收到的还是收到),但不在聊天面板渲染。
向后兼容:silent 缺省 = false = 当前行为,零破坏性。
四、收益
- 交互观感:用户只看到 agent 干净的回复,不会看到内部协议数据
- 协议自由度:Skill 可放心使用 base64 / JSON / 加密等任意结构化透传格式,不再受 “必须人类可读” 的隐性约束
- 降低敏感信息暴露面:透传字段(如服务端识别码、内部 ID、表单 token)不会出现在聊天历史里
- 零迁移成本:Skill 端只需在
sendToAgent调用上加一个字段,不需要平台升级配套发版
五、参考场景
以 alibabacloud-lingjun-cluster-scaling skill 为真实落地场景:
- Widget 形态:多 Tab 表单(批量创建节点分组、扩缩容配置)
- 提交协议:R2 envelope(base64 封装的结构化 JSON,含 region / clusterId / 多组节点配置 / 镜像 ID / 密码 / 系统盘等敏感字段)
- 当前问题:每次提交后聊天面板会出现一长串
[Widget interaction] {"__lj_b64":"..."},用户多次反馈"这是什么" - 增加
silent后:提交完全无感知,agent 直接执行后续动作,体验等同于桌面应用的表单交互
六、备选方案(如果 silent 字段实现成本高)
| 方案 | 说明 | 评价 |
|---|---|---|
A. 客户端默认折叠 [Widget interaction] 前缀消息 |
平台层做 UI 级折叠,识别特定前缀的消息收起为一行摘要 | 比 silent 简单,但需要约定前缀,且仍可见 |
B. 提供 sendToAgentSilent(payload) 独立 API |
与 sendToAgent 平行,语义完全一致只是不上屏 |
等价于方案 silent:true,命名不同 |
C. Widget 内的 data-tool-call 协议 |
类似 OpenAI tool_call,绕过聊天消息直接走 RPC 通道 | 改动最大,但最优雅 |
推荐方案 silent(即正文期望部分),改动最小、向后兼容、收益直接。
七、附:实测证据(探针 widget,2026-06-12)
为确认平台确实没有任何已实现但未公开的隐藏字段,构造了一个探针 widget,依次调用 sendToAgent 7 次,每次仅改变第二参数:
| 标签 | options | 候选语义 |
|---|---|---|
| A | {submit:true} |
基线(必然可见) |
| B | {submit:true, silent:true} |
候选 1 |
| C | {submit:true, hidden:true} |
候选 2 |
| D | {submit:true, suppressDisplay:true} |
候选 3 |
| E | {submit:true, display:false} |
候选 4 |
| F | {submit:true, visible:false} |
候选 5 |
| G | {submit:true, noEcho:true} |
候选 6 |
实测结果:
--- runAll begin 2026-06-12T01:58:41.899Z ---
[CALL] A opts={"submit":true}
[CALL] B opts={"submit":true,"silent":true}
[CALL] C opts={"submit":true,"hidden":true}
[CALL] D opts={"submit":true,"suppressDisplay":true}
[CALL] E opts={"submit":true,"display":false}
[CALL] F opts={"submit":true,"visible":false}
[CALL] G opts={"submit":true,"noEcho":true}
--- runAll end ---
聊天面板观察:A~G 7 条消息全部上屏,无一条被任何字段触发隐藏。
结论:平台当前不存在任何可用的隐藏开关,silent 字段是必须新增的。
八、附:当前可见的强制上屏副作用
(以 lingjun skill 为例)
用户视角:
用户: 帮我创建2个节点分组
Agent: [渲染表单]
用户: [点击表单提交按钮]
用户: [Widget interaction] {"__lj_b64":"eyJ2IjoxLCJhY3Rpb24iOiJjcmVhdGUtbm9kZS1ncm91cCIs...(整页 base64)..."} ← 这一行
Agent: [开始执行] ...
这一行 [Widget interaction] ... 在用户视角是"我自己发出去的"——但实际上这是 widget 的回灌消息,平台没有给 skill 任何规避手段。
如果有 silent: true,则:
用户: 帮我创建2个节点分组
Agent: [渲染表单]
用户: [点击表单提交按钮] ← 此后无任何视觉污染
Agent: [开始执行] ...
体验闭环、干净、专业。
九、提交人
- 工号邮箱:siyun.wt@alibaba-inc.com
- 关联 Skill:
alibabacloud-lingjun-cluster-scaling - 期望排期:建议本季度内
- 联系方式:钉钉 / 邮件均可
感谢 Qoder 平台同学。