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 andnika catalog --tools --json for the installed implementation; a registry declaration is not a runtime qualification.
Usage and behavior
illustration
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).
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: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. 🦋