
开头先从一个实际经历说起。有一次我让 Claude 帮我生成一份带表格、分章节、有前后置条件的发布说明。对话界面里用 Markdown 预览看起来一切正常标题层级清楚表格竖线对齐列表缩进也没有问题。结果我把这份 Markdown 粘到公司的发布系统里表格直接碎成一堆竖线和连字符列表层级也乱掉了一大半。当时我以为是模型不够聪明又试了几个不同的提示词写法反复强调“请保持表格列数一致”“请正确嵌套列表”。效果时好时坏直到我偶然让模型直接输出 HTML 片段问题才彻底消失。不是视觉上更好看而是它天然把内容当作一棵结构树来生成标签闭合、父节点子节点一目了然。后来我在技术社区里看到“Anthropic 工程师放弃 Markdown改用 HTML 和 AI 工作”这类讨论时第一反应不是惊讶而是想通了一个更底层的道理和 AI 协作时格式不是表现层问题而是协议设计问题。Markdown 是人类友好的速记法却未必是机器友好的结构语言。这篇文章想和你拆开聊聊为什么在 AI 场景里 HTML 反而会成为更可靠的选择以及你如果想切换该怎么落地。1. Markdown 不是不够好而是太容易让模型“猜结构”1.1 Markdown 的宽容性在人和机器之间有完全不同的代价Markdown 最大的优点是它几乎不需要学习成本。你写几个井号就是标题写一个短横线就是列表写两个竖线加一个小横杠就成了表格。人类阅读时会靠上下文自动脑补出结构哪怕缩进不一致、空行缺失也很少陷入理解障碍。但模型不是这样工作的。模型生成文本时并不是先在内存里构建一棵文档树再把它转换成字符串。它做的是“下一个字符”的预测是一段概率序列。它并不是真的“知道”这里有一个三层嵌套列表它只是看过太多类似文本认为这样写看起来合理。问题就出在“看起来合理”上。Markdown 的语法边界很模糊列表缩进是几个空格嵌套列表需要空行吗表格列数不一致时应该对齐还是忽略这些规则在不同渲染器里的解释不一样。人类可以靠视觉判断模型却只能靠统计学模式猜测于是压缩和结构错位的概率就被无限放大了。1.2 模型输出 Markdown 时真正崩溃的是嵌套与表格我在日常工作中很常用一个测试让模型生成一份带“前置条件”、“操作步骤”、“回滚方案”三个部分的发布文档。如果要求它用 Markdown 输出典型问题包括二层列表和一层列表缩进相同渲染后全变成同一层级代码块在列表中没有正确缩进导致整块代码脱离列表语义表格的列数不一致某一行少了一个单元格标题层级跳空从## 2直接跳到#### 2.3.1。这些问题在对话预览里你几乎注意不到。因为大部分聊天界面都内置了容错性很高的 Markdown 渲染器会自动修正一些解析歧义。但一旦把文本拿到 GitHub、语雀、Obsidian 或其他渲染库里每套渲染器的修复策略都不太一样结果就是“这边正常、那边碎掉”。这个现象背后有一个关键点你让模型输出 Markdown但你没有给模型任何关于“正确结构”的具象约束。它只能依赖训练资料里的习惯性写法去猜。猜的次数多了自然会出错。1.3 一个反复出现的现象Markdown 在预览里正常进系统就碎有不少人把问题归结为提示词写得不够好于是不断在提示里加“请保证嵌套正确”“请保持各表格列数一致”。但这类话术本质上是在要求模型把 Markdown 渲染器内置到生成逻辑里这本来就不在它的能力范围内。更合理的思路是换一种让模型“很难猜错”的表达语言。HTML 恰好就是这样一种语言。它把层级用标签显式标出写错了就是错不会存在“同一个符号在不同渲染器里读到不同含义”的情况。不是 HTML 比 Markdown 高级而是它作为结构协议歧义更少。先别急着调提示词。先看看你选的输出格式本身是不是在逼模型做它不擅长的结构猜测。这也正是我后来理解“Anthropic 工程师为什么偏向 HTML”的第一层答案他们可能未必认为 Markdown 不好而是因为在 AI 协作这条链路里结构稳定性比书写便捷度重要得多。2. HTML 的护城河它把输出从“文本猜测”变成“结构生成”2.1 标签闭合与嵌套规则相当于给模型画出一张结构棋盘HTML 和 Markdown 最本质的区别不在于语法复杂度而在于结构表达方式。Markdown 用缩进、空行、符号组合这些“格式信号”来表达层级。它需要看上下文才能判断某一行属于哪个块级元素。而 HTML 用成对标签来描述嵌套关系section开始就必须有/section结束table里面只能按顺序写thead、tbody、tr、td。标签本身就是机器学习中非常强的提示信号。模型在海量网页上训练过见过太多完整的 HTML 文档。标签的配对规律、嵌套限制、常见顺序它都掌握得很稳。你给模型一个article开始标签它会以很高的概率生成对应的/article你给它一个ul它会倾向于生成li而不是突然插入一段无关段落。这相当于你给模型画了一张结构棋盘它只需要在格子里放内容不需要自己发明棋盘。2.2 语义标签让模型更清楚“这段内容是什么”HTML 除了有结构约束还有语义信息。header表示文档头section表示章节table表示表格blockquote表示引用。模型看到这些标签时不仅知道内容的位置还能推断内容的功能。这一点在长文档生成里非常有用。比如让模型生成一份 API 迁移指南你可以在模板中提前定义article section classcontext h2背景/h2 /section section classbreaking-changes h2破坏性变更/h2 table thead trth旧接口/thth新接口/thth迁移说明/th/tr /thead tbody /tbody /table /section section classmigration-steps h2迁移步骤/h2 ol/ol /section /article然后让模型只填充表格行和列表项。它就不太会跑偏不会在“迁移步骤”里突然加进一段与主题无关的表格也不会把背景部分写成一长串没有层级的长文本。因为语义标签已经告诉它“这里是表格区域”“这里是步骤区域”。对比 Markdown## 背景只表达“标题叫背景”但并没有明确告诉模型这个标题下面应该出现什么类型的结构。语义信息越少模型自由发挥的空间就越大。2.3 对 Agent 工作流而言DOM 可解析是决定性的收益如果你只是和 AI 一对一聊天Markdown 和 HTML 的差异可能没那么致命。但如果你在搭 Agent 流程让 AI 的输出直接喂给下一个程序或工具HTML 的优势就非常明显。Markdown 解析出来的 AST 在不同库之间几乎不通用。同一个 Markdown 文档用marked、remark、markdown-it解析得到的节点结构可能截然不同。你的代码需要针对特定解析器编写逻辑后续升级和迁移都很痛苦。HTML 则不同。浏览器和 Node.js 都有标准的 DOMParser 和 DOM API。你可以直接用querySelector从 AI 输出的 HTML 中提取指定节点不需要自己写正则去猜const doc new DOMParser().parseFromString(aiOutput, text/html); const breakingChanges doc.querySelectorAll(section.breaking-changes tbody tr); breakingChanges.forEach((row) { const cells row.querySelectorAll(td); console.log(cells[0]?.textContent); });这比维护一套 Markdown 解析逻辑要轻松得多。只要 AI 输出的标签结构稳定下游代码就不需要经常跟着改。这个“可解析性”的收益在实际工程里远远超过“肉眼可读性”的价值。2.4 为什么很多工程师愿意牺牲一部分阅读体验当然HTML 也有明显缺点写起来冗长阅读体验比 Markdown 差。如果你直接在终端里看模型输出的原始 HTML会觉得很痛苦。但这里有一个真实权衡当文档的“消费者”不是人而是另一个程序、一个 Agent 步骤或一个长期维护的脚本时阅读体验就不是第一优先级。你真正需要的是稳定的、可验证的、可提取的结构。HTML 恰好能同时满足这三项。这也是为什么当讨论“Anthropic 工程师弃用 Markdown”时我并不觉得这是一个激进决定。它更像是一种合理工程选择降低模型输出与下游工具之间的语义损耗。3. 从 Markdown 换成 HTML 的真实落地步骤3.1 先定义最小 HTML 模板再让模型填内容很多人在提示词里只写一句“请用 HTML 格式输出”效果往往不好。因为模型不知道你期望的 HTML 结构长什么样它会自己发挥可能生成一大堆无意义的外层 div或者把内容塞进一个巨大的table。正确做法是先给模型一个最小 HTML 模板并明确告诉它“不要修改结构只替换占位符内容。” 这个模板相当于你和模型之间的契约。例如让模型生成一个新闻稿片段article header h1【标题】/h1 p classsummary【摘要】/p /header section h2事件核心/h2 p【正文第一段】/p /section section h2影响范围/h2 ul li【影响点一】/li li【影响点二】/li /ul /section /article把这段模板放在 Prompt 的尾部明确说明“把括号里的描述替换成真实内容”模型就会把注意力放在填充而不是重新设计结构。这种做法比单纯用文字描述想要的格式稳定很多因为模板本身就提供了结构先验。3.2 小样本验证两件事结构是否稳定、平台是否保留标签不要急着一次性生成几十个文档块。先用一条最小样例测试重点确认两件事。第一模型的输出是否可以被 DOM 解析。你可以在本地写一个小脚本把 AI 输出传给 DOMParser如果解析后document.querySelector(body).children结构合理说明没问题如果解析出大量空节点或标签错乱就需要调整模板。第二你常用的目标平台是否支持内嵌 HTML。有些在线 Markdown 编辑器出于安全考虑会默认转义或过滤 HTML 标签。你把 HTML 粘贴进去之后看到的是lt;divgt;而不是真正的div说明这个平台不适合内嵌 HTML你需要换一种消费路径比如直接保存成.html文件或者在本地用浏览器渲染或者通过 API 获取原始文本。3.3 用注释和类名维持可维护性HTML 写长了以后人眼确实很难迅速定位。这时候注释和类名就能帮你和模型建立共同记忆。我一般会在模板的关键位置插入注释!-- 这块内容会同步到每周周报请勿删除结构 --这种注释不仅仅是给人看的模型在生成下一个字符时也会把注释当作上下文信号。它知道这段结构是“被标记过的”不能随便破坏。对长文档生成尤其有用。类名也要尽量选择语义化、稳定的词比如project-plan、changelog-entry、risk-list。不要用box-1、div-2这类无意义命名。类名本身也是给模型的语义提示稳定之后下游程序可以拿它当锚点。后续如果 AI 不小心改变了结构脚本还能根据类名做容错匹配。3.4 混合策略Markdown 写正文HTML 写复杂组件如果你觉得纯 HTML 太笨重也可以走混合路线。很多 Markdown 渲染器允许在 Markdown 文档中嵌入 HTML并且会原样渲染而不是转义成纯文本。实际操作时我会这样做普通段落、简单的列表、简短的引用继续用 Markdown 写复杂的表格、卡片、多列布局、需要精确层级的内容用 HTML 片段代替整个文档的“外壳”用 Markdown 保持可读性内部复杂组件用 HTML 保证结构稳定。例如一个技术周报# 本周技术周报 ## 项目进展 div classgrid div classcard h3服务稳定性/h3 p本月整体可用性 99.98%/p /div div classcard h3发布次数/h3 p生产环境发布 32 次/p /div /div ## 风险清单 - 数据库延迟偶发超过阈值 - 部分接口文档未同步更新这样既保留了 Markdown 的标题层级和阅读节奏又用 HTML 把最容易错的结构隔离了起来。3.5 用工具链把“结构正确”制度化靠模型自觉并不是长久之计。更可靠的做法是在输出链路里加入自动化检查。我自己常用的工具组合包括# 格式化 HTML npx prettier --write output.html # 验证 HTML 合法性 npx html-validate output.html # 用 Node 脚本解析并提取关键节点 node extract-sections.js output.htmlprettier负责格式统一html-validate负责标签闭合和嵌套检查extract-sections.js负责验证关键类名是否还存在。这一套流程跑下来基本上可以保证“AI 输出的 HTML 至少不是坏掉的 HTML”。最终你会发现真正稳定的不是“某一次生成得好”而是“每次生成后都经过同一套检查规则”。这就是把单次经验沉淀成可复用流程的过程。4. 这不是 Markdown 与 HTML 的战争而是协议设计的习惯4.1 格式本质上是人和 AI 之间的接口协议先说一个更底层的观点。当我们讨论 Markdown 和 HTML 时我们其实不是在选一个“语法风格”而是在设计一套“接口协议”。在传统开发中接口协议决定了两套系统之间如何理解对方。如果协议足够明确双方就能稳定协作如果协议模糊就会有各种错位。AI 协作也是一样。你和模型之间的 Prompt 是协议模型返回的格式也是协议。格式如果表达不了清晰的层级和语义下游解析就会出问题。这解释了一个很有意思的现象同样的模型有人觉得它输出很乱有人觉得它输出很稳定。差别往往不在模型能力而在于你有没有给它提供足够清晰的结构约束。用 Markdown 时很多结构信息是靠上下文猜的用 HTML 时结构信息被显式写了出来。模型不需要猜自然就更稳定。4.2 HTML、JSON、YAML、CSV 怎么选在实际工程中可选的结构化格式远不止 HTML 一种。我的选择思路通常这样JSON Schema适合严格接口层面的数据交换比如 Agent 要返回某个字段程序需要直接读取。但它不适合写长文档嵌套一深人就看不懂了。CSV适合扁平数据比如 Excel 导出、统计报表。但它完全表达不了嵌套和层级。YAML适合配置文件可读性不错但缩进错误比 Markdown 更隐蔽。模型一旦生成前一行末尾有多个空格后一行就完全失去层级。Markdown适合人类阅读和轻量笔记语义标签弱结构判断依赖渲染器。HTML适合需要渲染效果、需要多层级、需要语义标签、还要能被 DOM API 稳定解析的文档型输出。一个很实际的经验是先问“谁消费这个输出”。如果消费方是页面、文档、知识库HTML 的高可渲染性会带来巨大优势如果消费方是纯程序逻辑JSON 更直接如果消费方是普通用户临时阅读Markdown 还是最轻量的选择。4.3 前沿讨论值得关注的真正信息让模型的猜测空间变小回到标题本身。“Anthropic 工程师放弃 Markdown 改用 HTML 跟 AI 工作”这句话我并没有去核实是否字面成立。我更倾向于把它理解成一个有代表性的信号在认真做 AI 协作工作流的人那里他们会关心模型的语义边界会更主动地用格式来约束模型。HTML 只是他们拿到的工具之一。这种做法的核心思想是少让模型猜。每一次你提供的结构越明确模型出错的概率就越低。这就像你在写库表结构时用外键和唯一约束把数据规则固定下来减少应用层的脏数据。格式就是 Prompt 层的约束条件。4.4 适用边界不是所有任务都要换成 HTML我也要说清楚HTML 并不是万能的。如果你只是随手记一个会议纪要写一个 TODO 清单或者让 AI 帮你整理一段学习笔记强制改成 HTML 反而会降低效率。这类任务不需要复杂的嵌套结构Markdown 已经足够。另外如果你的输出需要被某个不支持 HTML 的工具消费比如某些即时通讯软件、旧版富文本编辑器那么 HTML 可能根本发不出去反而让链路中断。所以“换 HTML”一定要在确认目标消费方支持的前提下进行不要把它当成默认最优解。判断标准很简单当结构复杂度超过 Markdown 的舒适区并且下游具备 HTML 渲染或解析能力HTML 就是更好的选择。否则不用强上。5. 风险与踩坑HTML 不是银弹可能带来新问题5.1 安全清洗是前提别把 AI 输出直接渲染AI 生成的 HTML 和人类手写的 HTML 一样必须经过安全清洗才能放进生产环境。不要因为“这是模型生成的文本”就放松警惕。它可能包含内联脚本、无效链接、外部资源引用甚至被训练数据污染出一些不可控的标签。在本地做原型验证时可以直接用浏览器打开。但如果要通过 Web 页面展示给用户至少要做三层防护用 DOMPurify 或 sanitize-html 做白名单过滤前端渲染时设置严格的 Content-Security-Policy如果允许异步加载用 iframe 配合 sandbox 属性禁止脚本执行。import DOMPurify from dompurify; const cleanHTML DOMPurify.sanitize(aiOutput, { ALLOWED_TAGS: [article, section, h1, h2, h3, p, ul, ol, li, table, thead, tbody, tr, th, td, blockquote, code, pre], ALLOWED_ATTR: [class, href, title], });安全永远排在效率前面这一点不能妥协。5.2 token 成本、可读性和工具兼容性要算清楚HTML 的标签冗余是真实成本。一个结构相同的内容HTML 的 token 消耗通常比 Markdown 高 20% 到 50%。如果你用的模型上下文窗口比较紧张或者调用 API 是按 token 计费这个开销要提前算进成本里。此外HTML 的可读性确实差。你在终端里直接看 AI 返回一大段 HTML很难快速找到某段文字。所以我在使用 HTML 时通常会要求模型在输出里保留注释并且配合格式化工具。如果实在需要人眼快速阅读原始输出也可以让模型同时返回一版 Markdown但这样 token 成本会翻倍。所以我的建议是不是所有对话都必须用 HTML。把 HTML 用在高频、重复、需要长期维护和自动化的任务上把 Markdown 用在一次性的、人读为主的对话上。两者不是替代关系而是分工关系。5.3 从“HTML 又坏了”开始排查一条完整链路如果你已经切换到 HTML但还是遇到渲染异常可以按这个顺序排查先看输出是不是被 Markdown 代码块包住了。很多模型会把 HTML 写在html和之间你需要先剥掉外层代码块否则整个 HTML 会被渲染成文本或错误解析。再看是不是被转义了。如果页面里显示的是lt;divgt;说明平台把 HTML 标签当作文本显示。这种情况要换一种保存或渲染路径而不是继续修改提示词。然后检查标签闭合。使用html-validate做静态检查重点搜一下table、section、div是否成对出现。接着看渲染器有没有白名单过滤。部分 Markdown 渲染器会过滤掉非白名单标签即使你的 HTML 本身没问题也会被吞掉。最后排除模型截断。上下文窗口不够时模型可能只输出一半就停了导致 HTML 缺了后半部分。这会表现为“结构很怪”或“结尾根本没有闭合标签”。先调大max_tokens或者把文档拆成多个小节逐段生成。这条链路虽然长但每一步都有明确验证方式。排查次数多了以后你基本能预判问题出在哪个环节。6. 真正值得形成的习惯每次都先设计输出协议6.1 一个最小可复用的格式选择框架在 AI 协作任务里我现在每次都会先想四件事输出给谁消费人、程序、页面、还是另一个 Agent结构是扁平的还是多层级嵌套输出是否会被后续脚本解析目标平台是否支持保留这种格式四个问题形成一张简单判断表消费方结构复杂度典型最佳格式原因人临时阅读低Markdown轻量、可读性好人阅读 页面渲染中高Markdown HTML 嵌入兼顾可读性和结构稳定程序解析中JSON Schema类型明确、容易映射页面渲染 程序提取高HTML可渲染、可解析、语义丰富配置项中YAML层级清晰适合枚举属性这张表不是绝对规则但它能帮你从“哪个格式流行”跳到“当前任务需要什么协议”。6.2 一个最小验证路径如果你想尝试 HTML 方案不要一次性铺开。按下面六步走挑一条你每天都用到的高频任务比如生成周报、生成发布日志、生成接口文档。用一个最小 HTML 模板代替原来的 Markdown 模板。让 AI 只做内容填充不改结构。在本地验证输出是否可以被 DOMParser 解析结构是否稳定。用 prettier 和 html-validate 做静态检查。稳定后再把模板和检查脚本固化成团队规范或 Agent 工作流配置。这套流程的关键不是追求“一次写对”而是把每次输出都纳入同一套验证规则让错误能在最早阶段被发现。6.3 最后说回工程选择不要追着“谁换了格式”要追“为什么换”“Anthropic 工程师为什么放弃 Markdown 改用 HTML”这个话题真正有信息量的部分不在 Markdown 和 HTML 谁更好而在于一个工程团队开始把“格式设计”当成 AI 工作流里的一等公民。他们意识到模型输出的稳定性和可维护性不只是提示词层面的问题更是格式协议层面的问题。你不需要立刻把所有的文档生成任务都改成 HTML。但你应该开始培养一个习惯每次和 AI 协作时先想清楚输出会被谁消费用哪种格式能最大程度减少误解。想清楚这一点你就能少踩很多“明明提示词写得很细输出还是翻车”的坑。这种习惯比选哪个格式更值得长期积累。