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 andnika catalog --tools --json for the installed implementation; a registry declaration is not a runtime qualification.
Usage and behavior
HTTP request + content extraction (reached viainvoke: 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
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.
Related concepts
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.