Skip to content

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

Terminal window
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.requestthrows 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.