想象一下这样的场景:你对着 AI 说"帮我在主流旅行网站上找出下周二从北京飞新加坡、价格在 3000 元以内的三个直飞航班,对比之后用我保存的信用卡订下最划算的那个"——然后 AI 真的打开了一个浏览器,自主导航预订流程,处理路上的各种弹窗与验证页,填写乘客信息,最终把订单确认号交到你手上。
这并不是科幻,而是 Web Agent(网页智能体) 正在成为现实。如果说 Extra06 介绍的 GUI Agent 教会了 AI 如何操作手机和桌面应用,那么本章要介绍的就是它在网页世界的近亲——以浏览器为主要行动表面的智能体。
Web 之所以值得拥有一章独立的篇幅,有两个理由。第一,世界上最有价值的数据与工作流,大部分都跑在网页上——比手机 App 或桌面软件多得多。第二,Web 是一个独立的技术问题:它的感知、行动和可靠性挑战和移动/桌面 GUI Agent 有本质区别。你没法把 Mobile-Agent-v3 直接接到 Chrome 上就当作 Web Agent,这条路走不通。
本章的承诺是,读完之后你将:
Web Agent 是一类以网页浏览器为主要行动表面的自主智能体。它通过 DOM、可访问性树和屏幕截图的某种组合来感知页面,用大语言模型推理下一步该做什么,然后在真实浏览器实例里执行动作——点击、输入、滚动、跳转。
关键词是 自主。一个用 Playwright 写死的爬虫脚本不是 Web Agent,它只是一段脆弱的程序,目标网站稍微改一下按钮位置就崩了。而 Web Agent 是在运行时根据自己 "看到" 的内容动态决定下一步动作的。
这条技术血缘很重要。我们把三者放在一起对比:
| 维度 | 传统 RPA(Selenium、UiPath) | GUI Agent(Mobile-Agent、AutoGLM) | Web Agent(Browser-Use、TinyFish) |
|---|---|---|---|
| 主要表面 | Web 或桌面 | 移动 + 桌面,以截图为主 | 网页浏览器 |
| 感知方式 | DOM 选择器(XPath、CSS) | 视觉(VLM 解析截图) | DOM + 可访问性树 + 视觉(混合) |
| 动作机制 | 固定脚本 | 基于坐标的点击 | 选择器、坐标和语义目标的混合 |
| 能否适应 UI 变化 | 不能——立即失效 | 能——视觉具备语义弹性 | 能——多种锚定信号 |
| 跨平台能力 | 有限 | 天然跨平台 | Web 本身就是跨平台 |
| 认证 / 会话处理 | 手动 | 有限 | 一等公民 |
| 反爬意识 | 几乎没有 | 不涉及 | 至关重要 |
两个最关键的点:
三股力量在同一时间汇合:
我们还正好赶上各大 AI 实验室开始直接把这个能力产品化的时刻——Anthropic 的 Computer Use、OpenAI 的 Operator、Google 的 Project Mariner。"Web Agent" 正在迅速成为每个 AI 原生产品都会接入的基础能力。
和所有 GUI Agent 一样,Web Agent 也是一个 感知 → 推理 → 行动 的闭环。但每一层都有 Web 特有的微妙之处。
业界有三种主流的感知策略,每一种都有另两种正好能补足的弱点:
策略 A——基于 DOM:解析页面的 HTML 和可访问性树。又快又准,能直接告诉你元素的类型、文本内容、选择器。失败场景:页面是 Canvas 渲染的 SPA(Google Docs、Figma 等),或者站点故意混淆 DOM,或者有意义的内容渲染进了爬虫读不到的 Shadow DOM。
策略 B——基于视觉:截屏 → 输入视觉大模型 → 模型识别要点击的元素并输出坐标。失败场景:模型把小字读错,元素位置幻觉,4K 页面上有些东西它就是看不到。而且成本高——每一步都要调一次 VLM 推理。
策略 C——混合(生产环境的赢家):用视觉做布局理解和上下文推理("这三个搜索框里,哪个才是我要的?"),再用 DOM 或可访问性树做精确定位("这是要点击的具体元素")。所有认真的生产级 Web Agent——Operator、Computer Use、Browser-Use、TinyFish——最终都走向了混合路线。
业界为什么会收敛到这一点?经验数据说话:在常见的生产工作流上,经过混合方案 + 隐身浏览器 + 反爬加固的成熟系统,成功率已经稳定在 90% 左右;而纯视觉、未加固的方案在 WebArena 这类对抗性学术基准上往往只有 30–40%。注意这两个数字衡量的是 不同的东西——学术基准刻意构造长链路、刁钻场景;生产系统是在真实业务流上做了大量针对性调优。但两条曲线都在显示同一件事:混合方案在工程上明显占优。
Web 在推理层最大的挑战是 状态突变。页面会在你眼皮底下变:
一个合格的 Web Agent 需要具备:
这正是第四章的 ReAct 范式 大放异彩的舞台。Web Agent 本质上就是一个 ReAct 循环,其中动作空间是 {click, type, scroll, navigate, wait, extract},观察是下一个页面状态。
动作空间乍看和移动 GUI Agent 类似——点击、输入、滚动。但 Web 层多出了:
只用坐标的 Web Agent 会碰上以上每一个限制。这就是混合方案成为生产标准的原因。
下面这些问题,Extra06 没有也无法覆盖,因为它们在移动和桌面上根本不存在:
反爬机制。Cloudflare、DataDome、PerimeterX、Akamai Bot Manager。它们盯着你的 TLS 指纹、浏览器 JavaScript 对象签名、鼠标移动模式、操作时序。一个朴素的 Playwright 脚本几秒钟就被拦下了。生产级 Web Agent 需要 隐身浏览器(打了补丁、看起来和真实用户浏览器无法区分的 Chromium),通常还要搭配住宅 IP 代理。
认证与会话保持。OAuth 流程、二次验证、会话 cookie、"记住我" token、登录时的验证码。一个登不进去的 Web Agent 只能看到公开网页。带加密凭据库(vault)的方案是新兴模式。
动态内容与竞态条件。无限滚动、懒加载图片、800ms 后才出现的模态框、阻塞点击的动画。智能体必须知道页面什么时候算 "就绪",而 "就绪" 没有清晰的定义。
JS 重型 SPA。当你访问一个现代 React 或 Vue 站点时,初始 HTML 基本是空的——真正的 DOM 是 JavaScript 在三秒后渲染出来的。朴素的爬虫看不到任何内容。
网络、地理与限流。有些内容被地理限制,有些接口按 IP 做限流,有些站点会在检测到 "太多" 来自同一来源的请求时静默降级响应。
成本与延迟。每一步动作都是一次 LLM 调用 + 一次浏览器往返。10 步的自动化任务可能要 30–60 秒,光 LLM 的 token 成本就是 0.10–1.00 美元。这正是业界拼命追求更小、更快、专门为 Web 微调的模型的原因。
2026 年的 Web Agent 生态系统大致可以分为四类,每一类的存在都对应一个真实的取舍:
| 类别 | 代表项目 | 优势 | 弱点 |
|---|---|---|---|
| 原始浏览器自动化 | Playwright、Puppeteer、Selenium | 快、可重复、免费、完全可控 | 没有 AI、脆弱,每次 UI 变动都要修脚本 |
| 开源 AI Web Agent | Browser-Use、Skyvern、WebVoyager、AgentE | 免费、可魔改、完全透明 | 自己部署,自己处理反爬、代理、基础设施、可观测性 |
| Computer-use API | Anthropic Computer Use、OpenAI Operator、Google Project Mariner | 通用推理能力强、模型前沿 | 贵、UX 有立场、没有内建反爬或地理路由,常常以桌面为主而非纯 Web |
| 托管型 Web 自动化 API | TinyFish、Browserbase、Apify、Bright Data | 隐身浏览器 + 代理 + 智能体循环一揽子打包,几分钟就能跑通;自带可观测性 | 有厂商依赖、对内部智能体循环控制更少、按任务计费 |
诚实的判断:每个类别都赢在不同的轴上。你是研究员、想研究 Agent 行为?用开源。你是个人开发者、爬一个没反爬的小站?纯 Playwright 就够了。你在为产品做功能、需要在真实世界(包含反爬)的站点上"开箱即用"?托管 API 能为你省下几周时间。
第二部分我们将用 TinyFish 来做实战练习——它的 API 设计在这一类里是最干净的,并且把智能体循环明确暴露出来,方便学习。
下面是 Web Agent 已经在生产环境落地的(不完全)列表:
请对你的读者诚实。Web Agent 既令人兴奋,又有它的边界:
我们按由浅入深三步走:
Tool,接入第七章框架里的 ReAct 智能体TinyFish 是一个托管型的 Web Agent API。你给它一个 URL 和一段自然语言 目标(goal),它返回结构化 JSON。
agent.tinyfish.ai 注册账号写进你的 shell:
export TINYFISH_API_KEY="sk-tinyfish-..."
# Python
pip install tinyfish
# 或 TypeScript
npm install @tiny-fish/sdk
Python:
from tinyfish import TinyFish, CompleteEvent
client = TinyFish() # 自动从环境变量读取 TINYFISH_API_KEY
with client.agent.stream(
url="https://scrapeme.live/shop",
goal="提取前 2 个产品的名称和价格,以 JSON 形式返回。",
) as stream:
for event in stream:
if isinstance(event, CompleteEvent):
print(event.result_json)
TypeScript:
import { TinyFish, EventType } from "@tiny-fish/sdk";
const client = new TinyFish();
const stream = await client.agent.stream({
url: "https://scrapeme.live/shop",
goal: "提取前 2 个产品的名称和价格,以 JSON 形式返回。",
});
for await (const event of stream) {
if (event.type === EventType.COMPLETE) {
console.log(event.result);
}
}
原始 HTTP(不用 SDK):
curl -N -X POST https://agent.tinyfish.ai/v1/automation/run-sse \
-H "X-API-Key: $TINYFISH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://scrapeme.live/shop",
"goal": "提取前 2 个产品的名称和价格"
}'
运行起来,你会看到 Server-Sent Events 实时流进终端:
{"type": "STARTED", "run_id": "abc123"}
{"type": "STREAMING_URL", "run_id": "abc123", "streaming_url": "https://tf-abc123.fra0-tinyfish.unikraft.app/stream/0"}
{"type": "PROGRESS", "run_id": "abc123", "purpose": "Visit the page to extract product information"}
{"type": "PROGRESS", "run_id": "abc123", "purpose": "Check for product information on the page"}
{"type": "COMPLETE", "run_id": "abc123", "status": "COMPLETED", "result": {
"products": [
{"name": "Bulbasaur", "price": "$63.00"},
{"name": "Ivysaur", "price": "$87.00"}
]
}}
就这样——你刚刚跑完了一个 Web Agent。这一次调用背后发生的事:数据中心里启动了一个真实的 Chromium 浏览器,导航到目标页面,解析布局,识别出商品卡片,提取数据,并把进度流式返回给你。
TinyFish 的 /run-sse 端点接收的 JSON 字段(重点字段已加粗):
| 字段 | 类型 | 说明 |
|---|---|---|
url |
string | 起始页面 |
goal |
string | 自然语言指令 |
output_schema |
object | 可选的 JSON Schema 子集,约束返回结构 |
browser_profile |
"lite" | "stealth" |
默认 lite |
proxy_config |
object | 可选 {enabled, type, country_code} |
use_vault |
boolean | 是否使用保存的凭据完成登录 |
credential_item_ids |
string[] | 限定 vault 中的具体凭据 |
三个端点,三种模式:
POST /v1/automation/run——同步,阻塞到完成,返回最终结果POST /v1/automation/run-async——发后即忘,立即返回 run_idPOST /v1/automation/run-sse——流式,实时把进度事件推回给你短任务(< 30 秒)用同步;批量作业用异步;要在 UI 上实时显示进度时用 SSE。
TinyFish 在教学上最有用的一个功能是 streaming_url:每次运行都会产生一个 URL,让你 实时观看浏览器。你可以把它嵌进自己产品的 iframe 里,也可以直接在浏览器开个 Tab 边调试边看。
from tinyfish import TinyFish, CompleteEvent
client = TinyFish()
with client.agent.stream(
url="https://scrapeme.live/shop",
goal="提取前 3 个产品的名称和价格",
on_streaming_url=lambda e: print(f"\n实时观看:{e.streaming_url}\n"),
on_progress=lambda e: print(f" → {e.purpose}"),
) as stream:
for event in stream:
if isinstance(event, CompleteEvent):
print("\n最终结果:", event.result_json)
跑起来几乎瞬间就拿到一个可点击 URL。在浏览器里打开它——你看到的就是 智能体正在驱动的真实浏览器会话。页面在加载、鼠标在移动、字段在填写。这是大多数读者会发出 "卧槽,它真的在做" 的瞬间。
而且这不只是个演示噱头。直播流是调试 Web Agent 最好用 的工具:
goal 这一个字段几乎就是 TinyFish 的全部 API 表面——写好它,是 90% 成功率和 30% 成功率的分水岭。
TinyFish 官方推荐的心智模型:把智能体当成一个 "字面执行" 的助理,坐在浏览器前。它能看到屏幕上的一切、能动手——但它没法猜你的意思。
一个出色的 goal 最多包含七个组件:
| 组件 | 示例 |
|---|---|
| 目标(Objective) | "提取定价信息" |
| 范围(Target) | "从定价表中" |
| 字段(Fields) | "套餐名、月费、包含功能" |
| 结构(Schema) | "返回 JSON:[{plan: string, price_monthly: number}]" |
| 步骤(Steps) | "先关掉 cookie 横幅" |
| 护栏(Guardrails) | "不要点击任何'立即购买'按钮" |
| 边缘情况(Edge cases) | "如果价格显示为'联系我们',置为 null" |
从最差到最好的演变:
模糊(必然失败):
"获取这个页面的定价"
好一些(可能能跑):
"提取产品名称、价格和库存状态"
生产级品质:
1. 等待页面完全加载。
2. 如果有 cookie 同意横幅,点击"全部接受"。
3. 定位定价区。
4. 对每个套餐,提取:套餐名称、月费(数字)、包含功能(字符串数组)。
不要点击任何购买或结账按钮。
如果套餐显示"联系我们",monthly_price 置为 null。
返回 JSON:[{"plan": string, "monthly_price": number | null, "features": string[]}]
TinyFish 自己的测试里,相同任务下具体的 goal 完成速度快 4.9 倍、返回的多余数据少 16 倍。Goal 写作就是新的 Prompt 工程,并且和所有 Prompt 工程一样,复利明显。
这一节是本章的核心。直接调 API 当然可以——但本书,尤其是第四章和第七章,一直在传达的核心信息是:当外部服务变成你自己框架里的工具,真正的力量才出现。这就是 "使用 AI" 和 "用 AI 构建" 之间的分水岭。
我们要把 TinyFish 包装成一个 HelloAgents 的 Tool,接入 ReActAgent。
提示:HelloAgents 是你在第七章构建的配套框架。如果还没装:
pip install hello-agents。想要和正文完全对应的版本,可以切到 GitHub 上的learn_version分支。
TinyFishWebTool我们写一个工具,把 Web 自动化暴露成单一能力。智能体用自然语言描述自己想做什么,工具负责调用 API 并返回结构化 JSON。
# tools/tinyfish_tool.py
import json
import os
from typing import Any, Dict, List
from tinyfish import (
TinyFish,
BrowserProfile,
ProxyConfig,
ProxyCountryCode,
)
from hello_agents.tools import Tool, ToolParameter
class TinyFishWebTool(Tool):
"""让 ReAct 智能体通过自然语言驱动真实浏览器的工具。"""
def __init__(self, api_key: str | None = None):
super().__init__(
name="web_automation",
description=(
"使用自然语言自动化任何网页。输入一个 JSON 字符串,包含两个必需字段:"
"`url`(起始页面)和 `goal`(清晰具体的任务描述)。"
"可选字段:`stealth`(布尔值,针对有反爬保护的站点)、"
"`country`(US/GB/CA/DE/FR/JP/AU,用于地理路由)。"
"返回智能体抽取的结构化 JSON,或错误描述。"
),
)
self.client = TinyFish(
api_key=api_key or os.environ["TINYFISH_API_KEY"],
)
def run(self, parameters: Dict[str, Any]) -> str:
# ToolRegistry 会把 ReAct 的输入文本包成 {"input": "..."}
raw = parameters.get("input", "")
try:
params = json.loads(raw)
except json.JSONDecodeError:
return json.dumps(
{"error": "输入必须是合法的 JSON 字符串"},
ensure_ascii=False,
)
url = params.get("url")
goal = params.get("goal")
if not url or not goal:
return json.dumps(
{"error": "缺少必需字段 url 或 goal"},
ensure_ascii=False,
)
kwargs: Dict[str, Any] = {"url": url, "goal": goal}
if params.get("stealth"):
kwargs["browser_profile"] = BrowserProfile.STEALTH
if (country := params.get("country")):
kwargs["proxy_config"] = ProxyConfig(
enabled=True,
country_code=ProxyCountryCode(country),
)
# 用同步 run——ReAct 循环要拿到结果再继续。
# 长任务可以改用 queue + 轮询。
run = self.client.agent.run(**kwargs)
if run.status.value != "COMPLETED" or run.result is None:
err = run.error.message if run.error else "未知失败"
return json.dumps(
{"error": err, "status": run.status.value},
ensure_ascii=False,
)
return json.dumps(
{"data": run.result, "run_id": run.run_id},
ensure_ascii=False,
)
def get_parameters(self) -> List[ToolParameter]:
return [
ToolParameter(
name="input",
type="string",
description=(
"JSON 字符串,字段:url(必需)、goal(必需)、"
"stealth(可选)、country(可选)"
),
required=True,
)
]
代码里有几处值得特别留意:
description 是 LLM 决定是否调用它时唯一看到的信息。要像在跟一个从没读过你代码的初级开发者交代一样写描述——把输入、输出、何时使用都讲清楚。stealth 和 country 不是默认开启而是可选参数。让 LLM 自己决定——通过工具描述告诉它什么时候该开。# main.py
from hello_agents import ReActAgent, HelloAgentsLLM, ToolRegistry
from tools.tinyfish_tool import TinyFishWebTool
llm = HelloAgentsLLM() # 从 .env 读取 provider 配置
registry = ToolRegistry()
registry.register_tool(TinyFishWebTool())
agent = ReActAgent(
agent_name="research_assistant",
llm=llm,
tool_registry=registry,
)
result = agent.run(
"查询苹果官方商店和京东上 iPhone 17 Pro 的当前价格,"
"在考虑商品页面所标的运费后告诉我哪个更便宜。"
)
print(result)
运行起来,ReAct 循环大致会经历这样的过程:
web_automation({"url": "https://www.apple.com/.../iphone-17-pro", "goal": "提取 iPhone 17 Pro 起步价。返回 JSON: {price_cny: number, free_shipping: boolean}"}){"data": {"price_cny": 9999, "free_shipping": true}}web_automation({"url": "https://item.jd.com/...", "goal": "...", "stealth": true}){"data": {"price_cny": 9799, "free_shipping": true}}刚刚发生的事,正是第七章希望传达的核心:外部服务作为一等公民进入你自己的框架。ReAct 循环没变,LLM 也没变。我们只是加了一个工具,你的智能体就具备了在公开网络上行动的能力。这就是 可组合性。
上面的版本演示足够了。真实生产环境还要再加几样:
1. 验证内容,不要只看状态
COMPLETED 的运行也可能返回垃圾,如果智能体撞上了软拦截(Cloudflare 挑战页、验证码、把 "访问被拒绝" 渲染成正文)。永远要检查 结果内容:
def is_real_success(result: dict | None) -> bool:
if not result:
return False
s = json.dumps(result, ensure_ascii=False).lower()
failure_signals = ["captcha", "blocked", "access denied", "could not", "unable to"]
return not any(signal in s for signal in failure_signals)
2. 能缓存就缓存
一次 30 秒的网页自动化是昂贵的。如果同一会话里 ReAct 智能体两次要求同一个 URL,应该返回缓存结果。(第八章的记忆系统是个合适的着力点。)
3. 设置超时
TinyFish 内部每次运行有 10 分钟超时,但你的工具应该更早失败——多数有意义的任务在 10–60 秒内完成。超过这个时间,多半是卡在挑战页上了。
4. 用直播流做可观测
把每次运行的 streaming_url 记下来,写日志。生产环境出问题时,运行录像是定位故障最快的工具。
你的智能体迟早会撞上一个返回空结果或 403 的站点。这是诊断流程:
第 1 步——确认问题就是反爬。打开失败那次运行的 streaming_url,找以下几种特征:
| 你看到什么 | 大概率原因 |
|---|---|
| Cloudflare "Checking your browser" 页 | Cloudflare 机器人检测 |
| DataDome 弹窗或重定向 | DataDome |
| 空白页或永远转圈 | 基于 IP 或指纹的拦截 |
| 验证码(reCAPTCHA、hCaptcha) | 验证码——硬上限 |
| "Access Denied" / 403 | IP 或 User-Agent 拦截 |
| 该看到内容时却出现登录墙 | 基于会话的反爬 |
第 2 步——隐身和代理一起开。隐身改变浏览器指纹,代理改变 IP。反爬厂商会关联两个信号——只改一个往往不够:
run = client.agent.run(
url="https://protected-site.com",
goal="提取商品价格",
browser_profile=BrowserProfile.STEALTH,
proxy_config=ProxyConfig(enabled=True, country_code=ProxyCountryCode.US),
)
第 3 步——让智能体表现得更像人类。有些站点关注行为而不只是指纹。在 goal 里加上:
第 4 步——实在不行就换打法。有些站点死命拦爬虫,但会大方提供 RSS、sitemap、公开 API。花五分钟翻一翻,省下几天试错时间。如果数据真的只在付费墙后的格式化页面里,问问自己:底层信息源(公告、新闻稿、厂商页面)是不是在防守更弱的地方也有。
一段完整的、加固过的范例:
from tinyfish import (
TinyFish, BrowserProfile, ProxyConfig, ProxyCountryCode,
CompleteEvent, RunStatus,
)
client = TinyFish()
with client.agent.stream(
url="https://protected-site.com/pricing",
browser_profile=BrowserProfile.STEALTH,
proxy_config=ProxyConfig(enabled=True, country_code=ProxyCountryCode.US),
goal="""
1. 等待页面完全加载。
2. 关闭任何 cookie 同意 / GDPR 横幅。
3. 继续之前等待 1 秒。
4. 定位定价区(通常是网格或卡片表格)。
5. 对每个套餐,提取:套餐名、月费、年费(如有)。
如果出现 Cloudflare 或安全检查页,等它自动通过。
如果看到 Access Denied 或 CAPTCHA 页,返回 {"error": "blocked"}。
不要点击任何购买或结账按钮。
返回 JSON:[{"plan": "Pro", "monthly_price": 49, "annual_price": 39}]
""",
on_streaming_url=lambda e: print(f"实时观看:{e.streaming_url}"),
on_progress=lambda e: print(f" → {e.purpose}"),
) as stream:
for event in stream:
if isinstance(event, CompleteEvent):
if event.status == RunStatus.COMPLETED:
print("结果:", event.result_json)
else:
print("失败:", event.error.message if event.error else "unknown")
重要的诚实声明:包括 TinyFish 在内,没有任何 Web Agent 能可靠地解开现代验证码(reCAPTCHA v2/v3、hCaptcha)。如果一个站点向你弹出验证码,那目前就是一道硬墙。正确的做法是把你的运行设计得不去触发它,而不是硬扛。
第十章介绍了 MCP(Model Context Protocol)——Anthropic 提出的、让 AI 助手连接外部工具和数据的开放协议。TinyFish 暴露了一个 MCP 服务器。这意味着,你可以让任何兼容 MCP 的助手(Claude Desktop、Cursor、Windsurf、Claude Code)具备驱动浏览器的能力——你自己一行代码都不用写。
一行命令安装:
# Claude Code
npx -y install-mcp@latest https://agent.tinyfish.ai/mcp --client claude-code
# Claude Desktop
npx -y install-mcp@latest https://agent.tinyfish.ai/mcp --client claude
# Cursor
npx -y install-mcp@latest https://agent.tinyfish.ai/mcp --client cursor
或者手动在 claude_desktop_config.json 里加:
{
"mcpServers": {
"tinyfish": {
"url": "https://agent.tinyfish.ai/mcp"
}
}
}
重启后,你的助手会多出 run_web_automation、search、fetch_content、create_browser_session 等工具。然后你就可以直接对 Claude 说:
"并行抓取以下 5 个竞品的定价页,把结果整理成表格。"
Claude 就会用 TinyFish 在背后完成这件事,批量执行,实时反馈进度。
这正是第十章预告的 一次构建、处处可用 的回报。MCP 作为分发协议,把每一个工具都变成了 每个 AI 助手都能直接使用 的能力。
为了诚实:托管 Web Agent 并不总是正确选择。
什么时候用托管 Web Agent:目标站点在外部、没有 API、有反爬保护、流程是多步的,而且工程时间比任务级单价更值钱。
这个领域走得很快。未来 12–24 个月值得关注的几件事:
如果这一章勾起了你的兴趣,下面几条路可以继续:
归根到底,Web Agent 不过就是一个 ReAct 循环——只不过它的行动表面是浏览器。前面章节里你学到的一切——感知、推理、行动、记忆、评估——都直接适用。新的东西是这个 对抗性环境:真实网站对自动化的敌意,是移动 App 和桌面软件所没有的,这种敌意正是 Web Agent 工程之所以独立成为一门学问的原因。
好消息是:你不需要从零解决这一切。像 TinyFish 这样的生产级原语,正是为此而存在。作为一个 AI 原生智能体的构建者,你的工作是把这些原语 组合 成有用的东西——并且把这件事在你自己 从头到尾理解 的框架里完成。
去构建吧。开放的 Web 是世界上最大的行动表面,从未有过比现在更好的时机,去教会一个智能体使用它。
致谢:感谢 TinyFish 团队对本章技术细节的输入。所有 API 细节核对自 TinyFish 官方文档。