# Impact Studio agent guide

For AI agents that use Impact Studio, and for the people who connect them. It covers Impact Studio 1.2 and later; working with the user's own samples (sections 4 and 5.7) needs 1.3. Last updated 2026-10-01.

Read it before your first task. Inside Impact Studio's MCP server it is the resource `impact-studio://agent-guide`. Online it is at https://useimpactstudio.com/agents.md.

## 1. What Impact Studio is

- A Mac app (Apple silicon, macOS 14.4 or later) that makes cinematic impacts, hits and whooshes for trailers, film, games and music. The sound engine runs on the user's Mac, not in the cloud.
- Every sound is built from five layers: **Whoosh** (the pre-whoosh), **Sub**, **Crack**, **Body** and **Debris**.
- **AI can be on or off.** With AI on, the sound engine generates new sounds. With AI off (the user chose "Only my own samples — no AI", or turned AI off in **Settings › AI generation**), new sounds are built from the user's own sound files in **Library › My samples**, and no engine is needed. A sound built from samples is not AI: say it was built from the user's samples, never that it was generated.
- **The HIT marker is the start of the attack**: the point where Crack, Sub, Body and Debris strike. Every result gives it in seconds and in samples. A pre-whoosh (0.6 s by default) or a swell in a layer rises into the HIT, so a sound starts before its HIT on purpose.
- Every sound you make is saved as a **take** in the user's Takes, in a folder named Agent, tagged `agent`. A take never changes after it is made. Exports and finish settings write new files; they never edit the take. A change to how a take sounds is saved as a new take next to it (section 6).
- You can make impacts from words or a style, export any take in any studio format, rebuild a reference sound and grow variations from it, and place timed hits against picture in one full-length track (a cue sheet). You can also change how a take, or the sound open in the studio, sounds: bigger, more reverb, more Ember and so on.
- You cannot train models, delete takes, edit the sound the user has open in the studio, or change the license, storage or settings. Only the user can turn Agent access on.

## 2. Connecting

### What the user does once

1. Installs and activates Impact Studio (activation needs the internet once), then downloads the sound engine in the app (also once). A user who works only with their own samples can skip the engine: AI is then off, and new sounds are built from their samples.
2. Opens **Settings › Agent access** and turns on **Allow AI agents on this Mac**.
3. Adds Impact Studio to their MCP app. **Settings › Agent access › Connect an app** shows the exact setup for their Mac, with a Copy button.

Impact Studio has to be running when you call a tool. If it is installed in Applications and closed, the MCP server opens it in the background and waits for it (about 10 to 40 s). It won't while an update is installing, or when the app runs from its disk image.

### MCP setup

The MCP server is a stdio program inside the app. It takes no arguments, no token and no port: it finds the running app by itself.

For Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json`), Cursor (`~/.cursor/mcp.json`), LM Studio (Program tab › Install › Edit mcp.json) and other apps that read an `mcpServers` file:

```json
{
  "mcpServers": {
    "impact-studio": {
      "command": "/Applications/Impact Studio.app/Contents/Resources/bin/impact-studio-mcp"
    }
  }
}
```

If the file already has `mcpServers`, add only the `impact-studio` entry, then restart the app.

For Claude Code, run once in Terminal:

```sh
claude mcp add --transport stdio --scope user impact-studio -- "/Applications/Impact Studio.app/Contents/Resources/bin/impact-studio-mcp"
```

Any other MCP client: run that command over stdio. The server speaks MCP 2026-07-28, which has no `initialize`: send `io.modelcontextprotocol/protocolVersion`, `io.modelcontextprotocol/clientCapabilities` and `io.modelcontextprotocol/clientInfo` in each request's `_meta` (`server/discover` is supported). It also speaks the older `initialize` handshake with 2025-11-25, 2025-06-18, 2025-03-26 or 2024-11-05; any other version sent to `initialize` gets 2025-11-25. It keeps working across Impact Studio updates.

### Offline use and local models

- After the one-time activation (and the engine download, for AI), Impact Studio and Agent access work with no internet connection. The MCP server talks to the app on the same Mac; no server sits in between. A license check that can't reach the internet never switches the app off.
- Any MCP client works, including apps that run an AI model on the Mac, such as LM Studio (0.3.17 or later). With a local model, the whole workflow stays on the Mac and offline.
- Small local models call tools less reliably: they drop required fields or make up values. Use a model with good tool calling, and send a cue sheet with `dry_run` first.

### Cost

Agent access is included with Impact Studio. There is no fee per sound, no API key to buy and no server to pay for. The AI app itself may cost money under its own terms.

## 3. The tools

| Tool | Use it to | Key arguments | Typical time |
|---|---|---|---|
| `studio_status` | Check the app is ready (license, engine, AI on or off, the user's samples), what it is busy with, session rates, the exports folder and limits. Call it first. | none | < 0.1 s |
| `list_styles` | Get style ids, control values, models, reverb spaces, export formats and frame rates. | none | < 0.1 s |
| `preview_direction` | See how a direction will be read (family, label, layers, one-strike check) before you generate. Makes no sound. | `direction` or `style`, `controls`, `avoid` | < 1 s |
| `generate_impact` | Make one or two new sounds (A and B): generated with AI, or built from the user's samples (section 5.7). | `direction` or `style`, `source`, `variations` (1 or 2, default 2), `whoosh_s`, `length_s`, `hit_at_s`, `finish`, `output`, `name` | ~40 s per variation with AI; a few seconds from samples |
| `get_job` | Read a job once. | `job_id` | < 0.1 s |
| `wait_for_job` | Wait for a job, then get its state and result. | `job_id`, `wait_s` | up to 50 s |
| `cancel_job` | Stop a running agent job. Takes already made are kept. | `job_id` | ~1 s |
| `list_takes` | Find takes, newest first. Adjusted takes show their `parent` and `version`. With `scope: "samples"`, find the user's own samples instead. | `scope` (`agent` default, `all`, `samples`), `search`, `folder`, `favorite`, `limit`, `offset` | < 0.1 s |
| `get_take` | One take: HIT, length, session rate, layers, parent and version, and every sound control with its value and what it does. | `take_id` (or `"open"`), `metrics` | < 0.1 s; up to about 0.5 s with `metrics` |
| `export_take` | Export a take again at any rate and format, with a HIT position or a finish. The take never changes. | `take_id` (or `"open"`), `output`, `sample_rate`, `hit_at_s`, `finish`, `stems` | ~1 to 6 s |
| `adjust_take` | Change how a take sounds (bigger, more reverb, turn Ember up) and save it as a new take next to the original. Nothing is generated. | `take_id` (or `"open"`), `moves`, `amount`, `set`, `change`, `dry_run`, `name`, `note` | ~2 s |
| `reconstruct_from_audio` | Rebuild a reference sound file faithfully, and/or grow two variations from it. Needs AI on. | `audio_path`, `faithful`, `variations` (0 or 2), `flavour`, `variation`, `prompt`, `length_s` | ~4 s faithful, 20 to 60 s more for variations |
| `render_cue_sheet` | Place timed hits against picture: one full-length track, per-cue clips, a report, optional EDL and markers. | `timeline`, `cues`, `defaults`, `output`, `stems`, `markers`, `dry_run` | ~40 s per new sound with AI, a few seconds from samples, ~2 s to retime from takes |

Times were measured on a test Mac on 2026-09-30. Two variations take about twice as long as one.

### Arguments that make a sound

- **`direction`**: one sound in plain words, with material, size, attack and what hits what. "One heavy steel door slam with a sharp clanging attack" works better than "epic hit".
- **`style`**: a studio preset with its own direction and controls. The ids are `cinematic.colossal`, `cinematic.drum-swell`, `cinematic.orchestral-strike`, `metal-debris.steel-collision`, `metal-debris.glass-splinter`, `organic.stone-fracture`, `organic.wood-leather`, `sci-fi.plasma-rupture`, `sci-fi.gravity-well`, `horror.rust-dread`, `horror.organic-rupture`, `sub-minimal.pure-low-drop` and `sub-minimal.dry-punch`. `list_styles` says which are available on this Mac. A `direction` you give wins over the style's own text.
- **`controls`**: the studio's character menus. `material`: Hybrid, Metal, Organic, Orchestral, Synthetic. `size`: Tight, Heavy, Massive. `attack`: Soft bloom, Punchy, Sharp crack. `texture`: Clean, Gritty, Distorted. `mood`: Dark, Epic, Horror, Sci-fi, Heroic.
- **`avoid`**: what to keep out of the sound.
- **`source`**: `ai` generates the sound; `samples` builds it from the user's own samples (My samples in Impact Studio), with no AI. Leave it out to follow the studio: `studio_status` gives `default_source`. With AI off, only `samples` works; `ai` answers `ai_off`. Section 5.7 says what a build from samples picks and how the other arguments apply to it.
- **`whoosh_s`**: pre-whoosh length before the HIT, 0 to 1.2 s (default 0.6). Use 0 for a hit with no lead-in. The default pre-whoosh goes on every sound, so when the user wants one on some hits only, set `whoosh_s: 0` on the others. Built from samples, any value above 0 plays the whoosh sample's own rise (section 5.7).
- **Layers can't be switched off one by one.** Words like "no whoosh" or "no crack" in a direction don't remove a layer. Choose a style instead, and `whoosh_s: 0` for no pre-whoosh. Common requests: a sub drop is `sub-minimal.pure-low-drop` with `whoosh_s: 0`; a metal impact is `metal-debris.steel-collision`; a big trailer hit is `cinematic.colossal`; a short punch is `sub-minimal.dry-punch`.
- **`length_s`**: how long the layers are generated, 1 to 15 s (default 3). The finished sound usually rings on 1 to 2.5 s longer than that after the HIT, because the default finish adds a Hall reverb tail; `get_take` gives the real `duration_s`. To keep a sound inside a spot, set `finish.max_tail_s` (with `fade_out_s`), or use `timeline.tail: "extend"` in a cue sheet.
- **`spread`**: Subtle, Different (default) or Wild. **`generation_mode`**: `layers` (default) or `coherent`. **`model`** and **`whoosh_model`**: `builtin` (default), `my-signature` (the user's own trained layers) or an id from `list_styles`.
- **`hit_at_s`**: puts the HIT exactly this far into the file, 0.01 to 30 s. A longer lead-in is cut (`lead_truncated_s` says how much).
- **`sample_rate`**: the session rate the sound is rendered at, and the rate `hit.sample` counts in (default `default_session_rate`; for `export_take`, the take's own rate). `output.sample_rate` only sets the file's rate.
- **`output`**: `format` WAV, AIFF, FLAC or MP3; `sample_rate` 44100, 48000, 88200, 96000 or 192000 (MP3: 44100 or 48000); `bit_depth` "16", "24" or "32f" (32f is WAV only); `bitrate` for MP3; `ceiling_db` -0.1, -0.3, -1 or -3 (true peak); `dither`. Fields you leave out use the user's export defaults.
- **`stems: true`** also writes each layer as its own file. **`name`** (up to 80 characters) names the files and folder. Each variation also comes back with its own `name`: the take's name in the user's Takes, made by the studio. It can differ from your `name`, which names only the files, so tell the user that one. **`destination`** puts them in a subfolder, see section 4.

## 4. Core concepts

**take_id.** Looks like `20260930-141512-9f8e7d`. Every sound you make has one. Keep them: `export_take`, `get_take`, `adjust_take` and a cue's `take_id` reuse the sound without generating it again. In `get_take`, `export_take` and `adjust_take`, `take_id: "open"` is the sound open in the studio right now (section 6.1).

**Jobs.** `generate_impact`, `export_take`, `adjust_take`, `reconstruct_from_audio` and `render_cue_sheet` start a job and wait up to `wait_s` seconds (default 45, at most 50, which keeps each call under the 60 s timeout most MCP apps use).

- Finished in time: `state: "complete"` and the `result`.
- Still running: `state: "running"` and a `job_id`. Call `wait_for_job` with it until the state changes.
- Other end states: `failed`, `stopped` and `interrupted` (Impact Studio quit or crashed). `partial` lists takes the job already made; reuse their `take_id` instead of generating them again.
- Cancelling your own MCP request only ends the wait; the job keeps running. `cancel_job` stops it.
- Send a `progressToken` to get progress notifications. Clients that declare the MCP Tasks extension get a task instead of a wait.

**One task at a time.** Impact Studio runs one heavy task at a time, whether the user or an agent started it. Starting work while another task runs returns `busy` with `retry_after_s` (30). If the running job is yours, call `wait_for_job` instead. Don't retry in a tight loop.

**idempotency_key.** Any string of up to 64 letters, digits, `_`, `.`, `:` or `-`. Retrying a start call with the same key and the same arguments within 24 hours returns the original job instead of starting another. The same key with different arguments returns `idempotency_conflict`. Use one whenever you might retry after a timeout.

**Units.**

- Every time is in seconds unless the field name says otherwise (`*_samples`, `*_frame`, `*_frames`, `*_timecode`, `offset_ms`, `gain_db`).
- Samples count at the session or track rate: 44100, 48000, 88200, 96000 or 192000 Hz. The default is `default_session_rate` from `studio_status`.
- Timecode is `HH:MM:SS:FF`. For drop frame (`29.97df`, `59.94df`) write `;` before the frames: `01:00:00;02`.
- Frame rates: `23.976`, `24`, `25`, `29.97`, `29.97df`, `30`, `48`, `50`, `59.94`, `59.94df`, `60`. Never guess the frame rate; ask the user or read it from their project.
- `start_timecode` is the timecode of the track's first sample (default `00:00:00:00`; film reels often start at `01:00:00:00`). `at_timecode` is absolute, on that same clock. `at_seconds`, `at_frame` and `at_samples` count from the track start.
- A requested time is rounded once to the nearest sample. Timecodes, frames and sample positions are exact.

**Where files go.** Only into the user's Agent Exports folder (default `~/Music/Impact Studio/Agent Exports`; `studio_status` gives it as `exports.root`). `adjust_take` writes no file there: it saves a take in the studio, and `export_take` makes a file of it.

- Each job that writes files makes a new folder named `YYYY-MM-DD HHMMSS <name>`, or uses `destination`: 1 to 3 folder names inside Agent Exports, like `Project X/Reel 1`. A `destination` that already exists is used again.
- Nothing is overwritten: a file name that exists gets " 2", " 3" and so on. In a reused `destination` that includes the result file, so the second job's result can be `result 2.json`; the result's `manifest` field names it.
- Results give absolute paths. The result file holds the full result, and each audio file has a signed `.provenance.json` beside it.

**The user's sound files.** Impact Studio never opens a path you give it. For `audio_path`, the MCP server reads the file with your MCP app's permissions and hands it to Impact Studio on the same Mac. It must be an absolute path to a WAV, AIFF or FLAC file of up to 100 MB, and not inside an app or Impact Studio's own data folders.

**Which takes you see.** Agents see all takes, including the user's own, and the user's saved directions (`my_directions` in `list_styles`), unless the user turned off **Share my takes with agents** in Settings. `list_takes` lists the sounds agents made unless you pass `scope: "all"`. With sharing off, the user's takes answer `takes_not_shared`, and so do `"open"` (the sound open in the studio) and the takes an agent adjusted from the user's takes or from the open sound. The user's own samples are shared separately, only while **Share my samples with agents** is on (it is off until the user turns it on); see section 5.7.

**AI on or off.** `studio_status` gives `ai.enabled`, `ai.ready` (AI is on and the engine is set up), `default_source` (`ai` or `samples`) and `samples` (`count`, `by_category`, `scanning`, `shared`). With AI off:

- `generate_impact` and the new sounds in a cue sheet are built from the user's samples. `source: "ai"` and `reconstruct_from_audio` answer `ai_off`.
- `list_styles` lists no models, and `engine.ready` may be false. That is expected; don't ask the user to set up the engine unless they want AI.
- Everything else works as usual. `export_take`, `adjust_take`, `get_take`, `list_takes` and cue sheets that place takes, files or samples never need the engine, with AI on or off.

With AI on, `source: "samples"` builds from the user's samples too. A cue sheet's new sounds always follow the studio's mode; to place a sample build while AI is on, build it with `generate_impact` first and give the cue its `take_id`.

## 5. Recipes

### 5.1 Hits to picture with a cue sheet

1. Call `studio_status`. If the license is not active, or AI is on (`ai.enabled`) and the engine is not ready, tell the user (section 9). With AI off, new sounds are built from the user's samples and no engine is needed. Note `busy` and `default_session_rate`.
2. Get from the user: the frame rate, the start timecode, the end timecode (or the length), and every hit with its timecode and what it is. Ask when something is missing; don't make up timecodes.
3. Write one cue per hit. Give each a `direction` or `style`, a `take_id` you already have, a `sample_id` (section 5.6), or `same_as` another cue for the same sound. With AI off, a `direction` or `style` is built from the user's samples. For a cue near the end of the timeline, remember that sounds ring on past `length_s` (section 3): set `finish.max_tail_s` so the tail ends in time, or `timeline.tail: "extend"`; otherwise the tail is cut at the end, with a warning.
4. Send it with `"dry_run": true`. Nothing is generated. Check each cue's `target_timecode` against what the user asked for, and for a long sheet tell the user the estimate (`estimate_s.low` to `estimate_s.high` seconds). The estimate counts AI time for every new sound; built from samples, each takes a few seconds.
5. Send the same sheet without `dry_run`, with an `idempotency_key`. Call `wait_for_job` until it is complete.
6. Tell the user where the track is (a DAW spots it to the start timecode by its BWF timestamp), where the clips and the report are, and which cues to listen to: those whose `onset_check.status` is `review`. Never move a cue by `measured_offset_ms` (section 7).
7. After a picture change, send the sheet again with each cue's `take_id` from the result (`cues[].source.take_id`) and the new times. Nothing is generated again, and it takes a few seconds. Give each cut its own `destination` (for example `Project X/Reel 1/Cut 2`) so its files don't mix with the last cut's.

```json
{
  "name": "Reel 1 hits",
  "timeline": {"fps": "24", "start_timecode": "01:00:00:00", "end_timecode": "01:05:00:00"},
  "defaults": {"variations": 1, "finish": {"max_tail_s": 3.0}},
  "cues": [
    {"id": "C1", "name": "Door slam", "at_timecode": "01:00:02:00", "direction": "One heavy steel door slam with a sharp clanging attack", "whoosh_s": 0.3},
    {"id": "C2", "name": "Title hit", "at_seconds": 7.25, "style": "cinematic.colossal"},
    {"id": "C3", "name": "Door again", "at_timecode": "01:00:15:12", "same_as": "C1", "gain_db": -3}
  ],
  "stems": "clips",
  "markers": ["edl", "wav_cues"],
  "destination": "Project X/Reel 1",
  "idempotency_key": "reel1-cut3"
}
```

Cue sheet fields:

- **`timeline`**: `fps` (needed for timecode or frame positions, and for EDL and markers), `start_timecode`, exactly one of `end_timecode` (exclusive), `duration_seconds`, `duration_frames` or `duration_samples`, then `sample_rate` and `tail` (`truncate`, the default, stops tails at the end; `extend` lets them ring up to 30 s past it).
- **Each cue**: `id` (default C001, C002 and so on), `name`, exactly one position (`at_timecode`, `at_seconds`, `at_frame` or `at_samples`), `offset_ms` (-1000 to 1000), and exactly one source: a `direction` or `style` (in the cue or in `defaults`), `take_id`, `sample_id`, `audio_path` or `same_as`. Also `variations` (1 or 2) with `pick` (A or B), `finish`, `gain_db` (-60 to 12), `sync` (`hit`, the default, or `start`) and `sync_at_s`.
- **`defaults`**: the same sound and cue fields for every cue. A cue's own fields win.
- **`output`**: `format` WAV (default), AIFF or FLAC (no MP3: its encoder delay breaks sample accuracy), `bit_depth` (default "24"), `ceiling_db`, `dither`, `normalize` (`ceiling`, the default, turns the whole track down once if it would go over the ceiling; `none` keeps levels as placed).
- **`stems`**: `clips` (default, one timestamped file per cue), `full_length` (one full-length file per cue) or `none`. **`markers`**: any of `edl` (needs `stems: "clips"`, WAV and `fps`), `resolve_markers` (a DaVinci Resolve marker EDL) and `wav_cues` (cue points inside the WAV). **`on_cue_error`**: `stop` (default) or `skip`.
- Limits: 1 to 500 cues, up to 100 new sounds, tracks up to 3 hours.

The result has `track.path`, and per cue `hit_sample`, `hit_timecode`, `clip.path`, `source.take_id`, `placement_check` and `onset_check`, plus `files.report_json`, `files.report_csv`, `files.edl`, `failed`, `generated`, `reused` and `renders`. A result with more than 25 cues lists 25 of them (the ones to check first) and gives the `take_id` of the rest in `other_cue_sources`; the report files always list every cue.

- **`generated`**: new sounds made for this sheet (built from samples while AI is off; the field keeps its name).
- **`reused`**: sounds placed from a take's own render as it is. New takes count too, so a first run can say `generated: 3` and `reused: 3`. Don't tell the user that sounds were reused unless their cues had a `take_id` or `same_as`.
- **`renders`**: sounds rendered again for this sheet, for example with a `finish` or at another rate.
- **Clips.** A clip starts on the whole frame at or before the sound's first sample, with silence in front, so the EDL lines up; with a pre-whoosh that is before the cue. Its file name starts with the cue id and that start timecode, like `C3 01001509 Trailer hit.wav` for a cue at 01:00:16:00. `clip.hit_offset_samples` is where the HIT sits in the clip. When you tell the user where a hit is, give the cue's `hit_timecode`, not the file name.

### 5.2 Make a sound and export it

1. Optional: `preview_direction` shows how your words will be read, for example the label "Metal collision" and whether it expects one clear strike.
2. `generate_impact` with `direction` (or `style`), `variations: 2` and a `name`. Each variation (A and B) comes back with its `take_id`, `name`, `file.path`, `hit.seconds` and `hit.sample`. That `name` is the take's name in the user's Takes, made by the studio; it can differ from your `name`, which names only the files. Tell the user that name.
3. Let the user listen and pick. For a delivery spec, call `export_take` with the picked `take_id`, for example `"output": {"format": "WAV", "sample_rate": 96000, "bit_depth": "24"}` and `"hit_at_s": 0.5`.

### 5.3 Deliver a file with a different finish

To change the sound itself, so the user can hear the result in the studio and keep it, use `adjust_take` (5.4 and section 6). For a delivered file only, call `export_take` with a `finish`. It writes a new file and the take stays as it was. Keys you leave out keep the sound's own values. Exports stay under the true-peak ceiling (`output.ceiling_db`, or the user's default): a louder result is turned down, never clipped.

| The user asks for | Try |
|---|---|
| more reverb, a bigger room | `reverb` up (0 to 1), `space` Hall, Cathedral or Cavern, a longer `tail_s` (0.3 to 8) |
| further away | more `reverb`, a longer `tail_s` and less `punch`. `distance` (0 to 0.2 s) is only the reverb's pre-delay: it keeps the attack clean but does not move the sound away. |
| heavier, more low end | `weight` up (the Sub level, 0 to 1.5) |
| more punch | `punch` up (0 to 1) |
| dirtier, grittier | `drive` up (0 to 1) |
| wider or narrower | `width` above or below 1 (0 to 1.8) |
| more detail and presence | `ember` up (0 to 1, the studio's exciter) |
| less whoosh | `lead_level` down (0 to 1.5), or generate again with `whoosh_s: 0` |
| a shorter tail | `max_tail_s` (0.05 to 30 s after the HIT) with `fade_out_s` |

The other spaces are Studio, Plate and Reverse. Say what you changed, and give the new file's path.

### 5.4 "Make that bigger and add more reverb"

1. Find "that" sound: the last take you made or adjusted in this conversation. If there is none, use `take_id: "open"`, the sound the user has open in the studio. When you are not sure, `get_take` with `"open"` gives its name; check it with the user.
2. Optional: send the call with `"dry_run": true` to see the planned moves and the new take's name. Nothing is rendered or saved.
3. Call `adjust_take`:

```json
{"take_id": "open", "moves": ["bigger", "more_reverb"]}
```

4. Read the result: `take.name`, `changes` (what moved), `checks` (whether each word measurably did its job), `safety` (`hit_clear`, `mono_safe`, the true peak) and `warnings`. Pass on the `summary` in your own words, including any word that missed and why.
5. Tell the user the new take's name. It is in their Takes, next to the original, and they click it to hear it. The original is unchanged, so if they prefer it, nothing needs undoing.
6. "More" is another `adjust_take` on the new `take_id`, optionally with `"amount": "a_lot"`. For a file, call `export_take` with the new `take_id`.

### 5.5 Rebuild a reference sound

`reconstruct_from_audio` with `audio_path` (a WAV, AIFF or FLAC file of 0.04 to 15 s). By default you get a faithful rebuild plus two new variations, Cinder and Flare. `variations: 0` skips them; `faithful: false` gives only the variations. `variation` (0.05 to 0.95, default 0.65) sets how far they move from the reference, and `flavour` gives them a character: `balanced`, `weight`, `bright`, `metal`, `air` or `dark`. `prompt` (up to 1500 characters) adds your own words to steer the variations. `length_s: 0` (the default) keeps the reference's length. Only use a file the user has the rights to (section 10).

### 5.6 Put the user's own sound file on a cue

Give the cue an `audio_path` (WAV, AIFF or FLAC, up to 120 s) and a position. The file is placed untouched: it is only resampled to the track rate. `sync: "hit"` (the default) puts its detected attack on the cue, refined to 0.5 ms. `sync: "start"` puts its first sample there. `sync_at_s` puts that point of the file there, such as the peak of a riser. `gain_db`, `finish.max_tail_s` and `finish.fade_out_s` apply to such a file; other finish keys don't. The same path used by several cues is handed over once.

A sample from the user's library works the same way, without a path: give the cue a `sample_id` from `list_takes` with `scope: "samples"` (section 5.7). Impact Studio reads the file itself, so its path never passes through you. It has to be a WAV, AIFF or FLAC file of up to 120 s on a connected drive (`available: true`); an MP3 sample can't be placed this way. A sync point the user set on the sample lands on the cue, unless you give `sync: "start"` or `sync_at_s`. It doesn't count toward the 2 GB a day (section 8). In the result the cue shows as `source.type: "upload"` with an `asset_id`.

### 5.7 Build from the user's own samples

`generate_impact` with `source: "samples"`, or with no `source` while AI is off, builds A and B only from the user's own files in **Library › My samples**, with no AI, no model and no built-in audio. It takes a few seconds. Impact Studio sorts each sample into a category: Whoosh, Riser, Sub / boom, Crack / transient, Body / impact, Full hit, Debris / tail or Other.

What a build picks:

- **One sample per layer, from that layer's categories.** Whoosh from Whoosh (Riser only when your words say riser, rise, rising, swell, build, build-up or uplifter, or when there are no whooshes, so don't write "build" in a `direction` unless you want a riser), Sub, Crack and Debris from their own, Body from Body / impact or Full hit. Never Other, samples the user marked "Don't use in Build", or samples still being measured. A layer with nothing to pick stays off.
- **Order.** Each word of your `direction` (or the style's) that matches a sample's name, folders, tags or embedded description scores 2, each `material`, `size`, `texture` and `mood` word 1, a favourite 1, and a sample from the user's last 5 builds −1. Sound words lean the order: dark or warm, bright or crisp (tone); short, tight or dry, long, big or huge (tail); deep or heavy (low end). The Body leans to samples near `length_s`, and "full", "complete", "designed" or "finished" lean to Full hits. `avoid` leaves out samples that match its words. Ties fall in random order.
- **`spread`** is how far down that order a pick may come from: Subtle the top 3, Different (default) the top 30% (at least 5), Wild anywhere. With Different, words steer gently; use Subtle when the user names a particular sound.
- **A and B** use different samples on every layer that has more than one to pick from.
- **The full-hit rule.** When the Body is a full hit (a Full hit, or a Body with heavy low end or a tail of 4 s or more), the sound is Body plus Whoosh: Sub, Crack and Debris stay off unless your words ask for them. "sub", "low", "deep", "bigger", "heavy", "bass" or "boom" bring back the Sub; "crack", "snap", "sharp", "crisp" or "punchy" the Crack; "debris", "rubble", "shatter", "glass" or "shard" the Debris. A layer brought back sits a few dB under the Body where it is heard (Sub in the lows, Crack and Debris in the highs); one that wouldn't be heard, or a Sub that would cancel the Body's low end, stays off. Most trailer hits in sample libraries are full hits, so most builds are Body plus Whoosh.
- **Samples play as they are**: no crop, stretch or pitch, levels matched by gain only. Layers start with no reverb of their own; the master keeps the studio's light Hall (more with words like "reverb", none with "dry"). A file that holds several hits plays only its first. A Debris tail plays at most 1 s past `length_s`, then fades.
- **The HIT** sits after the longest lead-in of the picked samples, so no sample is cut at the start.

How the other arguments apply:

- `whoosh_s: 0` leaves the whoosh out. Any other value keeps it, and the whoosh plays its whole rise, which can be longer than 1.2 s, so the sound can start well before its HIT. `hit_at_s` cuts a longer lead-in (`lead_truncated_s` says how much).
- `length_s` only steers the Body pick and caps the Debris tail; nothing is stretched to it.
- `model`, `whoosh_model` and `generation_mode` are ignored. `preview_direction` reads your words the same way, but the samples picked decide which layers sound.
- `variations`, `hit_at_s`, `finish`, `output`, `stems`, `name` and `destination` work as usual.

What to tell the user:

- The result has `source: "samples"`. Say the sounds were built from their samples; never call them generated or AI-made. In `get_take`, the layers that sound have `source: "sample"`.
- Takes you build are kept. The studio removes unkept sample builds after 7 days, but never the ones agents made.
- With no samples yet, the call answers `invalid_request`: "Add a folder of your samples in Library › My samples first." Ask the user to do that. Just after a folder is added it may say the samples are still being measured; try again in a moment (`samples.scanning` in `studio_status`).

Finding samples: `list_takes` with `scope: "samples"`, only while **Share my samples with agents** is on (otherwise `samples_not_shared`).

- Each row has `sample_id`, `name`, `category` (`whoosh`, `riser`, `sub`, `crack`, `body`, `full`, `debris`, `other` or `unsorted`), `folder` (the My samples folder's name and subfolders, like `Trailer Library/Glass/Hits`), `tags`, `favorite`, `length_s`, `hit_s` (the user's sync point, or the detected HIT), `brightness` (`dark`, `balanced`, `bright` or null), `sample_rate`, `channels` and `available` (usable and on a connected drive). Never where the file is.
- `search`: every word has to match a name, folder, tag or embedded description, as the start of a word or a common other spelling (woosh finds Whoosh); `-word` leaves matches out. `folder`: a category (`full` or `Full hit`) or the name of a folder the user added to My samples (the first part of a row's `folder`; for a subfolder, put its name in `search`). `favorite: true`: favourites only.
- Place one on a cue with its `sample_id` (section 5.6). `generate_impact` takes no `sample_id`: words from a sample's name in your `direction`, with `spread: "Subtle"`, make it likely to be picked.

### 5.8 Only the user's own samples: a hit for a cue, then change it

"Build a hit for the vault door at 01:02:10:05 and make it bigger", from a user who works only with their own samples:

1. `studio_status`: `samples.count` above 0 and `samples.scanning` false. With no samples, ask the user to add a folder in **Library › My samples**.
2. Build A and B. `source` can be left out while AI is off; with AI on, it is needed.

```json
{"direction": "Huge dark metal slam with a deep boom", "source": "samples", "variations": 2, "whoosh_s": 0, "spread": "Subtle", "name": "Vault door"}
```

"deep boom" asks for a Sub under a full-hit Body; `whoosh_s: 0` leaves out the lead-in for a hard cut.

3. Tell the user both take names, say they were built from their samples, and let them pick.
4. Change the pick with `adjust_take` (section 6). It saves a new take and leaves the original alone:

```json
{"take_id": "20261001-101512-4b5c6d", "moves": ["bigger", "more_reverb"]}
```

Words only move what the take has: on a take with no Sub, `bigger` and `heavier` raise the Body's low end and never switch on the synth sub. For other samples, build again with other words, or let the user step through a layer's samples with ◀ ▶ in the studio; `export_take` with `take_id: "open"` then delivers what they hear.

5. Place the new take with `render_cue_sheet` (`dry_run` first). Nothing is built again:

```json
{"timeline": {"fps": "24", "start_timecode": "01:00:00:00", "end_timecode": "01:05:00:00"},
 "cues": [{"id": "C4", "name": "Vault door", "at_timecode": "01:02:10:05", "take_id": "<the adjusted take_id>"}]}
