skip to content
$worker

browser

v0.2.7-rc.2

A browser on the iii bus - shared Chromium with persistent, restorable tabs and incognito tabs. Navigate, act, read the page console, pick elements. Also parses HTML natively without a browser (browser::* - css/xpath/regex, element search, markdown).

iiiverified
117 installs0 in 7d0 today
install
$iii trigger compose::add worker=browser@0.2.7-rc.2
  • macOS: arm64 · x64
  • Linux: arm64 · armv7 · x64

exact versions are immutable; binary and bundle artifacts are digest-pinned.

agent-ready brief for v0.2.7-rc.2
install + config + dependencies + readme + api reference, all in one place. fetch as agent-context.md for an llm to consume.
the same content rendered as discrete blocks below is exposed as a single markdown document at /workers/browser.md?version=0.2.7-rc.2. paste it into an llm prompt or pipe it through curl from a worker.

install

install
$iii trigger compose::add worker=browser@0.2.7-rc.2

dependencies

no dependencies for v0.2.7-rc.2

readme

README.md

browser

Interactive Chromium sessions on the iii engine bus. Agents start a session, read the page as an accessibility-tree outline, click and type against element refs, and read the page's own console and network history back as data. The single most important thing it gives you: "why is my dev server page blank?" becomes answerable, because the page's console errors are one browser::console::read away. The console worker adds the human window: a live Browser page with a streaming viewport (Chromium-pushed screencast frames), the console feed, and click-to-pick elements into chat.

It also carries a native Rust scraping surface, browser::*: HTTP and browser fetching, screenshots, persistent sessions and BFS crawling, plus CSS/XPath/regex queries, element search and HTML→Markdown that run over any HTML string with no browser at all. See Scraping and HTML parsing below.

In the console

An agent reads a page as an accessibility outline (browser::snapshot) while you watch the live viewport and console feed:

browser::snapshot rendered as an accessibility outline beside the live viewport

browser::screenshot renders the captured image inline in the chat card:

browser::screenshot rendered as an inline image in the chat card

Pick mode highlights the element under the cursor and drops it into the chat composer as an actionable ref:

pick mode highlighting an element and inserting it into the chat composer

Install

iii trigger compose::add worker=browser

iii trigger compose::add resolves the worker and its dependencies, writes exact declarations to worker-compose.yaml, and reconciles the Compose project. The worker drives a Chromium/Chrome already installed on the machine; point executable at a specific binary if auto-detection picks the wrong one.

To watch sessions live, pick elements into chat, and follow the agent's browsing from a UI, add the console worker as well:

iii trigger compose::add worker=console

Quickstart

Start a session, read the page, act on it, then read the console:

use iii_sdk::protocol::TriggerRequest;
use iii_sdk::{register_worker, InitOptions};
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let iii = register_worker("ws://localhost:49134", InitOptions::default());

    let started = iii.trigger(TriggerRequest {
        function_id: "browser::sessions::start".into(),
        payload: json!({ "url": "http://localhost:3000" }),
        action: None,
        timeout_ms: Some(30_000),
    }).await?;
    let session_id = started["session_id"].as_str().unwrap();

    // The page as text: an a11y outline with [ref=eN] handles.
    let snapshot = iii.trigger(TriggerRequest {
        function_id: "browser::snapshot".into(),
        payload: json!({ "session_id": session_id }),
        action: None,
        timeout_ms: Some(15_000),
    }).await?;
    println!("{}", snapshot["tree"].as_str().unwrap());

    // What did the page log? Errors only, no dump.
    let console = iii.trigger(TriggerRequest {
        function_id: "browser::console::read".into(),
        payload: json!({ "session_id": session_id, "level": "error" }),
        action: None,
        timeout_ms: Some(10_000),
    }).await?;
    println!("{console:#}");
    Ok(())
}

The rest of the surface: browser::act (click/hover/type/press/scroll by ref or coordinates, left/right/middle and double-click), browser::evaluate (JS expression), browser::screenshot (viewable JPEG), browser::history (back/forward/reload), browser::history::list (visited pages for a history panel), browser::find-in-page (find bar: highlight matches, step next/previous), browser::zoom (page zoom 50-200 %), browser::pdf (print the page to a PDF), browser::downloads::list / browser::download / browser::download::remove (files the session downloaded), browser::clear-data (cookies, cache, storage), browser::resize (live viewport size / device presets), browser::cookies::list / set / clear (import a cookie file), browser::network::read (requests + failures), browser::dom::read (DOM tree with refs), browser::styles::read / browser::styles::write (computed styles + live inline edits, the design panel backing), and browser::sessions::list / browser::sessions::stop. Function ids and schemas live in the code and iii worker info browser.

File transfer functions:

Function Purpose
browser::downloads::list List files the session downloaded
browser::download Read one recorded download as base64
browser::download::remove Delete and forget one recorded download
browser::upload Attach up to eight base64 files to exactly one input[type=file] selected by CSS

Beyond single actions: browser::execute runs a multi-step async script in the page — top-level await, log(...), sleep(ms), waitFor(selector), and a state object that persists across execute calls for the session — so one call replaces a chain of act/evaluate round-trips. browser::snapshot accepts diff: true to return only what changed since the previous snapshot, and reports the document generation its refs belong to (ref names are unique per snapshot and fail closed when stale, never resolving to a different element). browser::sessions::start accepts read_only: true for inspection-only sessions where act/evaluate/execute/styles::write are rejected. browser::doctor reports the environment — detected Chromium, version, capacity — with an enable_how string for anything degraded.

browser::sessions::attach binds a session to an already-running browser over CDP (start Chrome with --remote-debugging-port) instead of launching one, so it reaches the real profile with its logins and extensions. It opens a fresh tab the session owns, or adopts an existing tab by URL substring and releases it untouched on stop; browser::tabs::list enumerates a running browser's tabs. Attach reaches logged-in state, so it is off unless allow_attach is set in config, and adoption is exclusive per tab.

browser::handoff pauses a session for a step only a human can do (CAPTCHA, 2FA, payment): it mounts an in-page continue banner and blocks the call until the human clicks it, a browser::handoff::confirm call resolves it, or the timeout elapses, emitting browser::handoff-requested for the console to surface. Human acknowledgment is not proof, so the caller verifies the expected page state after it returns.

browser::recording::start / browser::recording::stop capture a session's live viewport to a webm or mp4 file by piping the screencast through ffmpeg (turning screencast on if needed); stop returns the path, duration, and frame count. While screencast is active a human watching the viewport also sees a ghost cursor following the agent's clicks and a session-status badge; both are fixed-position in-page overlays that never touch page content. browser::doctor reports whether ffmpeg (recording) and attach mode are available.

Scraping and HTML parsing (browser::*)

The worker also ships a native Rust port of the scrapling worker's surface: 19 functions covering HTTP and browser fetching, screenshots, persistent sessions, crawling, and — the part that needs no browser at all — parsing HTML you already have.

Start with the parse functions: they work on any HTML string with no browser or network. Adaptive CSS/XPath/extract calls are the exception to statelessness: they persist relocation identities in the configured SQLite database. They pair naturally with the session functions above (navigate, read the page, then parse it), but they don't need one.

iii trigger browser::css --payload '{
  "html": "<ul><li><a class=\"product\" href=\"/sku/1\">Widget</a></li><li><a class=\"product\" href=\"/sku/2\">Gadget</a></li></ul>",
  "query": "a.product",
  "attr": "href",
  "first": true
}'
# → { "result": "/sku/1" }

first defaults to false, in which case result is an array of every match instead of just the first.

iii trigger browser::extract --payload '{
  "html": "<div class=\"card\"><h3>Widget</h3><span class=\"price\">$19.99</span><a href=\"/sku/1\">buy</a></div>",
  "selectors": [
    { "name": "title", "css": "h3" },
    { "name": "price", "css": ".price" },
    { "name": "url", "css": "a", "attr": "href" }
  ]
}'
# → { "extracted": { "title": "Widget", "price": "$19.99", "url": "/sku/1" } }

The 10 parse functions: extract, css, xpath, regex, find, find-by-text, find-by-regex, find-similar, describe, to-markdown. Non-adaptive parsing has no operator-tunable defaults. The fixed limit, find / find-by-text / find-by-regex capping at 100 items per call (limit clamps to [0, 100]), mirrors the python worker's hardcoded cap.

Fetching, sessions and crawl

Nine more functions go out to the network. They share one response envelope — {status, url, headers, cookies, encoding} plus, on request, extracted (from selectors), content+format (markdown/text) and html — so the parse layer above is reachable inline, without a second call.

Three fetch tiers, cheapest first; escalate only when the cheaper one fails:

engine use when
fetch safe: reqwest/rustls; compat: frozen curl-impersonate static pages, APIs — no browser, fastest
dynamic-fetch frozen Chrome over raw CDP the page needs JavaScript to render
stealthy-fetch frozen Chrome with the Patchright command/launch sequence the site sniffs for automation
iii trigger browser::fetch --json '{
  "url": "https://example.com/",
  "selectors": [{ "name": "title", "css": "h1" }],
  "format": "text"
}'
# → { "status": 200, "url": "...", "extracted": { "title": "Example Domain" }, ... }

All three take a single url or a bulk urls list (bulk returns {results: [...]}, where a failed URL contributes {url, error} instead of sinking the batch). dynamic-fetch and stealthy-fetch additionally accept wait_selector (+ wait_selector_state), network_idle, and wait.

browser::screenshot-url captures a page as image content blocks the console renders inline — downscaled to 1024px wide and split into at most six 1536px tiles, with the caption saying so when a page is taller than that.

session-open / session-fetch / session-close / session-list keep state in a private Scrapling registry. HTTP sessions retain one cookie jar/transport; dynamic and stealthy sessions retain one browser process and context. All use UUID4 hex ids and serialize requests FIFO per session. They never appear in browser::sessions::list, and interactive ids are not accepted. One-shot browser calls get a fresh process/profile; retries get a fresh page in that process. Compat mode supports request proxies, remote cdp_url, and solve_cloudflare on stealthy calls.

crawl walks links breadth-first from start_urls, extracting per page. It stays on the seed domain by default (www. folded), strips URL fragments when deduping, and stops at max_pages (20) or max_depth (2). Every page is emitted on a stream; the RPC response carries only a ≤10-item sample plus the stream name and group id to read the rest with stream::on.

