Lovely Router文档
获取密钥
浏览器智能体

结构化输出

传入输出结构,即可在 data 中得到经过校验的 JSON,数据只取自智能体访问过的页面。

每次运行都会返回文本 answer。添加 output_schema 后,运行还会在 data 中返回符合该结构的 JSON。JSON 根据智能体访问过的页面的文本和链接以及它的回答生成,绝不靠猜测,因此其中的链接 URL 都是页面上真实的地址。结构化输出不额外收费。

用 output_schema 获取 JSON#

传入你想要的结构。简写形式把每个字段映射到一个类型:

curl https://lovelyrouter.com/v1/browser/runs \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "goal": "Get the top 3 stories on the front page.",
    "start_url": "https://news.ycombinator.com/",
    "output_schema": {
      "stories": [{"title": "string", "url": "string", "points": "integer"}]
    }
  }'

已结束的运行把 JSON 放在 data 中,与 answer 并列:

JSON
{
  "id": "brun_8f3c2d1e0a9b8c7d6e5f4a3b",
  "object": "browser_run",
  "status": "succeeded",
  "steps": 1,
  "answer": "The top 3 stories are \"Bitwarden Dual License Model\" (95 points), \"Talorys – A self-hosted personal AI agent\" (57 points) and \"REA Reverse – Engineer Anything\" (498 points).",
  "data": {
    "stories": [
      { "title": "Bitwarden Dual License Model", "url": "https://community.bitwarden.com/…", "points": 95 },
      { "title": "Talorys – A self-hosted personal AI agent", "url": "https://github.com/rociiu/talorys", "points": 57 },
      { "title": "REA Reverse – Engineer Anything", "url": "https://rea.tools/", "points": 498 }
    ]
  },
  "charge_usd": 0.006
}

Python 和 Node.js 示例沿用运行你的第一个任务中的 API、H 和 headers 设置。

简写结构#

简写就是普通的 JSON,其中每个值描述一个字段:

你写的你得到的
"string"、"number"、"integer"、"boolean"、"array"、"object"、"null"该类型的值;页面上没有显示时为 null
任何其他文本,例如 "price as shown, with currency"字符串或 null。你的文本告诉智能体该填什么
["string"]、[{...}]由该元素组成的列表。[] 表示可包含任意内容的列表
{"field": ...}恰好包含这些字段的对象,所有字段都会出现

带描述的字段是字符串:"price": "price in USD" 返回 "$19.99",而不是数字。需要数字时请用 "number"。

如果结构的顶层有名为 type、properties、items 或 $schema 的键,它会被当作完整的 JSON Schema 而不是简写来解析。如果要返回使用这些名称之一的字段,请编写完整的 JSON Schema。

完整 JSON Schema#

如需枚举、格式、必填字段,或为有类型的字段添加描述,请传入 JSON Schema(draft 2020-12):

JSON
{
  "goal": "Find the 2026 Toyota Camry trims on the build page with their starting MSRP and engine.",
  "start_url": "https://www.toyota.com/camry/",
  "output_schema": {
    "type": "object",
    "properties": {
      "trims": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "msrp_usd": { "type": "number", "description": "Starting MSRP, without fees" },
            "engine": { "type": "string" },
            "hybrid": { "type": "boolean" }
          },
          "required": ["name", "msrp_usd"]
        }
      }
    },
    "required": ["trims"]
  }
}

结果会按结构进行校验。如果第一次结果未通过校验,智能体会拿到校验错误并修正一次。结构最大可达 20 KB。不是有效 JSON Schema 的结构会在启动时返回 400:"output_schema" is not a usable JSON Schema: …。

读取 data 和 data_error#

字段何时出现
data运行结束后的 JSON。运行进行中、你没有要求结构化输出,或提取失败时为 null。
data_error仅在提取失败时出现,包含原因,例如 extracted data does not match the schema: …,后接未通过校验的字段。

页面上没有显示的值会返回 null,列表会返回为空,而不会凭空编造。密钥值永远不会出现在 data 中:它们会被替换为 [secret:<name>]。

使用 data 之前,先检查 data_error:

if run.get("data_error"):
    raise RuntimeError(f"no data: {run['data_error']}")
trims = run["data"]["trims"]

改在目标中描述格式#

你也可以直接在目标中要求某种结构,例如“以 JSON 列表返回所有空缺职位,包含职位名称、团队和地点。”当目标要求特定形式的结构化数据(JSON、指定的字段、带给定列的列表或表格)时,运行也会按该形式填充 data。没有结构就无从校验,所以当你的代码依赖确切的结构时,请使用 output_schema。

运行提前结束时#

  • 步数上限。 达到 max_steps 的运行以 failed 结束,错误为 reached the step limit (N)。它仍会根据最后一个页面写出 answer,并根据已看到的内容填充 data。
  • 失败或超时。 data 根据到目前为止访问过的页面填充,因此可能不完整。
  • 已停止。 被你停止的运行不返回 data。

获得更好的数据#

  • 按页面上的叫法给字段命名。 字段名会引导提取,顶层字段名还会加入智能体的指令,让它最终停在显示这些内容的页面上。points 和 comments 比 score 和 n 效果更好。
  • 在目标中要求结构里的所有内容。 “获取前 5 条新闻,包含标题、链接和分数”再配上相应的结构,效果好于只给结构。
  • 少用几个页面。 数据来自智能体最后访问的六个页面。如果数据分散在很多页面上,就每个页面或每组页面运行一个任务。
  • 让可选字段保持可选。 在完整的结构中,只把始终需要的字段列入 required。简写字段总是可以为 null。
  • 长表格用精准模式。 它可以用页面代码读取长表格或列表,而不只是读取可见文本。参见模式。

示例#

提交表单后的订单确认:

JSON
{
  "goal": "Order one Blue Mug (size large) for Ada Lovelace, 12 Main St, Springfield, IL 62701, and tell me the order number and total.",
  "start_url": "https://shop.example.com/mugs/blue",
  "secrets": ["shop_user", "shop_password"],
  "output_schema": { "order_number": "string", "total": "number", "currency": "string" }
}

在默认的 "approve": "risky" 下,这次运行会在下单前暂停,等待你批准。参见人工介入。

带嵌套字段的搜索结果:

JSON
{
  "goal": "Search for 'noise cancelling headphones' and get the first 5 results with name, price, rating and number of reviews.",
  "start_url": "https://www.example-store.com/",
  "output_schema": {
    "results": [
      { "name": "string", "price": "number", "rating": "number", "reviews": "integer", "url": "string" }
    ]
  }
}