跳转到主要内容
指南

如何为 AI agent 提供一条结构化路径穿过你的应用

不要把 agent 硬塞进为人设计的页面,而是为它们提供结构化路由。本指南涵盖格式、发现、按 actor class 路由以及公平限制。

Toshendra Sharma

作者 Toshendra Sharma创始人兼 CEO,AgentCredia · Updated November 13, 2026

中级 · 10 分钟阅读

为什么 AI agent 需要一条不同的路径穿过你的应用?

越来越多发往你的应用的请求来自 AI agent: 为用户获取文档的助手、阅读产品页面的研究工具、调用你的 API 的自治工作流。其中大多数都在通过为人设计的界面工作。它们下载完整的 HTML 页面,解析布局,跟随为鼠标设计的导航,并且在脚本很重的页面没有按预期渲染时重试。

这对所有人都低效。agent 会拿到嘈杂的内容并犯错。你的服务器把资源花在没人看的页面渲染上。而且这类流量很难推理,因为它看起来像一个行为异常的浏览器。如果你还不确定这类流量占多少,可以先看如何判断网站流量是否来自 AI agent。

更好的做法是给 agent 一条结构化路径: 以程序可用的格式提供内容和动作,在标准位置可被发现,并通过奖励正确标识自己的客户端的限制来管理。这个指南会说明如何做到这一点,而不必再搭建一个应用。

第 1 步: 决定 agent 应该能够做什么

先从意图开始,而不是技术。查看你已经看到 agent 流量的路由,并将它们分组:

  • 读取内容: 文档、产品信息、定价页面、帮助文章、公开资料页。
  • 查询数据: 搜索、目录查询、可用性、状态。
  • 执行操作: 代表用户创建、更新或删除某些内容。

读取和查询是适合结构化路径的好候选项,这种路径对任何行为良好的客户端都开放。无论客户端如何识别自己,执行操作都需要认证和授权,这部分内容在保护敏感操作的指南中有说明。

第 2 步: 提供机器友好的格式

对于内容路由,提供不带页面外壳的同样信息。下面两种格式已经覆盖大多数需求:

  • Markdown 用于文档和文章等叙述性内容,使用在 RFC 7763 中注册的 text/markdown 媒体类型提供。它保留标题、列表、链接和代码块,而且很紧凑。
  • JSON 用于产品、方案或状态等结构化记录。

使用内容协商,这样 URL 保持不变,客户端只需请求它想要的格式:

TS
import express from "express";

const app = express();

app.get("/docs/:slug", async (req, res) => {
  const doc = await loadDoc(req.params.slug);
  if (!doc) return res.status(404).end();

  res.vary("Accept");
  const preferred = req.accepts(["text/html", "text/markdown", "application/json"]);

  if (preferred === "text/markdown") {
    return res.type("text/markdown; charset=utf-8").send(doc.markdown);
  }
  if (preferred === "application/json") {
    return res.json({ title: doc.title, updatedAt: doc.updatedAt, body: doc.markdown });
  }
  return res.render("doc", { doc });
});

发送一个 Vary: Accept 头部(RFC 9110 中关于 Vary 的说明),这样缓存会分别存储每种表示。很多团队也会公开一个明确的备用 URL,例如在文档路径后追加 .md,因为有些客户端觉得这比协商更容易。通过 <link rel="alternate" type="text/markdown" href="..."> 在 HTML 页面中链接它,这样就可以被发现。像这样的类型化链接遵循 Web Linking 模型。

第 3 步: agent 如何发现你的结构化路径?

agent 无法使用它找不到的东西。把入口点发布到自动化客户端已经会查看的位置:

  1. 站点根目录下的 /llms.txt: 一份简短的 Markdown 摘要,说明你的网站提供什么,并附上最有用页面及其结构化版本的链接,遵循 llms.txt proposal。
  2. API 描述,例如 OpenAPI 文档,从你的开发者文档以及 /llms.txt 中链接出去。
  3. HTML 页面中的 备用链接,指向 Markdown 或 JSON 版本。
  4. 站点地图,列出你的规范内容 URL,格式遵循 Sitemaps protocol 定义。

一个最小的 llms.txt:

MARKDOWN
# Example App

> Example App helps teams plan projects. This file lists the best entry points for automated clients.

