Skip to main content
Builtins catalog / nika:image_generate

Media

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

illustration
Text-to-image generation as an asset pipeline, not a blob pipe: images are saved to output_dir: and the output carries paths + dimensions + sha256 (+ a provenance manifest) — image bytes NEVER ride workflow outputs (no base64 in tasks.X.output, logs, or traces · normative). Filenames (normative grammar) · {stem}-{provider}-{modelslug}-{index}-{sha8}.{ext} · every component sanitized to [a-z0-9._-] with no separators; name collisions probe -2..-99; an IDENTICAL payload already on disk is an idempotent re-run (no duplicate). The manifest lands beside the assets as {stem}-{provider}-{modelslug}-{batchsha8}.manifest.json (manifest_version: 1 · resolved request echo · per-image paths/dimensions/sha256 · usage · warnings · caller metadata: — and NEVER a credential: keys live a composition layer away by construction). Output (normalized · every provider + mock) · { provider, model, mode, prompt, revised_prompt, provider_text, created_at, count, images: [{ index, path, filename, mime_type, format, width, height, size_bytes, sha256, provider, model, seed, variant_id, warnings, metadata }], usage: { input_tokens, output_tokens, total_tokens, thoughts_tokens }, cost_usd, warnings, manifest_path, output_dir } — absent usage axes are null, never zero-that-looks-real. cost_usd is the render’s spend, and a non-null one rides with cost_basis, the origin of the figure: either the provider’s own exact report (provider_reported · xai bills cost_in_usd_ticks in the response · 1 cent = 10⁸ ticks), or the engine’s dated price catalog applied to what the provider reported: catalog_rate_x_usage (the model’s catalog token rates × the usage the responses reported, a response that reported none adding its images at the catalog price per image) or catalog_price_x_images (the model’s catalog price per image × the images delivered, when no response reports usage). The price per image is the catalog’s for the requested size class and quality; where the request leaves either open (quality: auto, a size the catalog does not list), the highest the catalog lists for what it could have rendered, never below. A catalog figure also carries cost_as_of, the date its rates were read from the provider’s public price page (YYYY-MM-DD). When neither the provider’s report nor the catalog yields a figure (a model the catalog does not price, or one it prices by tokens only whose response reports no usage), cost_usd is null and both markers are absent — never an estimate dressed as truth, never a zero. The catalog itself is engine data, not language surface (spend-honesty law · 07). Invoke-cost metering (normative) · a tool whose structured output carries a top-level numeric cost_usd reports real spend; engines SHOULD meter it into the run’s cost ledger through the same honest-spend channel infer: rides. Security (engine MUST) · provider endpoints are ENGINE-FIXED constants (never workflow data — the provider egress is engine transport, exactly like infer:; permits.net.http does not govern it, permits.tools + permits.fs DO; the local base URL is ENGINE CONFIG resolved at the composition root — NIKA_IMAGE_LOCAL_URL, default LocalAI’s http://localhost:8080 — still never workflow data) · decode validation is HEADER-ONLY (magic bytes + PNG IHDR / JPEG SOF / WebP VP8-VP8L-VP8X dimensions · no pixel decode → no decompression-bomb surface · declared-vs-actual mismatch is a warning, a non-image payload is a hard error) · atomic writes (temp+rename) · API keys are engine-configured (env/config at the composition root), never workflow args, never logged, never echoed. Warnings (normative shape) · every tolerated-but-lossy mapping lands a stable code: message warning string (size_conflict: · compression_ignored: · seed_unsupported: · quality_folded: · format_mismatch: · gemini_size_class: · xai_size_class: · aspect_remapped: · count_shortfall: · revised_prompt_clamped: · provider_option_unknown: · provider_text_clamped: · …) in warnings — silent degradation is non-conformant. provider_text/revised_prompt are captions, not payload channels (normative) · a provider’s accompanying text MUST be bounded by the engine (the reference engine clamps at 2 000 chars with a provider_text_clamped: warning) — a multimodal response interleaving megabytes of text (or base64-shaped junk) must never ride workflow outputs, the manifest, or the debug: echo unbounded. Result URLs are never fetched (normative) · engines request response_format: b64_json on url-capable wires (openai-compat · xai) and MUST refuse a url-only response with an actionable error — fetching a provider-supplied result URL would reopen the SSRF/net-boundary surface the const-endpoint design closed. The provenance manifest and output carry endpoint_host (which server actually rendered the asset — load- bearing for local, where the endpoint is configurable). Content credentials: detect-and-PRESERVE (normative) · upstream generators sign their returned bytes (OpenAI images and Google’s media models emit C2PA manifests as of mid-2026 · carriage: PNG caBX chunk · JPEG APP11 JUMBF · WebP/WAV RIFF C2PA · MP3 ID3v2 GEOB application/c2pa), and C2PA hard bindings hash the asset’s byte ranges — any engine-side insert into a signed payload converts valid credentials into « present but tampered », which is worse than stripping them. Engines MUST detect these signals before any in-file write, MUST stand their own embed down when credentials are present, and SHOULD surface presence as content_credentials in output + manifest (values are DETECTION labels — an engine that has not cryptographically validated the manifest must never say « verified »). Provider-declared watermarking (e.g. SynthID — detectable only by the vendor) MAY be surfaced as a watermark_declared manifest fact, marked as declared, never as verified. Preserving machine-readable marks is also the EU AI Act Article 50 robustness expectation (in force 2026-08-02). Provenance travels IN the file (PNG) · engines SHOULD embed the deterministic provenance core (tool · engine version · provider · model · clamped prompt · seed — no timestamp, so byte-determinism holds) as a nika tEXt chunk in saved PNG renders — the ComfyUI/InvokeAI interchange practice: a sidecar manifest answers « where does this come from? » only until the file is copied without it. JPEG/WebP have no equally-universal text container and are documented as manifest-only, never silently faked. Throws · NIKA-BUILTIN-IMAGE_GENERATE-001 invalid arguments (incl. the v0.1 RESERVED options · validation_error) · -002 provider unavailable (missing credentials / image plane unwired · validation_error) · -003 provider request failed (network_error · transient: true for 5xx/408/429 + timeout/connection · details.status_code) · -004 no image / malformed response (tool_error) · -005 content policy block (moderation / safety finish reasons · security_error · never transient · details {finish_reason? · moderation_details?}) · -006 save/manifest write failed (tool_error) · -007 image validation failed (magic mismatch · dimension/byte bounds · tool_error). Plus the boundary NIKA-SEC-004 (an output_dir: outside permits.fs.write).

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:image_generate. Specification revision: 5cd95cd25c0f.

Documentation

Guides, reference contracts and working examples.

Language spec

the nine-key envelope, Apache-2.0. The contract these docs explain.

Engine source

Rust, AGPL-3.0-or-later. Every commit public.

TypeScript SDK

Use one typed lifecycle locally or against authenticated nika serve HTTP.

Editor extension

The editor extension, frozen at 0.120 and not qualified with 0.124: use nika lsp and the JSON Schema.

Homebrew tap

brew install supernovae-st/tap/nika for the latest tagged CLI release.

SuperNovae

The Paris studio crafting Nika. 🦋