Lovely RouterДокументация
Получить ключ
Браузерный агент

Структурированный вывод

Передайте схему вывода и получите проверенный JSON в data, собранный только со страниц, которые посетил агент.

Каждый запуск возвращает текстовый answer. Добавьте output_schema, и запуск также вернёт в data соответствующий ей JSON. JSON собирается из текста и ссылок посещённых агентом страниц и из его ответа, а не из догадок, поэтому URL ссылок — настоящие, взятые со страницы. Структурированный вывод ничего не стоит сверх обычного.

JSON через output_schema#

Передайте нужную структуру. Краткая форма сопоставляет каждому полю тип:

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 КБ. Схема, не являющаяся корректной JSON Schema, при запуске возвращает 400: "output_schema" is not a usable JSON Schema: ….

Чтение data и data_error#

ПолеКогда
dataJSON после завершения запуска. null, пока запуск идёт, если вы не запрашивали структуру или если извлечь данные не удалось.
data_errorПрисутствует, только если извлечь данные не удалось, и содержит причину, например extracted data does not match the schema: … и затем поля, не прошедшие проверку.

Значения, которых нет на страницах, возвращаются как null, а списки — пустыми; ничего не выдумывается. Значения секретов никогда не попадают в data: они заменяются на [secret:<name>].

Проверяйте data_error, прежде чем использовать data:

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" }
    ]
  }
}