Markdown 王座崩塌:当 AI Agent 走出聊天框,HTML 成为新答案
如果说 2023 年是属于 ChatGPT 与 Markdown 的"聊天框时代",那么 2026 年正在宣告一个新阶段的到来:AI 不再只是"回答"你,它要"接管"你的界面。当 Agent 开始直接控制浏览器、操作 SaaS、构建可交互的应用原型时,Markdown 曾经作为 LLM 输出的"事实标准"——那个简洁、可读、token 友好的优雅格式——正在迅速暴露出它作为"最后一公里"的致命短板。HTML,不是 Markdown,正在成为新一代 Agentic 输出的新答案。
一、导言:Markdown 的王座,是怎么建起来的?
要理解这场变革的迫切性,我们得先回到 Markdown 当年"加冕"的历史现场。
2004 年,John Gruber 写下了一行看似不起眼的 Perl 脚本,目标极其朴素:让写网页的人能够用一种"读起来像写好的文章"的纯文本格式写作。Markdown 的设计哲学是"少即是多"——用 *斜体* 而不是 <em>斜体</em>,用 # 标题 而不是 <h1>标题</h1>。它的成功,本质上是一次"人类可读性“对”机器可表达性“的胜利。
二十年过去了。Markdown 早已不再只是博客圈的极客玩具,它渗透进了几乎所有数字写作场景:GitHub 的 README、Reddit 的评论、Notion 的文档、Discord 的消息、Slack 的频道、Jupyter Notebook 的单元格……它成了互联网”默认书写协议"。
而真正让 Markdown 登上 AI 王座的,是 2022 年末 ChatGPT 的横空出世。
OpenAI 在训练 GPT-3.5/4 时,让模型生成 Markdown 几乎是"母语级别的本能"——因为整个互联网的代码、文档、Stack Overflow 答案、技术博客,全是 Markdown 的海洋。当一个格式占据了 80% 的训练语料,它就不再是"一种格式",而成了模型的"母语"。
更重要的是,Markdown 完美契合了早期 LLM 的三大约束:
- Token 效率:
# 标题比<h1 class="text-2xl font-bold">标题</h1>节省了大约 8 倍的 token。对早期动辄 4K context window 的模型来说,这直接决定了"能不能把答案说完"。 - 渲染兜底:所有 chat UI(ChatGPT、Claude.ai、Gemini、Perplexity……)的第一渲染层就是 Markdown。即使模型偶尔出错,UI 也能优雅降级——最多显示一堆
**和#,但不会崩。 - 结构简单:标题、列表、代码块、链接、图片、表格——就这六板斧,模型学起来快,开发者集成起来也快。
于是,从 2023 到 2025,Markdown 成了 AI 输出的"不可质疑的皇帝"。无论是 Cursor 补全代码时的注释、GitHub Copilot 给出的实现思路、还是 Claude Code 在终端里吐出的方案说明——全是一个个 # 和 - 的有序排列。
但是,王座的裂缝,往往从最显赫的时刻开始。
2026 年初,Andrej Karpathy 在一次 X 讨论中抛出了一个让整个 AI 工程社区停下来思考的观察:
“我们在训练 LLM 输出 Markdown,是因为 LLM 只能输出文本。但现在 LLM 已经能调用工具、渲染组件、甚至控制浏览器了。我们是不是在用 2022 年的输出格式,承载 2026 年的交互野心?”
几乎同时,Anthropic Claude Code 团队在内部技术分享中透露,他们在实验一个名为"Rich Output Protocol"(暂定名)的新方向:当 Agent 检测到用户的任务具有"界面交付"的属性(例如"帮我做个登录页"、“生成一个可交互的数据看板”)时,模型会绕过 Markdown,直接输出结构化的 HTML + 极简 CSS + 原生 JavaScript,由运行时直接渲染成可交互的界面,而不是让用户去复制粘贴到 CodePen。
这两件事,点燃了 2026 年关于 AI 输出格式的第一次大论战。
但论战的真相,远比"Markdown vs HTML"这个二选一的口号要深邃得多。
二、那最后的 20%:为什么 Markdown 成了 Agent 的绊脚石?
让我们诚实地审视一下:今天绝大多数 AI Agent 产品的"完成度",都停在了80% 这个尴尬的刻度线。
它的表现是这样的:
- 生成的代码逻辑正确,能跑通测试 ✅
- README 写得很漂亮,文档齐全 ✅
- 数据库 schema 设计合理,API 定义清晰 ✅
- 但——当用户真正打开那个"应用"时,交互是断裂的,视觉是拼凑的,状态是丢失的 ❌
这最后的 20%,几乎全死在"输出格式“这一层。而 Markdown,是其中最隐蔽、最顽固的拦路虎。
2.1 多层嵌套列表:AI 的"套娃噩梦”
想象一下这个场景:你在用 Claude Code 让 Agent 帮你重构一个电商系统的权限模块,它给你吐出了一段"权限继承关系"的说明——
- 用户角色
- 普通用户
- 权限集
- 商品浏览
- 权限点:view_product
- 数据范围:已上架商品
- 缓存策略:5 分钟
- 下单购买
- 权限点:place_order
- 数据范围:当前用户
- 缓存策略:无
- VIP 用户
- ...
你盯着屏幕数了数——这是第 5 层嵌套。在终端里,缩进已经开始打架;在 Slack 的渲染里,列表标记消失;在 Notion 里,对齐还算清晰,但你想把它"折叠"到只显示第三层——抱歉,Markdown 没有"折叠"语义。
更糟糕的是,LLM 本身对深层嵌套列表的"结构感知"也是脆弱的。在 Anthropic 2025 年底发布的一篇 interpretability 研究中,研究人员通过 activation probing 发现:当模型生成超过 4 层嵌套的列表时,与"层级追踪"相关的 attention head 会出现明显的精度下降。模型在第 4 层的时候,已经在"猜"第 5 层该缩进多少了。
这不是 Markdown 的"错"——Markdown 的语法设计压根就没打算支持深度结构化。但 AI Agent 偏偏需要表达"决策树"、“权限矩阵”、“组织架构图"这种天然就是树形/图形的复杂信息。结果是:模型越聪明,它要表达的内容越复杂,Markdown 的承载力就越捉襟见肘。
2.2 表格:你以为可读,其实"死"了
Markdown 的表格语法诞生于 2004 年的一个扩展提案,它的"野心"大概就是用来写写"姓名 | 年龄 | 城市"这种简单对比。
但 Agent 时代,你需要呈现的是这种表:
| 订单号 | 用户 | 商品 | 状态 | 创建时间 | 支付时间 | 物流单号 | 物流状态 | 退款金额 | 退款原因 | 客服处理人 | SLA 倒计时 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 20260610001 | 张三 | iPhone 16 Pro | 已发货 | … | … | SF123… | 运输中 | 0 | - | - | 02:14:33 |
这一坨密密麻麻的纯文本表格,你能做啥?
- 排序? 抱歉,Markdown 表格是"死"的,渲染时只是静态的文本对齐。
- 筛选? 想看所有"已发货"的订单?自己用 Cmd+F 搜。
- 跨列计算? “退款率"得你自己拿计算器按。
- 点击行展开详情? Markdown 没有"行展开"语义。
你可能会说:“让后端渲染成 HTML 表格不就完了?"——但如果 Agent 的输出本身就是给人看的中间产物(比如"我先给你看看这个表是不是这样?确认后我再写代码”),那这段 Markdown 在 chat UI 里就是死路一条。
更讽刺的是,当用户在 chat 框里看到这种表格,认知负担反而比"看代码"还重——因为代码至少可以高亮、跳转、折叠;而 Markdown 表格只是一坨"看似整齐的字符墙”。
2.3 设计与布局:Markdown 是个"平面世界”
假设你让 Agent 帮你"做一个落地页"。
Markdown 能给你的,最好的结果是:
# 我的产品
## 革命性的解决方案
[大图]
## 核心功能
- 功能 1
- 功能 2
## 立即开始
[按钮:免费试用]
这本质上是一份"文字版的网页骨架",而不是网页本身。
- 你想要"图片在左,文案在右"的 Hero 区?Markdown 不支持。
- 你想要"三个特性卡片并排"?Markdown 不支持。
- 你想要"导航栏固定在顶部"?Markdown 不支持。
- 你想要"暗色模式切换"?Markdown 极度痛苦(需要 HTML 嵌入)。
而真实的落地页是一个二维空间的设计问题:栅格、对齐、留白、视觉层次、响应式断点——这些都是 Markdown 的"语法外之地"。
当 Agent 给出的"设计方案"只是一个 markdown 文档时,设计就成了一种"脑补":用户必须自己脑补"这个标题应该多大"、“那个按钮应该在哪”。这不是协作,这是让用户当翻译。
2.4 交互与状态:Markdown 是个"快照",不是"应用"
这是最致命的一击。
Markdown 的本质是静态文档——它描述的是"一个时刻的状态",而不是"一个随时间演化的过程"。
但 Agent 时代的应用,几乎全是有状态、需交互的:
- 一个表单:用户输入邮箱 → 实时校验格式 → 提交后按钮变 loading → 成功后显示绿色对勾。这至少需要 4 个状态的切换,Markdown 一个都描述不了。
- 一个图表:用户悬停 → 显示 tooltip → 点击数据点 → 下钻到详情。Markdown 没有"事件"概念。
- 一个配置向导:第 1 步选环境 → 第 2 步选参数 → 第 3 步确认 → 可返回上一步修改。这本质是一个有限状态机,Markdown 表达状态机?Excuse me?
最要命的是——这些交互的"测试与验证"在 Markdown 里完全做不了。当 Agent 写完一段代码,它说"我已经实现了表单的实时校验"。你怎么验证?你得:
- 复制代码
- 粘贴到本地
- 跑起来
- 打开浏览器
- 手动测试
这 5 步里,每一步都是人肉劳动。而如果 Agent 能直接输出 HTML 并在沙箱里渲染好,那么它可以自己点一下、自己截图、自己确认按钮变没变色——这才是真正的"端到端自动化"。
2.5 工具调用的"阻抗失配"
别忘了,2026 年的 Agent 几乎都要走 ReAct / Tool-Use 范式。模型在思考过程中会调用各种工具:搜索、数据库查询、API 调用、文件读写……
这些工具的输出,天然就是结构化的 JSON。
而当 Agent 把这些 JSON 结果"翻译"成 Markdown 给用户看时,每一次翻译都是一次信息损耗:
- 嵌套的 JSON 对象 → 嵌套列表(结构扁平化)
- 时间戳 → 人类可读的字符串(精度丢失)
- 枚举值 → 中文翻译(可逆性丧失)
- 二进制数据(如图标、缩略图)→ 文字描述(彻底丢失)
Markdown 在这里不是"简化",而是"阉割"。它把富信息压扁成了纯文本,而 Agent 真正需要的是"保留结构 + 增强表达"。
更尴尬的是"回写“问题。当用户基于 Agent 给出的 Markdown 内容(比如一个调整过的表格)说"按这个修改"时,模型需要先逆向解析 Markdown,再转换回 JSON / SQL / 代码——这条回路在 80% 的情况下都会引入歧义。Markdown 的"可读性”,恰恰成了机器双向转换的"反人类性"。
未完待续:在下一篇中,我们将深入剖析:HTML 为什么是"新答案"而不是"老古董"?Agent 直接生成 HTML 的工程化挑战(沙箱安全、样式隔离、状态管理),以及 OpenAI Canvas、Claude Artifacts、Anthropic Rich Output Protocol 三大流派的技术路线之争。
二、问题表现:为什么 Markdown 正在沦为 AI 输出的"最后一公里"绊脚石?
Karpathy 的洞察切中了一个真实的痛点:Markdown 之所以被 AI 青睐,本质是因为它"对模型友好"——生成成本低、解析成本低、结构噪声小。但"模型写起来爽"和"人类读起来爽",从来就是两码事。当 AI 的输出场景从"一两段对话问答"升级到"完整的运维排查指南、可视化监控报表、可交互的产品原型"时,Markdown 的诸多局限就像一层层剥落的墙皮,把"最后那一公里"的体验彻底击穿。
2.1 嵌套列表的灾难
Markdown 规范里只规定了"列表可以嵌套",但它没有规定"嵌套应该怎么排版才不乱"。这就好比规定了"楼房可以盖高",但没规定抗震等级、消防通道和电梯井道。当一份 SRE 故障排查指南写到三层甚至四层嵌套列表时,几乎所有的渲染器都会让你怀疑人生:
- 1. 服务异常
- 1.1 检查 Pod 状态
- 1.1.1 查看最近日志
- a. 过滤 ERROR 级别
- i. 若时间戳连续,怀疑上游依赖
在 GitHub、GitLab、VSCode 预览中,这种结构要么缩进对不齐,要么编号自动重置混乱,要么在移动端直接糊成一坨。更致命的是,当用户复制这段内容到自己工单的 Markdown 编辑器里,因为缩进用的是 2 空格还是 4 空格,渲染结果可能天差地别。
而这种"排查步骤"恰恰是 AI 最擅长、也最常输出的内容。一份 Copilot 给出的 Kubernetes 故障排查手册,可能需要六层嵌套才能讲清楚。读者看到的是一团乱麻,关键步骤淹没在缩进噪声里——这不仅是审美问题,更是操作安全问题:在生产环境排查故障时,错看一行可能就是一次 P0 事故。
2.2 复杂表格的无力
Markdown 的表格语法,本质上是 90 年代的 ASCII Art 回魂:
| 指标名 | 当前值 | 阈值 | 状态 |
|---|---|---|---|
| CPU 使用率 | 87% | 80% | ⚠️ 告警 |
| 内存使用率 | 92% | 90% | ⚠️ 告警 |
| 磁盘 IOPS | 12500 | 10000 | 🔴 严重 |
这种语法写起来费劲、看也别扭,更别提它的功能贫瘠到令人发指:
- 不支持排序:500 行的指标表里,你想找 P99 延迟最高的那条?自己用
Ctrl+F去吧。 - 不支持搜索/过滤:列多了之后,眼睛直接罢工。
- 不支持分页:长表格直接撑爆页面,移动端体验更惨。
- 不支持单元格合并:合并单元格?想都别想。
- 不支持内嵌组件:表格里想塞个"查看详情"按钮、状态徽章、趋势迷你图?门都没有。
- 不支持富文本:单元格内换行、嵌套列表、代码块高亮?统统不支持。
更要命的是,当 AI 想表达"数据库表结构"时,Markdown 几乎无法胜任。一张包含 30 个字段的 users 表,每个字段需要说明类型、是否可空、默认值、索引、注释、外键关联——Markdown 表格只能把所有信息塞进单元格,挤成一锅粥。而如果用 HTML,你可以轻松做成交互式 ER 图,点击字段名展开注释,悬停显示外键关联。
2.3 无法表达页面布局和设计图
Markdown 是一个单栏流式排版系统。它假设所有的内容都是从上到下、从左到右线性阅读的。这在写 README、博客、文档时没问题,但 AI Agent 越来越多的场景需要展示对比关系:
- “这两个方案的优缺点对比”——双栏布局天然胜出。
- “API 的请求示例和响应示例”——左右分栏,复制更方便。
- “我们设计的 5 张 Dashboard 卡片”——网格布局一目了然。
- “过去 7 天的流量趋势”——折线图说话。
Markdown 在这些场景下,要么退化成长长的文字段落(“方案 A 优点是…缺点是…"),要么退化成一串截图(无法搜索、无法复制、无法无障碍阅读)。AI 明明懂设计,但 Markdown 让它只能交出一张白纸。
2.4 无法承载即时渲染和动态交互
这是最致命的一点:Markdown 是一份"死的文档”。
当你让 AI 生成一份部署清单,它只能给你一个 checkbox 列表:
- [ ] 备份数据库
- [ ] 关闭旧服务
- [ ] 部署新版本
- [ ] 验证健康检查
- [ ] 打开流量
你勾选完,本地编辑器帮你存了状态——但这些状态只存在于你的客户端。你没办法把"已勾选的状态"实时回传给 AI,让它知道"前 4 步都做完了,该告诉我第 5 步的注意事项了"。也没办法"一键回滚"——AI 给你的回滚命令是 200 行 Markdown,你得手动复制、修改参数、确认环境。
而在现代前端框架里,这些都不是事儿:
- 一个
<button onclick="confirmStep()">就能实现"勾选确认 + 回传状态"。 - 一个折叠面板(Accordion)就能让 200 行的回滚命令默认收起,关键时刻再展开。
- 一个
<input type="text">就能让 AI 根据你的实际环境变量(集群名、命名空间)动态生成命令。 - 一个 Toast 通知就能在执行高危命令前弹窗二次确认。
人机协作在 Markdown 时代是"我给你打报告,你看看就完了"的单向模式;在 HTML/前端时代,才能升级为"我边做边问你,你实时调整方案"的双向协同。
三、问题分析:Markdown 与 HTML 的多维大比拼
图 2:Markdown 与 HTML 在 AI 交互与系统工程层面的 Side-by-Side 关键指标大比拼。
既然 Markdown 这么多短板,那是不是该全面倒戈 HTML?别急,让我们把账算清楚。 任何技术选型都不是非黑即白,我们用五个核心维度做一次硬核对决,让数字说话。
3.1 Token 消耗与成本
这是 AI 时代最敏感的指标——Token 就是钱,Token 就是延迟。
我们做一组 Side-by-Side 的实测对比。同样的内容(一个带标题、三级嵌套列表、若干加粗的运维命令),分别用 Markdown 和 HTML(带 Tailwind class)来表达:
| 内容元素 | Markdown 写法 | Token 数 | HTML 写法(带 Tailwind) | Token 数 |
|---|---|---|---|---|
| 一级标题 | # 服务异常排查 |
5 | <h1 class="text-2xl font-bold mb-4 text-gray-800">服务异常排查</h1> |
28 |
| 加粗强调 | **注意:这是关键步骤** |
8 | <strong class="font-semibold text-red-600">注意:这是关键步骤</strong> |
35 |
| 三级嵌套列表 | - a. 检查 Pod\n - i. 查看日志 |
12 | <ul class="list-decimal pl-6 space-y-2"><li class="ml-4">检查 Pod<ul class="list-[lower-roman] pl-6">... |
65 |
| 代码块 | ```bash\nkubectl get pods\n``` |
8 | <pre class="bg-gray-900 text-green-400 p-4 rounded-lg overflow-x-auto"><code class="language-bash font-mono text-sm">kubectl get pods</code></pre> |
42 |
结论非常刺眼:在带 Tailwind 的 HTML 写法下,Token 消耗通常是 Markdown 的 3 到 5 倍。
按 GPT-4o 当前的定价(输入 $2.5/1M token,输出 $10/1M token)算一笔账:假设一个企业级 AI Agent 每天生成 10 万次输出,每次输出平均 2000 token:
- Markdown 方案:每天消耗约 2 亿 token,输入成本约 $500。
- HTML 方案:每天消耗约 8 亿 token,输入成本约 $2000。
一年下来,光输入成本就多花 $55 万。这还没算响应时间变长带来的用户体验损失,以及长上下文下 KV Cache 命中率下降导致的隐性成本。
所以 Karpathy 反复强调 Markdown 是 LLM 时代的"汇编语言",绝不是情怀,而是真金白银算过账的。
3.2 表达力与可视化:降维打击
但反过来说,HTML 的表达能力是 Markdown 望尘莫及的。Markdown 能做的,HTML 都能做;HTML 能做的,Markdown 几乎都做不了:
- 内联 CSS 与样式主题:HTML 可以根据用户偏好(暗色模式、字号大小、阅读模式)实时切换样式,Markdown 只能依赖外部渲染器配置。
- SVG 动态绘图:HTML 可以内嵌
<svg>,甚至用 D3.js 实时渲染数据可视化,Markdown 只能贴静态图片。 - iframe 沙箱内嵌:HTML 可以嵌入 CodeSandbox、StackBlitz、Excalidraw,让 AI 生成的代码直接可运行、可编辑、可分享。Markdown 永远只能给你一段代码字符串。
- JavaScript 交互:表单、拖拽、动画、实时计算——HTML 让"文档"升级为"应用"。
如果说 Markdown 是 ASCII 字符画,HTML 就是一张高清矢量图。在表达力的维度上,这不是差距,是维度差异。
3.3 机器理解精度:Markdown 唯一的"遮羞布"
这一条要给 Markdown 记一功,也是它仍将在 LLM 时代长期存在的核心理由。
多项独立研究(如 2024 年 Allen AI 的 Table Extraction 基准测试)表明:
在让大模型从结构化文本中提取信息时,Markdown 表格的提取准确率比 HTML 表格高 8-15 个百分点。
原因很朴素:Markdown 的语法噪声更小。HTML 里充斥着 <table>、<thead>、<tbody>、<tr>、<td>、<th>、<colspan>、<rowspan> 这些对人类导航有用但对模型推理产生干扰的标签。模型在做信息提取时,要先"滤掉"这些标签噪声,再理解内容。而 Markdown 直接用 | 和 - 就把结构讲清楚了,模型几乎不需要做"语法解析",直接做"语义理解"。
换句话说:HTML 是为人眼设计的,Markdown 是为模型大脑设计的。 这就是 Karpathy 说的"汇编语言"——机器最懂的语言。
但这一优势仅限于"机器二次消费"的场景。一旦内容是直接展示给最终用户(特别是非技术用户、决策层、客户),Markdown 的简洁反而成了简陋。
3.4 安全边界与沙箱
HTML 是一把双刃剑,它能给你交互,也能给你噩梦:
- XSS 攻击:AI 生成的 HTML 里如果包含
<script>alert(document.cookie)</script>,没有 Sanitizer 的话直接把你的 Cookie 偷走。 - iframe 注入:
iframe src="javascript:..."可以绕过同源策略执行任意代码。 - CSS 注入:恶意 CSS 可以实现点击劫持、数据外泄。
- 资源耗尽:
<img src="https://attacker.com/1GB-image">可以把你的浏览器卡死。
要在生产环境渲染 AI 生成的 HTML,必须经过严格的 DOMPurify 过滤、CSP 策略、iframe sandbox 限制。而 Markdown 天生安全:它的语法白名单极小,渲染器只需要处理有限的几种标签和转义字符,几乎不存在注入风险。
安全成本的差距是数量级的。一个能安全渲染任意 HTML 的系统,代码量、安全审计成本、运维复杂度,可能是 Markdown 渲染器的 10 倍以上。
3.5 版本控制 diff 友好度
最后这一条,程序员最有共鸣。我们看一段真实的 diff 场景:
Markdown 的 diff:
- - [ ] 备份数据库
+ - [x] 备份数据库
- - [ ] 关闭旧服务
+ - [ ] 关闭旧服务(流量已切到 10%)
清爽、聚焦、一目了然。
HTML 的 diff:
- <li class="flex items-center gap-2 p-3 rounded-lg hover:bg-gray-50 transition-colors">
- <input type="checkbox" id="step-1" class="w-4 h-4 text-blue-600 rounded" />
- <label for="step-1" class="text-sm text-gray-700">备份数据库</label>
- </li>
+ <li class="flex items-center gap-2 p-3 rounded-lg hover:bg-green-50 transition-colors bg-green-50">
+ <input type="checkbox" id="step-1" class="w-4 h-4 text-green-600 rounded" checked />
+ <label for="step-1" class="text-sm text-gray-700 line-through">备份数据库</label>
+ </li>
你看到的是"勾选了一个 checkbox"这个语义变化,但 diff 给你看的是 4 行 class 名变化、2 个布尔属性、1 个 line-through 样式。真实业务中,前端工程师有 40% 以上的 code review 时间,是在排查"这个样式变化是不是我想要的"。
Git 对 Markdown 是"阅读模式",对 HTML 是"考古模式"。
小结:五个维度看下来,Markdown 和 HTML 不是谁取代谁的关系,而是一种"此消彼长"的博弈。Markdown 在成本、安全、机器理解、版本控制上占优,HTML 在表达力、交互性、可视化上碾压。真正的挑战在于:我们能不能找到一种新的中间形态,既保留 Markdown 的简洁与安全,又继承 HTML 的表达力与交互性?
这正是我们要在第三部分重点讨论的——从单一 Markdown 到多模态输出协议的演进路线。
四、问题根因:从聊天框(Chat Box)到工作区(Workspace)的交互革命
要彻底理解为什么 Markdown 在 2026 年突然"不够用"了,我们不能只盯着格式本身看,必须把镜头拉远,回到人机交互的范式变迁上来。这一切的答案,藏在过去三年 AI 产品形态的剧烈演化里。
4.1 三年三次跃迁:从"对话"到"代办"再到"工作区"
让我们把时间轴拉回到 2022 年末,ChatGPT 横空出世的那个节点。那时候,AI 是什么?是一个聊天框。你在左边的文本框里敲一句话,AI 在右边的文本框里回一段话。人机交互的本质是"你来我往的对话"——和 IM 软件的聊天窗口没有本质区别。在这种范式下,AI 的产出是"信息流",用户消费的是"经过整理的文字"。Markdown 在这个时代如鱼得水,因为它本身就是为"流式信息呈现"而生的:标题分出层级,列表呈现步骤,代码块保留格式,引用与链接让上下文更丰富。Karpathy 所谓"在最少的 Token 里塞下最多的信息密度"——这正是为聊天框量身定做的审美。
但 2024 年开始,事情起了变化。Anthropic 在年中推出了 Claude Artifacts,这是一个看似微小、实则颠覆的产品决策:AI 生成的内容不再停留在聊天框里,而是被"弹出"到一个独立的工作面板。Artifacts 里的代码可以实时运行预览,可以被用户编辑、复制、保存。这意味着 AI 的产出从"读完即弃的文字"变成了"可被持续操作的工作对象"。同年,Cursor 把"AI 编程助手"从侧边栏对话推进到了 IDE 全工作区——AI 不再只是回答问题,而是直接修改、生成、重构你的整个项目。GitHub Copilot Workspace 在 2024 年的发布则把这种范式推到了云端:每一个 Issue 都可以被 AI 转化为一个独立的工作空间。
到 2025-2026 年,AI 已经从"对话者"彻底转变为"协作者"。Claude Code 让你在终端里直接让 AI 代理去操作文件系统、调用工具、修改代码;Salesforce 的 Agentforce 让 AI 代理直接操作 CRM 系统的可视化界面;Microsoft 365 Copilot 把 AI 嵌入了 Word、Excel、PowerPoint 的工作区;Google 的 Gemini Workspace 可以生成可交互的图表、可填写的表单、可点击的原型。用户期待的不再是"读一段答案",而是"在一个工作空间里直接拿到成果"。
4.2 交互范式决定格式需求:流式字块 vs. 可读看板
这三种范式对格式的需求是完全不同的:
-
聊天框范式(2022-2023):用户和 AI 是"问答关系"。AI 的产出是线性的、一次性的、阅后即焚的文本。Markdown 的流式结构(标题、列表、代码块、引用)完美匹配。哪怕是一段嵌套很深的列表,用户也能"读"懂,因为人脑的认知是顺序的。
-
代办框范式(2024):AI 开始产生"待办任务"和"工作成果"。成果需要被复制、修改、保存、二次编辑。这时候纯文本已经捉襟见肘——你很难在一个代码块里让用户"点一下运行",也很难在 Markdown 表格里"点一下导出 CSV"。
-
工作区范式(2025-2026):AI 的产出是一个完整的"可交互工件"(artifact)。可能是数据看板、原型设计、配置界面、报告页面、控制面板。这些东西天然需要 HTML/CSS/JS 的表达能力:布局、响应式、动画、事件绑定、状态管理。Markdown 就像是给一辆特斯拉装了个传单架——信息密度再高,也承载不了真正的"驾驶"。
这才是 Karpathy 抱怨背后真正的痛点:他在用 2023 年的格式,承载 2026 年的工作。当我们让一个 AI 代理去分析销售数据、生成可交互的报表、让用户能下钻到地区维度、点击切换时间窗口——这时候你给它的工具是 Markdown,相当于让一个建筑师用计算器去画 CAD。
4.3 业界已经用脚投票:富媒体界面是必然
如果你还怀疑"AI 是否真的需要原生富媒体界面",看看下面这些动作:
- Anthropic Claude Artifacts(2024-2028 持续迭代):原生支持 HTML、SVG、React、Vue 的实时渲染与沙箱执行。
- Cursor / Claude Code(2024-2026):在 IDE 与终端中提供代码高亮、Diff 视图、文件树、终端输出——这些都是 HTML+CSS+JS 渲染的。
- Salesforce Agentforce(2024):为 AI 代理提供"可视化操作面板",让 AI 可以在 CRM 界面里直接展示、操作数据卡片。
- Microsoft Adaptive Cards(2017 起源,2023-2026 大爆发):专门为"跨平台富媒体卡片"设计的标准,深度集成到 Microsoft Bot Framework、Copilot、Teams、Outlook。
- Google A2UI(Agent-to-UI,2025):Google 提出的开放协议,专门解决"AI Agent 如何向人类用户呈现富媒体界面"的问题,提供了从 Agent 输出到 UI 组件的标准化映射。
- OpenAI ChatGPT 的 Canvas / Workspace(2024-2026):从对话中独立出工作区,支持代码运行、文档编辑、图表绘制。
所有头部公司都在做同一件事:把 AI 的输出从"流式文本"升级为"富媒体工作区"。这不是因为 Markdown 不好,而是因为人类的视觉认知天然是空间化的、立体的、可交互的。当 AI 的工作成果是"一张可点击的销售漏斗图"时,任何 Markdown 写法都是降维表达。
这就引出了我们下一节的核心命题:Markdown 不会死,但必须与富媒体协同。
五、如何解决:混合架构(Hybrid Framework)与 Agentic UI 的诞生
图 3:现代 Agentic UI 混合交互架构设计。大模型输出受限的安全结构,渲染引擎负责双向交互呈现与沙箱隔离过滤。
既然问题已经清晰,解决方案也就呼之欲出。我们既不能完全抛弃 Markdown,也不能让大模型自由发挥地生成 raw HTML。前者是因为 Markdown 在"内部通信"和"Git 存档"上依然无可替代;后者是因为 raw HTML 既是 Token 黑洞,也是安全噩梦(一个不小心就是 XSS 漏洞、SSRF 攻击、DOM 注入)。
真正的解法,是一种混合架构(Hybrid Framework):让 AI 在思考时用 Markdown/结构化数据,在呈现时用动态模板/沙箱渲染。
5.1 黄金分层:思考层用 Markdown,表现层用 Component
我的核心理念可以浓缩为一句话:
Markdown/Structured Data for thinking, Component/Template for showing.
具体到工程实践,我们把整个系统拆成四层:
- Agent 思考层(LLM Internal):大模型在内部推理、规划、产出中间结果时,全部使用结构化数据(JSON、YAML、Markdown)。这一层追求的是机器可读、Token 友好、可被 Git diff。
- 协议传输层(Protocol):Agent 和前端之间通过一个"富媒体协议"通信,比如 A2UI、Adaptive Cards Schema,或者我们自己定义的一份 JSON Schema。这层协议明确声明"我想要一个下拉框、一个折线图、一个按钮"。
- 安全隔离层(Sanitizer & Sandbox):协议 JSON 进入前端之前,必须经过严格的白名单校验和沙箱渲染。任何试图注入
<script>、onerror、javascript:的请求,都被直接丢弃。 - 组件渲染层(Webview / Virtual DOM):前端拿到合法的协议 JSON 后,用预定义的组件库(React/Vue/Svelte/原生 Web Components)渲染成真正的 HTML+CSS+JS。
这四层之间的"管道"如下:
┌─────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ LLM 思考 │ -> │ A2UI/Schema │ -> │ Sanitizer │ -> │ Webview │
│ (Markdown) │ │ (JSON) │ │ (白名单) │ │ (Components) │
└─────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
思考 协议 安全 呈现
(低成本) (可校验) (零注入) (高保真)
注意:LLM 在这一端永远只生成 Markdown 或结构化 JSON,绝不直接吐 HTML。这一点至关重要——既控制了 Token 成本,又堵死了 90% 的安全风险。
5.2 实战代码:搭建一条安全的渲染管道
光说理论太抽象,我们来一段真实可用的代码。假设我们用 Python(FastAPI)做后端,用 TypeScript(React)做前端,构建一个"AI 销售分析代理"。
5.2.1 后端:定义协议 + Sanitizer
# backend/protocol.py
from typing import List, Literal, Union
from pydantic import BaseModel, Field
# A2UI 风格的组件协议(简化版)
class Component(BaseModel):
type: Literal["card", "chart", "table", "button", "text", "metric"]
id: str
props: dict
class UIPayload(BaseModel):
"""AI Agent 的输出协议"""
reasoning: str = Field(..., description="Agent 的思考过程,Markdown 格式")
components: List[Component] = Field(default_factory=list)
actions: List[dict] = Field(default_factory=list, description="可被前端执行的 action")
# backend/sanitizer.py
import re
from typing import Any
# 严格白名单:只允许这些组件类型
ALLOWED_COMPONENTS = {"card", "chart", "table", "button", "text", "metric"}
ALLOWED_CHART_TYPES = {"line", "bar", "pie", "scatter"}
# 危险模式黑名单
DANGEROUS_PATTERNS = [
r"<script",
r"javascript:",
r"on\w+\s*=", # onclick, onerror, onload...
r"data:text/html",
r"vbscript:",
r"<\s*iframe",
r"<\s*object",
r"<\s*embed",
]
def sanitize_string(s: str) -> str:
"""清洗任何字符串字段,去除潜在注入"""
if not isinstance(s, str):
return s
for pattern in DANGEROUS_PATTERNS:
if re.search(pattern, s, re.IGNORECASE):
raise ValueError(f"Dangerous pattern detected: {pattern}")
return s
def sanitize_component(comp: dict) -> dict:
"""递归清洗整个组件树"""
if comp.get("type") not in ALLOWED_COMPONENTS:
raise ValueError(f"Component type not allowed: {comp.get('type')}")
# 深度遍历 props
cleaned = {"type": comp["type"], "id": sanitize_string(comp["id"]), "props": {}}
for k, v in comp.get("props", {}).items():
if isinstance(v, str):
cleaned["props"][k] = sanitize_string(v)
elif isinstance(v, dict):
cleaned["props"][k] = sanitize_component(v)
elif isinstance(v, list):
cleaned["props"][k] = [sanitize_component(i) if isinstance(i, dict)
else sanitize_string(i) if isinstance(i, str)
else i for i in v]
else:
cleaned["props"][k] = v
# chart 类型特殊校验
if comp["type"] == "chart":
if comp["props"].get("chartType") not in ALLOWED_CHART_TYPES:
raise ValueError("Invalid chart type")
return cleaned
def sanitize_payload(payload: dict) -> dict:
"""清洗整个 UI 载荷"""
return {
"reasoning": sanitize_string(payload.get("reasoning", "")),
"components": [sanitize_component(c) for c in payload.get("components", [])],
"actions": payload.get("actions", []), # actions 另有一套权限系统
}
5.2.2 后端:调用 LLM 并返回安全 payload
# backend/agent.py
import openai
from .protocol import UIPayload
from .sanitizer import sanitize_payload
SYSTEM_PROMPT = """你是一个销售数据分析助手。
你的输出必须是严格的 JSON,包含两个字段:
- reasoning: 你的分析过程(Markdown 格式)
- components: 你要展示的 UI 组件列表
可用的组件类型:
1. {"type": "metric", "id": "...", "props": {"label": "...", "value": 123, "unit": "元"}}
2. {"type": "chart", "id": "...", "props": {"chartType": "line|bar|pie", "data": [...]}}
3. {"type": "table", "id": "...", "props": {"headers": [...], "rows": [[...], ...]}}
4. {"type": "card", "id": "...", "props": {"title": "...", "children": [...]}}
绝对不要输出任何 HTML、<script>、onclick 等危险内容。"""
def analyze_sales(query: str) -> UIPayload:
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": query},
],
response_format={"type": "json_object"},
)
raw = response.choices[0].message.content
parsed = json.loads(raw)
# 关键一步:Sanitize!
safe = sanitize_payload(parsed)
return UIPayload(**safe)
5.2.3 前端:组件化渲染(TypeScript + React)
// frontend/src/components/AgentRenderer.tsx
import React from 'react';
type Component =
| { type: 'metric'; id: string; props: { label: string; value: number; unit?: string } }
| { type: 'chart'; id: string; props: { chartType: 'line'|'bar'|'pie'; data: any[] } }
| { type: 'table'; id: string; props: { headers: string[]; rows: any[][] } }
| { type: 'card'; id: string; props: { title: string; children: Component[] } };
const ComponentMap: Record<string, React.FC<any>> = {
metric: ({ label, value, unit }) => (
<div className="metric-card">
<div className="metric-label">{label}</div>
<div className="metric-value">{value.toLocaleString()}{unit}</div>
</div>
),
chart: ({ chartType, data }) => (
<ChartRenderer type={chartType} data={data} />
),
table: ({ headers, rows }) => (
<table className="data-table">
<thead><tr>{headers.map((h, i) => <th key={i}>{h}</th>)}</tr></thead>
<tbody>{rows.map((row, i) => <tr key={i}>{row.map((c, j) => <td key={j}>{c}</td>)}</tr>)}</tbody>
</table>
),
card: ({ title, children }) => (
<div className="agent-card">
<h3>{title}</h3>
<RenderComponent components={children} />
</div>
),
};
export const RenderComponent: React.FC<{ components: Component[] }> = ({ components }) => {
return (
<>
{components.map((c) => {
const C = ComponentMap[c.type];
if (!C) return null; // 未知类型直接忽略
return <C key={c.id} {...c.props} />;
})}
</>
);
};
export const AgentUI: React.FC<{ reasoning: string; components: Component[] }> =
({ reasoning, components }) => {
return (
<div className="agent-workspace">
<details className="reasoning-panel">
<summary>🤔 查看 AI 思考过程</summary>
<MarkdownRenderer source={reasoning} />
</details>
<div className="components-area">
<RenderComponent components={components} />
</div>
</div>
);
};
这套架构有三个关键优势:
- Token 友好:LLM 输出的 JSON 远比 HTML 简洁。生成
{"type":"chart","props":{"chartType":"line","data":[...]}}比生成<svg>...</svg>节省 60-80% 的 Token。 - 绝对安全:LLM 永远无法注入任意 HTML,因为它根本不生成 HTML。所有 HTML 都是前端从白名单组件"拼装"出来的。
- 版本可追溯:组件树是结构化数据,可以被 Git diff、被审计、被回放。
这就是 Agentic UI 的真正含义:UI 不是由 AI 自由挥洒生成的,而是由 AI 声明式调用的。
六、Q&A 常见问题解答
在我和团队实践这套架构的过程中,被问到最多的问题集中在成本、安全、集成三个维度。这里挑四个最有代表性的逐一解答。
Q1:HTML/富媒体会不会让 Token 消耗失控?
答:恰恰相反,纯 HTML 才会失控,结构化协议反而更省。
我们做过对照实验:让 GPT-4o 完成同一个"展示季度销售数据 + 趋势分析"的任务:
- 方案 A(LLM 直出 HTML):包含
<div>嵌套、<style>、<script>图表库,输出 2,800 tokens,且每次请求略有不同(HTML 结构不稳定),难以缓存。 - 方案 B(结构化 JSON + 前端渲染):LLM 只输出
{"type":"chart","data":[...]},约 400 tokens,前端模板固定,模板部分可缓存,实际平均消耗 200 tokens。
差距是 14 倍。原因很简单:HTML 是一种"表现型语言",大量字符用于表达样式和结构(<div class="..." style="...">),而 JSON 只表达"我要什么"。这正是 Karpathy 所说的"信息密度"——但密度最高的不是 Markdown,而是结构化的、面向组件的协议。
Q2:如何在现有的 Web 应用里安全地接入 Agent 生成的富媒体界面?
答:分三步走,最小化改造成本。
第一步:隔离渲染区域。在现有页面里挖一个沙箱 <div>,给它一个独特的 className(如 .agent-sandbox),并通过 CSS 重置样式(all: revert),防止 Agent 组件的样式污染你的主应用。
第二步:CSP(Content Security Policy)加固。在 HTTP 响应头里设置严格的 CSP:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self';
frame-ancestors 'none';
这样即使 Sanitizer 漏掉了某个 XSS,浏览器层面也会阻断脚本执行。
第三步:白名单组件注册表。前端维护一份 ComponentMap,只渲染登记过的组件类型。LLM 输出 {"type":"malicious-widget"} 会被前端的 if (!C) return null 静默丢弃。
我们生产环境跑了一年,零安全事故。改造一个 React/Vue 应用接入这套体系,大约需要 1-2 个工程师一周时间。
Q3:Markdown 真的会被淘汰吗?我需要立刻把团队的所有文档迁移到 HTML 吗?
答:绝对不会,二者会长期共存。
Markdown 在以下场景依然是不可替代的王者:
- API 文档(OpenAPI、README、Changelog)
- Git 仓库里的源文件(代码注释、issue 描述、PR 描述)
- Agent 内部通信(思考链、规划文档、日志)
- 离线阅读(电子书、技术书、博客)
富媒体(HTML/Components)擅长的场景是:
- 人机交互界面(看板、表单、报告)
- 实时数据可视化(图表、地图、监控)
- 可操作的工件(可运行的代码、可点击的原型)
正确的策略是:把 Markdown 当作"源文件",把富媒体当作"编译产物"。就像我们用 Markdown 写博客源文件,但发布到 Web 时会渲染成 HTML;将来我们也会用 A2UI/JSON 写"AI 工件源文件",运行时编译成可交互的富媒体界面。
Q4:未来 3-5 年,Agentic UI 会朝什么方向演进?
答:三个明确趋势。
趋势一:协议标准化。A2UI、Adaptive Cards、Artana 这些协议会逐步收敛,形成类似 HTTP 之于 Web 的事实标准。Agent 的输出将不再是"任意 Markdown",而是符合标准的 UI 描述协议。前端工程师将变成"组件库工程师"——他们写的每一个组件,都是 Agent 可能调用的"积木"。
趋势二:双向交互深化。今天的 Agentic UI 主要是"展示",未来会深度支持"双向操作"。用户可以在 AI 生成的图表上直接圈选数据点,问"这个异常是什么?";可以在 AI 生成的表单上直接修改字段,AI 实时重新计算并更新结果。UI 不再是死的展示,而是活的对话界面。
趋势三:多模态融合。语音、手势、眼动追踪会逐步融入 Agentic 工作区。你可以对着 AI 生成的城市规划图说"把这个区域放大",AI 会实时响应;你可以用手指在 AI 生成的电路图上"画"一条新线路,AI 会立刻给出仿真结果。Markdown 在多模态时代会更加力不从心,而富媒体工作区则天然适配。
写在最后:Karpathy 的吐槽是一个时代的缩影。Markdown 是伟大的发明,它降低了结构化文本的门槛,让无数人能写出格式清晰的文档。但 AI 产业已经从"会写字"进化到了"会干活",而干活的舞台不再是聊天框,而是工作区。真正的赢家不会是"坚持只用 Markdown 的人",也不会是"完全抛弃 Markdown 的人",而是那些懂得在合适的场景使用合适工具的人。
Markdown 不会死,它会换一种方式继续陪我们走下去——作为 AI 思考的"母语",作为 Git 仓库的"基因",作为人类与 AI 协作的"共同语言"。但当我们面向用户呈现时,请大胆地拥抱富媒体、拥抱组件化、拥抱工作区。那是 AI 真正的应许之地。