Explore the homelab

Personal projects & experiments

RustPythonDSPMCPAI AgentsHobby

Greybound – Building a virtual amplifier with agents

A fully agentic experiment: turn the Rust compiler's guarantees into a working framework for AI, then evaluate audio models autonomously in Python.

Context:Hobby
Period:2026

Spec-driven development · Autonomous Python evaluation · Real-time Rust audio engine

Greybound: a virtual guitar amplifier with control knobs and a crosshatch grille, next to a scope card comparing a candidate render against a reference waveform in an automated agent evaluation loop

Starting with a language that intimidates me

Rust is a language that intimidates me. Its ownership model, type system and memory constraints demand a level of rigour that I do not claim to have mastered in every detail. That is precisely where Greybound starts.

My hypothesis is that what makes Rust demanding for a developer can become an advantage for AI. The compiler gives agents a deterministic, precise feedback loop that is difficult to evade. A lifetime error, unsafe state sharing or a type mismatch cannot be hidden behind an implementation that merely looks plausible: the program must satisfy the contract before it can even be evaluated.

The real purpose of the experiment is therefore this: to test how far agents can autonomously develop a complex technical system when the language, specifications and evaluation tools impose strong guarantees.

Audio makes the experiment particularly useful. Successful compilation cannot prove that a virtual amplifier sounds or reacts correctly. Rust closes the first loop around program validity; a Python lab closes a second loop around the quality of the resulting models.

Modelling an amplifier, not merely producing a sound

Greybound is the concrete vehicle for this experiment: a real-time audio engine for guitar amplifiers and pedals. Its core is written in Rust and runs as a standalone application or a CLAP/VST3 plugin. The Nox30 model, for example, follows the structure of a British valve amplifier: ECC83 stages, tone stack, phase inverter, an EL84 quartet, a sagging supply and an output transformer.

The goal is neither to reproduce every component inside a general-purpose circuit simulator nor to capture the entire amplifier in a black box. Greybound uses a gray-box approach: circuit topology remains explicit, while expensive or uncertain cells can be approximated, fitted or learned offline. The final engine must remain deterministic, inspectable and suitable for real-time operation.

Greybound therefore becomes the test bed for fully agentic development, driven by specifications and closed by an objective evaluation loop.

Autonomy starts with a specification

An agentic loop only becomes genuinely autonomous when the agent knows what it may change, how to verify its work and when it must reject it.

In Greybound, the repository itself provides that contract. A general policy defines architecture and validation invariants. A versioned knowledge base then describes:

  • the engine, routing and lab architecture;
  • the topology and confidence level of every amplifier or pedal;
  • reusable circuit cells, their units and assumptions;
  • the current project state, decisions and open questions;
  • the protocol, inputs and decision criteria for every experiment.

JSON5 rig files contain musical topology and controls only. Runtime choices — sample rate, block size, input file, duration, reference and output — stay outside them. This separation lets the agent generate temporary variants without silently changing the reference configuration.

The specification is not a document written once and forgotten. It is the project's operational memory. When an experiment disproves a hypothesis, its result and observed limitation join that memory before the next iteration.

A closed development loop

Given a bounded objective, the agent can execute the whole campaign autonomously:

specification and hypothesis
          ↓
smallest useful Rust DSP change
          ↓
tests, build and deterministic WAV render
          ↓
Python evaluation against SPICE, NAM or a baseline
          ↓
report, decision and next hypothesis
          └──────────────────────────────↺

Every render retains its provenance: Git revision, exact command, source rig, temporary control overrides, audio input, impulse response, sample rate and generated artifacts. The monitor records xruns, silence, RMS and peak levels, clipping and internal quantities such as supply voltage, currents and transformer flux.

If a render is unstable or clips numerically, the experiment stops before any tonal comparison. An invalid output cannot become a “better model” through a flattering score.

Python as the measurement bench

Rust remains responsible for the real-time audio path. Python is used offline, where NumPy, SciPy, ngspice and PyTorch provide a scientific workbench.

The lab first aligns a candidate with its reference in time and gain. It then measures several families of behaviour: spectral distance, null residual, dynamic envelope, attacks, level response, harmonics, intermodulation, noise, aliasing, phase, decay and sag recovery. Synthetic stimuli isolate phenomena that are difficult to identify in a guitar phrase: level-stepped sines, two-tone tests, short attacks, high-frequency stress and power-supply bursts.

References change with the scale being observed:

  • SPICE is the electrical oracle for a particular cell or node;
  • NAM supplies a realistic external reference for the complete audio chain;
  • a previous Greybound render acts as the baseline when no stronger reference exists.

Metrics are never reduced to one universal truth. A composite score helps rank a campaign, but a spectral improvement may hide a weaker attack, flattened dynamics or instability. The agent must inspect metric families, state trade-offs and keep the test conditions fixed.

Giving the instruments directly to agents

Greybound Lab exposes this measurement chain through MCP. An agent can inspect a rig, list available inputs and references, apply temporary controls, launch a bounded render, analyse its health, compare two WAV files and summarise the generated report.

The same experiments are visible in a human-facing lab application. Both interfaces share the same versioned artifact, greybound.lab.run.v1. An experiment launched by an agent can therefore be replayed and inspected in the UI, while a render imported by a human can enter the agentic loop.

This surface is deliberately constrained. Renders have a maximum duration, variants do not overwrite source rigs and external plugin adapters are declarative. Autonomy applies to experimentation, not arbitrary command execution.

An agent must also know how to lose

The most important result of an autonomous loop is not that it produces more code. It is that it can reject its own solution.

One experiment trained a small static network in Python to reproduce a SPICE-simulated 12AX7 stage. It reached a weighted root mean square error of 49.555 mV. Adding eight input-history samples looked like the natural next step, yet the result regressed to 54.698 mV. The candidate was discarded instead of being retained merely because it was more sophisticated.

The following iteration returned to a more explicit gray-box structure with fast and slow physical states and a bounded nonlinearity. It reached 35.207 mV, compared with 95.318 mV for the analytic cell under the same conditions. But that local success was not sufficient: once inserted into the complete amplifier, the NAM-facing improvement remained small and another indicator became slightly worse. The model stayed an integration probe until further validation justified freezing a real-time variant.

That ability to try, measure, contradict and change direction is what turns AI code generation into an agentic engineering process.

The human role moves up one level

In this organisation, I do not intervene in every micro-iteration. I define the target, the credibility of references, real-time constraints and promotion rules. The agent then owns project-state discovery, implementation, experiments, analysis and documentation until it reaches a stopping criterion or exposes an uncertainty that requires a decision.

Listening and playing guitar remain useful, but they become product validation at selected milestones. They do not replace measurement and are not required to supervise every intermediate candidate.

Greybound interests me as much for its development process as for the sound it produces. It shows that an agent can work autonomously for extended periods on a difficult technical problem, provided it has structured memory, bounded tools and a way to prove that a change is actually better.

Link