当机器流量超过人类:AI Agent 时代如何重建开放 Web 的规则

2026-09-28 39 预计阅读时间: 1 分钟
来源: blog.cloudflare.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

Cloudflare 在 2026 年创始人信中提出了一个关键判断:互联网正在经历其成立以来最剧烈的一轮变化,自动化流量已经超过人类活动。网页的访问者不再只是拿着浏览器的人,也可能是搜索爬虫、AI 训练程序、替用户执行任务的 Agent,甚至是无法识别来源和意图的自动化客户端。

这不只是一次流量结构变化。它会重新定义内容如何被发现、创作者如何获得回报,以及网站应当怎样表达访问规则。

从“人访问网页”转向“软件消费资源”

传统 Web 默认访问链路相对清晰:用户打开浏览器,看到页面,网站通过订阅、广告、交易或品牌曝光获得价值。AI Agent 介入后,这条链路可能被压缩:

  1. 自动化程序读取大量页面;
  2. 模型或 Agent 提取、重组信息;
  3. 用户直接获得答案或执行结果;
  4. 原始网站未必得到访问、署名或收入。

并非所有自动化流量都应被视为恶意流量。搜索索引、可访问性工具、监控程序和获得授权的 AI 助手都可能创造价值。真正困难的是,服务器常常无法可靠回答三个问题:

  • 请求者是谁?
  • 它准备怎样使用内容?
  • 内容提供者能否拒绝、限速或要求付费?

仅凭 User-Agent 判断身份并不可靠,因为这个字段可以被任意伪造。IP 地址也只能提供有限线索:共享出口、代理网络和云平台都会让归属判断变得模糊。因此,面向 Agent 的 Web 需要的不只是更复杂的封禁名单,而是身份、策略、计量和结算能力。

公平的 Web 需要把访问意图变成机器可执行策略

对于内容网站,可以把 Agent 治理拆成四层:

  • 发现层:公开哪些路径允许抓取,哪些路径不希望被自动访问;
  • 身份层:要求高价值客户端使用 API 密钥、签名请求或其他可验证凭据;
  • 策略层:按用途、资源类型和合作关系设置允许、限速或拒绝规则;
  • 计量层:记录请求量、响应体积、缓存命中率和内容使用授权,为成本核算或收益分配提供依据。

robots.txt 仍然可以表达站点偏好,但它本质上是一种自愿遵守的约定,不是访问控制机制。对于私有数据、付费内容和高成本接口,应在服务器端执行认证与授权,而不能只依赖爬虫声明。

内容许可也不宜只有“全部开放”和“全部封锁”两个选项。网站可以区分搜索索引、实时问答、模型训练、商业再分发等场景。不过,目前并不存在一个能够覆盖所有 AI 客户端的统一策略格式;自定义声明文件可以用于合作方集成,但不能假设陌生 Agent 会自动遵守。

可以这样实践:先建立可观测、可执行的最小策略

下面是一个只依赖 Python 标准库的演示服务器。它会:

  • 提供 robots.txt;
  • 提供一个示例性的 /ai-policy.json 声明文件;
  • 根据 User-Agent 粗略标记自动化请求;
  • 对 /api/private 强制检查 Bearer Token;
  • 以 JSON 行格式记录请求,便于后续统计。

这里的 /ai-policy.json 是演示约定,并非通用标准。生产环境还需要可信身份、持久化限流、密钥轮换和隐私合规设计。

将下面内容保存为 agent_aware_server.py:

#!/usr/bin/env python3
import json
import os
import time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

HOST = "127.0.0.1"
PORT = 8080
API_TOKEN = os.environ.get("API_TOKEN", "change-me")
BOT_MARKERS = ("bot", "crawler", "spider", "agent", "scraper")


def is_declared_automation(user_agent: str) -> bool:
    value = user_agent.lower()
    return any(marker in value for marker in BOT_MARKERS)


