不要向你的代理喂入 HTML

发布: (2025年12月4日 GMT+8 23:49)
7 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的完整文本内容,我将为您翻译成简体中文并保留原始的格式、Markdown 语法以及技术术语。谢谢!

TL;DR — 给 AI 一个白盒,而不是黑盒

大多数 AI 代理通过 黑盒 方法与网页应用交互:读取 DOM 转储或截图,然后猜测该点击什么。HTML 从未为机器设计。从 AI 的视角来看,DOM 只是噪声,业务逻辑仅隐约埋藏其中。

本文主张 白盒 方法:公开一个 语义状态层,直接揭示应用的结构、规则、状态以及有效的转移。这并不是要取代 UI;而是要在传统用户界面旁提供一个 智能接口 (II)

Manifesto Playground 演示

自行尝试 → Manifesto Playground

1. 黑盒:AI 与网页应用的现状

以下是大多数团队今天向网页应用“添加 AI”的方式:

  • 使用 LangChain、AutoGPT 或浏览器自动化
  • 驱动 Playwright 或 Puppeteer
  • 将 DOM 或截图导入模型
  • 希望它能自行判断点击哪个位置

这就是 黑盒 方法。代理只能看到渲染后的表面,必须推断所有其他信息。

DOM Dump 有什么问题?

<div class="product-name">
  <label>Product Name</label>
  <input type="text" name="name" />
  <span class="error">This field is required.</span>
</div>

从代理的视角来看:

问题影响
令牌浪费90 % 的令牌都是类名和包装器
缺失约束它是必填吗?最大长度是多少?
无依赖此字段是否依赖其他字段?
无因果关系提交按钮被禁用——但为什么

代理被迫 猜测。一次 CSS 重构会导致一切失效。布局的改变会让模型困惑。逻辑从未被暴露——只有它的视觉投影。

信号 90 %。

2. 白盒:暴露应用的大脑

另一种方式是 白盒 协议。与直接返回 HTML 不同,引擎会暴露一个 语义快照 —— 一个结构化的、描述应用内部状态的表示,供代理直接读取。

{
  "topology": {
    "viewId": "product-create",
    "mode": "create",
    "sections": [
      { "id": "basic", "title": "Basic Info", "fields": ["name", "productType"] },
      { "id": "shipping", "title": "Shipping", "fields": ["shippingWeight"] }
    ]
  },
  "state": {
    "form": { "isValid": false, "isDirty": false },
    "fields": {
      "name": {
        "value": "",
        "meta": { "valid": false, "hidden": false, "disabled": false, "errors": ["Required"] }
      },
      "productType": {
        "value": "PHYSICAL",
        "meta": { "valid": true, "hidden": false, "disabled": false, "errors": [] }
      },
      "shippingWeight": {
        "value": null,
        "meta": { "valid": true, "hidden": false, "disabled": false, "errors": [] }
      }
    }
  },
  "constraints": {
    "name": { "required": true, "minLength": 2, "maxLength": 100 },
    "shippingWeight": { "min": 0, "max": 2000, "dependsOn": ["productType"] }
  },
  "interactions": [
    { "id": "updateField:name", "intent": "updateField", "target": "name", "available": true },
    { "id": "updateField:productType", "intent": "updateField", "target": "productType", "available": true },
    { "id": "submit", "intent": "submit", "available": false, "reason": "Name is required" }
  ]
}

现在代理拥有:

  • Topology – 屏幕结构、分区、字段层级
  • State – 每个字段的当前值、有效性、可见性、错误信息
  • Constraints – 必填、最小/最大值、依赖关系
  • Interactions – 可执行的操作以及 为何 某些操作被阻止

无需猜测,无需推断。代理直接读取应用的大脑。

3. 实际案例:“我在哪里选择周?”

🎮 实际操作演示: Manifesto Playground – 尝试更改字段值,实时观察语义状态的更新。

场景

User: “我看到一个日期选择器,但我在哪里选择哪一周?”

AI Chatbot: “只有在将频率设置为‘Weekly’时,周选择器才会出现。现在它被设置为‘Daily’。需要我帮你改成吗?”

为实现此功能,AI 需要了解:

  • 一个名为 weekSelector 的字段存在且当前被隐藏
  • frequency === 'WEEKLY' 时它会变为可见
  • 当前 frequency 的值是 'DAILY'

仅靠 DOM‑方式无法可靠提供这些信息,但语义快照可以:

{
  "fields": {
    "frequency": {
      "value": "DAILY",
      "meta": { "hidden": false }
    },
    "weekSelector": {
      "value": null,
      "meta": { "hidden": true },
      "visibleWhen": "frequency === 'WEEKLY'"
    }
  }
}

AI 读取此快照后 知道——无需推断——字段被隐藏的确切原因以及什么条件会让它出现。

4. 协议循环

Manifesto 在引擎和 AI 代理之间实现了一个持续的反馈循环:

┌─────────────────────────────────────────────────────────────────────┐
│                                                                     │
│  [Context Injection] → [Reasoning] → [Action Dispatch] → [Delta]    │
│          ▲                                                  │       │
│          └─────────────── Continuous Snapshots ────────────────┘       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

逐步说明

  1. 上下文注入 – 引擎导出包含拓扑、状态、约束和交互的语义快照。
  2. 推理 – 代理根据快照规划下一步操作。
  3. 动作分发 – 代理调用抽象意图(例如 updateFieldsubmitresetvalidate),而不是原始 DOM 事件。
  4. 增量反馈 – 引擎返回实际的变化,而不仅仅是“成功”。差异显示因果关系(例如,“我修改了 X,导致 Y 隐藏”。)
  5. 循环使用更新后的快照重复进行,使代理获得可预测、结构化的反馈,而不是“点击并期待”。

5. The API: Exploration and Execution

Manifesto 通过 @manifesto-io/ai 暴露此协议。

Exploration Mode – “What can I do here?”

import { createInteroperabilitySession } from '@manifesto-io/ai'

const session = createInteroperabilitySession({
  runtime,       // FormRuntime instance
  viewSchema,   // View definition
  entitySchema, // Entity definition
})

// Get the current semantic snapshot
const snapshot = session.snapshot()

// snapshot.interactions tells the agent:
// - submit: available = false, reason = "Name is required"

从这里,代理可以查询可用的交互、更新字段、提交表单,并接收增量差异,所有这些都由白盒语义表示驱动。

Back to Blog

相关文章

阅读更多 »