Guarded mutations
Every tool that changes the Live Set uses the same contract. A plan made against one state of the Set can only run against that same state.
The contract
- Observe. Read
stateVersionfromget_live_state, or from the context tool the mutation names in its description. - Plan. Call the mutation with
expectedStateVersion. IfdryRunis omitted ortrue, nothing changes. The result is the exact plan plus aconfirmation:{ token, planHash, expiresAt }. - Execute. Call the mutation again with the same arguments, plus
dryRun: false, theconfirmationTokenand theplanHash.
Execution is refused when:
- the Set's state version has moved since the plan,
- the plan, rebuilt from a fresh observation at execution time, no longer hashes to
planHash, - the token has already been used, or
- the token has expired. Tokens last 60 seconds.
Many plans also carry the observed objects themselves: the exact device, clip, notes or routing choice. The bridge rechecks that snapshot inside Live before it writes.
Read back
Queued bridge work is refused after cancellation, expiry or disconnection. A running operation may still finish. After a timeout or cancellation, re-read the affected objects before making a new plan; never blindly retry a transmitted write. See Cancel agent work.
A mutation's acknowledgement is not acceptance. Read the changed object again and compare it with the plan. Some UI-driven changes don't advance the bridge's state counter, so a readback is the only proof.
Destructive operations
Tools that can remove content or overwrite device state are annotated destructiveHint: true. Tools lists them under *Destructive mutations*. With delete_session_object, deleting a track or scene that holds clips or devices also requires allowContent: true. Deleting a Return Track always requires it. The last remaining scene cannot be deleted.
undo and redo are guarded mutations too. get_history_state reports whether each one is available, and a plan is refused when the requested step isn't.
Metadata edits
set_preset_metadata and set_browser_item_metadata change local tags and favorites, not the Live Set. They take expectedMetadataRevision instead of a state version, and they use the same dry-run and confirmation steps.
Fail closed
When Live's API doesn't expose a property or a setter, the tool says so in its result, or the plan refuses. It never pretends a write happened. For example, set_track_freeze_state plans and verifies, but Live 12.4.5 has no setter for Track.is_frozen, so execution fails with that reason.