These functions take a caller-supplied URL, so they are an SSRF surface. Safe mode rejects caller proxies and checks every connection against private, loopback, link-local (including cloud metadata), CGNAT, multicast and reserved ranges. Set browser.scrapling.allow_loopback: true to scrape a local dev server; every other private range stays blocked. Compat mode intentionally reproduces the standalone worker's unrestricted network behavior and should be enabled only for trusted calls. All nine functions remain at the needs_approval default in iii-permissions.yaml, unlike the ten parse functions.

The guarantee differs by tier, and the difference is worth knowing:

  • fetch (HTTP) — checked before every hop. Redirects are followed by hand precisely so each hop is validated before the request is made, and each connection is pinned to the address that was validated, closing the DNS rebinding window between check and connect. Authorization and Cookie are dropped on a cross-origin redirect, as curl has done since CVE-2018-1000007.
  • Browser tiers — checked at the socket boundary. Safe-mode Chrome is forced through an in-process HTTP/CONNECT gate. The gate resolves, checks, and pins every destination before dialing, including redirect destinations; direct bypass, QUIC and WebRTC are disabled.

Two more safe-mode limits worth stating: response bodies are bounded at 32 MiB whether or not the server declares a content length, and a fetch call is capped at three times its timeout in total. Compat mode preserves the frozen worker's unbounded response and retry/redirect quirks.

Compatibility modes and certification

Request/response schemas are golden-pinned to the frozen Python wrapper apart from provider-id mapping. Native calls use browser::; Python keeps scrapling::. Python scrapling::screenshot maps to native browser::screenshot-url, while browser::screenshot remains the interactive session screenshot. Crawl streams default to browser::crawl.

security_mode: safe is the default. It keeps SSRF checks and resource ceilings, refuses network options the safe engine cannot enforce, rejects verify: false, and bounds adaptive storage. security_mode: compat is only eligible on Tier-1 Linux x86_64/aarch64 builds produced with the certified curl-impersonate and Chromium artifacts. Other targets reject compat instead of silently degrading. Eligibility is not a claim that an arbitrary local build is certified: builds without the frozen artifacts return a capability error, and callers should keep using safe mode or the standalone worker.

The parser/query core, CSS-to-XPath translation, XPath 1.0 evaluation, Python regex behavior, Markdown conversion, selector generation, and adaptive relocation are repository-owned compatibility implementations covered by exact differential fixtures. Adaptive queries persist element identities in SQLite at adaptive_storage_path; parse functions remain auto-allowed, so operators should treat that path as durable worker state. Safe mode enforces adaptive_max_bytes (256 MiB by default) and rolls back a write that would exceed it. Compat mode keeps the frozen worker's unbounded behavior.

Safe HTTP uses the bounded native engine. Compat HTTP is linked to the frozen curl-impersonate archive; compat browser calls use the certified Chrome build through raw pipe/WebSocket CDP and reproduce the frozen Playwright/Patchright sequences. Persistent browser sessions, proxy rotation, remote CDP, Cloudflare handling and screenshot transforms use that same private runtime. Certified builds fail when pinned artifacts are absent or mismatched; there is no silent fallback from compat to safe.

The standalone worker remains the oracle and production fallback during rollout. Migrate calls to browser:: (with screenshot mapped to browser::screenshot-url) only after draining its sessions, then compare both providers through one stable release and at least 30 days without an untriaged mismatch. Removing the standalone worker is a separate change.

Regenerating the parse goldens

