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

# Durable _operations_

A unary invocation is an admission-sized interaction. A job that renders for minutes belongs in `operations`: reserve durable intent, return an operation identity, and let a bounded worker submit and observe the job.

## The lifecycle

`OperationService` exposes `start`, `status`, `list`, `log`, `plan`, and `cancel` verbs. `OperationJournal` stores intent and outcomes. `OperationRunner` performs background submission and observation through your `JobAdapter`. `OperationLogs` stores bounded, offset-addressed log pages.

| State         | Meaning                                                            |
| ------------- | ------------------------------------------------------------------ |
| `queued`      | Intent was reserved; work is awaiting execution                    |
| `running`     | The backend job is being observed                                  |
| `succeeded`   | The operation completed with a validated result                    |
| `failed`      | A known failure was recorded                                       |
| `cancelled`   | Cancellation reached its terminal outcome                          |
| `interrupted` | Restart ended the original worker lifecycle; observation is needed |

## Supply a backend adapter

Implement `JobAdapter` for your actual job system. The adapter handles submission, observation, and cancellation. Persist the external job reference when known. Redact log data before it enters the SDK’s retained log store.

Read operations never launch work. Effect verbs have a separate authority check. Make a plan describe the normalized intent and bounds that approval will bind to; a plan is not execution.

## Idempotency and uncertainty

Operation identity is scoped to the installed node, exact descriptor, and canonical input digest. Repeating an id with the same input returns the existing status. Reusing it for different input is refused. Retention pruning does not make an old operation id available again.

Submission tracks `pending`, `uncertain`, and `accepted`. If a backend might have accepted a request but no response arrived, record uncertainty. Automatically submitting again can create a duplicate resource or job.

## Restart and cancellation

Restart marks queued and running rows `interrupted`; it does not replay effects. Reconcile against the backend’s actual state. Cancellation goes through the backend adapter. Never signal a process group that the operation does not exclusively own.

## Output and retention bounds

Results are capped at 8 KiB. Status input echoes are capped at 24 KiB, log chunks at 8 KiB, and list pages at 16 entries. Larger media needs an artifact reference. Bounds apply before bytes enter the wire envelope; do not truncate a semantically complete result to make it fit.

[Operations API reference](https://developers.foxlight.ai/build/sdk/reference/operations/) describes adapter and service signatures, including failure conditions.
