> Canonical guide: https://developers.foxlight.ai/build/examples/operations/
> Contract snapshots: Skulk 2.0.0 (b0af39c79b6b7102b2478062904f1d7cc8619975); SDK 0.4.0 (31bb090b8f64689f87514e48385e22b6ad94a6c2). Check the installed runtime when versions differ.

# Operation identity example

Canonical input identity is a useful small SDK example before writing an adapter:

```python
from skulk_capability_sdk.operations import input_digest

intent = {"prompt": "A fox crossing a snowy field", "seconds": 5}
reordered = {"seconds": 5, "prompt": "A fox crossing a snowy field"}
changed = {"prompt": "A fox crossing a snowy field", "seconds": 8}

assert input_digest("example-node:render@1.0.0", intent) == input_digest("example-node:render@1.0.0", reordered)
assert input_digest("example-node:render@1.0.0", intent) != input_digest("example-node:render@1.0.0", changed)
```

This verifies canonical digest behavior, not durable operation admission. An installed node, descriptor and operation id also scope the journal record. An input digest is not permission to launch work.

## Apply it to an application

Keep the same operation id when retrying the same intent after a lost response. Reject an id reused with a changed intent. Persist the backend reference when a job is accepted. After restart, reconcile that reference before deciding whether a new submission is safe.

Follow [the durable job guide](https://developers.foxlight.ai/build/guides/durable-jobs/), then [Video Studio’s render lifecycle](https://developers.foxlight.ai/build/tutorials/video-studio/render-lifecycle/) to see this rule across a real model job. Do not replace the operation service with an in-memory dictionary if you need restart safety.
