live object model
live object model
the Live Object Model (LOM) is the python API a MIDI remote script (or Max for Live) gets to the running set: song, tracks, devices, parameters, clips, transport. it is complete enough to drive a mix, with a few hard edges.
every LOM call belongs on Live's main thread
the LOM is not thread-safe. a remote script that opens a socket and serves commands from another thread must marshal each command back with ControlSurface.schedule_message(delay_ticks, callback) and hand the result back through a queue. driving transport (start_playing, seeking) from a socket thread has crashed Live outright; reads from off-thread appear to work until they don't. one rule — everything through schedule_message — costs nothing and removes the whole class of bug.
a recurring main-thread job (metering, recording) is a callback that re-arms itself with schedule_message(1, self); one Live timer tick is roughly 100 ms.
a package reloads, its __init__ doesn't
Live imports the remote-script package once at launch and keeps it cached: toggling the control surface off and on does not re-import. importlib.reload on a submodule works fine. so keep __init__.py to the socket server and a reload command, put every handler in a sibling module, and iterate without restarting Live. a change to __init__.py itself still needs a restart.
property writes can read back stale
setting e.g. song.current_song_time and reading it in the same callback can return the old value; the next tick sees the new one. verify on the next command, not inline.
start_playing ignores a prior seek
start_playing() starts at the start marker regardless of where current_song_time was set. setting current_song_time while playing jumps playback. so "play from beat N" is: start, then seek, in one main-thread task. continue_playing() resumes from where playback last stopped, also ignoring the seek.
what is and isn't exposed
- routing — tracks and sidechain-capable devices (Compressor, Gate, …) expose
input_routing_type/input_routing_channelplus theavailable_*lists, each with adisplay_name. set the type first; the channel list depends on it. - meters — tracks have
output_meter_left/right/level(0.0–1.0, peak, Live-smoothed, no documented dB mapping). the main track's input meter reads 0. devices expose no gain-reduction meter. - automation — a parameter reports
automation_state(0 none, 1 playing, 2 overridden) but the arrangement lane's breakpoints are not readable; see als file format.Clip.automation_envelope/create_automation_envelopeare session-clip only — on an arrangement clip Live answersNot a session clip. writing a lane is possible only by recording it, see automation via recording. - undo —
song.begin_undo_step()/end_undo_step()group a scripted change into one undo;song.undo()reverts it. dir()works on LOM objects: a generic "introspect this path" command is the fastest way to find out what a given Live version exposes before building a tool on an assumption.
sources
- github.com/zzstoatzz/ableton-mcp —
AbletonMCP_Remote_Script/, 2026-08-23 (crash, reload split, seek quirk, routing/meter/automation probes against Live 12.4.3)
Did you enjoy this article?
Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.