Effects

An effect is an off-chain process that watches the event spine and produces derived output, such as a rendered image or generated data. Effects are a sibling convention, like the minter spine: they define no events of their own, add no extension, and do not change the token core. Rendering is the reference effect.

Effects produce derived, re-creatable output, never source bytes. A lost render is a re-render. The protocol already emits every event an effect triggers on, so effects live outside it.

The model

An effect is a key, a set of triggers, and a transform.

  • effectKey: a lowercase, dot-namespaced name such as render, inference.caption, or world.rebuild. It is the unit of subscription, storage, and binding.
  • outputs: named artifacts. Each outputKey names one content-typed artifact, such as image, traits, video, or model. An effect declares the type of each output.
  • inputsHash: keccak256(contentHash, canonical tokenData, environmentId). It identifies one run.

Each output has a deterministic address:

{chainId}/{address}/{tokenId}/{effectKey}/{inputsHash}/{outputKey}

A deterministic effect is idempotent: the same inputs produce the same artifact at the same address. A non-deterministic effect uses the same addressing and resolves latest-run-wins.

Triggers

Trigger Spine signal
mint Transfer from 0x0
parameter change TokenParamConfigured or ContractParamConfigured
schema change ParamSchemaConfigured
ownership change Transfer
manual an operator request, recorded but not an event

Binding output into metadata

  • render.image becomes the token image, but only when no explicit image field is set.
  • render.traits merges into attributes, unioned with the on-chain value winning on a trait_type conflict.
  • Any other output is a data plane artifact: listed in the artifacts manifest under {effectKey}/{outputKey} and served with its declared content type. Its provenance is source: "effect:<key>", status: "off-chain".

Optional write-back

After a run, a runner can post a commitment on-chain as a parameter, effect.<effectKey>.<outputKey>, holding keccak256(artifact) or a locator. This uses a parameter schema with Address authorization naming the runner. The output then becomes chain-verifiable, and a project that needed a live service can become freezable: run once, write the commitment back, and lock. Write-back is never required.

The reference render effect

The render effect triggers on mint, on output-affecting parameter or schema changes, and on ownership change when output depends on the owner. Its transform loads the same document a collector sees in a headless browser, waits for abx.done() (or render.captureDelay, or a default timeout), and captures the output at render.aspectRatio. Its outputs are image, the still, and traits. The engine and its versions are recorded as the environmentId in the inputs hash.

The reference runner

The runner is a long-running service that subscribes to the spine, usually a second container beside the resolver. Because addressing is by inputsHash, it is stateless: its work is any address its storage is missing, a crash-restart re-derives, and duplicate runners are idempotent. Run it locally with abx effects, render a project's missing stills with abx render <address>, or host it with abx deploy-effects. The only key a runner holds is a low-stakes posting key under Address authorization, never an owner key.