> ## Documentation Index
>
> Fetch the complete documentation index at: https://lithi.ai/llms.txt
>
> Use this file to discover all available pages before exploring further.

---
title: Start work from an event
description: >-
  Verify where an event came from, freeze the input it points at, and give the run one
  occurrence identity so duplicate, late or reordered events cannot charge you twice.
route: /docs/compute/automation/event-triggers
page_id: docs-compute-automation-event-triggers
page_type: howTo
content_layer: guided documentation
surface_profile: guided_docs
audience: Engineers triggering Compute work from their own system events
voice: D
reader_question: How do I start Compute work from an event without running it twice?
primary_action: Understand occurrence identity and replay
source_locale: en-US
source_status: APPROVED
source_version: docs-compute-automation-event-triggers-en-us-2026-09-05-v1
last_updated: '2026-09-05'
robots: index
claim_registry_pinned: true
claim_registry_resync: "npm run governed:tsx -- scripts/build-compute-public-claim-registry.ts --write"
---

## Before you start

You need a scoped automation identity, one workflow that already runs correctly by hand, and a source of events you control.

You also need a rule for which events matter. Event triggers fire on your data changing, and data changes far more often than work needs to run.

## Verify where the event came from

Treat every inbound event as a claim until you have checked it. An event that arrives at your endpoint is not evidence that your system sent it.

Check the sender, the signature and the time before you act. Then check that the event refers to something your automation is actually allowed to read.

An event you cannot attribute is not a trigger. Drop it, record that you dropped it, and do not start paid work on it.

## Freeze the input before you run

An event tells you something changed. It does not tell you what the data looks like now, and it will keep changing while you decide.

So pin the input before admission. The snapshot carries a `version_id` and a `content_sha256`, and the run reads those exact bytes for its whole life.

That pair is what makes the run explainable later. If someone asks which data produced a result, you answer with the snapshot, not with a timestamp. See [how an immutable snapshot is pinned](/docs/compute/inputs/immutable-snapshots) if the two values ever disagree.

## Give the run one occurrence identity

Every occurrence has a stable identity derived from the schedule, its version and the occurrence you intended:

```text
occurrence_key = H(schedule_id || version || intended_occurrence)
```

Derive that identity from the event, not from the moment you happened to process it. Two deliveries of the same event must produce the same identity.

That is the whole defense against double-charging. An exact replay of the same identity and the same payload digest returns the prior result rather than starting new work.

## Handle duplicate, late and reordered events

Assume all three will happen, because at-least-once delivery is normal and ordering is not promised.

- **Duplicate.** The same identity with the same digest returns the earlier result. Nothing new is admitted and nothing new is charged.
- **Equivocation.** The same identity with a different digest is refused. That is a real signal: two different requests are claiming to be the same occurrence.
- **Late.** A stale attempt cannot advance state. An event that arrives after its occurrence resolved is recorded, not replayed into it.
- **Reordered.** Compare versions rather than arrival order. A lower version never overwrites a higher one.

If you see equivocation, do not retry. Find out which of the two payloads is the one you meant, and send that as a deliberately new occurrence.

## Confirm success

Fire one real event and follow it end to end. You should see one occurrence, one fresh quote, one admitted job and one result.

Then fire the same event again on purpose. A correct integration produces the same occurrence identity and no second charge.

Keep the receipt reference from the first run. It is what you quote to support if the two runs ever look different.

[Understand occurrence identity and replay](/docs/compute/automation/occurrences-and-replay)