```

## 6. Change how a sound sounds

`adjust_take` changes how a take sounds and saves the result as a **new take** next to the original. The original never changes. Nothing is generated: the job re-renders the take's own layers with new settings, measures the result and saves it, in about 2 s. It works the same on takes built from the user's samples, and never needs the engine. The new take appears in the user's Takes, marked "Adjusted · from <the take it was made from>", and the user clicks it to hear it. It works the same with nobody at the studio, for example from a film-scoring tool: the result gives the new `take_id`, and `export_take` makes a file of it.

### 6.1 Which sound

- `take_id`: any take you can see (from a result or `list_takes`).
- `take_id: "open"`: the sound open in the studio right now, as the user left it (the studio saves it 0.6 s after each change). It is only read, never changed. `get_take` with `"open"` shows it: `open.source_take_id` is the take it was loaded from and `open.edited_since_take` says whether the user changed it since. `"open"` answers `nothing_open` when no sound is loaded, and `takes_not_shared` while the user has **Share my takes with agents** off.
- "That sound" in a conversation is the last take you made or adjusted. If there is none, it is `"open"`.

### 6.2 Words

Put the user's request into `moves`, a list of up to 6 sound words. Each word moves a few controls by measured amounts and stays inside safe limits. `amount` scales every word: `subtle` (×0.6), `normal` (the default) or `a_lot` (×2). Two opposite words in one call are refused (`bigger` and `smaller`, `wider` and `narrower`, and so on); `heavier` with `less_boomy` is allowed.

| Word | What the user hears | What moves (at `normal`) |
|---|---|---|
| `bigger` | A bigger space and more weight | tail +1.2 s; reverb +0.08; sub +2 dB, or the Body's low shelf +2.5 dB when no sub sounds; width +0.1 only when correlation is 0.5 or more and mono bass loss under 1.5 dB. With `more_reverb` in the same call, that word sets the reverb. |
| `smaller` | Shorter, lighter, narrower | reverb −0.08, tail −1.2 s, Ember −0.15, width −0.1, sub −1.5 dB |
| `more_reverb` | More room, a longer tail | reverb +0.1, tail +1.5 s |
| `less_reverb` | Drier | reverb −0.08, tail −1 s |
| `longer_tail` | Rings on longer | tail +1.5 s (reverb +0.04 when it is under 0.12) |
| `shorter_tail` | Stops sooner | tail ×0.6, reverb −0.03; a sound that rings more than 1.2 s is also cut at 60 % of its measured tail (at least 0.8 s after the HIT), with a short fade |
| `more_distant` | Farther away | reverb +0.12, tail +0.8 s, punch −0.15, crack −2 dB, then every layer −1.5 dB |
| `closer` | Closer and drier, a harder front | reverb −0.1, tail −1 s, punch +0.25, crack +1.5 dB |
| `wider` | Wider stereo | width +0.15; when the bass is already wide, Ember +0.2 instead |
| `narrower` | Narrower stereo | width −0.2 |
| `brighter` | More top end and snap | Ember +0.2, crack tone +0.08 |
| `darker` | Less top end | Ember −0.2, crack tone −0.12, debris tone −0.1, Body tone −0.08 (with `a_lot` also crack −1.5 dB); a Plate room becomes Hall |
| `punchier` | A harder, sharper hit | punch +0.3, crack +2 dB, reverb −0.03 (−0.06 from 0.3) |
| `softer` | A softer attack | punch −0.25, crack −3 dB |
| `heavier` | More low end | sub +2 dB, or the Body's low shelf +3 dB when no sub sounds |
| `lighter` | Less low end | sub −2 dB, or the Body's low shelf −3 dB |
| `less_boomy` | Less low boom; takes some weight too; the sub stays | Body low shelf −4 dB (not together with `heavier`), crack and debris low shelves −4 dB when their own reverb is 0.3 or more, reverb −0.03 |
| `more_aggressive` | Grittier and harder | drive +0.15, Ember +0.15, punch +0.15, crack +1.5 dB, reverb −0.03 |
| `cleaner` | Less grit | drive −0.15, Ember −0.1 |
| `louder` | Louder | every sounding layer +2 dB; a sound already at the ceiling does not change |
| `quieter` | Quieter | every sounding layer −3 dB, plus however far the limiter already turns the sound down |
| `more_whoosh` | A louder rush into the hit | whoosh +2 dB |
| `less_whoosh` | A quieter rush into the hit | whoosh −3 dB |
| `cut_whoosh_tail` | The whoosh stops just after the HIT instead of ringing on under it | the whoosh fades out 0.08 s after the HIT with a smooth fade (`subtle` 0.2 s, `a_lot` 0.04 s); a shorter cut stays as it is. Not on a whoosh fitted to end at the HIT. |

Everyday words: huge is `bigger`; roomy is `more_reverb`; muddy is `less_boomy`; harsh is `darker`; tight is `shorter_tail` with `punchier`; far away is `more_distant`; in your face is `closer`; gritty is `more_aggressive`; more sub is `heavier`.

Limits the words keep:

- Every word stops at each control's safe range (`safe` in `get_take` `controls`) and never pushes a value that is already past it further. Words leave silent layers alone and never switch a layer on.
- Reverb: words stop at 0.35 (0.40 with `a_lot`) and add at most 0.12 per call (0.20 with `a_lot`). When words take the reverb to 0.25 or more in a Studio, Plate or Hall room, the pre-delay (`distance`) goes to 0.05 s to keep the attack clean (not with `more_distant`).
- Layer levels: words add at most 3 dB to a layer per call.
- Drive: only `more_aggressive` raises it, and never above 0.35. A sound is "at the ceiling" when the limiter already turns it down 1 dB or more (or limits 1.5 dB or more). `louder` then answers `nothing_to_change`: more level would only come from distortion. Ask the user whether they want `more_aggressive`, or set `drive`.
- Wide bass (a mono fold-down already loses more than 2 dB of it): words don't raise `width`, `bigger` skips its reverb step, `more_reverb` and `more_distant` add half as much reverb, and `more_reverb` adds 2 s of tail. `wider` then raises Ember instead, whose added width stays out of the bass.
- On a sound at the ceiling, `brighter` (Ember 0.4 or more), `punchier` (Ember 0.3 or more) and `wider` (when it raised Ember) also turn on `ember_match`.
- Tone moves skip layers that use movement curves; the notes say so.
- `less_boomy` keeps a Cavern or Cathedral room at `normal` and says a Hall room would cut more boom. With `a_lot` it switches to Hall.

### 6.3 Exact values: set and change

Use them when the user names a control or a number. Words, `set` and `change` can go in one call.

- `set`: exact values, like `{"space": "Cathedral", "reverb": 0.4}`.
- `change`: amounts added to the current values, with layer levels in dB as `<layer>_level_db` (−24 to +12). "Turn Ember up" is `{"ember": 0.2}`; "lower the whoosh 3 dB" is `{"whoosh_level_db": -3}`. Every number control except `max_tail_s` and `fade_out_s` can be changed. A silent layer can't be scaled: `set` its level to switch it on.
- For the same control, `set` wins over `change`, and `change` wins over words.
- Exact values may go past a control's safe range, up to its full range. They are kept as asked and never taken back by the guard; a value above the safe range is marked `beyond_safe` and noted.
- Setting `sub_level` above 0 on a take whose sub has no audio plays the studio's synth sub (a tone, not deep sub); the notes say so. In `get_take`, each layer's `source` is `ai`, `sample` (the user's own audio), `synth` or `none`.

### 6.4 The controls

After the layers are summed, the whole sound runs through the reverb (`space`, `reverb`, `tail_s`, `distance`), then `drive`, `width`, Ember and the true-peak limiter, in that order. `get_take` returns every control in `controls`: its `value`, `range`, `safe` range, `studio` name and `about`, a fuller version of the text below.

| Control | In the studio | Range (words stay in) | Typical move | What it does |
|---|---|---|---|---|
| `space` | REVERB SPACE | Studio, Plate, Hall, Cathedral, Cavern, Reverse | | The reverb room, heard only when `reverb` is above 0. Hall: wide and cinematic (new takes). Studio: small and tight. Plate: bright, the least low end. Cathedral: tall and dark, adds low end. Cavern: darkest and boomiest; above reverb 0.3 it blurs the hit and widens the bass. Reverse: the reverb swells up after each hit and stops abruptly; it is not a riser into the hit. |
| `reverb` | SPACE knob | 0 to 1 (0 to 0.35) | 0.05 to 0.1 | How much reverb, as a dry/wet crossfade on the whole sound, sub included. New takes 0.10; finished trailer hits often 0.25 to 0.38. 0.2 to 0.35 sounds bigger and wider; past 0.35 the attack softens, and from 0.6 the hit is no longer clear. The layers have their own reverb, so 0 is not bone dry. |
| `tail_s` | TAIL | 0.3 to 8 s (0.5 to 6) | 1 to 1.5 s | Reverb decay time (new takes 1.8 s); 3.5 to 5 s is a big hall. You hear it once it is longer than the sound's own ring (about 2 to 3 s), or with more reverb. The file gets longer by as much. |
| `distance` | DISTANCE | 0 to 0.2 s (0 to 0.15) | 0.01 to 0.025 s | Reverb pre-delay (default 0.025 s): the reverb starts this much after the dry hit, so the attack stays clean with more reverb. 0.1 or more at reverb 0.3 lands the reverb as a second hit. It does nothing at reverb 0, and on its own it does not move the sound away. |
| `drive` | DRIVE | 0 to 1 (0 to 0.35) | 0.1 to 0.15 | Saturation (Clean 0, Warm below 0.4, Gritty below 0.75, then Crushed). The sound gets denser, warmer and grittier and the hit flatter. From 0.5 it is real distortion and leaves the sound 1.5 to 4.5 dB under the ceiling. |
| `width` | WIDTH | 0 to 1.8 (0.5 to 1.4) | 0.1 to 0.2 | Stereo width (1 = as made, 0 = mono). It widens the bass too, so it is not mono-safe: keep it at 1.4 or below, and at 1.2 or below with reverb 0.3 or more or Ember 0.7 or more. |
| `ember` | Ember dial | 0 to 1 (0 to 0.7) | 0.15 to 0.2 | The studio's exciter, see below. |
| `ember_match` | Level match | on or off | | Ember changes tone and width but not level. Turn it on for loud sounds with Ember at 0.4 or more. |
| `punch` | PUNCH (Body) | 0 to 1 (0 to 0.7) | 0.25 to 0.3 | Attack boost on the Body at the HIT: 1.0 adds about 7 dB at the strike, gone after about 0.1 s. A harder, sharper hit that costs a little loudness on loud sounds. 0.3 to 0.6 is typical; small effect when the sub or crack sets the peaks. |
| `max_tail_s` | main edit END | 0.05 to 30 s | | Cuts the sound this many seconds after the HIT, with a smooth fade. A length cut, not less reverb; under 0.5 s it cuts into the hit. The HIT stays where it sounds and is fixed in the new take. |
| `fade_out_s` | main edit FADE OUT | 0 to 10 s | | The fade at the end: 0.3 s with a new `max_tail_s` unless given, and at most half of the kept tail. |
| `whoosh_level` | Whoosh LEVEL | 0 to 3 (0 to 1) | 1.5 to 3 dB | The pre-whoosh, the rush into the HIT (new takes 0.65). When the whoosh would cover the hit, the app turns it back down, by up to 3 dB, to keep the hit clear. 0 silences it and the HIT stays where it is. |
| `sub_level` | Sub LEVEL | 0 to 3 (0 to 1.4) | 1.5 to 3 dB | The low-end boom (typical 0.8 to 1.4). More sub on a loud sound turns the rest of the mix down a little. |
| `crack_level` | Crack LEVEL | 0 to 3 (0 to 2.5) | 1.5 to 3 dB | The short bright snap at the HIT; the strongest control for bright and sharp. |
| `body_level` | Body LEVEL | 0 to 3 (0 to 2.5) | 1.5 to 3 dB | The main hit. In a single-layer take (coherent mode or a reconstruction) the Body is the whole sound. |
| `debris_level` | Debris LEVEL | 0 to 3 (0 to 3) | 1.5 to 3 dB | Fragments and texture after the hit. |
| `whoosh_cut_s` | Whoosh Cut tail | 0 to 1 s | | How quickly the whoosh fades out after the HIT (0 = its whole tail). Only the word `cut_whoosh_tail` moves it; it is not in `set` or `change`. |
| `whoosh_tone`, `crack_tone`, `body_tone`, `debris_tone` | TONE | 0 to 1 (0.25 to 0.75) | 0.08 to 0.12 | 0.5 is the layer as made. Lower is a low-pass: 0.45 is about 9 kHz, 0.4 about 6 kHz, 0.3 about 2.5 kHz, 0.25 about 1.6 kHz (very dark). Higher lifts up to 5 dB above 2.5 kHz. No effect on a layer that uses movement curves. |
| `crack_low_db`, `body_low_db`, `debris_low_db` | EQ LOW | −12 to 12 dB (−9 to 6) | 2 to 3 dB | A low shelf at 120 Hz: −3 dB for less boom, +2 to +3 dB on the Body for weight when there is no AI sub. A layer whose EQ is off gets it switched on with its other bands flat. |

Layer pitch, timing and fades, the layers' own reverb, the EQ's other bands and the synth sub's note are not controls here. The user can change them in the studio, or you can make a new sound. A whoosh is placed for you: a sample whoosh lands with its peak, the moment it reaches full level, on the HIT, or at the user's sync point.

**Ember**, the dial in the studio, is 0 to 1 here (the dial's 0 to 100: CLEAN at 0, SILK below 30, GLOW below 70, then INFERNO). It works on the whole finished sound and does several things at once:

- **Detail and density.** It lifts the quiet parts of the sound in three bands (lows, mids and highs, most in the highs) and adds presence to the mids and highs. This is upward compression: texture, decays and tails come up, while the attack is never turned down. Tails ring longer.
- **Harmonics.** A soft saturation, mixed in lightly (a tenth of the signal at 1.0), adds a little grit and warmth. For real distortion, use `drive`.
- **Width.** It widens the stereo image above about 300 Hz and adds a shimmer in the sides. The bass stays in the middle, and the added width cancels out when the sound is played in mono.
- **Level.** It adds up to 3.5 dB of gain at 1.0 on top of the lifted detail, so the sound gets louder going into the limiter. On a loud sound the limiter takes that back by turning the whole sound down (at 1.0 it was turned down 9 to 10 dB). With `ember_match` on, Ember follows the level of what goes in, so it changes tone and width, not loudness (at 1.0 the sound was turned down 3.4 dB instead of 9.4).

"Turn Ember up" is `change {"ember": 0.2}`; in tests that added about 0.4 to 0.8 dB of air above 2 kHz and took 0.7 to 1 dB off the low end. Keep it at 0.7 or below, and turn on `ember_match` on loud sounds, meaning sounds at the ceiling (`turned_down_db` 1 dB or more, see 6.2). An exact Ember of 0.4 or more on such a sound without it gets a note saying so.

### 6.5 Dry run

With `"dry_run": true` you get the plan at once and nothing is rendered or saved: `{"type": "adjust_plan", "valid": true, "source": {...}, "plan": {"name", "changes", "notes"}, "planned_with"}`. `planned_with` is `measured` when the sound had a render to measure, otherwise `settings`: the job measures it first, so the real moves can differ a little. Through MCP the plan comes back as a complete result with `job_id: ""`. A few older takes can't be planned ahead (`invalid_request` on `/dry_run`); adjust them without `dry_run`. Clashing words and `nothing_to_change` are answered the same way with or without `dry_run`.

### 6.6 What comes back

`result.type` is `adjust`:

- **`take`**: the new `take_id`, `name`, `parent`, `root` (the original the chain started from), `version` (2 for a first adjustment), `folder` and `from_open_sound`.
- **`changes`**: every control that moved, as `{control, from, to, by}`. `by` names the words that moved it, or `set`, `change` or the guard's reason. `beyond_safe` marks an exact value past its safe range.
- **`notes`** and **`no_change`**: plain sentences, and each word that could not move anything, with the reason.
- **`before`** and **`after`**: the sound card of the original and of the new take.
- **`checks`**: one per word that moved something: `{word, ok, measure, before, after, note}`. A word passes only when its own measure moved far enough (60 % of that with `subtle`) and, unless the word is about tone or a softer attack, the attack did not smear (punch down more than 2 dB, 3 with `a_lot`, or down 1 dB with a much slower attack). A missed word says why and what to try.
- **`safety`**: `true_peak_dbtp` (measured on the new take at its own rate), `ceiling_dbtp` (−1), `clipped`, `hit_clear` (the hit still steps up clearly from what comes before it, and the attack did not smear), `attack_ms`, `punch_change_db`, `mono_bass_loss_db`, `mono_safe`, `turned_down_db` and `whoosh_trim_db`.
- **`guards`**: moves the job took back after the first render, with why.
- **`warnings`**: `{code, text}`, with codes `true_peak_above_ceiling`, `mono_broken`, `mono_risk`, `attack_smeared`, `hit_not_clear`, `tone_moved`, `level_moved`, `got_quieter` and `turn_down_grew`.
- **`summary`**: one paragraph to pass on. `elapsed_s`: how long the job took.

| Word | Passes when |
|---|---|
| `bigger` | tail +0.3 s or correlation −0.05, and the low end did not drop more than 0.3 dB nor the punch more than 2 dB (also with `a_lot`) |
| `smaller` | tail −0.2 s, correlation +0.03 or low end −0.5 dB |
| `more_reverb`, `less_reverb` | tail +0.3 s or correlation −0.05; tail −0.2 s or correlation +0.03 |
| `longer_tail`, `shorter_tail` | tail +0.3 s; tail −0.3 s |
| `more_distant` | punch −0.5 dB or tail +0.3 s, and the hit is no louder than before (0.1 LU at most) |
| `closer` | punch +0.5 dB or tail −0.2 s |
| `wider`, `narrower` | correlation −0.05; +0.05 |
| `brighter`, `darker` | air ±1 dB or brightness ±5 % |
| `punchier`, `softer` | punch or hit crest ±0.5 dB |
| `heavier`, `lighter` | low end ±0.5 dB |
| `less_boomy` | boom −0.5 dB |
| `more_aggressive` | air +1 dB, hit crest −0.5 dB or loudness +0.5 LU |
| `cleaner` | hit crest +0.3 dB or air −0.5 dB |
| `louder`, `quieter` | loudness ±0.5 LU |
| `more_whoosh`, `less_whoosh` | whoosh lead ±1 dB |
| `cut_whoosh_tail` | the attack did not smear (it has no measure of its own) |

**The sound card** (also `get_take` with `metrics: true`) measures the rendered sound. Level: `loudness_lufs`, `hit_loudness_lufs` (the loudest 400 ms around the HIT, so a shorter tail does not change it), `true_peak_dbtp`, `limiter_db`, `turned_down_db` (how far the limiter turned the whole sound down), `whoosh_trim_db`. Hit: `hit_step_db` and `hit_low_step_db` (how clearly the hit steps up; clear at 1 and 3 dB), `punch_db`, `attack_ms`, `hit_crest_db`. Tone: `brightness_hz`, and band levels in dB: `air_db` (above 2 kHz against everything above 120 Hz, so more or less sub does not read as a tone change), `boom_db` (60 to 250 Hz against everything above 250 Hz), `low_end_db` (20 to 120 Hz against everything above 120 Hz), `sub_db` (20 to 60 Hz against the whole sound). Width: `correlation` (1 is mono, below 0 is out of phase) and `mono_bass_loss_db` (how much bass below 120 Hz a mono fold-down loses). Time: `tail_s` (from the HIT until the sound is 60 dB down), `lead_db` (how loud the whoosh arrives), `duration_s`, `hit_s`.

**The guard.** After the first render the job backs word moves off once, and renders again, when:

- the bass lost mono safety: width goes back, and the reverb increase is halved or undone;
- the attack smeared or the hit is no longer clear: the reverb increase is undone or halved, and the pre-delay goes to 0.05 s when reverb stays at 0.25 or more in a Studio, Plate or Hall room;
- a word that is not about tone moved the air more than 1.5 dB: its Ember and tone moves are undone;
- the hit got quieter or louder than the original: every sounding layer's level is raised (within the true-peak headroom) or lowered to keep the original's hit loudness (not with a level word or an exact level).

Exact values are never backed off; they only get warnings. Each render is compared with the take it came from and with the root take, so asking for `bigger` five times can't pile up width or smear. When the guard would take back every move, no take is saved and the job ends with `nothing_to_change`.

**True peak.** The master limiter holds the true peak at −1 dBTP at the internal 44.1 kHz rate. The take is then converted to its session rate, which can read a few tenths of a dB higher (about −0.9 to −0.4 dBTP at 48 kHz); the `true_peak_above_ceiling` warning then gives the measured value. Exports are turned down to the export ceiling. Don't tell the user a take never goes above −1 dBTP.

### 6.7 Names, versions and undo

- The new take is named "<original name> · <words>", like "Impact 3 · bigger + more reverb", with "(a little)" or "(a lot)" for other amounts. With only exact values, it names the first one, like "Impact 3 · Ember 0.2 → 0.4 + 1 more". Your own `name` (up to 80 characters) replaces it. `note` (up to 200 characters) keeps the user's own words with the take.
- It goes into the original's Takes folder (Agent when the original has none), tagged `agent`, `adjusted` and the sound's family.
- Adjusting an adjusted take makes version 3, then 4, and so on; the name always starts from the root's name. `list_takes` rows and `get_take` show `parent` and `version`, and `get_take` `lineage` also gives `root`, the takes adjusted from this one (`children`) and what its own adjustment was.
- Undo means going back to the parent: use `lineage.parent` (or the earlier `take_id`). Nothing needs to be deleted, and you can't delete takes.
- From `"open"`: while the open sound is unchanged since the user loaded it, that take is the parent. Once the user has edited it, the new take is version 1 with no parent, so going back never throws away the user's own edits. Its Takes line then reads "Adjusted · from the open sound (<name>)", and it goes into the folder of the take the open sound came from.

### 6.8 When nothing changes

`nothing_to_change` means no take was made because nothing would move: every word is already at its limit (at the ceiling for `louder`, already clean for `cleaner`, no whoosh to change, a tail at its cap), the values you set are the sound's own, or the guard had to take every move back. The message says why and often what to ask for instead. Tell the user in plain words, and don't repeat the same call. When some words moved and others could not, the take is made and `no_change` lists the others.

## 7. What "on the cue" means

- The HIT sample of every placed sound lands exactly on its cue's target sample. Every cue is checked (`placement_check: "ok"`).
- A pre-whoosh or a swell rises into the HIT, so on the track a sound starts before its cue by design. For no lead-in, use `whoosh_s: 0`. To put a file's first sample on the cue, use `sync: "start"`.
- `onset_check` measures where the attack edge nearest the HIT is: on the attack layers without the whoosh (`measured_on: "attack_layers"`), on the whole sound, whoosh included, when the layer files are missing (`"mix"`), or on the file itself for the user's own audio (`"file"`). `status` is `ok` within 2 ms, `review` beyond that or when no clear attack is found within 60 ms of the HIT (`measured_offset_ms: null`), and `n/a` for `sync: "start"` and `sync_at_s` cues.
- `measured_offset_ms` is not a correction. The HIT is still exactly on the cue. Ask the user to listen to `review` cues, and move one with `offset_ms` only if it sounds early or late to them.

## 8. Limits

These limits are local safeguards so that a broken agent can't fill the Mac's disk. The sound files an agent hands over (`audio_path`) go from the MCP app to Impact Studio on the same Mac. Nothing goes to the internet, and nothing is charged.

In `studio_status`, `uploads.quota_bytes`, `uploads.used_today_bytes` and `limits.upload_bytes` count these hand-overs on this Mac. When you tell the user about them, don't call them uploads: nothing goes to the internet and nothing costs money.

| | |
|---|---|
| Sound files handed over | WAV, AIFF or FLAC, mono or stereo, 8 to 192 kHz, up to 100 MB each and 2 GB a day in total (it resets at midnight). References 0.04 to 15 s, cue sounds 0.01 to 120 s. Files that were refused count toward the day. |
| Free disk space | Work that would leave less than 5 GB free is refused. Making new sounds with AI also keeps room for the engine's prepared models (up to about 17 GB the first time, about 3 GB once they are ready). |
| Cue sheets | 1 to 500 cues, up to 100 new sounds, tracks up to 3 hours. WAV tracks up to 3.9 GB, AIFF up to 1 GB; use FLAC or split reels beyond that. |
| Calls | Up to 50 s of waiting per tool call (`wait_s`). Poll jobs every 1 to 2 s at most. |
| Cleanup | Sound files handed over are removed after 7 days without use. References go after 1 day unless a reconstruction still uses them. An `asset_id` or `source_id` can stop working then, so hand the file over again. The user's own files are never touched. |

## 9. Errors and what to tell the user

A failed tool call returns `isError: true` with text like `busy: <message>`. Fix what you can yourself, and pass on what only the user can do.

| Code | What happened | What to do |
|---|---|---|
| `agent_access_disabled` | Agent access is off. | Ask the user to turn on **Settings › Agent access › Allow AI agents on this Mac** in Impact Studio. |
| `app_not_running` | Impact Studio is closed and could not be opened. | Ask the user to open Impact Studio. |
| `app_starting` | The app is opening. | Wait about 10 s and call again. |
| `app_updating` | An update is installing. | Wait a minute and call again. |
| `app_updated` | The app was updated to a version this connection can't use. | Ask the user to quit and reopen their MCP app. |
| `license_inactive` | No active license on this Mac. | Ask the user to activate Impact Studio (this needs the internet once). |
| `engine_not_ready` | The sound engine is not set up. | Ask the user to finish the engine download and terms in Impact Studio, or, if they work with their own samples, build from those (`source: "samples"`). |
| `content_locked` | The built-in sounds are not unlocked yet. | Ask the user to connect to the internet once and open Impact Studio. |
| `ai_off` | AI generation is turned off in Impact Studio. | Build from the user's samples (leave out `source`), or ask the user to turn AI on in **Settings › AI generation**. Reconstructing needs AI. |
| `samples_not_shared` | The user hasn't shared their samples with agents. | Ask the user to turn on **Settings › Agent access › Share my samples with agents**, or work without them. |
| `unverified`, `unsafe_files` | The running app could not be verified. | Ask the user to quit and reopen Impact Studio. |
| `busy` | Another task is running. | Wait `retry_after_s` and try again, or `wait_for_job` if it is your job. |
| `rate_limited` | Too many requests. | Slow down; retry after `retry_after_s`. |
| `connection_failed` | The connection dropped. | Call the tool again. |
| `invalid_request` | An argument is wrong. The text names the field, like `/cues/3/at_timecode`. | Fix it and call again. Ask the user only if the value has to come from them. |
| `invalid_destination` | `destination` is not a folder inside Agent Exports. | Use 1 to 3 plain folder names. |
| `not_found` | Unknown job, take or file id. | Check the id; `list_takes` finds takes. |
| `not_running` | `cancel_job` was called for a job that already ended. | Call `get_job` to see how it ended. |
| `takes_not_shared` | The user turned off sharing their takes. This also covers `"open"` and takes adjusted from the user's sounds. | Use sounds agents made, or ask the user to turn sharing back on. |
| `nothing_open` | `take_id: "open"`, but no sound is open in the studio. | Ask the user which take they mean, or to load it in the studio. |
| `nothing_to_change` | `adjust_take` would move nothing (section 6.8). No take was made. | Tell the user the reason from the message; don't repeat the same call. |
| `unsupported_audio` | The file is not usable WAV, AIFF or FLAC, or has the wrong length, channels or rate. | Tell the user what the file needs (section 8). |
| `private_audio` | The file is protected content. | Use another file. |
| `feature_unavailable` | The direction needs a model that isn't installed (for example drum swells). | Choose another direction or style. |
| `idempotency_conflict` | The same key was used with different arguments. | Use a new key. |
| `quota_exceeded` | 2 GB of sound files were handed over today. | Tell the user it resets at midnight. Nothing was sent over the internet. |
| `insufficient_storage` | Less than 5 GB would be left free. | Ask the user to free some disk space. |
| `exports_unavailable` | The Agent Exports folder is missing or not writable (for example, its drive is disconnected). | Ask the user to reconnect the drive or choose another folder in **Settings › Agent access**. |
| job `failed` or `interrupted` | The job ended early. | Say what failed. Reuse the `take_id` values in `partial` instead of generating them again. |

## 10. Privacy and rights

**Privacy.** Audio stays on the Mac. Impact Studio sends nothing about Agent access to anyone. Your AI provider sees what you send and get back: directions, timings, file names, paths and settings. While **Share my takes with agents** is on, that includes the names, folders, tags and directions of the user's own takes, the user's saved directions, and the name, direction and settings of the sound open in the studio. While **Share my samples with agents** is on (it is off until the user turns it on), it also includes the names, categories, tags and folder names of the user's samples, never where the files are. With a local model, nothing leaves the Mac. While Agent access is on, any app the user runs on this Mac can use it.

**Using the sounds.** Sounds made through an agent are the user's sounds, with the same rights as sounds made in the studio:

- They may be used in music, films, trailers, games, ads and client work, with no royalty per sound or per project.
- They may not be sold, licensed or given away as sounds in their own right: not as a sound library, sample pack or sound-effect collection, edited or not.
- They may not be used to train other AI or machine-learning models.
- Audio handed over for reconstruction or placement must be audio the user has the rights to use.
- The two limits above don't apply to a sound built only from the user's own samples: the user may use it as far as their rights in those samples allow, so those files' own license terms decide.

The Impact Studio license agreement has the full terms.

## 11. For developers: the HTTP API

The same features are on a local HTTP API at `http://127.0.0.1:<port>/api/agent/v1`, for code that doesn't speak MCP. It listens on this Mac only and refuses requests from web pages.

