Drex
Browser runs
A browser run gives an agent a task and a website: it browses in a cloud browser of its own, only on the origins you allow, and returns an answer. nace browser run starts one and waits for it. A run is billed once, when it ends: its Drex Max and LLM tokens and its browser seconds, never more than --max-cost. Reading and listing runs is free; a run cancelled while queued isn't charged, one cancelled while running is charged its browser seconds so far. See Browser runs for prices, the sites runs may not browse, limits and retention.
Run a task
nace browser run "Find the price of the blue ceramic mug" --start-url https://shop.example.com/
nace browser run "Find the cheapest 1 TB SSD" --start-url https://shop.example.com/ \
--answer-schema '{"type": "object", "properties": {"name": {"type": "string"}, "price": {"type": "number"}}, "required": ["name", "price"]}' \
--max-cost 0.1 --max-seconds 300
nace browser run "Read the opening hours" --start-url https://example.com/ --no-wait # prints brun_...nace browser run TASK takes the task in plain language, 1 to 4000 characters. It starts the run, prints browser run <id> queued on stderr, and waits until the run ends:
- Stdout gets the answer: the structured
answeras JSON when you gave--answer-schema, else the agent'sanswer_text. - Stderr gets
browser run <id> <status>, with how it ended in parentheses when that says more (partial (blocked_login)), then the reason, thefinal url:and thecost:in US dollars. - With
--json, stdout gets the whole run instead:id,status,answer,answer_text,outcome,final_url,steps,usage,limitsand the rest.
It exits 0 when the run succeeded. A run that ended partial, failed, cancelled or timed_out is printed the same way, then error: browser run <id> ended <status> [<outcome>] goes to stderr and it exits 1. A wait that runs out exits 1 with the run id on stdout (the run with --json); the run keeps going, so read it later with nace browser get.
| Flag | What it does |
|---|---|
--start-url URL | Required. The page to open first: an http:// or https:// URL on a public host, on the default port. |
--allow ORIGIN | An origin the browser may load, such as https://shop.example.com (no path). Repeatable, up to 20. It must include the start URL's origin. Without it, the run may load only the start URL's origin. |
--answer-schema SCHEMA | A JSON Schema for a structured answer, as a JSON object: a file path, @FILE, inline JSON, or -. At most 16 KB, without pattern or patternProperties. An answer that doesn't match fails the run as answer_invalid, charged. |
--max-cost USD | The most the run may be charged, in US dollars: at least 0.01 and at most 1 (default 0.04). Anything else exits 2. |
--max-seconds N | How long the run may browse, 1 to 1800 seconds (default 600). |
--max-llm-calls N | How many planning and reading calls the agent may make, 1 to 100 (default 20). |
--metadata KEY=VALUE | A string of your own, returned with the run. Repeatable, up to 20. |
--idempotency-key KEY | The same key returns the same run instead of starting another; the same key with a different task or flags is refused with 409 idempotency_conflict. Without it, nace sends a new key on each run, so retries inside one run never start a second one. |
--no-wait | Print the run id (the queued run with --json) and return at once. |
--wait-timeout SECONDS | How long to wait for the run (default 3000), which outlasts any run: Drex times out a run queued for 15 minutes or browsing past --max-seconds. |
A --max-seconds or --max-llm-calls outside its range, a --start-url that isn't http:// or https://, a --metadata without =, an --answer-schema that isn't a JSON object, and a negative --wait-timeout exit 2 before anything is sent. Drex refuses a run with 422: origin_blocked for a site runs may not browse, invalid_request for anything else it doesn't take. Past 20 queued or running runs, or past the account's daily spending limit for runs, it answers 429 (rate_limited or daily_spend_limit).
Read a run
nace browser get brun_...
nace browser artifacts brun_...| Command | What it prints |
|---|---|
browser get RUN_ID | The run as nace browser run prints it, with steps in --json. It exits 0 whatever the run's status, so check it: a run still queued or running prints only its status line. |
browser artifacts RUN_ID | One line per artifact the run reported, <kind> step <n> <url>. Each link works until its expires_at. An empty list says no artifacts on stderr. With --json, {"items": [...]}. |
A run's task, answer, steps and evidence are erased 48 hours after it ends; the run, its status and its usage stay, with an empty task.
List runs
nace browser list
nace browser list --status running --allnace browser list prints one line per run, newest first, without its steps: brun_... <status> <cost> <created_at> <task>, the task cut to 60 characters and the cost - until the run ends.
| Flag | What it does |
|---|---|
--status {queued,running,succeeded,partial,failed,cancelled,timed_out} | Only runs in this status. |
--limit N | Runs per page, 1 to 50 (default 20). A larger number exits 2. |
--cursor CURSOR | Start at this page: the next_cursor of the page before. |
--all | Every run, across every page. Not with --cursor. |
--json | Print {"items": [...], "next_cursor": ...}. |
Without --json, when more pages follow, stderr says more runs: --cursor <next> (or --all). An empty list says no runs on stderr.
Cancel a run
nace browser cancel brun_...nace browser cancel <run_id> stops a queued or running run and its browser. Stderr says browser run <run_id> cancelled; stdout stays empty, or gets {"id", "object", "status"} with --json. Cancelling a cancelled run succeeds again; any other run that already ended fails with 409 run_finished. A run cancelled while queued isn't charged; one cancelled while running is charged its browser time so far.