Skip to main content
Builtins catalog / nika:fetch

Network

Tool family from the canonical registry.

invoke

Call this builtin through the invoke verb.

Read this contract

This reference preserves the specification at the revision linked below. Source examples are fragments: their surrounding tasks, inputs and permissions are not supplied here. Consult engine status and nika catalog --tools --json for the installed implementation; a registry declaration is not a runtime qualification.

Usage and behavior

HTTP request + content extraction (reached via invoke: because fetching a URL is calling a tool, not a verb · see 02-verbs.md).
illustration
Payload exclusivity (normative) · at most ONE of body · form · multipart; form/multipart require a body-bearing method (POST · PUT · PATCH) and OWN their content-type (a user-supplied content-type header alongside them is a refused conflict). The data-as-code sink (normative pointer · NEP-0006) · a fetch whose resolved URL path names a code-bearing class (serialized-executable · script/interpreter · executable binary/module · the closed list in 10-authority.md §the data-as-code sink) is refused at check (NIKA-SEC-008) and at run (NIKA-SEC-004) unless the task declares the read inert (lift: [{law: data-as-code, because: "…"}] · the honest door · it never lifts the host boundary or the SSRF floor). traverse semantics (normative) · same-origin BFS from url · fragment-stripped dedup · per-page output is the fixed page digest {url, status, title, description, headings ≤16, links ≤30, images ≤24, colors ≤20, text ≤4000} · crawl output is {url, page_count, pages[], assets: {images ≤40, colors ≤30}} · robots.txt honored by default (RFC 9309 group semantics · User-agent: * Disallow prefixes · the probe’s outcome follows RFC 9309 §2.3.1: a 4xx is unavailable and allow-all · a 5xx or a transport failure is unreachable and a COMPLETE DISALLOW, refused loudly and transiently before a page is spent · rules are per origin, so a root that lands on another origin re-reads that origin’s robots before any descendant is enqueued · a disallowed ROOT is a loud failure · disallowed descendants are silently skipped) · the page digest passes the same depth admission every HTML mode passes (a depth-bomb root is a loud failure · a depth-bomb descendant is an honest {url, status, error} entry) · discovery reads every link a page carries (the links ≤30 facet is a preview, never the frontier’s bound) · every hop rides the engine’s SSRF defense · a failing descendant page becomes an honest {url, status|error} entry and the crawl continues · the effect certificate bounds logical GET calls per invocation: max_pages with literal respect_robots: false, otherwise max_pages + 2 (the seed’s robots, then at most one probe of the landed root’s different origin). An unchanged origin needs only one robots probe, but a literal initial URL and the same-origin link filter do not exclude a root redirect; an unknown final origin therefore requires the two-probe bound. Dynamic page bounds use the valid runtime maximum 25, hence at most 27 logical GETs (25 with literal robots false); dynamic robots options reserve both probes. Invalid resolved options still refuse before any GET. These are logical calls, not a bound on physical transmissions, redirect hops or transport retries; aggregate saturation is not a proven global bound. crawl/http/website are intentions, not tools — they all route HERE (no nika:crawl). Non-2xx is failure by default (normative) · without response, a non-2xx response throws NIKA-BUILTIN-FETCH-001 (category: network_error · transient: true for 5xx/408/429 · false for other 4xx · details.status_code carries the status) — with the effect-safe carve-out (normative · issue #1371): a keyless effect-capable method (POST · PUT · DELETE · PATCH without an idempotency-key header) is transient: false on EVERY failure, status-table and transport alike — the failure may be ambiguous (the server may have committed before the socket dropped or the error was emitted) and a blind retry replays the effect; a declared retry: on such a call is the static NIKA-SEC-016 refusal (05 §the effect-safe retry law). GET/HEAD and keyed calls keep the status table. To poll a pending resource · the jq-error pattern (08 H19), not status-code inspection. Redirects follow up to an engine cap · the FINAL status decides. Status as data (normative) · a present response opts into an exact accepted-status set. Every listed status produces the same output shape, including a 2xx only when explicitly listed:
body is the result of the existing mode extraction, with its existing failure rules. url identifies the final response route after redirects, serialized as an HTTP(S) URL without userinfo, query or fragment; it is null when that identity is unavailable or invalid. An engine MUST NOT substitute the requested URL for an unknown final destination. Response headers are not emitted. The presence of response, never the status itself, determines this output shape. Without response, the extracted body and existing diagnostics are unchanged. An unlisted status remains NIKA-BUILTIN-FETCH-001, with the existing effect-safe transient classification and details.status_code; an opted-in call additionally reports details.accepted. Transport, permission, SSRF, TLS, redirect-limit, body-limit and extraction failures do not become successful observations. An extraction failure after a received response also carries its known details.status_code and details.accepted; a transport failure MUST NOT fabricate a status. A missing final URL alone does not discard a known status or body. An accepted status is a successful observation, never a skipped or recovered failure, and does not trigger retry:. Successful sibling outputs therefore remain durable in the absence of another unhandled failure. An unaccepted status or other unhandled failure retains the engine’s existing failure and output-quarantine behavior. Declaring a keyless effect-capable call’s error status as data does not prove whether the server committed its effect, and does not relax the effect-safe retry law. Followed redirect statuses are intermediate responses; only the final status is compared with accept. Literal malformed policies refuse at check. Resolved policies, including agent tool calls, are revalidated before any HTTP request. Dynamic values are unknown at check, never permission: invalid literal siblings still refuse. Unknown keys, a present null, empty or oversized sets, duplicates, non-integers and out-of-range statuses are errors, never silently coerced, deduplicated or ignored. For a health probe, use mode: raw and response: { accept: [200, 404] }. A downstream task binds the observed status through with before its when condition reads it:
illustration
Its 404 follows the success edge; a failure edge is reserved for actual failures. JSON extraction of an HTML error body still fails, and a HEAD or 204 response with an empty body remains an empty string under mode: raw. Security (engine MUST) · SSRF defense (reject private-net + cloud-metadata 169.254.169.254 unless configured) · honor task-level timeout · reject self-signed TLS by default.

Arguments

Pass the values required by the tool contract.

Permissions

Understand authority before granting effects.

Errors and recovery

Read diagnostics and choose a recovery policy.

Workflow templates

Put the fragment inside a complete workflow.

Contract provenance

Read the pinned specification · Canonical registry. Tool identity: nika:fetch. Specification revision: 480f5b80cb77.