Skip to content

Tool Reference ​

Every Producer Pal tool and its parameters. For what Producer Pal can do in plain terms, start with Features.

The AI picks these tools and fills in the parameters itself; you don't call them by hand. Read this when you want to know exactly what a tool accepts, or when you're driving Producer Pal from the REST API or the Agent Skill.

About the example output

Every tool shows one example call and what it returns. They all run against the same made-up Live Set (three tracks: Drums, Bass, Vocals, plus one return and two scenes), so the names, IDs, colors, and file paths are invented. IDs are opaque in real Live Sets too: read one from a tool result, don't guess it.

The examples are pretty-printed here. Producer Pal sends a more compact form over the wire by default; ?format=json on the REST API gives you this shape.

Core Tools ​

Connect (ppal-connect) ​

  • Summarizes the state of the current Live Set
  • Returns a skill set and context that teach the AI how to use Producer Pal effectively. Standard skills cover the full feature set. Small model mode provides simplified skills and schemas for less capable models.
  • Call it first when a model is driving Producer Pal. That's how the AI learns the notation and conventions. A plain REST script can skip it.

(no parameters)

Example output

Called with {}:

json
{
  "connected": true,
  "producerPalVersion": "2.3.0",
  "abletonLiveVersion": "12.4.1",
  "liveSet": {
    "name": "Example Set",
    "tempo": 110,
    "timeSignature": "4/4",
    "sceneCount": 2,
    "regularTrackCount": 3,
    "returnTrackCount": 1,
    "isPlaying": true,
    "scale": "F Minor",
    "scalePitches": "F,G,Ab,Bb,C,Db,Eb"
  }
}

The response carries these as separate text blocks after the JSON, in this order — ppal-connect does not return them as fields on the result. What goes in them is up to you: see Context & Memory and Customizing Skills.

# Producer Pal Skills

## Positions & Meter
… 370 more lines
Project context (this Live Set):

Downtempo sketch in F minor. Keep the drums sparse.
Global context (all projects):

I write downtempo and lo-fi house. Keep arrangements under 3 minutes.
Memory index. Load a body with ppal-context (action:"read", scope:"memory", name:"<name>"):

- `prefers-hardware-drums` — Records drums on hardware, wants MIDI kept out of the kick bus
Report the connection status and Live Set overview to the user, then wait for their instructions.

Context (ppal-context) ​

  • Read and write the three context layers: project context (notes about this Live Set), global context (preferences that apply to every project), and memory (facts AI records about you as you work)
Parameters
ParameterTypeDescription
action"read" |
"write" |
"delete" 🐘
read (default): project/global → the document; memory → the entry named name, or the whole index if no name. write: replace the document, or create/update the memory entry name. delete: remove the memory entry name.
scope"project" |
"global" |
"memory" 🐘
project (default): facts about THIS Live Set (genre, song structure), always in its context. global: who the user is across ALL projects (style, preferences, high-level goals), always in context. memory: durable facts and rules that matter only in CERTAIN situations, loaded on demand by name.
contentstringText to write — project/global: the whole document; memory: the entry body (one fact). Max 10000 chars.
name 🐘stringMemory entry name (read/write/delete on scope:memory). Reuse a name to update, not duplicate.
description 🐘stringMemory entry's one-line recall hook for the index — what's inside and when it's relevant. Required on a memory write.
forcebooleanOnly when a write was skipped for dropping the whole document: true replaces it anyway.

🐘 = large model only (hidden in small model mode)

Example output

Called with {"action":"read"}:

json
{
  "content": "Downtempo sketch in F minor. Keep the drums sparse."
}

Session Tools ​

Playback (ppal-playback) ​

  • Start/stop playback in Session or Arrangement view
  • Play specific scenes or clips
  • Set loop points and playback position
  • Jump to arrangement locators by ID or name
  • Set loop start/end using locators
  • Playback always follows the Arrangement (no per-track override)
  • Stop all clips or specific clips
Parameters
ParameterTypeDescription
action"play-arrangement" |
"update-arrangement" |
"play-scene" |
"play-session-clips" |
"stop-session-clips" |
"stop-all-session-clips" |
"stop"
(required)
play-arrangement: from startTime, or from wherever it already is
update-arrangement: set startTime and/or loop, without playing
play-scene: all clips in scene
play-session-clips: by id(s) or path(s)
stop-session-clips: by id(s) or path(s)
stop-all-session-clips: all
stop: session and arrangement; takes startTime to park the next play
startTimestringwhere arrangement playback starts, and restarts from if it's already playing. Stays put until something changes it: bar|beat in song meter, or loc:<locator name or id> (e.g. '5|1' or 'loc:Verse')
loopbooleanarrangement loop?
loopStartstringbar|beat (song meter) or loc:<locator>; turns the loop on
loopEndstringbar|beat (song meter) or loc:<locator>; turns the loop on
idstringclip ID(s), comma-separated for multiple; for play-scene, a scene ID (or a clip ID in that scene)
pathstringclip slot(s) 't<track>/s<scene>', both 0-based, comma-separated (e.g., 't0/s1' or 't0/s1,t2/s3'); for play-scene, a scene 's<scene>' (e.g., 's3') or any position in it
Example output

Called with {"action":"play-scene","path":"s0"}:

json
{
  "playing": true,
  "scene": {
    "id": "201",
    "path": "s0",
    "name": "Intro"
  }
}

Library (ppal-library) ​

Requires Live 12.4+

