
让 AI Agent 直接读你的网站:Accept: text/markdown 内容协商实战教程
手把手教你把网站变成 AI Agent 友好:用 Accept: text/markdown 内容协商,让 Claude Code、Cursor 等工具直接读到干净的 Markdown。含 Caddy、Nginx、Next.js、Cloudflare 配置和验证方法。
原文来源:Accept Markdown — 用 HTTP 内容协商的 Accept: text/markdown 约定,让 AI Agent 从你的网站直接读到干净的 Markdown,而不是充满导航和脚本的 HTML。
越来越多的 AI 工具(Claude Code、Cursor、Copilot)自带"读网页"的能力,但它们的抓取器拿到的是给浏览器看的 HTML:导航、脚本、样式、广告位全混在一起。你的文章本身可能只有几千字,HTML 却有好几十 KB。本文教你用 HTTP 标准里的内容协商(Content Negotiation)机制,让 AI Agent 直接拿到干净的 Markdown。
为什么值得做
内容协商的含义是:同一个 URL,服务器根据请求头里的 Accept 字段决定返回什么格式。给 AI Agent 返回 Markdown 有三个实打实的好处:
- 省 Token:Markdown 去掉导航、样式、脚本后体积可能只有 HTML 的零头,Agent 的上下文窗口留给你的正文,而不是 DOM。
- 检索质量更高:RAG 管道做嵌入时不会被广告、相关推荐、弹窗干扰,文本的信噪比高得多。
- 首字延迟更低:要抓的字节少了,解析也快了,模型更快开始思考。
这个约定不是厂商私有方案:媒体类型定义在 RFC 7763(text/markdown),协商语义来自 RFC 9110(HTTP 语义),都是标准协议。
—— 广告 ——
三步快速开始
任何栈的实现都逃不出这三步,总共不到 20 行配置。
第一步:检测 Accept 头。 请求进来时读 Accept,如果它把 text/markdown 排在 text/html 前面,就返回 Markdown。注意不要做子串匹配——要按 q 值排序、按媒体类型精确度分胜负,或者直接用现成的解析库。q 值规则要理解对:Accept: text/markdown;q=0.9, text/html;q=0.8 表示两个都接受但更想要 Markdown;q=0 表示明确拒绝;同权重时更具体的媒体类型胜出。
第二步:返回对应的表示。 响应里做两件事:Content-Type 设为 text/markdown; charset=utf-8(或 text/html),同时设置 Vary: Accept,让缓存按请求头区分版本。如果客户端明确要求了你不支持的类型,返回 406 Not Acceptable,而不是悄悄回退。
第三步:用 curl 验证。
curl -sI -H "Accept: text/markdown" https://你的域名/文章
# 应该看到 Content-Type: text/markdown 和 Vary: Accept把 Accept 换成 text/html 再请求同一个 URL,应该拿到 HTML。检查你的实现是否完整,就看四条:Markdown 表示是否只在 Accept: text/markdown 时返回、是否设置了 Vary: Accept、不支持的类型是否返回 406、q 值是否被正确处理——acceptmarkdown.com 的在线检测工具可以帮你对任意 URL 跑这四项检查。
关键陷阱
Vary: Accept 不能省。 没有它,CDN 和浏览器缓存会把 Markdown 和 HTML 当成同一个资源,第一个来的人拿到什么,后面所有人都拿到什么。Markdown 版本被浏览器缓存、或者 HTML 版本被 Agent 缓存,都是灾难。Vary 是必要条件,但不同 CDN 的处理还有各自的坑——Cloudflare、Fastly、Vercel 都有各自的怪癖,上线前要分别测过。
406 别乱用。 只有客户端明确要求了你给不了的东西才返回 406。浏览器一般发 Accept: text/html,application/xhtml+xml,...,这时候你当然要回 HTML。最常见的错误是协商逻辑写得太激进,把正常浏览器请求也 406 了。
Markdown 从哪来。 三种做法:内容本来就是 Markdown 源(直接用,比如很多静态博客);构建时双渲染(同一份源同时生成 HTML 和 Markdown);运行时把 HTML 转 Markdown。选哪种取决于你的内容管线。Cloudflare 用户还有个零配置选项:站点在 Cloudflare 后面时,开"Markdown for Agents"开关,边缘层直接完成协商,源站零改动。
各栈配置速查
-
Caddy:用命名匹配器(named matchers)最简洁,预渲染的
.md文件在同一 URL 下给 Agent,HTML 给浏览器:codeexample.com { @markdown header Accept text/markdown handle @markdown { rewrite * /{path}.md root * /var/www/site file_server } handle { root * /var/www/site file_server } } -
Nginx:
map+try_files实现,Markdown 和 HTML 从同一个 URL 分发。 -
Next.js(App Router):写一个 middleware 做 Accept 解析,设置
Vary和 406 语义,注意区分 Vercel、Cloudflare 和自托管 Node 的部署差异。 -
Astro / SvelteKit / Nuxt:各自有 middleware 或 handle hook 的写法,SvelteKit 可以用路由端点直接返回 Markdown,并带上
Link: rel="alternate"广告备用版本。 -
Express / Django / Rails / Go:都有一行中间件或
respond_to的写法——Rails 甚至内置了text/markdownMIME 类型和 markdown 渲染器,还会自动设置Vary: Accept。 -
WordPress / Discourse:Roots 团队提供了 post-content-to-markdown 和 discourse-to-markdown 插件,装完即用。
哪些 AI Agent 支持
根据 acceptmarkdown.com 的实测矩阵(最后更新于 2026-06-22):Claude Code、Copilot Chat、Copilot CLI、Cursor、OpenCode、OpenClaw 会发送 Accept: text/markdown,开箱即用;Codex CLI 是部分支持——它先抓 HTML,再解析 <link rel="alternate" type="text/markdown"> 找 Markdown 兄弟版本,所以如果你用 Codex,记得在页面 <head> 里加上这个 link;ChatGPT 网页浏览、Gemini CLI、Perplexity、Devin、Cline、Grok 目前只抓 HTML,协商对它们无效。矩阵是站点作者逐个实测出来的,验证方法公开在页面上,Agent 行为随版本变化,你可以随时用自己的服务器复测。
想验证自己的站点:先在访问日志里加上 Accept 字段(Nginx 用 log_format 加 $http_accept,Caddy 的 JSON 日志默认就带),然后让某个 Agent 去抓你的一篇文章,回日志里 grep 那篇文章的 URL,看 accept 字段里有没有 text/markdown。
对独立开发者来说,这可能是成本最低的"AI 友好化"改造:你的内容本来就在,只是多一个按请求头分发的副本。改完之后还可以顺手在 <head> 里加上 <link rel="alternate" type="text/markdown">,给 Codex CLI 这类走备用链接的 Agent 指路。等 AI 流量占比越来越高,这个提前量会越来越值。
© 2026 四月
原文链接:https://www.aprilzz.com/tutorials/serve-markdown-to-ai-agents
相关文章
在 Mac 上搭建本地编程 Agent:llama.cpp + Gemma 4 + MTP 投机解码完整指南
断网也能用的编程 Agent:用 llama.cpp 在 Mac 上跑 Gemma 4 26B,配合 MTP 投机解码把生成速度从 58 提到 72 token/s,再接上支持图片输入的 Pi 终端 Agent。
把本地开源模型接进 OpenClaw:llama.cpp 自托管完整教程(零成本跑 Agent)
手把手教你把 llama.cpp 起的本地模型接入 OpenClaw:安装、启动 OpenAI 兼容服务器、写配置、配混合 fallback,所有参数来自官方文档,抄完就能用。
n8n 入门指南:2026 年搭建你的第一个 AI Agent 工作流
从零开始学习 n8n——开源的工作流自动化平台。本文将教你如何搭建 AI Agent 工作流,连接 LLM、API 和 400+ 服务。