4 Tool reference
30 tools, generated from the running registry so it cannot drift.
Signatures and descriptions come from the source; regenerate with ./scripts/gen_docs.py after changing any tool.
4.1 Index
- Discovery —
lom_search,lom_describe,lom_canonical_path,lom_count,lom_types,lom_ping - Read / write —
lom_get,lom_set,lom_call,lom_get_batch,lom_set_batch,lom_transaction - MIDI notes —
clip_get_notes,clip_add_notes,clip_modify_notes,clip_remove_notes - Browser —
browser_list,browser_load - Automation —
clip_envelope_get,clip_envelope_insert_step,clip_envelope_clear - Arrangement —
arrangement_list_clips,arrangement_create_clip,arrangement_duplicate_clip - Observers —
lom_observe,lom_unobserve,lom_observers,lom_unobserve_all,lom_poll_events - Other —
clip_set_warp_markers
4.2 Discovery
4.2.1 lom_search
lom_search(query: str | None = None, type: str | None = None, root: str = 'live_set', max_results: int = 50, max_depth: int = 6)Find LOM paths by name and/or type, without walking the tree by hand.
query - substring of the object’s name, case-insensitive (“bass”, “drums”) type - substring of the type (“Track”, “Clip”, “DeviceParameter”)
Give at least one. Examples: lom_search(query=“bass”) -> live_set tracks 3 lom_search(type=“DeviceParameter”) -> every automatable parameter
Check truncated - the walk is bounded so it cannot freeze Live’s UI. The browser is deliberately excluded (6000+ samples); use browser_list.
4.2.2 lom_describe
lom_describe(path: str = 'live_set', include_values: bool = True)Discover everything at a Live Object Model path: properties (with current values), navigable children (with counts), and callable functions.
START HERE. This is how you find out what exists rather than guessing.
Returns an unavailable map for members that exist on the type but not on THIS instance - e.g. a MIDI track has no input_meter_left, only the main track has a crossfader. That is correct Live behaviour, not an error.
Paths are space-separated and zero-indexed, e.g. “live_set tracks 0 mixer_device volume”. Roots: live_set, live_app, app_view.
4.2.3 lom_canonical_path
lom_canonical_path(path: str)Resolve an alias path to where the object actually lives.
Many paths point at the same object: “live_set view selected_track” is whichever track is selected right now. This returns the stable form (“live_set tracks 3”) which is what you want to store or reuse. is_alias says whether the input was one.
4.2.4 lom_count
lom_count(path: str, child: str)Count items in a Live collection, e.g. lom_count(“live_set”, “tracks”).
4.2.5 lom_types
lom_types()Census of every LOM type Live exposes and every member of each.
This is the map of the entire addressable surface. Large - prefer lom_describe for day-to-day navigation.
4.2.6 lom_ping
lom_ping()Check the connection to Ableton Live and whether the engine loaded.
4.3 Read / write
4.3.1 lom_get
lom_get(path: str, property: str, offset: int | None = None, limit: int | None = None)Read one property from a Live object.
Example: lom_get(“live_set”, “tempo”) -> 120.0 lom_get(“live_set tracks 0”, “name”) -> “1-MIDI”
A list longer than 64 reports only {“vector”: true, “count”: N}, which hides exactly the long lists worth reading. Pass offset/limit to page through one - Drift’s 66 parameters, a rack’s chains:
lom_get("live_set tracks 0 devices 0", "parameters", limit=25)
lom_get("live_set tracks 0 devices 0", "parameters", offset=25, limit=25)
The window returns items plus count, returned and truncated. Max 512 per page; a limit above that is clamped, not refused.
Use lom_describe first to discover valid member names; do not guess.
4.3.2 lom_set
lom_set(path: str, property: str, value: Any)Write one property on a Live object. Wrapped in a native undo step, so the user can revert it with Cmd-Z.
Example: lom_set(“live_set”, “tempo”, 128) lom_set(“live_set tracks 0”, “name”, “Drums”)
For a property that holds a Live OBJECT rather than a scalar, name it by path with {“path”: “
lom_set("live_set view", "selected_track",
{"__path__": "live_set tracks 3"})
Use lom_describe first to discover valid member names; do not guess.
4.3.3 lom_call
lom_call(path: str, function: str, args: list[Any] | None = None, confirm: bool = False, offset: int | None = None, limit: int | None = None)Call a function on a Live object. Wrapped in a native undo step.
Example: lom_call(“live_set”, “create_midi_track”, [-1]) lom_call(“live_set tracks 0 clip_slots 0”, “fire”)
Some functions take a Live OBJECT, not a scalar - a path string reaches them as a str and Live rejects the call (“did not match C++ signature”). Pass {“path”: “
lom_call("live_set", "move_device",
[{"__path__": "live_set tracks 5 devices 0"},
{"__path__": "live_set tracks 7"}, 0])
Markers work anywhere in args, including nested in lists/dicts. A plain string is never reinterpreted as a path, so ordinary string args are safe.
When the return value is a long list it reports only its count. Page it with offset/limit - this is how you read a plugin’s real parameter list, which Live knows even while parameters exposes one entry:
lom_call(dev, "get_parameter_names", limit=50) -> 50 of 2362 names
When the call returns a Live object that sits directly under path (a new track, a new clip), result_path gives its path, e.g. create_midi_track -> “live_set tracks 5”.
Destructive functions refuse to run unless confirm=True - anything named delete_, remove_ or clear_*, plus crop. Ask the user before setting it.
4.3.4 lom_get_batch
lom_get_batch(specs: list[dict[str, Any]])Read many properties in ONE round trip instead of N calls.
specs: [{“path”: “live_set”, “property”: “tempo”}, {“path”: “live_set tracks 0”, “property”: “name”}, …]
Never fails as a whole - each result carries its own ok/error, so one unavailable property does not lose the other reads.
4.3.5 lom_set_batch
lom_set_batch(specs: list[dict[str, Any]], stop_on_error: bool = True)Write many properties inside one undo step.
specs: [{“path”: …, “property”: …, “value”: …}, …] See lom_transaction for the undo-grouping caveat.
4.3.6 lom_transaction
lom_transaction(ops: list[dict[str, Any]], stop_on_error: bool = True, rollback_on_error: bool = False)Run several ops as one undo step, so the user gets one Cmd-Z rather than N.
ops: [{“op”: “set”, “path”: …, “property”: …, “value”: …}, {“op”: “call”, “path”: …, “function”: …, “args”: […]}]
UNDO CAVEAT (measured on Live 12.2.7, not assumed): grouping does NOT cover automatable parameters. tempo, mixer volume, mute and device parameters each form their own undo step in Live even inside an explicit one. Track name, colour and time signature do group. The undo field in the result restates this.
NOT a database transaction - Live has no intra-step rollback, so if op 5 fails, ops 1-4 have already applied. rollback_on_error defaults to FALSE on purpose: it is a mutation on an error path, and if the step captured nothing it would revert whatever the user did beforehand. Prefer to inspect the result and let the user press Cmd-Z.
4.4 MIDI notes
4.4.1 clip_get_notes
clip_get_notes(path: str, from_pitch: int = 0, pitch_span: int = 128, from_time: float = 0.0, time_span: float | None = None)Read MIDI notes from a clip, with note_id, pitch, start_time, duration, velocity, mute, probability, velocity_deviation and release_velocity.
path is a clip path, e.g. “live_set tracks 0 clip_slots 0 clip”. Defaults cover the whole clip. Keep the note_ids - clip_modify_notes needs them.
4.4.2 clip_add_notes
clip_add_notes(path: str, notes: list[dict[str, Any]])Add MIDI notes to a clip. Undoable.
Each note: {“pitch”: 60, “start_time”: 0.0, “duration”: 1.0, “velocity”: 100, “mute”: false} pitch is a MIDI note number (60 = C3); times are in beats.
4.4.3 clip_modify_notes
clip_modify_notes(path: str, notes: list[dict[str, Any]])Edit existing notes in place. Undoable.
Each entry needs “note_id” (from clip_get_notes) plus the fields to change, e.g. {“note_id”: 3, “pitch”: 62, “velocity”: 80}. Returns unmatched_note_ids for ids that no longer exist rather than failing.
4.4.4 clip_remove_notes
clip_remove_notes(path: str, from_pitch: int = 0, pitch_span: int = 128, from_time: float = 0.0, time_span: float | None = None)Remove notes in a pitch/time range. Undoable. Defaults remove ALL notes.
4.5 Browser
4.5.1 browser_list
browser_list(path: str = '')Browse Live’s library. Empty path lists the roots (instruments, sounds, drums, audio_effects, midi_effects, plugins, clips, samples, packs, user_library, current_project, max_for_live).
Then descend by name with “/”, e.g. “instruments/Drift” or “plugins/VST3”.
4.5.2 browser_load
browser_load(path: str, track_index: int | None = None)Load a browser item (instrument, effect, plugin, sample) onto a track.
path is a browser path from browser_list, e.g. “instruments/Drift”. Loads onto the selected track unless track_index is given. Undoable.
4.6 Automation
4.6.1 clip_envelope_get
clip_envelope_get(path: str, parameter: str, samples: int = 8, times: list[float] | None = None)Sample a clip’s automation envelope for one device/mixer parameter.
path - clip path, e.g. “live_set tracks 0 clip_slots 0 clip” parameter - parameter path, e.g. “live_set tracks 0 mixer_device volume” or “live_set tracks 0 devices 0 parameters 1”
4.6.2 clip_envelope_insert_step
clip_envelope_insert_step(path: str, parameter: str, time: float, length: float, value: float)Write a flat automation step into a clip envelope, creating the envelope if it does not exist. Times are in beats. Undoable.
4.6.3 clip_envelope_clear
clip_envelope_clear(path: str, parameter: str | None = None)Clear one parameter’s envelope, or ALL envelopes on the clip if parameter is omitted. Undoable.
4.7 Arrangement
4.7.1 arrangement_list_clips
arrangement_list_clips(path: str)List clips in a track’s Arrangement, e.g. path “live_set tracks 0”.
4.7.2 arrangement_create_clip
arrangement_create_clip(path: str, start_time: float, length: float = 4.0, kind: str = 'midi', file_path: str | None = None)Create a clip directly in the Arrangement view. Undoable.
path - track path, e.g. “live_set tracks 0” start_time - position in beats kind - “midi” (uses length) or “audio” (requires file_path)
Returns clip_path, e.g. “live_set tracks 0 arrangement_clips 2”.
4.7.3 arrangement_duplicate_clip
arrangement_duplicate_clip(path: str, clip: str, destination_time: float)Copy a session clip into the Arrangement. Undoable.
path - track path, e.g. “live_set tracks 0” clip - source clip path, e.g. “live_set tracks 0 clip_slots 0 clip”
4.8 Observers
4.8.1 lom_observe
lom_observe(path: str, property: str)Watch a property and record every change Live makes to it - including changes the USER makes in the GUI, not just ones made through this server.
Then call lom_poll_events to collect them.
Not every property is observable. If there is no add_
4.8.2 lom_unobserve
lom_unobserve(path: str, property: str)Stop watching one property.
Returns outcome: “removed”, or “object_gone” if the underlying track/clip was deleted (harmless - Live discarded its listeners with the object).
4.8.3 lom_observers
lom_observers()List active observers, buffered event count, and whether each observed object is still valid (object_valid: false means it was deleted).
4.8.4 lom_unobserve_all
lom_unobserve_all()Remove every observer. Reports leaked - the number that could NOT be detached and are still firing inside Live. Should always be 0.
4.8.5 lom_poll_events
lom_poll_events(since: int | None = None, limit: int = 500, consume: bool = False)Collect change events recorded by lom_observe.
The buffer is shared with every earlier session, so start from the latest_seq that lom_observe returned. Then pass since = the previous next_since to get only new events, oldest first. When truncated is true, more are waiting: poll again with since=next_since. reset true means Live restarted the sequence: the page starts over from the oldest buffered event. gap true means events after since are gone (dropped or consumed by another client) and the page skips them. limit must be at least 1. consume=true removes exactly the returned events.
Check dropped_events: the buffer holds 2000 events and drops oldest first, so a nonzero value means changes were lost between polls.
4.9 Other
4.9.1 clip_set_warp_markers
clip_set_warp_markers(path: str, markers: list[list[float]], warp_mode: int | None = None)Replace an audio clip’s warp map, turning warping on. Undoable.
path - audio clip path, e.g. “live_set tracks 0 clip_slots 0 clip” markers - [[beat_time, sample_time], …], at least 2, beat_times strictly increasing. beat_time is beats from the sample start; sample_time is SECONDS from the sample start, NOT frames - do not scale by the sample rate.
Cannot be done with lom_call: Live wants a C++ WarpMarker object, which JSON cannot express, so it must be built inside Live.
Existing markers the new map does not occupy are removed. A fresh clip carries a marker Live refuses to delete, so remove_failed may be 1.