# 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](minting.md):
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](data-plane.md) 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](../using-abx/self-hosting.md). 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.
