⚙ /v1/scrape · /v1/browse · /v1/document · /v1/execute

Tools — substrate, not resold APIs.

Open-source primitives for the agent's hands. Cheerio scrape, Playwright browse via BullMQ queue, Readability parse, and a sandboxed execute for JS / Python / bash. We don't proxy LLMs, search APIs, or commercial proxy networks — bring your own keys via vault.

We charge for the infra surface — storage, compute time, queue, network egress. Not for a markup on a third-party SaaS we resell.

Scrape — static HTML

POST /v1/scrape Bearer required

Cheerio-based static-HTML extraction. 30× cheaper than browse — use this when the page returns full HTML without JS rendering.

FieldTypeDescription
urlrequiredstringThe URL to fetch.
selectorsoptionalobjectCSS selectors mapped to output keys: {"title": "h1", "body": "article"}.
headersoptionalobjectExtra request headers.

Browse — JS-rendered pages

POST /v1/browse Bearer required

Playwright-based browse. Queued via BullMQ to a single in-process worker. Returns when the page settles or when a selector matches.

FieldTypeDescription
urlrequiredstringTarget URL.
wait_foroptionalstringCSS selector to wait for before extracting (e.g. article.loaded).
screenshotoptionalbooleanInclude a full-page screenshot in the response (base64).
selectorsoptionalobjectCSS selectors → output keys.

Browse jobs return a job_id. Poll /v1/jobs/:id for status, or pass ?wait=true for synchronous return (capped at 60s).

Document — Readability + plain-text

POST /v1/document Bearer required

Mozilla Readability + plain-text conversion. Pass HTML or a URL; receive cleaned title, byline, and body text.

FieldTypeDescription
urloptionalstringURL to fetch + parse. Either url or html required.
htmloptionalstringRaw HTML to parse without fetching.
formatoptional"text" · "markdown"Output shape. Default text.

Execute — sandboxed runtime

POST /v1/execute Bearer required

Run code in a sandboxed runtime. Node vm for JavaScript; isolated child_process for Python and bash. Time-limited; resource-capped.

FieldTypeDescription
runtimerequired"javascript" · "python" · "bash"Sandbox to run in.
coderequiredstringThe script source.
envoptionalobjectEnvironment variables. Vault secrets are auto-injected when you reference them by name via {vault: ["openai-key"]}.
timeout_msoptionalintDefault 10000, max 60000.
stdinoptionalstringStdin to feed the process.
example · embed via OpenAI, store in memory
curl -X POST https://api.agenttool.dev/v1/execute \
  -H "Authorization: Bearer $AT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "runtime": "python",
    "code": "import os; from openai import OpenAI;\nc = OpenAI(api_key=os.environ[\"OPENAI_KEY\"]);\nprint(c.embeddings.create(input=\"hi\", model=\"text-embedding-3-small\").data[0].embedding[:8])",
    "env": { "vault": ["openai-key"] },
    "timeout_ms": 15000
  }'

Why execute exists. The agent needs to call paid third-party APIs (OpenAI, Brave, Anthropic, etc.). We don't proxy those — we'd become a bottleneck and a privacy hole. Instead, the agent stores its keys in vault and calls out from execute. We never see the traffic.

Jobs (queued execution)

GET /v1/jobs/:id Bearer required

Poll a queued job (browse, long-running execute). Returns status, progress, and result on completion.

What we dropped

Earlier versions of agenttool included /v1/search (Brave / SerpAPI proxy) and a Bright Data proxy network. Both were paid-third-party-API resale, which violates promise 6 of IDENTITY-ANCHOR.md. They were dropped in the consolidation. The substrate that remains — scrape, browse, document, execute — is open-source primitives running on our infra.

If you want search, store a Brave/SerpAPI key in vault and call it from /v1/execute. You pick the provider; we never see the query.

What to read next