- `~/Library/Application Support/Impact Studio/State/agent/connection.json` (readable by the Mac user only) has the `port` and `token` while the app runs with Agent access on. The port can change when Impact Studio restarts, so read the port and token from this file every time.
- Send `Authorization: Bearer <token>`. **Settings › Agent access › Advanced** can copy the token and make a new one.
- `GET /hello?nonce=<32 to 64 hex characters>` (no token) returns a proof, `HMAC-SHA256(token, "impact-studio-agent-v1\0" + nonce + "\0" + instance)`, so your code can check it is talking to Impact Studio before sending the token.
- Routes: `GET /status`, `GET /styles`, `POST /interpret`, `POST /audio?purpose=cue|reference&name=<file>` (hands over a sound file's bytes; returns `asset_id` or `source_id`), `POST /generate`, `POST /takes/{take_id}/export`, `POST /takes/{take_id}/adjust`, `POST /reconstruct`, `POST /cue-sheets`, `GET /jobs/{job_id}`, `POST /jobs/{job_id}/cancel`, `GET /takes` (`?scope=samples` for the user's samples), `GET /takes/{take_id}` (`?metrics=true` adds the sound card). `{take_id}` can be `open` in the take routes.
- Bodies are the MCP tools' arguments without `wait_s`, with `asset_id` or `source_id` where MCP takes `audio_path`. Start routes answer `202` with a `job_id`; poll `GET /jobs/{job_id}` every 1 to 2 s. A dry run (cue sheet or adjust) answers `200` with its plan and starts no job. Up to 20 requests a second.
