8+16:一个让 AI 操作任何界面的协议设计

2 阅读1分钟

为什么 AI 浏览器自动化需要协议,而不是更多 AI

现在所有 AI 浏览器自动化工具的思路都一样:LLM 看页面 → 决定点哪里 → 点击 → 再看 → 再决定。每一步都要调用一次大模型。

这在根本上是错的。

AI-Per-Step 模式的问题

Browser-Use、Stagehand 这些工具演示很酷,但生产环境中:

  • :每步要 LLM 调用(1-3秒),10步操作要 30+ 秒
  • :每次交互消耗 token,日跑 1000 次 = 真金白银
  • 不确定:LLM 会幻觉,每次运行结果可能不同
  • 脆弱:AI 可能点错按钮、误读选择器、被弹窗搞混

核心洞察:操作一个界面,一旦你搞清楚怎么做,就是个已解决问题。 难的是理解页面——找到 API、定位选择器、知道该点什么。这是 AI 擅长的。简单的是重复执行同样的步骤。这根本不需要 AI。

解法:把理解和执行分开

如果 AI 只运行一次——分析站点,创建确定性脚本——然后这个脚本永远运行呢?

forge_inspect → forge_verify → forge_save → 永远运行
   AI 分析        AI 测试        AI 保存     零 AI,零 token

这就是 Tap:一个给 AI agent 用的界面协议。

协议设计:8 + 16

Tap 定义了一个最小且完备的界面操作契约。

8 个内核原语——交互的不可约原子

eval · pointer · keyboard · nav · wait · screenshot · tap · capabilities

为什么是这 8 个?因为人类和任何界面的交互,归根结底就是这些:

原语做什么为什么不可约
eval在界面内执行代码读取/修改状态的唯一方式
pointer鼠标/触摸操作所有点击、拖拽、悬停的基础
keyboard键盘输入所有文字输入、快捷键的基础
nav导航到 URL页面跳转是独立原语
wait等待条件/时间异步世界的同步点
screenshot截图视觉反馈唯一通道
tap调用其他 tap组合的基础
capabilities声明运行时能力能力协商

16 个标准库操作——由内核组合而成

click · type · hover · scroll · pressKey · select · upload · dialog
fetch · find · cookies · download · waitFor · waitForNetwork · ssrState · storage

每个标准库操作都由内核原语组合而成。比如:

click(target) = eval(find(target)) + pointer(x, y, 'click')
type(sel, text) = click(sel) + keyboard(text)

为什么 8+16 是完备的

POSIX 用 6 个系统调用(open/close/read/write/fork/exec)抽象了所有操作系统操作。Tap 用 8 个原语抽象了所有界面操作。

关键设计原则:

  1. 内核最小化 — 只有 8 个原语,新运行时实现 8 个方法就能获得 16 个标准库操作
  2. 标准库可组合 — 每个操作由内核调用构建
  3. 运行时可覆盖 — 标准库有默认实现,但运行时可以为性能覆盖
  4. 能力协商 — 运行时声明支持什么,脚本声明需要什么

Tap 长什么样

// API 优先:直接获取数据
export default {
  site: "bilibili", name: "hot",
  description: "B站热门视频",
  extract: async () => {
    const res = await fetch(
      'https://api.bilibili.com/x/web-interface/ranking/v2',
      { credentials: 'include' }
    )
    const data = await res.json()
    return data.data.list.map(v => ({
      title: v.title,
      author: v.owner.name,
      views: String(v.stat.view)
    }))
  }
}
// 操作界面:发推文
export default {
  site: "x", name: "post",
  args: { content: { type: "string" } },
  async run(page, args) {
    await page.nav('https://x.com/compose/post')
    await page.type('[data-testid="tweetTextarea_0"]', args.content)
    await page.click('[data-testid="tweetButton"]')
    return [{ status: 'posted' }]
  }
}

没有 LLM。没有 token。纯 JavaScript。1 秒内完成。

运行时架构

                    ┌─ Chrome 扩展 (内核通过 CDP)
AI Agent ←→ MCP ←→ Deno 执行器 ─┤
                                └─ Playwright (内核通过 pw API)

今天支持 Chrome 和 Playwright 两个运行时。明天:Android、iOS、桌面应用。写一次 tap,在所有平台运行。

经济学对比

AI-per-stepTap
Forge 成本~¥0.3(一次性)
运行成本¥0.05-0.5/次¥0.00
跑 1000 次¥50-500¥0.3 总计
延迟10-30秒<1秒
确定性

现状

81 个技能覆盖 41 个站点 — GitHub、Reddit、HN、X、YouTube、B站、知乎、小红书、微博、Medium、arXiv 等。

curl -fsSL https://raw.githubusercontent.com/LeonTing1010/tap/master/install.sh | sh
tap install    # 安装 81 个社区技能
tap list       # 查看全部

作为 MCP server 接入任何 AI agent:

{
  "mcpServers": {
    "tap": { "command": "tap", "args": ["mcp"] }
  }
}

GitHub: github.com/LeonTing101…

Forge once, run forever. 铸造一次,永远运行。

~1,800 行 Deno 代码。零依赖。AGPL-3.0。