class Handler(BaseHTTPRequestHandler):
    def send_body(self, status: int, body: bytes, content_type: str) -> None:
        self.send_response(status)
        self.send_header("Content-Type", content_type)
        self.send_header("Content-Length", str(len(body)))
        self.send_header("Cache-Control", "no-store")
        self.end_headers()
        self.wfile.write(body)

    def log_request_event(self, status: int) -> None:
        user_agent = self.headers.get("User-Agent", "")
        event = {
            "timestamp": int(time.time()),
            "client_ip": self.client_address[0],
            "method": self.command,
            "path": self.path,
            "status": status,
            "user_agent": user_agent,
            "declared_automation": is_declared_automation(user_agent),
        }
        print(json.dumps(event, ensure_ascii=False), flush=True)

    def do_GET(self) -> None:
        if self.path == "/robots.txt":
            body = (
                "User-agent: *\n"
                "Allow: /public/\n"
                "Disallow: /api/private\n"
            ).encode()
            self.send_body(200, body, "text/plain; charset=utf-8")
            self.log_request_event(200)
            return

        if self.path == "/ai-policy.json":
            # 示例格式,不代表行业标准。
            policy = {
                "version": 1,
                "public_content": {
                    "indexing": "allowed",
                    "answer_generation": "allowed-with-attribution",
                    "model_training": "permission-required"
                },
                "contact": "licensing@example.com"
            }
            body = json.dumps(policy, ensure_ascii=False, indent=2).encode()
            self.send_body(200, body, "application/json; charset=utf-8")
            self.log_request_event(200)
            return

        if self.path == "/api/private":
            expected = f"Bearer {API_TOKEN}"
            if self.headers.get("Authorization") != expected:
                body = b'{"error":"unauthorized"}'
                self.send_body(401, body, "application/json")
                self.log_request_event(401)
                return

            body = b'{"data":"licensed content"}'
            self.send_body(200, body, "application/json")
            self.log_request_event(200)
            return

        body = b'{"message":"public content"}'
        self.send_body(200, body, "application/json")
        self.log_request_event(200)


if __name__ == "__main__":
    server = ThreadingHTTPServer((HOST, PORT), Handler)
    print(f"Listening on http://{HOST}:{PORT}")
    server.serve_forever()

启动服务器,并分别模拟普通访问、声明为 Agent 的访问和经过授权的 API 请求:

export API_TOKEN='replace-with-a-long-random-token'
python3 agent_aware_server.py

在另一个终端运行:

curl -i http://127.0.0.1:8080/robots.txt
curl -i -A 'ExampleResearchAgent/1.0' http://127.0.0.1:8080/ai-policy.json
curl -i -A 'ExampleResearchAgent/1.0' http://127.0.0.1:8080/api/private
curl -i -A 'ExampleResearchAgent/1.0' \
  -H "Authorization: Bearer replace-with-a-long-random-token" \
  http://127.0.0.1:8080/api/private

这个示例刻意把“声明”和“执行”分开:robots.txt 与策略文件负责表达意图,Bearer Token 则在服务器端真正控制私有资源。上线时还应把明文 Token 替换为短期凭据或签名请求,并避免在日志中记录密钥、Cookie、完整查询参数等敏感数据。

创作者经济不能只靠拦截维持

自动化访问增加后,单纯提高封禁强度可能保护资源,也可能误伤搜索发现、合作伙伴和有价值的 Agent。更可持续的做法,是让内容提供者拥有可选择的交换方式,例如:

  • 免费开放摘要,但对完整数据集收费;
  • 允许搜索索引,但训练用途需要单独授权;
  • 对已验证 Agent 提供结构化 API,而不是让其反复解析 HTML;
  • 按请求量、数据新鲜度或商业用途设置不同额度;
  • 为引用、署名和来源回流建立可审计记录。

这也意味着网站运营指标需要改变。页面浏览量仍然重要,但不再足够。团队还应观察自动化请求占比、带宽与计算成本、拒绝率、认证 Agent 数量,以及机器访问最终带来的订阅、引用或交易价值。

落地时应检查什么

面对 Agent 流量,团队可以从以下清单开始,而不必一次设计完整的“AI 商业模式”:

  • 盘点哪些内容公开、付费、私有或受许可约束;
  • 将人类访问、已验证自动化流量和未知自动化流量分开统计;
  • 为昂贵接口设置认证、配额、超时和速率限制;
  • 明确索引、回答生成、训练和再分发是否采用不同政策;
  • 保留申诉与合作渠道,避免只有封禁而没有授权路径;
  • 检查日志中的个人信息、密钥和内容许可风险;
  • 定期测试规则是否会误伤辅助技术和正常用户。

自动化流量超过人类活动,并不意味着开放 Web 必然消失。真正的分水岭在于,Web 能否从模糊的默认许可,走向可验证身份、可执行政策和可持续价值交换。对开发团队而言,最务实的起点不是猜测每一个 Agent,而是先让自己的资源边界清晰、访问行为可观测、授权规则能够真正执行。


相关推荐