## Docs
- [Getting started](https://example.com/docs/getting-started.md): setup in five steps
- [API reference](https://example.com/openapi.json): OpenAPI description of the public API

## Policies
- [Automated access](https://example.com/docs/automated-access.md): limits and how to sign requests

保留一个页面,说明你对自动化客户端的规则: 哪些路由开放、适用哪些限制,以及客户端如何通过签名请求标识自己以获得更好的待遇。清晰的规则会把猜测变成协作。

第 4 步: 按 actor class 路由,而不是按 user agent 字符串

一旦你有了结构化响应,就决定默认把它们给谁。使用 actor class 及其 basis,而不是临时解析 user agent 字符串。AI operator 的确会发布它们的 user agent,就像 OpenAI 和 Anthropic 为它们的 crawler 和 fetcher 所做的那样,但字符串匹配仍然只是一种声明。

TS
type ActorClass = "human" | "human_ai" | "agent" | "unknown";
type Basis = "verified" | "declared" | "inferred" | "unknown";

function preferStructured(actor: ActorClass, basis: Basis, accept: string): boolean {
  if (accept.includes("text/markdown") || accept.includes("application/json")) return true;
  return actor === "agent" && (basis === "verified" || basis === "declared");
}

下面两个原则可以保持安全:

  • 显式请求始终优先。 如果客户端请求 Markdown 或 JSON,就提供它,不论 class 是什么。
  • 默认值绝不会夺走任何内容。 Human 或 Unknown 访问者始终拿到完整页面。给 agent 设定结构化默认值只会改变格式,不会改变它们被允许看到的内容。

第 5 步: AI agent 应该获得什么速率限制?

速率限制是 actor 上下文最直观发挥作用的地方。不要给所有人一条限制,而是为每个 class 和 basis 的组合分配合理额度:

Actor and basis Read routes Notes
Agent, verified 更高限制 Operator 可识别且可追责
Agent, declared or inferred 标准限制 声明无法核实
Unknown 标准限制 默认不惩罚
Human or Human + AI 标准限制 交互式使用很少接近限制

以可用的最稳定标识符来键定限制。对于 verified agent,那是 operator origin 和 key identifier。对于其他情况,则使用 credential 或网络级 key。

TS
function limitKey(actor: { actor: ActorClass; basis: Basis; operator?: string }, ip: string, apiKey?: string) {
  if (actor.actor === "agent" && actor.basis === "verified" && actor.operator) return `op:${actor.operator}`;
  if (apiKey) return `key:${apiKey}`;
  return `ip:${ip}`;
}

function limitFor(actor: { actor: ActorClass; basis: Basis }): number {
  if (actor.actor === "agent" && actor.basis === "verified") return 600;
  return 120;
}

这些数字只是占位符。根据你观察到的基线设置自己的数值。当客户端超出限制时,返回 429 Too Many Requests 并带上一个 Retry-After 头部,以及指向你的自动化访问页面的链接。构建良好的 agent 会退避并读取它。

第 6 步: 将操作保留在授权之后

针对读取的结构化路径,不是绕过你的安全模型的路径。任何会更改数据的操作仍然需要:

  1. 使用应用签发的凭证进行认证,
  2. 针对该特定操作进行授权,
  3. 以及该路由风险等级要求的任何额外检查。

经过验证的签名告诉你是谁在调用。它并不能告诉你该客户端是否可以代表某个用户执行操作。把这些问题分开处理。我们关于签名的 AI agent 请求能证明什么的文章解释了其中的区别。

第 7 步: 衡量效果

先以观察模式运行结构化路径,然后比较:

  • 使用结构化格式的 agent 请求占比,
  • 结构化前后 agent 流量的服务器成本和延迟,
  • agent 客户端的错误率和重试率,
  • 在你发布签名指南后,有多少自动化客户端从 declared 转为 verified。

这些数字能说明结构化路径是否在发挥作用,以及下一步应扩展到哪里。

第 8 步: 为结构化路径做版本管理并写文档

把结构化路径视为公共接口,因为 agent 会在其上构建。下面几个习惯能让它保持可靠:

  1. 保持 URL 稳定。 如果 agent 已经知道 /docs/getting-started.md 存在,它就应该继续可用。当内容迁移时,返回一个到新位置的 301,而不是一个 404。
  2. 包含更新时间。 在 JSON 响应中加入 updatedAt 字段,并在 Markdown 上加入 Last-Modified 头部,这样 agent 可以合理缓存,只在内容变更时刷新。
  3. 支持 条件请求。 对 If-None-Match 和 If-Modified-Since 返回 304 Not Modified。当 agent 可以重新验证而不是再次下载全部内容时,轮询你的内容的成本会低得多。
  4. 为破坏性变更做版本管理。 如果 JSON 结构必须改变,就添加新的版本路径或媒体类型,并在公开期内保留旧版本。
  5. 为自动化访问页面发布变更日志。 行为良好的 agent operator 会阅读它,而这也给你提供了一个宣布新结构化路由的地方。
TS
app.get("/api/plans", async (req, res) => {
  const plans = await loadPlans();
  const etag = `"${plans.version}"`;
  res.set("ETag", etag);
  res.set("Cache-Control", "public, max-age=300");
  if (req.get("if-none-match") === etag) return res.status(304).end();
  return res.json({ updatedAt: plans.updatedAt, plans: plans.items });
});

这些实践同样有利于你自己的前端和合作伙伴集成。稳定、可缓存且有文档的结构化路径,很快就会成为任何程序与应用协作的最简单方式。

常见陷阱

  • 对 agent 和人提供不同事实。 结构化版本应包含与页面相同的信息。内容不一致会让向助手询问产品的用户感到困惑。
  • 把结构化路径藏起来。 如果它没有从 /llms.txt、你的 API 文档或页面本身链接出去,agent 就会继续抓取 HTML。
  • 奖励声明。 更高限制应该给 verified 客户端。复制来的 user agent 字符串不应获得更大的额度。
  • 忘记缓存。 没有 Vary: Accept,缓存可能会把 Markdown 提供给浏览器。

Proof of Actor 在哪里发挥作用

Proof of Actor 会为你提供将 agent 路由到结构化内容并设置公平限制所需的 actor class 和 basis。它会检测已签名、已声明和推断出的 agent,帮助你理解它们如何使用你的路由,并把路由决策留在你的代码中。

如果你想和我们的团队一起为自己的应用设计结构化路径, 申请早期访问。对于 API 和 MCP 场景,另请参阅 APIs 和 MCP Servers,并阅读谁在调用你的 MCP server?,了解 actor 上下文如何应用于 Model Context Protocol 工具调用。

来源

与我们一起构建。

加入 Proof of Actor founding developer program。

想先聊聊? 联系创始人