http.request
Schema
Input = { url: string, method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS', // default 'GET' headers?: Record<string, string>, body?: unknown, // string sent as-is; anything else JSON.stringify'd (sets Content-Type) json?: boolean, // default true — try to parse the response as JSON timeoutMs?: number, // 1000-60000, default 20000}
Output = { status: number, ok: boolean, url: string, // final URL after redirects headers: Record<string, string>, data?: unknown, // parsed JSON, only present when json=true and it actually parsed body: string, // raw text, capped at 1MB truncated: boolean, durationMs: number,}This is the generic escape hatch: any REST or JSON API an agent needs to call that isn’t covered by
a dedicated skill. It never throws on a non-2xx response — that’s for the caller to check via ok /
status — it only throws on a genuine network failure or timeout.
http.request is one of the five world-acting skills:
an agent’s tool loop calling it directly is refused — it reaches an arbitrary endpoint in the being’s
name, so a decision Signal goes to your desktop instead, and the call only actually runs once you tap
“Do it”.
Example
curl -s -X POST http://localhost:4000/api/studio/skills/invoke \ -H 'content-type: application/json' -b cookies.txt \ -d '{"name":"http.request","input":{"url":"https://api.github.com/repos/vercel/next.js","method":"GET"}}'{ "ok": true, "output": { "status": 200, "ok": true, "url": "https://api.github.com/repos/vercel/next.js", "headers": { "content-type": "application/json; charset=utf-8" }, "data": { "full_name": "vercel/next.js", "stargazers_count": 128000 }, "body": "{\"full_name\":\"vercel/next.js\", ...}", "truncated": false, "durationMs": 244 }}A stricter sibling that isn’t in the canonical list
The registry also ships http.json: same idea, but it always parses query params separately
(query: Record<string, string|number|boolean>), and — unlike http.request — throws on a
non-2xx status or a non-JSON body, so a tool loop sees a clean error instead of having to check
ok itself. It isn’t one of the 25 canonical BUILTIN_SKILLS, so no generator step can reference it
yet by validation, but it is registered and invokable via POST /api/studio/skills/invoke today.
http.json takes the same arbitrary method and body as http.request, so it is gated exactly the
same way: it’s in WORLD_ACTING_SKILLS (packages/skills/src/registry.ts) and declares
world-acting in BUILTIN_CAPABILITIES (packages/skills/src/plugins/builtin-capabilities.ts), so
an agent’s tool loop calling it directly is refused just like http.request — a decision Signal
goes to your desktop instead, and it only runs once you tap “Do it”. This was a deliberate fix:
gating one sibling without the other would have let an agent refused a POST on http.request
simply switch to http.json and send it anyway.