The library tools require Ableton Live 12.4 or later. On older versions they return an error explaining the requirement. Use the version of Max bundled with Live, or make sure your standalone Max is up to date. See Troubleshooting for details.

  • Search Live's browser library by name, tags, content kind, device kind, or source category (User Library, Pack, Built-in, Cloud, Plugin, or your sample folder)
  • Also includes the user-configured sample folder when set, with results merged and de-duplicated against Live's library
  • Sort by use_count (Live's persistent usage counter, which surfaces what you actually use most), mod_date, or name
  • Enumerate available tags with action: "listTags" so the AI can discover the tag vocabulary on your machine, or browse Live's category taxonomy (Sounds, Drums, Genres, …) with action: "listCategories"
  • Run many filtered searches in one call by passing searches (an array of query objects, each with its own filters); results grouped per query, so the AI can assemble a whole drum kit in one round trip
  • List the VST/VST3/AU plug-ins Live knows about with action: "listPlugins" (filter by query, vendor, format, device kind, or subcategory)
  • Rank samples by audio similarity to a seed sample with action: "findSimilar" (Live's own similarity index, not Producer Pal listening), or group library samples with identical audio (re-shipped duplicates) with action: "findDuplicates". Both can be narrowed with the search filters
Parameters
ParameterTypeDescription
action"search" |
"listTags" |
"listCategories" 🐘 |
"listPlugins" 🐘 |
"findSimilar" 🐘 |
"findDuplicates" 🐘
search: filter library items (default) | listTags: available tags | listCategories: Live's category taxonomy (Sounds, Drums, Genres, …); pass category to drill into its tags | listPlugins: installed VST/VST3/AU plugins (filter with query, vendor, format, deviceKind, subcategory) | findSimilar: rank samples by audio similarity to similarTo | findDuplicates: group library samples with identical audio. findSimilar and findDuplicates also take the search filters.
querystringname substring (search: supports * as a multi-character wildcard, e.g. kick*acoustic; listPlugins: plain case-insensitive substring)
searches 🐘arraysearch only: run several filtered searches in one call (e.g. build a drum kit) instead of the top-level filters. Each entry takes the same filters as a single search, plus an optional label; results come back in order, grouped per query (max 20)
tagsstringcomma-separated tag names; results must match ALL listed tags (search only)
kind"audio" |
"midi" |
"live-clip" 🐘 |
"preset" |
"device-group" |
"m4l-device" 🐘 |
"live-set" 🐘 |
"plugin" 🐘 |
"image" 🐘 |
"video" 🐘 |
"folder" 🐘
content kind filter (search only; default: audio — the only kind loadable into clips/Simpler, the rest are discovery-only). audio=samples | midi=.mid files plus MIDI .alc clips, so it covers all MIDI content | live-clip=all .alc clips (MIDI+audio; each result reports subtype) | preset=instrument/effect presets | device-group=.adg racks | m4l-device=.amxd | live-set=.als | plugin=VST/AU | image/video=media | folder=directory entries (distinct from source:sampleFolder)
type"loop" |
"oneshot" |
"impulse-response"
playback type filter (search only): loop=loops | oneshot=one-shots (e.g. a kick) | impulse-response=convolution IRs. Prefer oneshot for hits and loop for grooves. Also reported per result as type.
category 🐘stringlistCategories only: a top-level category name (from listCategories with no category) to drill into; returns its tag names, each usable as a tags filter
similarTo 🐘stringfindSimilar only: absolute path of a seed sample (e.g. a path from a prior search) to rank other samples by audio similarity. Combine with the search filters to constrain candidates — e.g. similarTo a kick + tags=Kick for 'more kicks like this one'. Each result carries a similarity score (-1 to 1, ~1 = very similar).
deviceKind 🐘"instrument" |
"audiofx" |
"midifx"
device classification filter (search + listPlugins; for listPlugins only instrument/audiofx apply)
vendor 🐘stringvendor/manufacturer substring, case-insensitive (listPlugins only)
format 🐘"VST" |
"VST3" |
"AU"
plugin binary format filter (listPlugins only)
subcategory 🐘stringsubcategory substring filter, case-insensitive (listPlugins only; matches any of a plugin's genre/role tags, e.g. reverb, delay, synth). Also reported per result as subcategories.
source"sampleFolder" |
"user" |
"pack" |
"builtin" |
"cloud" |
"plugin"
where the file lives (search only). sampleFolder=user-configured sample folder on disk (bypasses Live's DB) | user=your User Library | pack=installed Packs (factory + 3rd-party) | builtin=Ableton's Core Library | cloud=Cloud-stored items | plugin=installed VST/AU/etc. plugins
inFolderstringabsolute folder path; returns only immediate children of that folder (search only). Composes with other filters. Case-insensitive (ASCII). Unresolvable paths return no results with a reason explaining the path wasn't found.
sort 🐘"use_count" |
"mod_date" |
"name"
sort order (search only); defaults to use_count desc
verifyPaths 🐘booleansearch only: stat each result's path and add pathExists (true/false) so you can skip files moved/deleted since Live last indexed. Off by default (one filesystem check per result).
limitnumbermax results; defaults to 50 (search) or 200 (listTags)

🐘 = large model only (hidden in small model mode)

Example output

Called with {"query":"kick","limit":2}:

json
{
  "dbAvailable": true,
  "items": [
    {
      "name": "Kick Deep 01.wav",
      "path": "/Users/example/Music/Ableton/Factory Packs/Kick Deep 01.wav",
      "kind": "sample",
      "type": "oneshot",
      "tags": [
        "Kick",
        "Drums"
      ],
      "useCount": 12,
      "source": "builtin",
      "parentFolder": "One Shots"
    },
    {
      "name": "Bass Sub.adg",
      "path": "/Users/example/Music/Ableton/User Library/Bass Sub.adg",
      "kind": "instrument-rack",
      "tags": [
        "Bass"
      ],
      "useCount": 3,
      "source": "user",
      "parentFolder": "Instruments"
    }
  ]
}

Select (ppal-select) ​

  • Read current selection and view state (when no arguments)
    • Returns only non-null fields: selected track, scene, clip, device
    • Rich object shapes with IDs, types, and context (path, etc.)
  • Update selection and return only relevant fields
    • Select any object by ID (auto-detects track/scene/clip/device)
    • Select by path: a clip slot (e.g., t0/s3), a track (t0), a return track (rt0), the main track (mt), a scene (s3), or a device (e.g., t0/d1)
    • Switch between Session and Arrangement views
    • Auto-switches to session view for scene/clipSlot selection
    • Detail views auto-managed: clip detail opens on clip selection, device detail on device selection
Parameters
ParameterTypeDescription
idstringselect by ID (auto-detects track/scene/clip/device/chain/drum pad)
pathstringselect by path, 0-based: 't0/s3' a clip slot, 't0' a track, 'rt0' a return track, 'mt' the main track, 's3' a scene, 't0/d1' a device, 't0/d0/c1' a rack chain, 't0/d0/pC1' a drum pad
openPluginWindow 🐘booleanopen (true) or close (false) a plug-in's (VST/AU) floating editor window; targets the device given by id or path
view"session" |
"arrangement"
main view

🐘 = large model only (hidden in small model mode)

Example output

Called with {"path":"t0/s0"}:

json
{
  "view": "session",
  "selectedClip": {
    "id": "301",
    "path": "t0/s0"
  }
}

Action Tools ​

Delete (ppal-delete) ​

  • Remove tracks, return tracks, scenes, clips, devices, drum pads, or rack chains
  • Bulk delete multiple objects
Parameters
ParameterTypeDescription
idstringID(s) to delete, comma-separated for multiple (must be same type)
pathstringpath(s) to delete, comma-separated for multiple: tracks ('t0', 'rt1'), scenes ('s0'), session clips ('t0/s1'), arrangement clips by where they start ('t0[5|1]'), devices ('t0/d1'), drum pads ('t1/d0/pC1'), one layer of a pad ('t1/d0/pC1/c1'). Deleting shifts every later sibling down, so a path in the result is the address from before the call.
type"track" |
"scene" |
"clip" |
"device" |
"drum-pad" |
"chain"
(required)
type of objects to delete; 'chain' removes one chain from a Drum Rack pad
Example output

Called with {"id":"303","type":"clip"}:

json
{
  "id": "303",
  "deletedPath": "t2/s1",
  "type": "clip",
  "deleted": true
}

Duplicate (ppal-duplicate) ​

  • Copy tracks, scenes, clips, devices, or drum pads
  • Create multiple copies at once
  • Copy clips anywhere in the Session, Arrangement, or from Session to Arrangement
    • Position in the Arrangement by bar|beat or locator
    • Auto-tile clips to fill longer arrangement durations
  • Apply transforms to each duplicated clip (e.g. transpose copies, vary velocities) without a separate update step
  • Stack variations on take lanes: naming one lane twice in toPath, toPath: "t2/l0[9|1],t2/l0[13|1]", stacks both takes on it. A lane per copy is a lane index per copy, toPath: "t2/l0,t2/l1,t2/l2"
  • Copy devices to any track, return track, or rack chain
  • Copy a whole drum pad to another pad in the same rack, bringing its chain trim, pan, sends, choke group, and devices. A device-only copy leaves the chain (and its trim) behind
  • Copy a chain of any rack with type: "chain", carrying its name, color, mute/solo, chain trim, and devices. toPath names the destination rack and may cross racks of the same kind; omit it to append to the chain's own rack. Sends carry when the destination rack has a return chain of the same name. Macro mappings can't be reproduced through the Live API, so a rack that has them says so
  • Route duplicated tracks to source instrument for MIDI layering

Note: Return tracks and devices on return tracks cannot be duplicated (Live API limitation).

Parameters
ParameterTypeDescription
idstringid(s) of the object(s) to duplicate, comma-separated for multiple
pathstringpath(s) of the object(s) to duplicate, instead of or alongside id, comma-separated for multiple (e.g. 't0', 's1', 't0/s1', 't0[5|1]', 't0/d0', 't0/d0/pC1')
type"track" |
"scene" |
"clip" |
"device" |
"drum-pad" |
"chain"
(required)
type of object to duplicate
namestringname for all, or comma-separated one per copy, in order
colorstring#RRGGBB for all, or comma-separated one per copy, in order
count 🐘integer copies per source (tracks/scenes only, ignored for clips/devices)
withoutClips 🐘booleanexclude clips?
withoutDevices 🐘booleanexclude devices?
arrangementLengthstringduration: <count>bar (e.g., '4bar'), n<fraction> note value (e.g., 'n/4'), or <count>bar+n<fraction> (e.g., '1bar+n/4'); song meter. Shorter than the source trims the copy; longer tiles copies to fill the span (many clips, not one) — for a single clip use ppal-update-clip with looping false and notes for the full length
toPathstringdestination(s), comma-separated for multiple. Clips: 't2/s1' = a clip slot, third track and second scene (both count from 0); 't2[5|1]' = that spot on that track's arrangement, and '[5|1]' the same spot on the source clip's own track (a position is bar|beat or loc:<locator name or id> — 't2[loc:Chorus]' names a section instead of counting bars; an arrangement track must match the clip's MIDI/audio type); 't2/l0' = its first take lane, and lanes are created up to that index; 't2' alone needs a position, and omitting toPath uses the source clip's own track. Devices: 't1/d0'. Scenes: '[5|1]' = that spot on the arrangement, across every track. Drum pads: 't0/d0/pD1', required, and must be in the same rack as the source pad (id or path names the source). One destination covers every source and position; a list pairs one per copy, in order, and never cycles. A clip slot, device or pad holds one object, so name one per copy
routeToSource 🐘booleantracks only (errors otherwise): the copy gets no clips or devices of its own and plays the source track's instrument (for MIDI layering/polyrhythms)
transforms 🐘stringtransform expressions (broadcast across copies; clips only); newline-separated for multiple. Use clip.index / clipseq() for per-copy variation. Note-count operations (ratchet()/repeat()/split()/merge()) change how many notes exist

🐘 = large model only (hidden in small model mode)

Example output

Called with {"type":"clip","id":"301","toPath":"t0/s1"}:

json
{
  "id": "603",
  "path": "t0/s1"
}

Live Set Tools ​

Read Live Set (ppal-read-live-set) ​

  • Get complete Live project overview
  • View all tracks and scenes at once, with a clip count per track (clip contents come from Read Track, Read Scene, and Read Clip)
  • See tempo, time signature, and scale settings
  • View arrangement locators with times and names
  • Check what's playing and track states
Parameters
ParameterTypeDescription
includearray of:
"tracks" |
"scenes" |
"routings" 🐘 |
"mixer" |
"color" |
"locators" 🐘 |
"*" 🐘
tracks, scenes = lists. routings, mixer, color = detail (use with tracks/scenes). locators = arrangement markers. "*" = all

🐘 = large model only (hidden in small model mode)

Example output

Called with {"include":["*"]}:

json
{
  "name": "Example Set",
  "tempo": 110,
  "timeSignature": "4/4",
  "scenes": [
    {
      "id": "201",
      "path": "s0",
      "name": "Intro",
      "color": "#FF4C4C",
      "clipCount": 1
    },
    {
      "id": "202",
      "path": "s1",
      "name": "Verse",
      "color": "#B87A35",
      "tempo": 96,
      "timeSignature": "6/8",
      "clipCount": 2
    }
  ],
  "isPlaying": true,
  "tracks": [
    {
      "id": "101",
      "path": "t0",
      "type": "midi",
      "name": "Drums",
      "color": "#FF4C4C",
      "isArmed": true,
      "instrument": "Drum Rack",
      "gainDb": "0.0 dB",
      "pan": 0,
      "sends": [
        {
          "gainDb": "-inf dB",
          "return": "A Reverb",
          "returnId": "104"
        }
      ],
      "sessionClipCount": 1,
      "arrangementClipCount": 0,
      "deviceCount": 1,
      "playingSlotIndex": 0,
      "inputRoutingType": {
        "name": "Ext. In",
        "inputId": "17"
      },
      "inputRoutingChannel": {
        "name": "In 1",
        "inputId": "1"
      },
      "outputRoutingType": {
        "name": "Track Out",
        "outputId": "25"
      },
      "outputRoutingChannel": {
        "name": "Master",
        "outputId": "26"
      },
      "monitoringState": "auto"
    },
    {
      "id": "102",
      "path": "t1",
      "type": "midi",
      "name": "Bass",
      "color": "#B87A35",
      "instrument": "Analog",
      "gainDb": "-3.0 dB",
      "pan": -0.25,
      "sends": [
        {
          "gainDb": "-12.0 dB",
          "return": "A Reverb",
          "returnId": "104"
        }
      ],
      "sessionClipCount": 1,
      "arrangementClipCount": 1,
      "takeLaneCount": 2,
      "deviceCount": 2,
      "inputRoutingType": {
        "name": "Ext. In",
        "inputId": "17"
      },
      "inputRoutingChannel": {
        "name": "In 1",
        "inputId": "1"
      },
      "outputRoutingType": {
        "name": "Track Out",
        "outputId": "25"
      },
      "outputRoutingChannel": {
        "name": "Master",
        "outputId": "26"
      },
      "monitoringState": "auto"
    },
    {
      "id": "103",
      "path": "t2",
      "type": "audio",
      "name": "Vocals",
      "color": "#3DC300",
      "gainDb": "-6.0 dB",
      "pan": 0.5,
      "sends": [
        {
          "gainDb": "-6.0 dB",
          "return": "A Reverb",
          "returnId": "104"
        }
      ],
      "sessionClipCount": 1,
      "arrangementClipCount": 0,
      "deviceCount": 0,
      "state": "muted",
      "inputRoutingType": {
        "name": "Ext. In",
        "inputId": "17"
      },
      "inputRoutingChannel": {
        "name": "In 1",
        "inputId": "1"
      },
      "outputRoutingType": {
        "name": "Track Out",
        "outputId": "25"
      },
      "outputRoutingChannel": {
        "name": "Master",
        "outputId": "26"
      },
      "monitoringState": "auto"
    }
  ],
  "returnTracks": [
    {
      "id": "104",
      "path": "rt0",
      "name": "A Reverb",
      "color": "#7F7F7F",
      "gainDb": "0.0 dB",
      "pan": 0,
      "sessionClipCount": 0,
      "arrangementClipCount": 0,
      "deviceCount": 0,
      "inputRoutingType": null,
      "inputRoutingChannel": null,
      "outputRoutingType": {
        "name": "Track Out",
        "outputId": "25"
      },
      "outputRoutingChannel": {
        "name": "Master",
        "outputId": "26"
      }
    }
  ],
  "mainTrack": {
    "id": "105",
    "path": "mt",
    "name": "Master",
    "color": "#7F7F7F",
    "gainDb": "0.0 dB",
    "pan": 0,
    "sessionClipCount": 0,
    "arrangementClipCount": 0,
    "deviceCount": 0,
    "inputRoutingType": null,
    "inputRoutingChannel": null,
    "outputRoutingType": null,
    "outputRoutingChannel": null
  },
  "scale": "F Minor",
  "scalePitches": "F,G,Ab,Bb,C,Db,Eb",
  "locators": [
    {
      "id": "locator-0",
      "name": "Intro",
      "time": "1|1",
      "position": "loc:Intro"
    },
    {
      "id": "locator-1",
      "name": "Verse",
      "time": "9|1",
      "position": "loc:Verse"
    }
  ]
}

Update Live Set (ppal-update-live-set) ​

  • Change tempo, time signature, scale
  • Create, rename, or delete arrangement locators
Parameters
ParameterTypeDescription
temponumber BPM
timeSignaturestringN/D (4/4)
scalestring"Root ScaleName" ("C Major", "F# Minor", "Bb Dorian"). Empty string disables scale
locatorOperation 🐘"create" |
"delete" |
"rename"
Locator operation
locatorId 🐘stringLocator ID for delete/rename (e.g. locator-0). Positional — shifts if locators are added/removed, so prefer locatorTime or locatorName
locatorTime 🐘stringBar|beat position, song meter (required for create, alt ID for delete/rename)
locatorName 🐘stringName for create/rename, or name-match filter for delete

🐘 = large model only (hidden in small model mode)

Example output

Called with {"tempo":124,"scale":"F Minor"}:

json
{
  "id": "1",
  "tempo": 124,
  "scale": "F Minor",
  "$meta": [
    "Scale applied to selected clips and defaults for new clips."
  ],
  "scalePitches": [
    "F",
    "G",
    "Ab",
    "Bb",
    "C",
    "Db",
    "Eb"
  ]
}

Track Tools ​

Create Track (ppal-create-track) ​

  • Add MIDI, audio, or return tracks
  • Position tracks exactly where you want
  • Set initial mute/solo/arm states
Parameters
ParameterTypeDescription
pathstringwhere it goes: 't+' appends, 't<index>' inserts there (t0 is the first track, so a user's "track 3" is t2), 'rt+' adds a return track
count 🐘integer number to create
namestringname for all, or comma-separated one per track, in order
colorstring#RRGGBB for all, or comma-separated one per track, in order
type"midi" |
"audio"
type
mute 🐘booleanmuted?
solo 🐘booleansoloed?
arm 🐘booleanrecord armed?

🐘 = large model only (hidden in small model mode)

Example output

Called with {"path":"t3","name":"Keys"}:

json
{
  "id": "601",
  "path": "t3"
}

Read Track (ppal-read-track) ​

  • Get detailed track information
  • View all clips in Session and Arrangement
  • List take lanes and their clips (with the arrangement-clips include)
  • See devices, routing options, and drum pad mappings
  • Check track states (muted, soloed, armed)
  • View mixer properties: gain, pan, panning mode, and send levels
Parameters
ParameterTypeDescription
idstringprovide this or path
pathstringtrack path instead of id: 't<index>' (t0 is the first track, so a user's "track 3" is t2), 'rt0' for a return, 'mt' for the main track
includearray of:
"session-clips" |
"arrangement-clips" |
"notes" |
"timing" |
"sample" |
"warp" 🐘 |
"devices" |
"drum-map" |
"routings" 🐘 |
"available-routings" 🐘 |
"mixer" |
"color" |
"*" 🐘
session-clips, arrangement-clips = clip lists (arrangement-clips also lists take lanes). notes, timing, sample, warp = clip detail (use with clips). devices, routings, available-routings, mixer = track data. drum-map = the kit's actual pad pitches and names, plus drumRackPath (pad paths are <drumRackPath>/p<note>); read it before writing drums. color = track + clip color. "*" = all

🐘 = large model only (hidden in small model mode)

Example output

Called with {"path":"t0","include":["*"]}:

json
{
  "id": "101",
  "path": "t0",
  "type": "midi",
  "name": "Drums",
  "color": "#FF4C4C",
  "isArmed": true,
  "instrument": "Drum Rack",
  "gainDb": "0.0 dB",
  "pan": 0,
  "sends": [
    {
      "gainDb": "-inf dB",
      "return": "A Reverb",
      "returnId": "104"
    }
  ],
  "sessionClips": [
    {
      "id": "301",
      "name": "Kick + Hats",
      "color": "#FF4C4C",
      "playing": true,
      "path": "t0/s0",
      "timeSignature": "4/4",
      "looping": true,
      "start": "1|1",
      "end": "2|1",
      "length": "1bar",
      "notes": "v110 n/16 C1 1|1 v100 C1 1|2,4\nv70 Gb1 1|1.5x4@n/4\nv105 D1 1|3"
    }
  ],
  "arrangementClips": [],
  "devices": [
    {
      "id": "401",
      "path": "t0/d0",
      "type": "drum-rack",
      "name": "Kit"
    }
  ],
  "drumMap": {
    "C1": "Kick",
    "D1": "Snare"
  },
  "drumRackPath": "t0/d0",
  "playingSlotIndex": 0,
  "inputRoutingType": {
    "name": "Ext. In",
    "inputId": "17"
  },
  "inputRoutingChannel": {
    "name": "In 1",
    "inputId": "1"
  },
  "outputRoutingType": {
    "name": "Track Out",
    "outputId": "25"
  },
  "outputRoutingChannel": {
    "name": "Master",
    "outputId": "26"
  },
  "monitoringState": "auto",
  "availableInputRoutingTypes": [
    {
      "name": "Ext. In",
      "inputId": "17"
    }
  ],
  "availableInputRoutingChannels": [
    {
      "name": "In 1",
      "inputId": "1"
    }
  ],
  "availableOutputRoutingTypes": [
    {
      "name": "Track Out",
      "outputId": "25"
    }
  ],
  "availableOutputRoutingChannels": [
    {
      "name": "Master",
      "outputId": "26"
    }
  ]
}

Update Track (ppal-update-track) ​

  • Change track gain (volume), panning, and send levels, several sends at once with sends: [{return, gainDb}] (each return named by id, exact name, or letter)
  • Change mute, solo, arm, I/O routings, and monitoring state
  • Change track name and color
  • Update multiple tracks at once
Parameters
ParameterTypeDescription
idstringtrack ID(s) to update, comma-separated for multiple
pathstringtrack path(s) to update instead of id, comma-separated: 't<index>' (t0 is the first track, so a user's "track 3" is t2), 'rt<index>' (return), or 'mt' (main) - e.g. 't0' or 't0,rt1'
namestringname for all, or comma-separated one per track, in order, ideally unique
colorstring#RRGGBB for all, or comma-separated one per track, in order
gainDbnumber track gain in dB
pannumber pan: -1 (left) to 1 (right)
panningMode 🐘"stereo" |
"split"
panning mode: stereo or split
leftPan 🐘number left channel pan in split mode (-1 to 1)
rightPan 🐘number right channel pan in split mode (-1 to 1)
mutebooleanmuted?
solobooleansoloed?
armbooleanrecord armed?
inputRoutingType 🐘stringname from availableInputRoutingTypes, set before channel
inputRoutingChannel 🐘stringname from availableInputRoutingChannels
outputRoutingType 🐘stringname from availableOutputRoutingTypes, set before channel
outputRoutingChannel 🐘stringname from availableOutputRoutingChannels
monitoringState 🐘"in" |
"auto" |
"off"
input monitoring
sendGainDb 🐘number send gain in dB, requires sendReturn
sendReturn 🐘stringreturn track: id, exact name (e.g., "A-Reverb"), or letter (e.g., "A")
sends 🐘arrayset several of the track's sends at once: [{return, gainDb}], where return is a return track's id, exact name, or letter — the return/returnId read-track reports. Use instead of sendGainDb + sendReturn, which set one

🐘 = large model only (hidden in small model mode)

Example output

Called with {"id":"103","mute":false,"gainDb":-3}:

json
{
  "id": "103",
  "path": "t2",
  "gainDb": -3
}

Scene Tools ​

Create Scene (ppal-create-scene) ​

  • Add new scenes at any position
  • Set scene name, color, tempo, and time signature
  • Scenes can follow song tempo or have their own
  • Ability to capture currently playing clips into a new scene
Parameters
ParameterTypeDescription
pathstringwhere they go: 's+' appends, 's<index>' inserts there and shifts the rest down (s0 is the first scene, so a user's "scene 3" is s2). Required when capture=false, optional when capture=true
count 🐘integer number to create
capture 🐘booleancopy playing session clips instead of creating empty?
namestringname for all, or comma-separated one per scene, in order
colorstring#RRGGBB for all, or comma-separated one per scene, in order
tempo 🐘numberBPM (-1 disables when capturing)
timeSignature 🐘stringN/D (4/4) or "disabled" when capturing

🐘 = large model only (hidden in small model mode)

Example output

Called with {"path":"s2","name":"Chorus"}:

json
{
  "id": "602",
  "path": "s2"
}

Read Scene (ppal-read-scene) ​

  • View scene details and all its clips
  • Check which clips are playing/triggered
  • See scene tempo and time signature
Parameters
ParameterTypeDescription
idstringprovide this or path
pathstringscene path instead of id: 's<index>', where s0 is the first scene (a user's "scene 3" is s2)
includearray of:
"clips" |
"notes" |
"sample" |
"timing" |
"warp" 🐘 |
"color" |
"*" 🐘
clips = clip list. notes, sample, timing, warp = clip detail (use with clips). color = scene + clip color. "*" = all

🐘 = large model only (hidden in small model mode)

Example output

Called with {"path":"s1","include":["*"]}:

json
{
  "id": "202",
  "path": "s1",
  "name": "Verse",
  "color": "#B87A35",
  "tempo": 96,
  "timeSignature": "6/8",
  "clips": [
    {
      "id": "302",
      "type": "midi",
      "name": "Bass Line",
      "color": "#B87A35",
      "path": "t1/s1",
      "timeSignature": "4/4",
      "looping": true,
      "start": "1|1",
      "end": "3|1",
      "length": "2bar",
      "notes": "v100 n/4d F1 1|1\nv90 n/8 F1 1|3\nv85 n/4 C2 1|4\nv100 n/2 Eb1 2|1",
      "trackName": "Bass"
    },
    {
      "id": "303",
      "type": "audio",
      "name": "Vocal Take",
      "color": "#3DC300",
      "muted": true,
      "path": "t2/s1",
      "timeSignature": "4/4",
      "looping": true,
      "start": "1|1",
      "end": "3|1",
      "length": "2bar",
      "gainDb": -2.6,
      "sampleFile": "/Users/example/Music/Samples/Vocal Take.wav",
      "sampleLength": 352800,
      "sampleRate": 44100,
      "warping": true,
      "warpMode": "complex",
      "trackName": "Vocals"
    }
  ]
}

Update Scene (ppal-update-scene) ​

  • Change scene name, color, tempo, and time signature
  • Update multiple scenes at once
Parameters
ParameterTypeDescription
idstringscene ID(s) to update, comma-separated for multiple
pathstringscene path(s) to update instead of id, comma-separated: 's<index>', where s0 is the first scene (a user's "scene 3" is s2) - e.g. 's0' or 's0,s3'
namestringname for all, or comma-separated one per scene, in order
colorstring#RRGGBB for all, or comma-separated one per scene, in order
temponumberBPM (-1 disables)
timeSignaturestringN/D (4/4) or "disabled"
Example output

Called with {"id":"202","name":"Verse A","tempo":96}:

json
{
  "id": "202",
  "path": "s1"
}

Clip Tools ​

Parameters shown use the default notation

The notes parameter on Create Clip and Update Clip is rewritten to match the active notation. The tables below show it in bar|beat, the default. See MIDI Notation for how it reads under MIDI JSON and Stark.

Create Clip (ppal-create-clip) ​

  • Generate MIDI clips with notes, velocities, and timing using custom notation
  • Place clips in clip slots or the Arrangement timeline
  • Place arrangement clips on take lanes with a t0/l1[5|1] path
  • Support for probability, velocity ranges, and complex rhythms
  • Apply transforms to shape notes with math expressions
  • Create audio clips from a sample file with sampleFile, and choose whether Live warps it with warping (see Audio Clips)
  • Auto-create scenes as needed
Parameters
ParameterTypeDescription
pathstringwhere the clip(s) go, comma-separated for multiple. 't<track>/s<scene>' is a clip slot; 't<track>[<position>]' is that spot on the track's arrangement, where a position is bar|beat or loc:<locator name or id>. An arrangement path needs both halves. 't<track>/l<lane>[<position>]' puts it on a take lane, creating lanes up to that index. All indices 0-based, so 't0/s0' is the first track's first scene, and a number the user says is 1-based - their "scene 3" is s2 (e.g., 't0/s0' or 't0[5|1]' or 't0/s0,t1[loc:Chorus]')
namestringname for all, or comma-separated one per position, in order (clip slots first, then arrangement)
colorstring#RRGGBB for all, or comma-separated one per position, in order
timeSignaturestringN/D (4/4), default: global time signature
startstringbar|beat position where loop/clip region begins (clip meter)
lengthstringduration: <count>bar (e.g., '4bar'), n<fraction> note value (e.g., 'n/4'), or <count>bar+n<fraction> (e.g., '1bar+n/4'). Clip meter. MIDI only, default: next full bar after latest note. Audio clip length comes from the sample
loopingbooleanenable looping for the clip
firstStart 🐘stringbar|beat playback start (looping clips, when different from start; clip meter)
notesstringMIDI in bar|beat notation: v0-127 n<dur> [p0-1] note(s) bar|beat(s) - MIDI clips only
transforms 🐘stringtransform expressions (parameter: expression per line). Note-count operations (ratchet()/repeat()/split()/merge()) change how many notes exist
sampleFilestringabsolute path to audio file - audio clips only
warpingbooleanaudio clips only. Omit and Live decides per its Loop/Warp Short Samples setting, often time-stretching the file to the tempo. false = play the file as rendered. The settled state comes back as warping
gainDbnumber audio clip gain in decibels, 0 = unity (ignored for MIDI)
pitchShiftnumber audio clip pitch shift in semitones, supports decimals (ignored for MIDI)
warpMode"beats" |
"tones" |
"texture" |
"repitch" |
"complex" |
"pro"
audio clip warp mode (ignored for MIDI)
auto 🐘"play-scene" |
"play-clip"
auto-play the new session clip(s) — worth setting whenever the user will want to hear what you made. play-scene launches the whole scene so the new clip stays in sync with the others (it restarts them; say so first). play-clip fires the clip alone

🐘 = large model only (hidden in small model mode)

Example output

Called with {"path":"t1/s0","name":"Bass Fill","notes":"v100 n/8 F1 1|1 C2 1|2"}:

json
{
  "id": "603",
  "path": "t1/s0",
  "noteCount": 2,
  "length": "1bar"
}

Read Clip (ppal-read-clip) ​

  • Get detailed info about any clip in Session or Arrangement
  • Read MIDI notes in custom notation (C3, D#4, etc.)
  • Get audio clip gain, pitch, warp settings, and sample info
Parameters
ParameterTypeDescription
idstringprovide this or path
pathstringwhere the clip is, 0-based: a clip slot 't<track>/s<scene>' (e.g., 't0/s3'), or an arrangement clip by where it starts, 't<track>[<position>]' (e.g., 't0[5|1]'). provide this or id
includearray of:
"sample" |
"notes" |
"color" |
"timing" |
"warp" 🐘 |
"*" 🐘
notes = MIDI data. timing = loop/start/end markers. sample = audio file info (sampleFile, gainDb, pitchShift). warp = warp settings (sampleLength, sampleRate, warping, warpMode). color. "*" = all

🐘 = large model only (hidden in small model mode)

Example output

Called with {"id":"302","include":["*"]}:

json
{
  "id": "302",
  "type": "midi",
  "name": "Bass Line",
  "view": "session",
  "color": "#B87A35",
  "path": "t1/s1",
  "timeSignature": "4/4",
  "looping": true,
  "start": "1|1",
  "end": "3|1",
  "length": "2bar",
  "notes": "v100 n/4d F1 1|1\nv90 n/8 F1 1|3\nv85 n/4 C2 1|4\nv100 n/2 Eb1 2|1"
}

Update Clip (ppal-update-clip) ​

  • Change clip name, color, and loop settings
  • Add/remove MIDI notes using custom notation
  • Apply transforms to modify existing notes and audio properties (use clip.index/clipseq() for per-clip variation when updating multiple)
  • Change audio clip gain, pitch shift, and warp settings (see Audio Clips)
  • Move clips and change their length in the Arrangement, addressing a clip by where it starts (t0[5|1], or t0[loc:Chorus])
  • Move a clip with toPath: along its own track, to another track, onto or off a take lane, or back into a session slot. A move Live has no API for re-creates the clip, which costs its automation envelopes; the result says when that applied
  • Split arrangement clips at specified positions
  • Update multiple clips at once
Parameters
ParameterTypeDescription
idstringclip ID(s) to update, comma-separated for multiple
pathstringclip(s) to update instead of id, comma-separated: a clip slot 't<track>/s<scene>', or an arrangement clip by where it starts 't<track>[<position>]' (e.g., 't0/s1' or 't0[5|1],t2/s3')
namestringname for all, or comma-separated one per clip, in order
colorstring#RRGGBB for all, or comma-separated one per clip, in order
timeSignaturestringN/D (4/4)
startstringbar|beat position where loop/clip region begins (clip meter)
lengthstringduration: <count>bar (e.g., '4bar'), n<fraction> note value (e.g., 'n/4' = quarter), or <count>bar+n<fraction> (e.g., '1bar+n/4'); clip meter
loopingbooleanenable looping for the clip
duplicateLoopbooleandouble the clip length and copy existing notes (and automation envelopes) into the new half (Live's Duplicate Loop). MIDI clips only. Cannot be combined with start/length - they set the region this doubles, so the clip would end up twice the length you asked for; to double a portion, send start/length in its own call first. preTransforms edit the source before the double; notes/transforms then apply across the full doubled clip
firstStart 🐘stringbar|beat playback start (looping clips, when different from start; clip meter)
arrangementLengthstringduration(s), comma-separated: <count>bar (e.g., '4bar'), n<fraction> note value (e.g., 'n/4'), or <count>bar+n<fraction> (e.g., '1bar+n/4'). Arrangement clips only; song meter. One length applies to every clip; a list pairs 1:1 with id/path in order. Lengthening a looping clip tiles copies to fill the span (many clips, not one); for a single clip, set looping false and supply notes for the full length
arrangementSplit 🐘stringcomma-separated song positions to cut clips at: bar|beat in song meter, or loc:<locator name or id> (e.g., '9|1, loc:Chorus') - max 32 points. Cuts the clip into separate clips; to cut a held note into separate notes use split() in transforms. A position outside a clip is ignored, so one call can cut several clips at the same song position. Arrangement clips only; song meter. Cannot be combined with toPath or arrangementLength: the cut makes new clips, so those would either miss the new pieces or apply to every one of them - cut in one call, then move/resize the pieces in the next
toPathstringwhere to move the clip(s), comma-separated for multiple: a clip slot 't<track>/s<scene>', a spot on the arrangement 't<track>[<position>]' (a position is bar|beat or loc:<locator name or id>), a take lane 't<track>/l<lane>' (lanes are created up to that index), or '[<position>]' alone to keep the clip's own lane (e.g., 't2/s3' or 't2[5|1],[loc:Chorus]'). A lane with no position keeps the clip's own start. A clip re-created in a slot or on a take lane drops its automation envelopes. One '[<position>]' moves every clip, each on its own lane; anything naming a lane pairs 1:1 with id/path in order, since a lane or slot holds one clip and the rest would land on top of it
gainDbnumber audio clip gain in decibels, 0 = unity (ignored for MIDI)
pitchShiftnumber audio clip pitch shift in semitones, supports decimals (ignored for MIDI)
warpMode"beats" |
"tones" |
"texture" |
"repitch" |
"complex" |
"pro"
audio clip warp mode (ignored for MIDI)
warpingbooleanaudio clip warping on/off (ignored for MIDI). false resets the region to the whole file and turns looping off; looping:true forces warping back on
notesstringMIDI notes in bar|beat notation: v0-127 n<dur> [p0-1] note(s) bar|beat(s) - MIDI clips only. MERGES into existing notes (overwrites at same pitch+start - restate a note to edit it in place). To delete/move existing notes or replace a region use preTransforms; don't rewrite the whole clip
transforms 🐘stringtransform expressions applied AFTER merging notes (broadcast across the clips); newline-separated for multiple. Use clip.index / clipseq() for per-clip variation. Note-count operations (ratchet()/repeat()/split()/merge() - see Skills) change how many notes exist; prefer them over rewriting notes by hand
preTransformsstringtransform expressions applied to EXISTING notes BEFORE merging any new notes (broadcast across the clips); clear or edit notes already in the clip. 'delete' (alias 'v0') removes: a whole bar ('3|: delete', | wildcard avoids spilling onto the next downbeat), a span ('1|1-2|1: delete'), one pitch ('C1: delete'), a pitch range ('C1-C5: delete'), or all ('delete'); also remap a drum lane ('C1: C4'). Works with or without notes
quantizenumber quantize strength 0-1; default 1 (full snap) when quantizeGrid is set. Snaps note starts to quantizeGrid. MIDI clips only
quantizeGrid"1/4" |
"1/8" |
"1/8T" |
"1/8+1/8T" |
"1/16" |
"1/16T" |
"1/16+1/16T" |
"1/32" |
"n/4" |
"n/8" |
"n/12" |
"n/16" |
"n/24" |
"n/32"
grid that note starts snap to: 1/16 (default), 1/8, 1/4, 1/8T, 1/16T, 1/32; n/N note values also accepted (n/12=1/8T, n/24=1/16T); mixed grids 1/8+1/8T and 1/16+1/16T are enum-only
quantizePitch 🐘stringlimit quantization to specific pitch (e.g., C3, D#4)

🐘 = large model only (hidden in small model mode)

Example output

Called with {"id":"302","name":"Bass Line A","transforms":"pitch += 12"}:

json
{
  "id": "302",
  "noteCount": 4,
  "transformed": 4,
  "path": "t1/s1"
}

Audio Clips ​

A new audio clip's region comes from its sample, so start, length, firstStart, and looping are MIDI-only on Create Clip and are ignored (with a warning) alongside a sampleFile. timeSignature and the audio properties (gainDb, pitchShift, warpMode, warping) do apply. On Update Clip, start and length reshape an existing audio clip's region normally.

Warping. When you create an audio clip, Live decides for itself whether to warp the sample, following your Loop/Warp Short Samples preference, which no API can read, so the same call can land differently on two machines. Pass warping: false to play the file exactly as recorded or rendered. Omit it and Live still decides, but the result reports which way it went.

warping: false means the same thing on Create Clip and Update Clip: reset the region to the whole file and turn looping off, which is what Live does underneath. Two consequences on Update Clip:

  • It erases a start/length sent in the same call. Reshape the region in a follow-up call.
  • looping: true forces warping back on, so it vetoes a warping: false sent alongside it, and warns that it did.

Unwarped clips are measured against the sample. Live switches a clip's markers from beats to seconds when warping is off, and reports an unwarped session clip's length as though it were still warped. Producer Pal measures the region from the markers instead, so a 1.2-second one-shot reads as the beats it really occupies at your tempo rather than as 1.2 beats. That's also what keeps Duplicate from tiling copies over audio that's still sounding.

Device Tools ​

Create Device (ppal-create-device) ​

  • Add native Live devices (instruments, MIDI effects, audio effects)
  • Place devices on any track type: MIDI, audio, return, or the main track
  • Position devices at a specific index in the device chain
  • Create devices inside rack chains or drum pads using path notation
  • List the native Live devices
  • Load a sample into a Simpler instrument via params: [{name: "sample", value: "<path>"}], and set its level with {name: "gainDb", value: <dB>} (new in Live 12.4)
Parameters
ParameterTypeDescription
deviceNamestringdevice name, omit to list available devices
pathstringinsertion path(s), required with deviceName, comma-separated for multiple (e.g., 't0' or 't0,t1,t0/d0/c0'). An insert renumbers the chain, so no later entry may be spelled through a chain an earlier one inserts into
namestringname for all, or comma-separated one per device, in order
paramsarrayapplied after creation — array of {name, value}. name = a param name, or a param id from read-device; value in display units (enum string, note name, number) — use the unit read-device reports for that param, or no unit at all; a param with no unit takes a bare number. Many params only accept a coarse ladder of values, so a request lands on the nearest one — the response reports what each param reads as afterward. For a Drum Rack, prefix the name with a pad path to address a pad's device, e.g. {name:'pC1/sample', value:'<abs file path>'} loads a sample into pad C1 (auto-creates the pad's Simpler) — build a full kit in one call
Example output

Called with {"deviceName":"Saturator","path":"t1"}:

json
{
  "id": "604",
  "path": "t1/d2"
}

Read Device (ppal-read-device) ​

  • Get detailed info about any device, including inside rack chains and drum pad chains
  • List device parameter names and values (the state of knobs, dials, etc)
  • See a rack chain's own volume, pan, and sends when they're not at default
Parameters
ParameterTypeDescription
idstringdevice or drum pad ID to read. provide this or path
pathstringpath (e.g., 't1/d0', 't1/d0/c0', 't1/d0/pC1', 't1/d0/rc0')
includearray of:
"actions" 🐘 |
"chains" |
"drum-map" |
"drum-pads" 🐘 |
"params" |
"param-values" |
"return-chains" 🐘 |
"sample" |
"options" |
"*" 🐘
chains, return-chains, drum-pads = rack contents (use maxDepth; a chain lists its own gainDb/pan/sends only when non-default). params, param-values = parameters. drum-map = pad names keyed by note (drum name in stark, MIDI number in midi-json), plus drumRackPath naming the rack they belong to. sample = Simpler sample file path (flat top-level field; gainDb and other sample params are in params). actions = device-specific actions for update-device (name, signature, description). options = valid pseudo-param values (paramOptions) + dynamic catalogs for specialized devices (IR files, sidechain sources, wavetables) + Wavetable mod routes. "*" = all
maxDepthinteger Device tree depth for chains/drum-pads. 0=chains only with deviceCount, 1=direct devices, 2+=deeper
paramSearchstringFilter parameters by case-insensitive substring match on name

🐘 = large model only (hidden in small model mode)

Example output

Called with {"id":"401","include":["*"]}:

json
{
  "id": "401",
  "path": "t0/d0",
  "type": "drum-rack",
  "name": "Kit",
  "parameters": [
    {
      "id": "4010",
      "name": "Device On",
      "value": 1,
      "min": 0,
      "max": 1
    },
    {
      "id": "4011",
      "name": "Macro 1",
      "value": 0,
      "min": 0,
      "max": 127
    },
    {
      "id": "4012",
      "name": "Decay (Macro 2)",
      "value": 64,
      "min": 0,
      "max": 127
    }
  ],
  "drumMap": {
    "C1": "Kick",
    "D1": "Snare"
  },
  "drumRackPath": "t0/d0",
  "drumPads": [
    {
      "id": "408",
      "path": "t0/d0/pC1",
      "name": "Kick",
      "note": 36,
      "pitch": "C1",
      "chains": [
        {
          "id": "402",
          "path": "t0/d0/pC1/c0",
          "type": "Chain",
          "name": "Kick",
          "color": "#FF4C4C",
          "devices": [
            {
              "id": "403",
              "path": "t0/d0/pC1/c0/d0",
              "type": "instrument: Simpler",
              "name": "Kick"
            }
          ]
        }
      ]
    },
    {
      "id": "409",
      "path": "t0/d0/pD1",
      "name": "Snare",
      "note": 38,
      "pitch": "D1",
      "chains": [
        {
          "id": "404",
          "path": "t0/d0/pD1/c0",
          "type": "Chain",
          "name": "Snare",
          "color": "#FF4C4C",
          "devices": [
            {
              "id": "405",
              "path": "t0/d0/pD1/c0/d0",
              "type": "instrument: Simpler",
              "name": "Snare"
            }
          ]
        }
      ]
    }
  ]
}

Update Device (ppal-update-device) ​

  • Change device name
  • Change device parameter values (control knobs, dials, etc)
  • Update multiple devices at once
  • Move devices anywhere else in the Live Set, including into racks / wrapping in a new rack
  • Create, load, delete, revert, and randomize rack macro variations
  • A/B Compare with supported devices
  • Control chain and drum pad mute and solo state
  • Set a rack chain's own volume, pan, and send levels, several sends at once with the same sends argument update-track takes
  • Change the choke group and output MIDI note of drum chains
  • Move a drum pad to another pad, keeping its chain trim, choke group, and devices together
  • Load a sample into a Simpler instrument (see Create Device above)
Parameters
ParameterTypeDescription
idstringID(s) to update (device, chain, or drum pad), comma-separated for multiple
pathstringcomma-separated path(s) (e.g., 't1/d0', 't1/d0/c0', 't1/d0/pC1')
toPathstringmove to path (e.g., 't2', 't0/d0/c1', 't0/d0/pD1'). To move a whole drum pad (chain trim, choke group and devices together), target the pad path (e.g. path 't0/d0/pC1', toPath 't0/d0/pD1') rather than its device; a pad move stays within one rack and layers onto an occupied destination rather than replacing it. Moving just a device carries its chain's trim only when the destination chain is empty and untouched, and warns otherwise
namestringname for all, or comma-separated one per device, in order (not drum pads)
paramsarrayarray of {name, value}. name = a param name, or a param id from read-device; value in display units (enum string, note name, number) — use the unit read-device reports for that param, or no unit at all; a param with no unit takes a bare number. Many params only accept a coarse ladder of values, so a request lands on the nearest one — the response reports what each param reads as afterward. For a Drum Rack target, prefix the name with a pad path, e.g. {name:'pC1/sample', value:'<abs file path>'} sets pad C1's sample (auto-creates the pad's Simpler)
forcebooleanOnly when a sample write was skipped for replacing a pad's instrument: true replaces it anyway.
actions 🐘arrayDevice-specific action(s), function-call syntax: bare name or name(args). E.g. "reverse", "warpAs(4)", "setModulation('Osc 1 Pos','Env 2',0.5)"
macroVariation 🐘"create" |
"load" |
"delete" |
"revert" |
"randomize"
Rack only: create/load/delete/revert variation, or randomize macros. load/delete require macroVariationIndex. create always appends.
macroVariationIndex 🐘integer Rack only: variation index for load/delete operations (0-based)
macroCount 🐘integer Rack only: set visible macro count (0-16)
abCompare 🐘"a" |
"b" |
"save"
AB Compare: switch to 'a' or 'b' preset, or 'save' current to other slot
mutebooleanmute state (chains/drum pads only)
solobooleansolo state (chains/drum pads only)
colorstring#RRGGBB for all, or comma-separated one per chain, in order (chains only)
gainDb 🐘number chain's own gain in dB (chains only; a pad path works unless the pad has layers, which take a layer path like 't0/d0/pC1/c1')
pan 🐘number chain's own pan, -1 (left) to 1 (right) (chains only; a pad path works unless the pad has layers, which take a layer path)
sendGainDb 🐘number chain's send level in dB, requires sendReturn (chains only)
sendReturn 🐘stringrack return chain for sendGainDb: id, exact name (e.g. "a Reverb"), or letter (e.g. "a"); requires sendGainDb
sends 🐘arrayset several of a chain's sends at once: [{return, gainDb}], where return is a rack return chain's id, exact name, or letter — the return/returnId read-device reports. Use instead of sendGainDb + sendReturn, which set one
chokeGroup 🐘integer choke group 0-16, 0=none (drum chains only)
mappedPitch 🐘stringoutput MIDI note e.g. 'C3' (drum chains only)
wrapInRack 🐘booleanWrap device(s) in a new rack (auto-detects type from device)

🐘 = large model only (hidden in small model mode)

Example output

Called with {"id":"406","params":[{"name":"Filter Freq","value":"0.6"}]}:

json
{
  "id": "406",
  "path": "t1/d0",
  "params": [
    {
      "id": "4062",
      "name": "Filter Freq",
      "value": 0.6
    }
  ]
}

Advanced Tools ​

Live API (ppal-live-api) ​

Direct access to the Ableton Live Object Model for scripting and debugging.

Off by default. Producer Pal's specialized tools are tuned for reliable results across most models; the raw Live API is low-level and can give weaker results out of the box, so it's hidden rather than competing with them. It's an escape hatch for scripting and advanced workflows, especially with capable coding agents. Enable it on the Setup tab of the Producer Pal Max for Live device, or programmatically via POST /config (the npx producer-pal MCP server also accepts a --live-api flag). See the REST API's Live API section for the full operation reference and examples.

Parameters
ParameterTypeDescription
pathstringOptional LiveAPI path (e.g., 'live_set tracks 0')
operationsarray Array of operations to execute (max 50)
Example output

Called with {"path":"live_set","operations":[{"type":"getProperty","property":"tempo"},{"type":"getChildIds","property":"tracks"}]}:

json
{
  "path": "live_set",
  "id": "1",
  "results": [
    {
      "operation": {
        "type": "getProperty",
        "property": "tempo"
      },
      "result": 110
    },
    {
      "operation": {
        "type": "getChildIds",
        "property": "tracks"
      },
      "result": [
        "id 101",
        "id 102",
        "id 103"
      ]
    }
  ]
}

Spawn Subagent (spawn_subagent) ​

Built-in chat only. Every other tool on this page is an MCP tool the server provides. This one belongs to the Producer Pal Chat UI, which runs the nested session itself, so it isn't available over MCP, the REST API, or the Agent Skill.

Off by default. Turn it on with the experimental Subagent checkbox under Advanced on the chat's Tools tab. See Subagents for what the cards show, resuming a subagent, and choosing what workers run under.

  • Hands a self-contained subtask to a nested assistant with the full Producer Pal toolset, working in the same Live Set
  • Several calls in one response run their subtasks in parallel
  • A subagent can't spawn its own, and one turn gets at most 10 spawn attempts
  • The AI sees only each subagent's final message, labeled with its number
  • resumeFrom gives more work to a subagent that already ran, keeping everything it did and knows, instead of briefing a fresh one
Parameters
ParameterTypeDescription
taskstring What the subagent should do, with all the context it needs, since it can't see the conversation. With resumeFrom, just the follow-up.
resumeFromnumberNumber of an earlier subagent to continue instead of starting a fresh one.
Example output

Called with {"task":"On the Bass track, write a 4-bar bassline into scene 1 that follows the kick pattern in the Drums clip. A minor, eighth notes, root-heavy."}:

text
[subagent 1]
Wrote a 4-bar bassline to Bass, scene 1, named "Bass A". Eighth notes in A
minor, roots on the kick hits and passing tones between them. I left it
unlooped to match the Drums clip in that scene.

The result is plain text, not JSON: the [subagent N] label, then that subagent's own closing message. Pass the number back as resumeFrom to give the same subagent more work. The AI never sees the subagent's tool calls or working notes, only this; the full log stays in the chat UI's card.

Released under the GPL-3.0 License.