The AI Assistant
FaustWave ships an in-app AI assistant pane with full read + write access to the IDE. It's not a chat sandbox — when you ask it to add a node, it adds the node. When you ask it for a chord progression, it drops the progression into your sequencer. Every action it takes lands in the Activity log so you can audit + (where applicable) undo. This section covers the user-facing side; for what the assistant sees + how external clients can drive the same surface, jump to § 3 (MCP).
Opening the assistant
actions:
- action_id: chat.panel.toggle
input: { open: true }
label: "▶ Open the Assistant panel"
- action_id: settings.open
input: { section: ai-provider }
label: "▶ Jump to provider setup (endpoint / model / key)"
Press Ctrl+L (Cmd+L on macOS), click the Sparkles icon in the topbar right cluster — or the first button above. The Assistant pane docks to the right of the workspace.
If you haven't configured a model + API key yet, the pane prompts you. Click Open Settings (or the second button above) to jump to the configuration section.
Bring your own key
FaustWave does NOT host its own LLM. You bring your own provider + API key. Two reasons: (1) latency to a self-hosted model means seconds-long pauses on every tool call, ruinous UX; (2) your key, your data, your spend.
Supported providers:
| Provider | Status |
|---|---|
| Anthropic Claude | First-class — recommended for tool-use richness |
| OpenAI | Supported — uses the chat/completions tool-use protocol |
| Any OpenAI-compatible endpoint | Works — point at the URL + key (Groq, Together, local Ollama with the OpenAI compat shim, etc.) |
Configure via Settings → AI Assistant:
- Endpoint — Anthropic's default URL, or your OpenAI-compatible URL.
- API key — pasted, encrypted at rest in
app.json. - Model — the model id (e.g.
claude-sonnet-4-6,gpt-4o,llama-3.1-70b-instruct).
You can swap models mid-conversation; the next turn uses the new model.
What the assistant sees
Every turn, FaustWave injects a system prompt + tool catalog into the model's context. The system prompt is composed of fragments contributed by each loaded extension:
<core extension prompt> ← project, FaustWave conventions, key idioms
<dsp-builder prompt> ← node-kinds reference, MIDI conventions, mono/poly
<sequencer prompt> ← track + slot + scale + chord-progression API
<keyboard prompt> ← keyboard-source idioms
<hub prompt> ← publishing + installation workflows
<recorder prompt> ← recording + recordings library
Each fragment is short (< 1 KB typically) — they're not embedded reference content, just operational hints. For deeper context, the assistant searches the local Knowledge Base — your installed books, including this manual.
The tool catalog is the curated set of hot-path actions (~25 today, well under the 128-tool cap) plus the palette.* meta-actions for reaching the rest of the ~130-action registry. See § 3 for the discipline.
The dsp-builder prompt fragment also teaches the assistant about per-kind library imports — kinds from faust-vintage declare imports: ["tubes.lib"] / ["tonestacks.lib"] / ["vaeffects.lib"], and faustGen collects the union + emits import("…") lines after the default stdfaust.lib header. The assistant doesn't have to manage imports — it just adds the kind and the generator does the right thing. See FaustWave — Node-Pack Authoring § 3 for the plumbing.
The tool-use loop
A turn looks like:
- You type a message ("add a 4-voice poly sine to my Builder + sequence A minor over 16 steps").
- Assistant receives your message + the system prompt + the tool catalog + recent message history (up to a context-length cap).
- Model responds with either:
- A text reply ("here's what I'll do…").
- A list of tool calls (e.g.
builder.graph.node.add { module_id, kind: "osc" }+builder.graph.connect { ... }+ ...).
- FaustWave executes each tool call through the action registry (same path you'd hit via UI or palette), captures the result, feeds it back to the model.
- Model responds again with text or more tool calls. Loop until text-only response, or the model signals done.
The loop streams as it happens — you see each tool call land in the Activity rail panel (right rail) in real time, and the assistant's text turns stream token-by-token.
Everything the assistant writes is copyable: every fenced code block in a reply carries its own copy button (top-right of the block), and each assistant message has a copy-as-markdown button that grabs the whole reply as raw markdown — handy for moving a generated Faust snippet into the .dsp editor or a JSON blob into a node-pack manifest.
Activity — audit + undo
Open the Activity rail panel from the right rail (it ships seeded; if you removed it, + Add → Activity). It shows every action that flowed through the registry — your clicks, palette runs, AI tool calls, MCP calls — with input, outcome, timing, and result / error.
Each entry shows:
- Timestamp.
- Surface —
mcpfor AI / external MCP,palettefor your gestures,controllerfor a controller binding fired by a MIDI trigger (a pad, a button). - Action id + input.
- Outcome (
completed/failed) + duration (ms). - Result (success path) or error (failure path).
For a multi-step AI session, the entries land in execution order. You can scroll back, see exactly what happened, and:
- Re-run an action with the same input (handy for "do that again").
- Copy as MCP the action id + input, so you can replay it from a script.
- Filter by surface (mcp / palette / controller) and outcome (completed / failed) to find issues.
Common patterns
"Build me a DSP"
Describe the sound. The assistant adds nodes + wires them.
User: build me a fat saw lead in poly mode, 8 voices, with an envelope and a lowpass with some resonance
Assistant: I'll set up a
sawsource →adsrenvelope →moog_vcflowpass →output, in 8-voice poly mode. Adding nodes… (executesdsp.polyphonic.set { voices: 8 },builder.graph.node.add×4,builder.graph.connect×4)
Five seconds, working DSP.
"Tweak this"
You're hearing the DSP + want a change. Ask for it.
User: lower the cutoff a bit and bring up the resonance to something dramatic
Assistant: dropping cutoff to 600 Hz and resonance to 0.85. (
builder.graph.node.param.set×2)
The change is audible immediately (params live-write to the running engine).
"Suggest a progression"
The KB has 8 curated progressions with theory metadata. The Suggest Progression UI surfaces them; the AI does too.
User: drop a sad, 4-chord progression in A minor over my pattern
Assistant: that fits the "i-vi-iv-v" loop in minor — A minor, F major, D minor, E minor. Inserting at steps 0/4/8/12 of the current sequencer. (
sequencer.progression.insert { progression_id: "i-vi-iv-v", key: "A", distribution: "bar" })
"Walk me through X"
The assistant searches the KB before answering, so it can ground itself in the actual project + bundled theory + node reference. Ask things like "what's the difference between a moog_vcf and an lp node?" — it pulls the relevant node-pack entries and answers with the actual schemas.
KB books — research the assistant keeps
Ad-hoc answers evaporate when the conversation ends. For research worth keeping — "how does FM synthesis actually work", a deep-dive on a genre's drum programming, the harmonic analysis of a song you're covering — turn it into a KB book: a local book the assistant (and you) can recall in every future session.
The flow:
- Research — ask the assistant (or any external MCP client) to dig into the topic.
- Write the book — save the findings as a project
.mdfile: one# Titleheading, then## Sectionheadings per chapter. Tutorialactions:YAML blocks work here too, so a book can carry playable chains. - Install —
kb.book.install { file_path }. No Hub, no auth, no network — the file indexes straight into the local KB. The pack id derives from the title aslocal-<slug>; re-installing the same book replaces its previous sections (clean update, nothing lingers).
{ "action_id": "kb.book.install", "input": { "file_path": "asset:assets/fm-synthesis-notes.md" } }
(No button for this one — it needs YOUR file: a project ref like above, or an absolute OS path for a file outside the project. Ask the assistant to run it, or fire it via palette.run.)
Once installed, the book behaves like any Hub-installed book: it appears in the Knowledge rail's Installed Packs list, opens in the Book Reader, and its sections answer kb.search — so next week's "what was that sidechain trick again?" grounds in YOUR book, not a fresh guess. Remove with kb.book.uninstall { book_id }; share it later with hub.publish kind: "book" using the same file.
Scoping the assistant to a section
When you open a section in the Book Reader, the Reader auto-pushes that section as the assistant's primary context. The next time you ask a question while reading FaustWave — Builder § 1, the answer is grounded in that section first, then the rest of the manual, then the global corpora.
You can pin a scope explicitly via the MCP kb.context.scope.set action — useful for a tutorial-walkthrough scenario where you want every question scoped to one chapter. kb.context.scope.clear releases the pin; the assistant returns to global grounding.
Limits + things to know
- Context length — the session history the model sees is capped: the system prompt plus the last 50 messages; older turns are dropped. The message the assistant is currently working on is never dropped, however many tool calls it takes. Tool results always reach the model in full — nothing is truncated.
- Response length — Settings → AI Provider → Max response tokens (default 8192, minimum 256) is the output budget per request. Pay-per-use providers reserve it against your credit up front; reasoning models spend it on thinking too, so raise it if replies get cut off.
- No tool retries — if a tool fails (e.g. wrong
module_id), the error feeds back into the model and it can correct. You see the failed entry in the Activity log. - No daemon mode interaction — the Assistant pane is a renderer surface. For headless / scripted automation use MCP via Claude Desktop or a custom client; see § 3.
- Cost — the assistant pays for tokens at YOUR provider's rate. Long sessions with the full tool catalog can run dozens of cents per turn at Claude rates. Use a smaller model (haiku, gpt-4o-mini, an open 70B) for cheaper iteration.
The hard parity rule
This is the rule that makes the assistant trustworthy as a working partner:
Every UI gesture in FaustWave routes through
api.actions.run(action_id, input). The Assistant + the Command Palette + the MCP server all expose the same registry. There's no "AI-only" surface, no "human-only" surface — what you can do, the AI can do. What the AI can do, you can replay manually.
The registry is the single source of truth for what's possible in the IDE. The lint that enforces this (tools/check-ai-parity.mjs) grep-checks that every action handler is reachable from both paths and runs on every PR.
Where to go from here
- § 2 (The Command Palette) — the human-side surface to the same registry.
- § 3 (MCP — external clients) — same surface, different transport (Claude Desktop, custom scripts, daemon mode).
- FaustWave — Reference for the full keyboard-shortcuts catalog.