tests/golden/schemas/browser.*.json and tests/golden/behavior/** are written only by scripts/gen_goldens.py, run against the reference Python implementation — never by UPDATE_GOLDENS=1, so a passing test always means "Rust still agrees with Python":

~/.iii/managed/scrapling/usr/local/bin/python3.12 scripts/gen_goldens.py schemas
~/.iii/managed/scrapling/usr/local/bin/python3.12 scripts/gen_goldens.py behavior

Configuration

Stored in the configuration worker under the browser key. Existing interactive-browser settings retain their current behavior. Scrapling settings live in an isolated nested block: bulk/default policy can be read per call, while the session cap, idle timeout, and adaptive database path are snapshotted at worker startup. Restart after changing a startup-snapshotted value.

browser:
  executable: ''            # empty = auto-detect Chrome/Chromium/Edge
  user_data_dir: ''         # set a path to persist cookies/logins across sessions
  headless: true            # false shows a real window locally
  max_sessions: 4           # concurrent Chromium processes
  console_buffer: 500       # per-session console ring buffer (entries)
  network_buffer: 500       # per-session network ring buffer (entries)
  viewport_width: 1280
  viewport_height: 800
  default_timeout_ms: 30000 # navigation/act/evaluate default
  max_timeout_ms: 120000    # ceiling; caller timeout_ms clamped DOWN to this
  idle_stop_ms: 300000      # stop sessions idle this long; 0 disables
  screenshot_quality: 60    # JPEG quality 1-100
  allowed_schemes: [http, https, file]  # `file` lets a local document be rendered; see below
  max_snapshot_nodes: 2000  # a11y outline size cap
  default_origin_policy:    # omitted fields default to allow
    access: allow
    downloads: allow
    uploads: allow
    scripting: allow
  origin_policies:
    'https://app.example.com:8443':
      uploads: deny
    app.example.com:
      scripting: deny
  allow_history_access: true
  allow_cookie_import: true
  allow_attach: false       # true = allow sessions::attach into a running browser's real profile

  scrapling:
    security_mode: safe        # safe | compat; compat is Tier-1 certified builds only
    chromium_executable: ''    # certified Chrome path; empty = discovery
    allow_loopback: false      # true = permit 127.0.0.1 / ::1 in outbound calls

    defaults:
      impersonate: chrome
      headless: true
      network_idle: false
      proxy: ''
      include_html: false

    max_bulk_concurrency: 5
    max_sessions: 8
    session_idle_timeout_s: 900
    adaptive_storage_path: data/scrapling/elements.db # relative to III_COMPOSE_DIR
    adaptive_max_bytes: 268435456 # safe only; compat preserves unbounded oracle behavior

file is on the default scheme list so a local document can be opened and rendered, which is how document::ocr gets pixels out of a scanned PDF. It is worth knowing what that permits: navigation is not checked against a session's filesystem scope the way the workers that read files directly are, so anything that can reach browser::navigate can open any file this process can read. Narrow the list on a shared machine.

Origin policy keys do not accept wildcards. An exact origin, including its scheme and non-default port, wins over a bare host; a bare host matches any scheme or port. Origin keys are URL-normalized before matching, including lowercased hosts and removal of explicit default ports; bare-host keys match case-insensitively. URLs with no matching key use default_origin_policy. Each policy field defaults to allow when omitted.

Sessions started while any origin policy is configured reload the policy on every top-document request, so edits apply to their later navigations. A session started with no origin policy does not enable interception; adding the first policy later applies the navigation gate to new sessions.

The compatibility fields are part of the stable configuration surface. Non-Tier-1 or artifact-free builds retain safe mode and reject compat explicitly instead of approximating it.

The declared production envelope is 4 GiB memory and 2 CPUs. Tier-1 release validation budgets for five concurrent browser processes; that is a release test envelope, not permission to exceed configured session caps.

Custom trigger types

Sibling workers (and the console UI) can subscribe to session activity. All bindings accept an optional { "session_id": "..." } filter.

Trigger type Fires when Payload to subscribers
browser::session-started A session is up and ready { session_id, url, headless, timestamp }
browser::session-stopped A session ended { session_id, reason: "stopped" | "idle" | "crashed", timestamp }
browser::navigated The page committed a navigation { session_id, url, timestamp }
browser::console-event A console/log/exception entry was captured { session_id, entry }
browser::picked The human picked an element in inspect mode { session_id, element, timestamp }
browser::handoff-requested A session paused for a human step (CAPTCHA, 2FA, payment) { session_id, handoff_id, instructions, timestamp }

browser::console-event is high-volume; bind it with a session_id filter and treat browser::console::read as the durable record. browser::picked elements carry a ref that browser::act accepts directly, so a human pick flows straight into agent action.

Element picking

browser::pick::start puts the page in DevTools inspect mode (native hover highlight); the human's click resolves to tag, attributes, outer HTML, text, bounds, and recent console errors, emitted as browser::picked. The pick, hint, screencast, and frame functions are internal: console-UI plumbing, not agent surface, and they stay out of agent tool lists.

api reference (json)

agent-api-reference.json
{
  "functions": [
    {
      "description": "Interact with the page: click (left/right/middle, single or double), hover, type, press, scroll, or drag (press at the start point, glide to x2/y2, release). Address elements with a [ref=eN] handle from browser::snapshot (or a pick), or raw viewport coordinates.",
      "metadata": {},
      "name": "browser::act",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "action": {
            "description": "`click`, `hover`, `type`, `press`, `scroll`, or `drag`.",
            "type": "string"
          },
          "button": {
            "default": null,
            "description": "Mouse button for `click`: `left` (default), `right`, or `middle`.",
            "type": [
              "string",
              "null"
            ]
          },
          "click_count": {
            "default": null,
            "description": "Clicks in the gesture: 2 double-clicks (`click` only, default 1).",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "delta_y": {
            "default": null,
            "description": "Scroll distance in pixels; positive scrolls down (`scroll`).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "key": {
            "default": null,
            "description": "Key name for `press`: Enter, Tab, Escape, Backspace, Delete, ArrowUp/Down/Left/Right, Home, End, PageUp, PageDown.",
            "type": [
              "string",
              "null"
            ]
          },
          "ref": {
            "default": null,
            "description": "Element ref from `browser::snapshot` (`e3`) or `browser::picked` (`p1`). Refs die on navigation; re-snapshot after.",
            "type": [
              "string",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          },
          "text": {
            "default": null,
            "description": "Text to insert (`type`).",
            "type": [
              "string",
              "null"
            ]
          },
          "x": {
            "default": null,
            "description": "Viewport x, when acting by coordinates instead of ref.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "x2": {
            "default": null,
            "description": "Drag end x, in viewport pixels (`drag`). The start is `x`/`y` or a `ref`; the end is `x2`/`y2`.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "y": {
            "default": null,
            "description": "Viewport y, when acting by coordinates instead of ref.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "y2": {
            "default": null,
            "description": "Drag end y, in viewport pixels (`drag`).",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "action",
          "session_id"
        ],
        "title": "ActInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "detail": {
            "description": "What was done, for the transcript.",
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "detail",
          "ok"
        ],
        "title": "ActOutput",
        "type": "object"
      }
    },
    {
      "description": "Clear the session's browsing data (cookies, cache, storage), like the browser's Clear browsing data. Scoped to this session's browser context.",
      "metadata": {},
      "name": "browser::clear-data",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "cache": {
            "default": null,
            "description": "Clear the HTTP cache. Default true.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "cookies": {
            "default": null,
            "description": "Clear cookies. Default true.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          },
          "storage": {
            "default": null,
            "description": "Clear localStorage / sessionStorage / IndexedDB for the current origin. Default true.",
            "type": [
              "boolean",
              "null"
            ]
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ClearDataInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "cleared": {
            "description": "What was cleared, for the confirmation message.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "cleared",
          "ok"
        ],
        "title": "ClearDataOutput",
        "type": "object"
      }
    },
    {
      "description": "Read the session's captured console: console.* calls, uncaught exceptions, and browser-level log entries. Filter with pattern/level and page with since_seq instead of dumping everything.",
      "metadata": {},
      "name": "browser::console::read",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "level": {
            "default": null,
            "description": "Only entries at this level: `log`, `info`, `warning`, `error`, `debug`, `exception`. `error` also matches `exception`.",
            "type": [
              "string",
              "null"
            ]
          },
          "limit": {
            "default": null,
            "description": "Maximum entries returned, newest kept (default 100).",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "pattern": {
            "default": null,
            "description": "Regex applied to entry text. Use it: dumping an unfiltered console wastes the caller's context.",
            "type": [
              "string",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          },
          "since_seq": {
            "default": null,
            "description": "Only entries with `seq` greater than this; resume from the cursor returned as `last_seq`.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ConsoleReadInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "ConsoleEntry": {
            "description": "One captured console/log/exception entry.",
            "properties": {
              "level": {
                "description": "`log`, `info`, `warning`, `error`, `debug`, or `exception`.",
                "type": "string"
              },
              "seq": {
                "description": "Monotonic per-session cursor; pass back as `since_seq`.",
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "source": {
                "description": "`url:line` of the emitting frame, when known.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "text": {
                "type": "string"
              },
              "timestamp": {
                "format": "int64",
                "type": "integer"
              }
            },
            "required": [
              "level",
              "seq",
              "text",
              "timestamp"
            ],
            "type": "object"
          }
        },
        "properties": {
          "dropped": {
            "description": "Entries evicted from the ring buffer since session start.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "entries": {
            "items": {
              "$ref": "#/definitions/ConsoleEntry"
            },
            "type": "array"
          },
          "last_seq": {
            "description": "Cursor for the next `since_seq`.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "dropped",
          "entries",
          "last_seq"
        ],
        "title": "ConsoleReadOutput",
        "type": "object"
      }
    },
    {
      "description": "Clear all of the session's cookies.",
      "metadata": {},
      "name": "browser::cookies::clear",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "CookiesClearInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "CookiesClearOutput",
        "type": "object"
      }
    },
    {
      "description": "The cookies visible to the session's current page (name, value, domain, path, flags).",
      "metadata": {},
      "name": "browser::cookies::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "CookiesListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "CookieSpec": {
            "description": "One cookie as read from or written to the session. A subset of the CDP cookie shape: what a person setting a cookie actually provides.",
            "properties": {
              "domain": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "expires": {
                "description": "Seconds since the Unix epoch; omitted for a session cookie.",
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              },
              "http_only": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "name": {
                "type": "string"
              },
              "path": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "same_site": {
                "description": "`Strict`, `Lax`, or `None`.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "secure": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "value": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "value"
            ],
            "type": "object"
          }
        },
        "properties": {
          "cookies": {
            "items": {
              "$ref": "#/definitions/CookieSpec"
            },
            "type": "array"
          }
        },
        "required": [
          "cookies"
        ],
        "title": "CookiesListOutput",
        "type": "object"
      }
    },
    {
      "description": "Set cookies on the session, like importing a cookie file. A cookie without a domain is scoped to the current page's URL. same_site is Strict, Lax, or None.",
      "metadata": {},
      "name": "browser::cookies::set",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "CookieSpec": {
            "description": "One cookie as read from or written to the session. A subset of the CDP cookie shape: what a person setting a cookie actually provides.",
            "properties": {
              "domain": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "expires": {
                "description": "Seconds since the Unix epoch; omitted for a session cookie.",
                "format": "double",
                "type": [
                  "number",
                  "null"
                ]
              },
              "http_only": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "name": {
                "type": "string"
              },
              "path": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "same_site": {
                "description": "`Strict`, `Lax`, or `None`.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "secure": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "value": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "value"
            ],
            "type": "object"
          }
        },
        "properties": {
          "cookies": {
            "description": "Cookies to set. A cookie without a domain is scoped to the current page's URL.",
            "items": {
              "$ref": "#/definitions/CookieSpec"
            },
            "type": "array"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "cookies",
          "session_id"
        ],
        "title": "CookiesSetInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "count": {
            "description": "How many cookies were sent.",
            "format": "uint",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "count",
          "ok"
        ],
        "title": "CookiesSetOutput",
        "type": "object"
      }
    },
    {
      "description": "BFS-crawl from start_urls (follow same-domain links), extract per page, stream items.",
      "metadata": {},
      "name": "browser::crawl",
      "request_schema": {
        "properties": {
          "allowed_domains": {
            "description": "only follow links on these hosts",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "concurrency": {
            "type": "integer"
          },
          "css_selector": {
            "description": "scope the render to this CSS subtree (e.g. a page's content div)",
            "type": "string"
          },
          "download_delay": {
            "description": "seconds to wait between crawl rounds",
            "type": "number"
          },
          "fetcher": {
            "enum": [
              "http",
              "stealthy",
              "dynamic"
            ],
            "type": "string"
          },
          "format": {
            "description": "render page body to this format",
            "enum": [
              "markdown",
              "text"
            ],
            "type": "string"
          },
          "impersonate": {
            "type": "string"
          },
          "include_html": {
            "type": "boolean"
          },
          "main_content_only": {
            "description": "strip nav/scripts/hidden before rendering",
            "type": "boolean"
          },
          "max_depth": {
            "type": "integer"
          },
          "max_pages": {
            "type": "integer"
          },
          "same_domain": {
            "description": "follow only same-host links (default true)",
            "type": "boolean"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "start_urls": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "stream_name": {
            "description": "stream to emit items on (default browser::crawl)",
            "type": "string"
          },
          "url": {
            "description": "single start URL (alternative to start_urls)",
            "type": "string"
          }
        },
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "items": {
            "description": "a small sample of streamed items",
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "stats": {
            "properties": {
              "crawled": {
                "type": "integer"
              },
              "errors": {
                "type": "integer"
              },
              "items": {
                "type": "integer"
              },
              "stopped": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "stream": {
            "description": "read the full item stream via stream::on with this name + group_id",
            "properties": {
              "group_id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "type": "object"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "One CSS query over HTML; first-or-all; `attr` pulls an attribute else text.",
      "metadata": {},
      "name": "browser::css",
      "request_schema": {
        "properties": {
          "adaptive": {
            "description": "relocate elements after a site change via saved identities",
            "type": "boolean"
          },
          "adaptive_domain": {
            "description": "page URL/domain that keys saved identities",
            "type": "string"
          },
          "attr": {
            "type": "string"
          },
          "auto_save": {
            "description": "save matched identities (defaults on when adaptive)",
            "type": "boolean"
          },
          "first": {
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "identifier": {
            "description": "stable key for the saved element",
            "type": "string"
          },
          "query": {
            "type": "string"
          }
        },
        "required": [
          "html",
          "query"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "result": {
            "items": {
              "type": [
                "string",
                "null"
              ]
            },
            "type": [
              "array",
              "string",
              "null"
            ]
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Describe the first css/xpath match: attrs, generated selectors, class list, DOM context.",
      "metadata": {},
      "name": "browser::describe",
      "request_schema": {
        "properties": {
          "html": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "css",
              "xpath"
            ],
            "type": "string"
          },
          "query": {
            "type": "string"
          }
        },
        "required": [
          "html",
          "query"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "element": {
            "properties": {
              "attrs": {
                "type": "object"
              },
              "children": {
                "type": "integer"
              },
              "classes": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "css": {
                "type": "string"
              },
              "full_css": {
                "type": "string"
              },
              "full_xpath": {
                "type": "string"
              },
              "html": {
                "type": "string"
              },
              "parent_tag": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "siblings": {
                "type": "integer"
              },
              "tag": {
                "type": "string"
              },
              "text": {
                "type": "string"
              },
              "xpath": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "found": {
            "type": "boolean"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Read-only environment diagnostics: which Chromium the worker would launch, its version, session capacity, and any degraded capability with how to enable it. Never starts a browser.",
      "metadata": {},
      "name": "browser::doctor",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "DoctorInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "DoctorIssue": {
            "description": "One degraded capability plus the way to enable it.",
            "properties": {
              "enable_how": {
                "type": "string"
              },
              "what": {
                "type": "string"
              }
            },
            "required": [
              "enable_how",
              "what"
            ],
            "type": "object"
          }
        },
        "properties": {
          "active_sessions": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "allow_cookie_import": {
            "type": "boolean"
          },
          "allow_history_access": {
            "type": "boolean"
          },
          "allowed_schemes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "attach_enabled": {
            "description": "Whether attach mode is enabled (allow_attach).",
            "type": "boolean"
          },
          "chromium_path": {
            "type": [
              "string",
              "null"
            ]
          },
          "chromium_version": {
            "type": [
              "string",
              "null"
            ]
          },
          "configured_origin_policies": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "default_origin_policy_set": {
            "type": "boolean"
          },
          "headless_default": {
            "type": "boolean"
          },
          "issues": {
            "items": {
              "$ref": "#/definitions/DoctorIssue"
            },
            "type": "array"
          },
          "max_sessions": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "description": "True when sessions can start right now.",
            "type": "boolean"
          },
          "recording_available": {
            "description": "Whether ffmpeg is on PATH, which browser::recording requires.",
            "type": "boolean"
          }
        },
        "required": [
          "active_sessions",
          "allow_cookie_import",
          "allow_history_access",
          "allowed_schemes",
          "attach_enabled",
          "configured_origin_policies",
          "default_origin_policy_set",
          "headless_default",
          "issues",
          "max_sessions",
          "ok",
          "recording_available"
        ],
        "title": "DoctorOutput",
        "type": "object"
      }
    },
    {
      "description": "Read the DOM as a tree of tags with id/class and refs. Structure-oriented complement to browser::snapshot; read deep subtrees by passing a ref.",
      "metadata": {},
      "name": "browser::dom::read",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "depth": {
            "default": null,
            "description": "Levels of children to include (default 3).",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "ref": {
            "default": null,
            "description": "Subtree root from an earlier ref (`e3`/`p1`) or dom node. Omit for the document root.",
            "type": [
              "string",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "DomReadInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "DomNode": {
            "description": "One DOM node in the outline. `ref` resolves in `browser::act`, `browser::styles::read`, and `browser::styles::write`.",
            "properties": {
              "child_count": {
                "description": "Total children in the document, which may exceed `children` returned at this depth.",
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              },
              "children": {
                "items": {
                  "$ref": "#/definitions/DomNode"
                },
                "type": "array"
              },
              "classes": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ref": {
                "type": "string"
              },
              "tag": {
                "description": "Lowercase tag (`div`, `button`) or node name (`#text`).",
                "type": "string"
              },
              "text": {
                "description": "Trimmed text content for text nodes.",
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "child_count",
              "ref",
              "tag"
            ],
            "type": "object"
          }
        },
        "properties": {
          "root": {
            "$ref": "#/definitions/DomNode"
          },
          "truncated": {
            "description": "True when the node cap cut the tree short; read a subtree via `ref`.",
            "type": "boolean"
          }
        },
        "required": [
          "root",
          "truncated"
        ],
        "title": "DomReadOutput",
        "type": "object"
      }
    },
    {
      "description": "Read one downloaded file's bytes by guid (from browser::downloads::list), base64, for saving or attaching to the chat.",
      "metadata": {},
      "name": "browser::download",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "guid": {
            "description": "The download's CDP guid, from `browser::downloads::list`.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "guid",
          "session_id"
        ],
        "title": "DownloadInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "data": {
            "description": "The file, base64.",
            "type": "string"
          },
          "file_name": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "size_bytes": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "data",
          "file_name",
          "ok",
          "size_bytes"
        ],
        "title": "DownloadOutput",
        "type": "object"
      }
    },
    {
      "description": "Forget a download and delete its file from the session's download dir.",
      "metadata": {},
      "name": "browser::download::remove",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "guid": {
            "description": "The download to forget, and delete from disk.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "guid",
          "session_id"
        ],
        "title": "DownloadRemoveInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "DownloadRemoveOutput",
        "type": "object"
      }
    },
    {
      "description": "The files this session downloaded (name, url, size, state), newest first. Downloads are allowed and named per session; read one with browser::download.",
      "metadata": {},
      "name": "browser::downloads::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "DownloadsListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "DownloadRecord": {
            "description": "A download Chromium started, tracked by its CDP guid.",
            "properties": {
              "file_name": {
                "type": "string"
              },
              "guid": {
                "type": "string"
              },
              "received_bytes": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "started_ms": {
                "format": "int64",
                "type": "integer"
              },
              "state": {
                "description": "`in_progress`, `completed`, or `canceled`.",
                "type": "string"
              },
              "total_bytes": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "file_name",
              "guid",
              "received_bytes",
              "started_ms",
              "state",
              "total_bytes",
              "url"
            ],
            "type": "object"
          }
        },
        "properties": {
          "downloads": {
            "description": "Newest first.",
            "items": {
              "$ref": "#/definitions/DownloadRecord"
            },
            "type": "array"
          }
        },
        "required": [
          "downloads"
        ],
        "title": "DownloadsListOutput",
        "type": "object"
      }
    },
    {
      "description": "Playwright/Chromium fetch: JS render, waits, XHR capture, CDP; extraction + bulk.",
      "metadata": {},
      "name": "browser::dynamic-fetch",
      "request_schema": {
        "properties": {
          "block_ads": {
            "type": "boolean"
          },
          "blocked_domains": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "capture_xhr": {
            "type": "string"
          },
          "cdp_url": {
            "type": "string"
          },
          "cookies": {
            "type": "object"
          },
          "css_selector": {
            "description": "scope the render to this CSS subtree (e.g. a page's content div)",
            "type": "string"
          },
          "disable_resources": {
            "type": "boolean"
          },
          "dns_over_https": {
            "type": "boolean"
          },
          "extra_flags": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "extra_headers": {
            "type": "object"
          },
          "format": {
            "description": "render page body to this format",
            "enum": [
              "markdown",
              "text"
            ],
            "type": "string"
          },
          "google_search": {
            "type": "boolean"
          },
          "headless": {
            "type": "boolean"
          },
          "include_html": {
            "type": "boolean"
          },
          "load_dom": {
            "type": "boolean"
          },
          "locale": {
            "type": "string"
          },
          "main_content_only": {
            "description": "strip nav/scripts/hidden before rendering",
            "type": "boolean"
          },
          "max_pages": {
            "type": "integer"
          },
          "network_idle": {
            "type": "boolean"
          },
          "proxy": {
            "type": "string"
          },
          "real_chrome": {
            "type": "boolean"
          },
          "retries": {
            "type": "integer"
          },
          "retry_delay": {
            "type": "number"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "timeout": {
            "description": "milliseconds (browser fetcher)",
            "type": "number"
          },
          "timezone_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "urls": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "useragent": {
            "type": "string"
          },
          "wait": {
            "description": "extra ms to wait after load",
            "type": "number"
          },
          "wait_selector": {
            "type": "string"
          },
          "wait_selector_state": {
            "enum": [
              "attached",
              "detached",
              "visible",
              "hidden"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "captured_xhr": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "content": {
            "description": "markdown/text render when `format` requested",
            "type": "string"
          },
          "cookies": {
            "type": "object"
          },
          "encoding": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": "string"
          },
          "extracted": {
            "type": "object"
          },
          "format": {
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "html": {
            "type": "string"
          },
          "results": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Evaluate a JavaScript expression in the page and return its completion value. Use for reads the snapshot can't express; prefer browser::act for interactions.",
      "metadata": {},
      "name": "browser::evaluate",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "expression": {
            "description": "JavaScript expression evaluated in the page. The completion value is returned by value; wrap statements in an IIFE.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          },
          "timeout_ms": {
            "default": null,
            "description": "Upper bound on evaluation; clamped to `max_timeout_ms`.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "expression",
          "session_id"
        ],
        "title": "EvaluateInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "error": {
            "description": "Exception text when not `ok`.",
            "type": [
              "string",
              "null"
            ]
          },
          "ok": {
            "type": "boolean"
          },
          "value": {
            "description": "JSON completion value when `ok`."
          }
        },
        "required": [
          "ok"
        ],
        "title": "EvaluateOutput",
        "type": "object"
      }
    },
    {
      "description": "Run a multi-step async JavaScript script in the page: top-level await and return work, with log(...), sleep(ms), waitFor(selector), and a state object that persists across execute calls for the session. One call replaces a chain of act/evaluate round-trips; returns { result, logs, state }.",
      "metadata": {},
      "name": "browser::execute",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "code": {
            "description": "Async JavaScript body run in the page. Top-level `await` and `return` work. In scope: `state` (JSON object persisted across execute calls for the session), `log(...)` (collected into the response), `sleep(ms)`, and `waitFor(selector, { timeout })`. Return plain JSON.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          },
          "timeout_ms": {
            "default": null,
            "description": "Upper bound on the run; clamped to `max_timeout_ms`.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "code",
          "session_id"
        ],
        "title": "ExecuteInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "error": {
            "description": "Exception text when not `ok`. A \"context destroyed\" error usually means the script navigated; split the script at the navigation.",
            "type": [
              "string",
              "null"
            ]
          },
          "logs": {
            "description": "`log(...)` output collected during the run, in order.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ok": {
            "type": "boolean"
          },
          "result": {
            "description": "The script's return value when `ok`."
          },
          "state": {
            "description": "Session state after the run; the next execute call sees this as `state`."
          }
        },
        "required": [
          "logs",
          "ok",
          "state"
        ],
        "title": "ExecuteOutput",
        "type": "object"
      }
    },
    {
      "description": "Parse HTML with a selector list (css/xpath/regex, text/attr/html, all-or-first).",
      "metadata": {},
      "name": "browser::extract",
      "request_schema": {
        "properties": {
          "adaptive": {
            "description": "relocate elements after a site change via saved identities",
            "type": "boolean"
          },
          "adaptive_domain": {
            "description": "page URL/domain that keys saved identities",
            "type": "string"
          },
          "auto_save": {
            "description": "save matched identities (defaults on when adaptive)",
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          }
        },
        "required": [
          "html",
          "selectors"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "extracted": {
            "type": "object"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Fast HTTP fetch, TLS impersonation: get/post/put/delete, inline extraction, bulk `urls`.",
      "metadata": {},
      "name": "browser::fetch",
      "request_schema": {
        "properties": {
          "cookies": {
            "type": "object"
          },
          "css_selector": {
            "description": "scope the render to this CSS subtree (e.g. a page's content div)",
            "type": "string"
          },
          "data": {
            "type": "object"
          },
          "follow_redirects": {
            "type": "boolean"
          },
          "format": {
            "description": "render page body to this format",
            "enum": [
              "markdown",
              "text"
            ],
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "http3": {
            "type": "boolean"
          },
          "impersonate": {
            "description": "TLS/UA fingerprint, e.g. 'chrome'",
            "type": "string"
          },
          "include_html": {
            "type": "boolean"
          },
          "json": {
            "type": "object"
          },
          "main_content_only": {
            "description": "strip nav/scripts/hidden before rendering",
            "type": "boolean"
          },
          "max_redirects": {
            "type": "integer"
          },
          "method": {
            "enum": [
              "get",
              "post",
              "put",
              "delete"
            ],
            "type": "string"
          },
          "params": {
            "type": "object"
          },
          "proxies": {
            "description": "per-scheme proxies, e.g. {\"https\": \"http://...\"}",
            "type": "object"
          },
          "proxy": {
            "type": "string"
          },
          "proxy_auth": {
            "description": "[user, password]",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "retries": {
            "type": "integer"
          },
          "retry_delay": {
            "type": "number"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "stealthy_headers": {
            "type": "boolean"
          },
          "timeout": {
            "description": "seconds (HTTP fetcher)",
            "type": "number"
          },
          "url": {
            "type": "string"
          },
          "urls": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "verify": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "captured_xhr": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "content": {
            "description": "markdown/text render when `format` requested",
            "type": "string"
          },
          "cookies": {
            "type": "object"
          },
          "encoding": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": "string"
          },
          "extracted": {
            "type": "object"
          },
          "format": {
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "html": {
            "type": "string"
          },
          "results": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Find elements by tag/attribute filters (+ optional text regex); BeautifulSoup-style.",
      "metadata": {},
      "name": "browser::find",
      "request_schema": {
        "properties": {
          "attrs": {
            "description": "attribute filters, e.g. {\"class\": \"card\"}",
            "type": "object"
          },
          "first": {
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          },
          "tag": {
            "description": "tag name or list of tag names",
            "items": {
              "type": "string"
            },
            "type": [
              "string",
              "array"
            ]
          },
          "text_regex": {
            "description": "keep only elements whose text matches this regex",
            "type": "string"
          }
        },
        "required": [
          "html"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "count": {
            "type": "integer"
          },
          "items": {
            "items": {
              "properties": {
                "attrs": {
                  "type": "object"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "type": "string"
                },
                "tag": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Find elements whose visible text matches a regex pattern.",
      "metadata": {},
      "name": "browser::find-by-regex",
      "request_schema": {
        "properties": {
          "case_sensitive": {
            "type": "boolean"
          },
          "clean_match": {
            "type": "boolean"
          },
          "first": {
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          },
          "pattern": {
            "type": "string"
          }
        },
        "required": [
          "html",
          "pattern"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "count": {
            "type": "integer"
          },
          "items": {
            "items": {
              "properties": {
                "attrs": {
                  "type": "object"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "type": "string"
                },
                "tag": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Find elements whose visible text matches a string (exact or `partial`).",
      "metadata": {},
      "name": "browser::find-by-text",
      "request_schema": {
        "properties": {
          "case_sensitive": {
            "type": "boolean"
          },
          "clean_match": {
            "description": "ignore surrounding/collapsing whitespace",
            "type": "boolean"
          },
          "first": {
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "limit": {
            "type": "integer"
          },
          "partial": {
            "description": "match elements that contain the text",
            "type": "boolean"
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "html",
          "text"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "count": {
            "type": "integer"
          },
          "items": {
            "items": {
              "properties": {
                "attrs": {
                  "type": "object"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "type": "string"
                },
                "tag": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Find text in the page like the browser's find bar: highlights every match in the live document, scrolls the current one into view, and steps with next / previous. close clears the highlights. Returns count and the 1-based index.",
      "metadata": {},
      "name": "browser::find-in-page",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "action": {
            "default": null,
            "description": "`search` (default: run the query from the top), `next`, `previous`, or `close`.",
            "type": [
              "string",
              "null"
            ]
          },
          "case_sensitive": {
            "default": null,
            "description": "Match case. Default false.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "query": {
            "default": "",
            "description": "Text to look for. Empty with `action: close` clears the search.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "FindInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "count": {
            "description": "Number of matches in the visible text of the page.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "index": {
            "description": "1-based index of the highlighted match; 0 when there is none.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "type": "boolean"
          },
          "query": {
            "description": "The query the counts refer to.",
            "type": "string"
          }
        },
        "required": [
          "count",
          "index",
          "ok",
          "query"
        ],
        "title": "FindOutput",
        "type": "object"
      }
    },
    {
      "description": "Structural auto-match: given one example element, return it plus similar elements.",
      "metadata": {},
      "name": "browser::find-similar",
      "request_schema": {
        "properties": {
          "anchor": {
            "description": "CSS selector to one example element",
            "type": "string"
          },
          "html": {
            "type": "string"
          },
          "match_text": {
            "type": "boolean"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "similarity_threshold": {
            "type": "number"
          }
        },
        "required": [
          "html",
          "anchor"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "count": {
            "type": "integer"
          },
          "items": {
            "items": {
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Internal: newest screencast frame, or nothing when since_frame is still current. No capture round-trip; poll fast. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::frame",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "since_frame": {
            "default": null,
            "description": "Frame cursor from the previous read; when the newest frame still has this seq the response omits `frame` (nothing changed, nothing to redraw).",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "session_id"
        ],
        "title": "FrameInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "active": {
            "description": "False when no screencast is running (call screencast::start first).",
            "type": "boolean"
          },
          "frame": {
            "description": "Base64 JPEG of the newest frame; absent when `since_frame` is still current or no frame has arrived yet.",
            "type": [
              "string",
              "null"
            ]
          },
          "frame_seq": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "height": {
            "description": "Page-viewport height the frame maps to.",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "timestamp": {
            "format": "int64",
            "type": "integer"
          },
          "width": {
            "description": "Page-viewport width the frame maps to (input coordinate space).",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "active",
          "frame_seq",
          "height",
          "timestamp",
          "width"
        ],
        "title": "FrameOutput",
        "type": "object"
      }
    },
    {
      "description": "Pause a session for a step only a human can do (CAPTCHA, 2FA, payment): show an in-page continue banner and block until the human clicks it, a browser::handoff::confirm call resolves it, or the timeout elapses. Human acknowledgment is not proof — verify the expected page state after it returns.",
      "metadata": {},
      "name": "browser::handoff",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "instructions": {
            "description": "What the human must do before the call continues. Shown in the in-page banner and the handoff-requested event.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          },
          "timeout_ms": {
            "default": null,
            "description": "Give up after this long and return with `via: \"timeout\"`. Defaults to the config default; clamped to `max_timeout_ms`. Set generously; a human is slow.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "instructions",
          "session_id"
        ],
        "title": "HandoffInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "confirmed": {
            "description": "True when a human confirmed; false when the wait timed out.",
            "type": "boolean"
          },
          "handoff_id": {
            "type": "string"
          },
          "url": {
            "description": "The page URL when the wait ended, so the caller can verify the step actually landed (human acknowledgment is not proof).",
            "type": "string"
          },
          "via": {
            "description": "How the confirmation arrived: `in_page`, `confirm_call`, or `timeout`.",
            "type": "string"
          }
        },
        "required": [
          "confirmed",
          "handoff_id",
          "url",
          "via"
        ],
        "title": "HandoffOutput",
        "type": "object"
      }
    },
    {
      "description": "Resolve a paused browser::handoff by handoff_id, or the one pending handoff for a session_id. The console calls this when the human confirms outside the page.",
      "metadata": {},
      "name": "browser::handoff::confirm",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "handoff_id": {
            "default": null,
            "description": "Confirm a specific handoff by id. Omit to confirm the one pending handoff for `session_id`.",
            "type": [
              "string",
              "null"
            ]
          },
          "session_id": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "HandoffConfirmInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "handoff_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "ok": {
            "description": "True when a pending handoff matched and was resolved.",
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "HandoffConfirmOutput",
        "type": "object"
      }
    },
    {
      "description": "Go back, go forward, or reload the session's page. Back/forward at the history edge is a no-op with moved=false.",
      "metadata": {},
      "name": "browser::history",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "action": {
            "description": "`back`, `forward`, or `reload`.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "action",
          "session_id"
        ],
        "title": "HistoryInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "moved": {
            "description": "False when back/forward had no entry to move to.",
            "type": "boolean"
          },
          "ok": {
            "type": "boolean"
          },
          "url": {
            "description": "URL after the action. `back`/`forward` at the history edge is a no-op with ok=true.",
            "type": "string"
          }
        },
        "required": [
          "moved",
          "ok",
          "url"
        ],
        "title": "HistoryOutput",
        "type": "object"
      }
    },
    {
      "description": "The session's visited pages, newest first, for a history panel or address-bar suggestions. Filter with query. Distinct from browser::history, which moves back / forward / reloads.",
      "metadata": {},
      "name": "browser::history::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "limit": {
            "default": null,
            "description": "Cap on returned entries. Default 100.",
            "format": "uint",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "query": {
            "default": null,
            "description": "Only entries whose url or title contains this (case-insensitive).",
            "type": [
              "string",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "HistoryListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "HistoryVisit": {
            "description": "One entry in a session's navigation history.",
            "properties": {
              "timestamp": {
                "format": "int64",
                "type": "integer"
              },
              "title": {
                "type": "string"
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "timestamp",
              "title",
              "url"
            ],
            "type": "object"
          }
        },
        "properties": {
          "visits": {
            "items": {
              "$ref": "#/definitions/HistoryVisit"
            },
            "type": "array"
          }
        },
        "required": [
          "visits"
        ],
        "title": "HistoryListOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: appends browser::* scraping and HTML parsing guidance to the agent system prompt.",
      "metadata": {
        "internal": true
      },
      "name": "browser::inject-guidance",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "GenerateContext": {
            "properties": {
              "system_prompt": {
                "default": "",
                "type": "string"
              }
            },
            "type": "object"
          }
        },
        "properties": {
          "generate": {
            "$ref": "#/definitions/GenerateContext"
          }
        },
        "title": "PreGenerateEvent",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "PreGenerateMutations": {
            "properties": {
              "system_prompt": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "type": "object"
          }
        },
        "properties": {
          "mutations": {
            "$ref": "#/definitions/PreGenerateMutations"
          }
        },
        "required": [
          "mutations"
        ],
        "title": "PreGenerateResponse",
        "type": "object"
      }
    },
    {
      "description": "Navigate a session to a URL and wait for the page to load. Element refs from earlier snapshots are invalidated by navigation.",
      "metadata": {},
      "name": "browser::navigate",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "timeout_ms": {
            "default": null,
            "description": "Upper bound on the navigation wait; clamped to `max_timeout_ms`.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "description": "Absolute URL; scheme must be on the configured allowlist.",
            "type": "string"
          }
        },
        "required": [
          "session_id",
          "url"
        ],
        "title": "NavigateInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "timed_out": {
            "description": "True when the load event did not fire inside the timeout; the page may still be usable; snapshot to check.",
            "type": "boolean"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "description": "URL after redirects.",
            "type": "string"
          }
        },
        "required": [
          "ok",
          "timed_out",
          "url"
        ],
        "title": "NavigateOutput",
        "type": "object"
      }
    },
    {
      "description": "Read the session's captured network requests (method, URL, status, failures). failed_only=true is the fast path for 'what broke'.",
      "metadata": {},
      "name": "browser::network::read",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "failed_only": {
            "default": null,
            "description": "Only failed requests (network error or status >= 400).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "limit": {
            "default": null,
            "description": "Maximum entries returned, newest kept (default 100).",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "pattern": {
            "default": null,
            "description": "Regex applied to the request URL.",
            "type": [
              "string",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          },
          "since_seq": {
            "default": null,
            "description": "Only entries with `seq` greater than this.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "session_id"
        ],
        "title": "NetworkReadInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "NetworkEntry": {
            "description": "One captured network request.",
            "properties": {
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "failed": {
                "type": "boolean"
              },
              "method": {
                "type": "string"
              },
              "mime_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "seq": {
                "description": "Monotonic per-session cursor; pass back as `since_seq`.",
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "status": {
                "format": "int64",
                "type": [
                  "integer",
                  "null"
                ]
              },
              "timestamp": {
                "format": "int64",
                "type": "integer"
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "failed",
              "method",
              "seq",
              "timestamp",
              "url"
            ],
            "type": "object"
          }
        },
        "properties": {
          "dropped": {
            "description": "Entries evicted from the ring buffer since session start.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "entries": {
            "items": {
              "$ref": "#/definitions/NetworkEntry"
            },
            "type": "array"
          },
          "last_seq": {
            "description": "Cursor for the next `since_seq`.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "dropped",
          "entries",
          "last_seq"
        ],
        "title": "NetworkReadOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: reload browser settings from the authoritative configuration on change.",
      "metadata": {
        "internal": true
      },
      "name": "browser::on-config-change",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "OnConfigChangeRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "OnConfigChangeResponse",
        "type": "object"
      }
    },
    {
      "description": "Print the page to a PDF (the browser's Print -> Save as PDF) and return it base64 with a file name from the title.",
      "metadata": {},
      "name": "browser::pdf",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "landscape": {
            "default": null,
            "description": "Landscape orientation. Default portrait.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "print_background": {
            "default": null,
            "description": "Print background colours and images. Default true (what the page looks like, not what a printer would save ink on).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "scale": {
            "default": null,
            "description": "Page scale, 0.1–2. Default 1.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "PdfInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "data": {
            "description": "The PDF, base64.",
            "type": "string"
          },
          "file_name": {
            "description": "Suggested file name, from the page title.",
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "size_bytes": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "data",
          "file_name",
          "ok",
          "size_bytes",
          "url"
        ],
        "title": "PdfOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: element preview at a viewport point (tag, id, classes, bounds) so the console UI can draw a hover highlight in pick mode. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::pick::hint",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "x": {
            "description": "Viewport x of the cursor.",
            "format": "double",
            "type": "number"
          },
          "y": {
            "description": "Viewport y of the cursor.",
            "format": "double",
            "type": "number"
          }
        },
        "required": [
          "session_id",
          "x",
          "y"
        ],
        "title": "PickHintInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Bounds": {
            "properties": {
              "height": {
                "format": "double",
                "type": "number"
              },
              "width": {
                "format": "double",
                "type": "number"
              },
              "x": {
                "format": "double",
                "type": "number"
              },
              "y": {
                "format": "double",
                "type": "number"
              }
            },
            "required": [
              "height",
              "width",
              "x",
              "y"
            ],
            "type": "object"
          }
        },
        "properties": {
          "bounds": {
            "anyOf": [
              {
                "$ref": "#/definitions/Bounds"
              },
              {
                "type": "null"
              }
            ],
            "description": "Viewport-space box to draw the highlight over."
          },
          "classes": {
            "type": [
              "string",
              "null"
            ]
          },
          "hit": {
            "description": "False when no element sits at the point.",
            "type": "boolean"
          },
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "tag": {
            "description": "Lowercase tag name.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "hit"
        ],
        "title": "PickHintOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: resolve the element at a clicked viewport point and emit browser::picked. The console calls this on a pick-mode click. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::pick::resolve",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "x": {
            "description": "Viewport x of the click.",
            "format": "double",
            "type": "number"
          },
          "y": {
            "description": "Viewport y of the click.",
            "format": "double",
            "type": "number"
          }
        },
        "required": [
          "session_id",
          "x",
          "y"
        ],
        "title": "PickResolveInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Neutral acknowledgement returned by the fire-and-forget internal functions (pick start/stop/resolve, screencast start/stop): they emit their result as a trigger event, so the direct return is just `{ ok }`.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "AckOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: enter pick mode so the human can select an element in the console UI. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::pick::start",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "PickStartInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Neutral acknowledgement returned by the fire-and-forget internal functions (pick start/stop/resolve, screencast start/stop): they emit their result as a trigger event, so the direct return is just `{ ok }`.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "AckOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: leave DevTools inspect mode without picking. Idempotent. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::pick::stop",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "description": "Cancelling pick mode on an unknown session succeeds.",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "PickStopInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Neutral acknowledgement returned by the fire-and-forget internal functions (pick start/stop/resolve, screencast start/stop): they emit their result as a trigger event, so the direct return is just `{ ok }`.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "AckOutput",
        "type": "object"
      }
    },
    {
      "description": "Record a session's live viewport to a video file (webm or mp4) by piping the screencast through ffmpeg. Turns screencast on if needed. Requires ffmpeg on PATH; browser::doctor reports whether it is available.",
      "metadata": {},
      "name": "browser::recording::start",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "format": {
            "default": null,
            "description": "`webm` (VP9) or `mp4` (H.264). Defaults to webm.",
            "type": [
              "string",
              "null"
            ]
          },
          "path": {
            "description": "Output file path. The extension should match `format`.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "path",
          "session_id"
        ],
        "title": "RecordingStartInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "format": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "path": {
            "type": "string"
          }
        },
        "required": [
          "format",
          "ok",
          "path"
        ],
        "title": "RecordingStartOutput",
        "type": "object"
      }
    },
    {
      "description": "Stop a session's recording, finalize the file, and return its path, duration, and frame count. Idempotent: stopping when nothing is recording returns ok=false.",
      "metadata": {},
      "name": "browser::recording::stop",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "RecordingStopInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "duration_ms": {
            "description": "Wall-clock duration captured, milliseconds.",
            "format": "int64",
            "type": "integer"
          },
          "frames": {
            "description": "Frames written to the encoder.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "description": "False when no recording was running.",
            "type": "boolean"
          },
          "path": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "duration_ms",
          "frames",
          "ok"
        ],
        "title": "RecordingStopOutput",
        "type": "object"
      }
    },
    {
      "description": "Run a regex over the visible text of provided HTML; `first` returns the first match, else all.",
      "metadata": {},
      "name": "browser::regex",
      "request_schema": {
        "properties": {
          "first": {
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "pattern": {
            "type": "string"
          }
        },
        "required": [
          "html",
          "pattern"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "result": {
            "items": {
              "type": [
                "string",
                "null"
              ]
            },
            "type": [
              "array",
              "string",
              "null"
            ]
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Set the session's live viewport size (CSS pixels). The console calls this as its browser pane resizes so the streamed frame fills the pane with no letterboxing and clicks map 1:1; the device toolbar calls it with a preset. Clamped 200..4000.",
      "metadata": {},
      "name": "browser::resize",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "device_scale_factor": {
            "default": null,
            "description": "Device pixel ratio. Default 1.",
            "format": "double",
            "type": [
              "number",
              "null"
            ]
          },
          "fit": {
            "default": null,
            "description": "This resize is a pane auto-fit, not an explicit choice. A fit is refused (current size returned) while more than one viewer watches the session, so two open panes do not fight over the shared viewport; explicit resizes (device toolbar, agents) always apply.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "height": {
            "description": "Viewport height in CSS pixels (clamped 200..4000).",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "mobile": {
            "default": null,
            "description": "Emulate a mobile device (viewport meta, overlay scrollbars, touch). Default false. The device toolbar sets this for phone presets.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          },
          "width": {
            "description": "Viewport width in CSS pixels (clamped 200..4000).",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "height",
          "session_id",
          "width"
        ],
        "title": "ResizeInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "height": {
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "type": "boolean"
          },
          "width": {
            "description": "The clamped size actually applied.",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "height",
          "ok",
          "width"
        ],
        "title": "ResizeOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: start pushing live viewport frames for browser::frame. Console-UI plumbing; agents use browser::screenshot. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::screencast::start",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ScreencastStartInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Neutral acknowledgement returned by the fire-and-forget internal functions (pick start/stop/resolve, screencast start/stop): they emit their result as a trigger event, so the direct return is just `{ ok }`.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "AckOutput",
        "type": "object"
      }
    },
    {
      "description": "Internal: stop the live frame push. Idempotent. Not an agent function.",
      "metadata": {
        "internal": true
      },
      "name": "browser::screencast::stop",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "description": "Stopping the screencast on an unknown session succeeds.",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ScreencastStopInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Neutral acknowledgement returned by the fire-and-forget internal functions (pick start/stop/resolve, screencast start/stop): they emit their result as a trigger event, so the direct return is just `{ ok }`.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "AckOutput",
        "type": "object"
      }
    },
    {
      "description": "Capture the session viewport as a viewable JPEG. Use browser::snapshot for machine-readable structure; screenshot when layout or rendering matters.",
      "metadata": {
        "display": true
      },
      "name": "browser::screenshot",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "full_page": {
            "default": null,
            "description": "Capture the full scrollable page instead of the viewport.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ScreenshotInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "ContentBlock": {
            "description": "One block of a viewable response: an image block plus a text line.",
            "properties": {
              "data": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "mime": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "type": {
                "type": "string"
              }
            },
            "required": [
              "type"
            ],
            "type": "object"
          },
          "ScreenshotDetails": {
            "properties": {
              "height": {
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              },
              "session_id": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "width": {
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              }
            },
            "required": [
              "height",
              "session_id",
              "url",
              "width"
            ],
            "type": "object"
          }
        },
        "properties": {
          "content": {
            "items": {
              "$ref": "#/definitions/ContentBlock"
            },
            "type": "array"
          },
          "details": {
            "$ref": "#/definitions/ScreenshotDetails"
          }
        },
        "required": [
          "content",
          "details"
        ],
        "title": "ScreenshotOutput",
        "type": "object"
      }
    },
    {
      "description": "Capture a page screenshot as image content blocks via a browser fetcher (dynamic or stealthy).",
      "metadata": {},
      "name": "browser::screenshot-url",
      "request_schema": {
        "properties": {
          "fetcher": {
            "enum": [
              "dynamic",
              "stealthy"
            ],
            "type": "string"
          },
          "format": {
            "enum": [
              "png",
              "jpeg"
            ],
            "type": "string"
          },
          "full_page": {
            "type": "boolean"
          },
          "headless": {
            "type": "boolean"
          },
          "network_idle": {
            "type": "boolean"
          },
          "proxy": {
            "type": "string"
          },
          "timeout": {
            "type": "number"
          },
          "url": {
            "type": "string"
          },
          "wait_selector": {
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "content": {
            "description": "image blocks (one per tile, width<=1024/height<=1536) + a text caption",
            "items": {
              "properties": {
                "data": {
                  "description": "base64 image bytes (image blocks)",
                  "type": "string"
                },
                "mime": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "type": {
                  "enum": [
                    "image",
                    "text"
                  ],
                  "type": "string"
                }
              },
              "required": [
                "type"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "mime": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Close a session and free its browser/connection.",
      "metadata": {},
      "name": "browser::session-close",
      "request_schema": {
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "closed": {
            "type": "boolean"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Fetch a URL on an open scraping session (reuses its cookies/state); returns page content, shows nothing. For a page the user should see, use browser::sessions::start + browser::navigate.",
      "metadata": {},
      "name": "browser::session-fetch",
      "request_schema": {
        "properties": {
          "css_selector": {
            "description": "scope the render to this CSS subtree (e.g. a page's content div)",
            "type": "string"
          },
          "data": {
            "type": "object"
          },
          "format": {
            "description": "render page body to this format",
            "enum": [
              "markdown",
              "text"
            ],
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "include_html": {
            "type": "boolean"
          },
          "json": {
            "type": "object"
          },
          "main_content_only": {
            "description": "strip nav/scripts/hidden before rendering",
            "type": "boolean"
          },
          "method": {
            "enum": [
              "get",
              "post",
              "put",
              "delete"
            ],
            "type": "string"
          },
          "params": {
            "type": "object"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "session_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "wait_selector": {
            "type": "string"
          }
        },
        "required": [
          "session_id",
          "url"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "captured_xhr": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "content": {
            "description": "markdown/text render when `format` requested",
            "type": "string"
          },
          "cookies": {
            "type": "object"
          },
          "encoding": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": "string"
          },
          "extracted": {
            "type": "object"
          },
          "format": {
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "html": {
            "type": "string"
          },
          "results": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "List open sessions with their type and idle time.",
      "metadata": {},
      "name": "browser::session-list",
      "request_schema": {
        "properties": {
          "type": {
            "description": "filter by type",
            "enum": [
              "http",
              "dynamic",
              "stealthy"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "sessions": {
            "items": {
              "properties": {
                "created_at": {
                  "type": "number"
                },
                "idle_s": {
                  "type": "number"
                },
                "last_used": {
                  "type": "number"
                },
                "session_id": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Open a persistent scraping session (HTTP or headless fetcher) whose session_id reuses cookies and state across fetches. Renders nothing the user can see; to open a page in the visible browser use browser::sessions::start.",
      "metadata": {},
      "name": "browser::session-open",
      "request_schema": {
        "properties": {
          "capture_xhr": {
            "description": "regex; capture matching XHRs (browser sessions)",
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "headless": {
            "type": "boolean"
          },
          "impersonate": {
            "type": "string"
          },
          "proxies": {
            "type": "object"
          },
          "proxy": {
            "type": "string"
          },
          "real_chrome": {
            "type": "boolean"
          },
          "solve_cloudflare": {
            "type": "boolean"
          },
          "timeout": {
            "type": "number"
          },
          "type": {
            "description": "session engine",
            "enum": [
              "http",
              "dynamic",
              "stealthy"
            ],
            "type": "string"
          },
          "useragent": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "session_id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Attach a session to an already-running browser over CDP (start Chrome with --remote-debugging-port). Opens a fresh tab the session owns, or adopts an existing user tab by URL substring and releases it untouched on stop. Reaches the real profile with its logins; disabled unless allow_attach is set in config.",
      "metadata": {},
      "name": "browser::sessions::attach",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "adopt_url_substring": {
            "default": null,
            "description": "Adopt the existing tab whose URL contains this substring, exclusively, and release it untouched on stop. Omit to open a fresh tab the session owns and closes on stop. Must match exactly one open tab.",
            "type": [
              "string",
              "null"
            ]
          },
          "cdp_url": {
            "description": "CDP endpoint of the running browser: `http://127.0.0.1:9222` (the worker resolves the WebSocket URL from `/json/version`) or a `ws://` debugger URL directly. Start Chrome with `--remote-debugging-port=9222` to expose one.",
            "type": "string"
          },
          "read_only": {
            "default": null,
            "description": "Inspection-only session; see browser::sessions::start.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "url": {
            "default": null,
            "description": "URL to open in the fresh tab (ignored when adopting). Omit for about:blank.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "cdp_url"
        ],
        "title": "AttachInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "adopted": {
            "description": "True when the session adopted an existing user tab (released, not closed, on stop); false when it opened a fresh tab it owns.",
            "type": "boolean"
          },
          "read_only": {
            "type": "boolean"
          },
          "session_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "adopted",
          "read_only",
          "session_id",
          "url"
        ],
        "title": "AttachOutput",
        "type": "object"
      }
    },
    {
      "description": "List live browser sessions with their current URL and activity.",
      "metadata": {},
      "name": "browser::sessions::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "ListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "SessionInfo": {
            "properties": {
              "console_entries": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "created_ms": {
                "format": "int64",
                "type": "integer"
              },
              "headless": {
                "type": "boolean"
              },
              "last_used_ms": {
                "format": "int64",
                "type": "integer"
              },
              "read_only": {
                "type": "boolean"
              },
              "session_id": {
                "type": "string"
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "console_entries",
              "created_ms",
              "headless",
              "last_used_ms",
              "read_only",
              "session_id",
              "url"
            ],
            "type": "object"
          }
        },
        "properties": {
          "sessions": {
            "items": {
              "$ref": "#/definitions/SessionInfo"
            },
            "type": "array"
          }
        },
        "required": [
          "sessions"
        ],
        "title": "ListOutput",
        "type": "object"
      }
    },
    {
      "description": "Start an interactive Chromium session and return its session_id. Sessions keep console and network history; stop them with browser::sessions::stop when done.",
      "metadata": {},
      "name": "browser::sessions::start",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "headful": {
            "default": null,
            "description": "Force a visible window for this session, overriding the configured `headless` default.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "read_only": {
            "default": null,
            "description": "Inspection-only session: act, evaluate, execute, and styles::write are rejected while navigation, snapshots, reads, and screenshots work. Immutable for the session's lifetime.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "url": {
            "default": null,
            "description": "URL to open immediately. Omit to start on about:blank.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "StartInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "headless": {
            "type": "boolean"
          },
          "read_only": {
            "type": "boolean"
          },
          "session_id": {
            "description": "Pass this to every other browser function.",
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "headless",
          "read_only",
          "session_id",
          "url"
        ],
        "title": "StartOutput",
        "type": "object"
      }
    },
    {
      "description": "Stop a browser session and its Chromium process. Idempotent: stopping an unknown or already-stopped session succeeds with was_running=false.",
      "metadata": {},
      "name": "browser::sessions::stop",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "session_id": {
            "description": "Session to stop. Stopping an unknown or already-stopped id succeeds.",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "StopInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "was_running": {
            "description": "False when the session was already gone.",
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "was_running"
        ],
        "title": "StopOutput",
        "type": "object"
      }
    },
    {
      "description": "Read the page as an accessibility-tree outline. Lines carry [ref=eN] handles that browser::act accepts; refs stay valid until the next navigation. Prefer this over browser::screenshot; it is cheaper and machine-readable.",
      "metadata": {},
      "name": "browser::snapshot",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "diff": {
            "default": null,
            "description": "Return only what changed since this session's previous snapshot instead of the full outline. Falls back to a full snapshot when there is no baseline (first snapshot, or first after a navigation).",
            "type": [
              "boolean",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "SnapshotInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "SnapshotDiff": {
            "description": "Changes since the previous snapshot. Lines are compared without their `[ref=eN]` suffix (ref names are unique per snapshot); `added` lines carry current refs and are directly actionable.",
            "properties": {
              "added": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "removed": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "unchanged": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              }
            },
            "required": [
              "added",
              "removed",
              "unchanged"
            ],
            "type": "object"
          }
        },
        "properties": {
          "diff": {
            "anyOf": [
              {
                "$ref": "#/definitions/SnapshotDiff"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when the caller asked for `diff: true` and a baseline existed. Covers only the emitted nodes of both snapshots; check `truncated` before trusting it as a complete change set."
          },
          "generation": {
            "description": "Document generation the refs belong to; navigation advances it and kills every ref from earlier generations.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "tree": {
            "description": "Indented outline; lines carry `[ref=eN]` handles for `browser::act`. Empty when `diff` is populated.",
            "type": "string"
          },
          "truncated": {
            "description": "True when the tree hit `max_snapshot_nodes` and was cut short. Also the signal that a `diff` may be incomplete: the diff is computed over emitted nodes only, so when either snapshot was truncated a node that was emitted before and capped out now can show up in `removed` even though it still exists (and vice versa for `added`).",
            "type": "boolean"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "generation",
          "tree",
          "truncated",
          "url"
        ],
        "title": "SnapshotOutput",
        "type": "object"
      }
    },
    {
      "description": "Camoufox stealth browser: solves Cloudflare, hardens WebRTC/canvas; extraction + bulk.",
      "metadata": {},
      "name": "browser::stealthy-fetch",
      "request_schema": {
        "properties": {
          "allow_webgl": {
            "type": "boolean"
          },
          "block_ads": {
            "type": "boolean"
          },
          "block_webrtc": {
            "type": "boolean"
          },
          "blocked_domains": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "capture_xhr": {
            "type": "string"
          },
          "cookies": {
            "type": "object"
          },
          "css_selector": {
            "description": "scope the render to this CSS subtree (e.g. a page's content div)",
            "type": "string"
          },
          "disable_resources": {
            "type": "boolean"
          },
          "dns_over_https": {
            "type": "boolean"
          },
          "extra_flags": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "extra_headers": {
            "type": "object"
          },
          "format": {
            "description": "render page body to this format",
            "enum": [
              "markdown",
              "text"
            ],
            "type": "string"
          },
          "google_search": {
            "type": "boolean"
          },
          "headless": {
            "type": "boolean"
          },
          "hide_canvas": {
            "type": "boolean"
          },
          "include_html": {
            "type": "boolean"
          },
          "load_dom": {
            "type": "boolean"
          },
          "locale": {
            "type": "string"
          },
          "main_content_only": {
            "description": "strip nav/scripts/hidden before rendering",
            "type": "boolean"
          },
          "max_pages": {
            "type": "integer"
          },
          "network_idle": {
            "type": "boolean"
          },
          "proxy": {
            "type": "string"
          },
          "retries": {
            "type": "integer"
          },
          "retry_delay": {
            "type": "number"
          },
          "selectors": {
            "items": {
              "properties": {
                "all": {
                  "description": "return every match as a list",
                  "type": "boolean"
                },
                "attr": {
                  "description": "extract this attribute instead of text",
                  "type": "string"
                },
                "css": {
                  "type": "string"
                },
                "html": {
                  "description": "extract inner HTML instead of text",
                  "type": "boolean"
                },
                "name": {
                  "type": "string"
                },
                "regex": {
                  "type": "string"
                },
                "xpath": {
                  "type": "string"
                }
              },
              "required": [
                "name"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "solve_cloudflare": {
            "type": "boolean"
          },
          "timeout": {
            "description": "milliseconds (browser fetcher)",
            "type": "number"
          },
          "timezone_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "urls": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "useragent": {
            "type": "string"
          },
          "wait": {
            "description": "extra ms to wait after load",
            "type": "number"
          },
          "wait_selector": {
            "type": "string"
          },
          "wait_selector_state": {
            "enum": [
              "attached",
              "detached",
              "visible",
              "hidden"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "captured_xhr": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "content": {
            "description": "markdown/text render when `format` requested",
            "type": "string"
          },
          "cookies": {
            "type": "object"
          },
          "encoding": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": "string"
          },
          "extracted": {
            "type": "object"
          },
          "format": {
            "type": "string"
          },
          "headers": {
            "type": "object"
          },
          "html": {
            "type": "string"
          },
          "results": {
            "items": {
              "type": "object"
            },
            "type": "array"
          },
          "status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Read an element's computed styles (curated design set by default, or named properties) plus its inline style attribute.",
      "metadata": {},
      "name": "browser::styles::read",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "properties": {
            "default": null,
            "description": "Computed property names to return. Omit for a curated design-panel set; pass `[\"*\"]` for every computed property.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "ref": {
            "description": "Element ref from `browser::snapshot`, `browser::dom::read`, or a pick.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "ref",
          "session_id"
        ],
        "title": "StylesReadInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "StyleProperty": {
            "properties": {
              "name": {
                "type": "string"
              },
              "value": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "value"
            ],
            "type": "object"
          }
        },
        "properties": {
          "inline_style": {
            "description": "The element's inline `style` attribute, when present.",
            "type": [
              "string",
              "null"
            ]
          },
          "properties": {
            "items": {
              "$ref": "#/definitions/StyleProperty"
            },
            "type": "array"
          },
          "ref": {
            "type": "string"
          }
        },
        "required": [
          "properties",
          "ref"
        ],
        "title": "StylesReadOutput",
        "type": "object"
      }
    },
    {
      "description": "Set one inline CSS property on an element, live in the page. Visual experiment only: the page's source files are untouched, and the edit dies with the next navigation.",
      "metadata": {},
      "name": "browser::styles::write",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "important": {
            "default": null,
            "description": "Apply with `!important`.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "property": {
            "description": "CSS property name (`background-color`).",
            "type": "string"
          },
          "ref": {
            "description": "Element ref to edit.",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          },
          "value": {
            "description": "CSS value (`#101418`). Empty string removes the inline property.",
            "type": "string"
          }
        },
        "required": [
          "property",
          "ref",
          "session_id",
          "value"
        ],
        "title": "StylesWriteInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "inline_style": {
            "description": "The element's inline `style` attribute after the edit.",
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "inline_style",
          "ok"
        ],
        "title": "StylesWriteOutput",
        "type": "object"
      }
    },
    {
      "description": "List the open tabs of a running browser reachable at a CDP endpoint (url, title, and whether a session already adopted each). Read-only; adopt one with browser::sessions::attach.",
      "metadata": {},
      "name": "browser::tabs::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "cdp_url": {
            "description": "CDP endpoint of the running browser, as in browser::sessions::attach.",
            "type": "string"
          }
        },
        "required": [
          "cdp_url"
        ],
        "title": "TabsListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "TabInfo": {
            "description": "One open tab reported by `browser::tabs::list`.",
            "properties": {
              "adopted": {
                "description": "True when a session already adopted this tab; it cannot be adopted again until that session stops.",
                "type": "boolean"
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "url": {
                "type": "string"
              }
            },
            "required": [
              "adopted",
              "url"
            ],
            "type": "object"
          }
        },
        "properties": {
          "tabs": {
            "items": {
              "$ref": "#/definitions/TabInfo"
            },
            "type": "array"
          }
        },
        "required": [
          "tabs"
        ],
        "title": "TabsListOutput",
        "type": "object"
      }
    },
    {
      "description": "Convert HTML to compact Markdown (or text/html); optional CSS scope + main-content clean.",
      "metadata": {},
      "name": "browser::to-markdown",
      "request_schema": {
        "properties": {
          "css_selector": {
            "description": "convert only the subtree matching this CSS selector",
            "type": "string"
          },
          "format": {
            "enum": [
              "markdown",
              "text",
              "html"
            ],
            "type": "string"
          },
          "html": {
            "type": "string"
          },
          "main_content_only": {
            "description": "strip nav/scripts/hidden nodes first",
            "type": "boolean"
          }
        },
        "required": [
          "html"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "content": {
            "type": "string"
          },
          "format": {
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Serve the browser worker's injected console UI assets (content function for its console:script / console:style triggers).",
      "metadata": {
        "internal": true
      },
      "name": "browser::ui-content",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Input of the content function: the console asks for one asset by path.",
        "properties": {
          "path": {
            "description": "The asset path from the trigger config (e.g. `state/page.js`).",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "title": "UiContentInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Output of the content function.",
        "properties": {
          "content": {
            "description": "The asset source, verbatim.",
            "type": "string"
          },
          "content_type": {
            "description": "MIME type the console should serve the asset with.",
            "type": "string"
          }
        },
        "required": [
          "content",
          "content_type"
        ],
        "title": "UiContentResult",
        "type": "object"
      }
    },
    {
      "description": "Attach up to eight base64 files to exactly one input[type=file] selected by CSS. Files are staged privately for the session and removed when it stops.",
      "metadata": {},
      "name": "browser::upload",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "UploadFile": {
            "properties": {
              "data": {
                "description": "File bytes, base64.",
                "type": "string"
              },
              "name": {
                "description": "File name exposed to the page. Path components are rejected.",
                "type": "string"
              }
            },
            "required": [
              "data",
              "name"
            ],
            "type": "object"
          }
        },
        "properties": {
          "files": {
            "description": "Up to eight files, each at most 25 MB decoded.",
            "items": {
              "$ref": "#/definitions/UploadFile"
            },
            "type": "array"
          },
          "selector": {
            "description": "CSS selector that must match exactly one input[type=file].",
            "type": "string"
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "files",
          "selector",
          "session_id"
        ],
        "title": "UploadInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "attached": {
            "format": "uint",
            "minimum": 0,
            "type": "integer"
          },
          "file_names": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "attached",
          "file_names",
          "ok"
        ],
        "title": "UploadOutput",
        "type": "object"
      }
    },
    {
      "description": "One XPath query over HTML; first-or-all; `attr` pulls an attribute else text.",
      "metadata": {},
      "name": "browser::xpath",
      "request_schema": {
        "properties": {
          "adaptive": {
            "description": "relocate elements after a site change via saved identities",
            "type": "boolean"
          },
          "adaptive_domain": {
            "description": "page URL/domain that keys saved identities",
            "type": "string"
          },
          "attr": {
            "type": "string"
          },
          "auto_save": {
            "description": "save matched identities (defaults on when adaptive)",
            "type": "boolean"
          },
          "first": {
            "type": "boolean"
          },
          "html": {
            "type": "string"
          },
          "identifier": {
            "description": "stable key for the saved element",
            "type": "string"
          },
          "query": {
            "type": "string"
          }
        },
        "required": [
          "html",
          "query"
        ],
        "type": "object"
      },
      "response_schema": {
        "properties": {
          "result": {
            "items": {
              "type": [
                "string",
                "null"
              ]
            },
            "type": [
              "array",
              "string",
              "null"
            ]
          }
        },
        "type": "object"
      }
    },
    {
      "description": "Zoom the page in, out, to a level (50-200 %) or back to 100 %, the way the browser's zoom menu does. The viewport keeps its size; the page scales inside it. The level belongs to the loaded document and resets on navigation.",
      "metadata": {},
      "name": "browser::zoom",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "action": {
            "default": null,
            "description": "`in`, `out`, `reset`, `set` (default when `level` is given), or `read` to report the current level without changing it.",
            "type": [
              "string",
              "null"
            ]
          },
          "level": {
            "default": null,
            "description": "Explicit level in percent (50–200); snapped to the ladder.",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ZoomInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "level": {
            "description": "Level in percent now applied to the document.",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "level",
          "ok"
        ],
        "title": "ZoomOutput",
        "type": "object"
      }
    }
  ],
  "triggers": [
    {
      "description": "A console/log/exception entry was captured on a session's page.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::console-event",
      "return_schema": {}
    },
    {
      "description": "A download started, progressed, or finished in a session.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::download-changed",
      "return_schema": {}
    },
    {
      "description": "A session is paused waiting for a human to complete a step (CAPTCHA, 2FA, payment).",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::handoff-requested",
      "return_schema": {}
    },
    {
      "description": "A paused handoff finished (confirmed in page, by call, or timed out).",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::handoff-resolved",
      "return_schema": {}
    },
    {
      "description": "The session's page committed a navigation.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::navigated",
      "return_schema": {}
    },
    {
      "description": "A network request was captured (completed or failed) on a session's page.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::network-event",
      "return_schema": {}
    },
    {
      "description": "The human picked an element in inspect mode.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::picked",
      "return_schema": {}
    },
    {
      "description": "A Chromium session is up and ready.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::session-started",
      "return_schema": {}
    },
    {
      "description": "A Chromium session ended (stopped, idle, or crashed).",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "description": "Config accepted by every `browser::*` trigger binding. The only filter is an optional session-id equality match; unknown fields fail at registration so a misspelled filter key fails loudly instead of silently receiving nothing.",
        "properties": {
          "session_id": {
            "description": "Only deliver events for this browser session.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BindingConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "browser::session-stopped",
      "return_schema": {}
    }
  ]
}