combining langgraph agent and SDR for fun

I Built an Agent That Can Capture and Analyze Radio Spectrum

I have been experimenting with a fairly simple idea: what happens if you give an AI agent the same basic radio tools I normally use manually?

The result is an early LangGraph-based SDR agent written in Python.

Right now the radio interface is just the available Python wrapper around the USB driver. The agent itself is running GPT-5.6 and currently has only two real RF tools:

  • capture_iq
  • fft_analysis

The FFT analysis is implemented with PyFFT.

That is basically it.

My goal was not to build some giant SDR framework. I wanted to start by giving the model a few of the same primitive tools I already understand from GNU Radio and see what it could do with them.

Capturing the FM band

I gave the agent a pretty casual instruction:

Let’s try a 30 second capture centered at the middle of the FM dial at 20 MS/s worth of bandwidth.

The agent translated that into:

  • Center frequency: 98 MHz
  • Sample rate: 20 MS/s
  • Bandwidth: 20 MHz
  • Duration: 30 seconds
  • Gain: 30 dB
  • Samples: 600,000,000
  • Data size: about 4.8 GB
  • Format: SigMF, cf32_le

It captured the data and stored both the SigMF data and metadata files.

Nothing particularly magical there. It is just calling the capture tool.

The interesting part came next.

“Examine the captured data”

My next instruction was:

Examine the captured data and tell me at what frequencies the most prominent peaks are.

The agent already knew which capture I meant from the conversation context.

It ran a 4096-point FFT over the capture and reported 23 detected peaks, along with an estimated noise floor.

The ten strongest peaks it found were:

Rank Frequency Above noise
1 88.498 MHz 35.0 dB
2 94.899 MHz 19.3 dB
3 95.700 MHz 17.7 dB
4 99.699 MHz 17.2 dB
5 106.901 MHz 16.1 dB
6 91.101 MHz 15.3 dB
7 103.708 MHz 14.9 dB
8 96.501 MHz 14.6 dB
9 104.499 MHz 14.6 dB
10 106.101 MHz 13.5 dB

The FFT tool also writes a JSON analysis report, so the result becomes another piece of data the agent can refer back to later.

Identifying the stations

Then I asked:

Remake that list and identify which are known stations in Oakland, California.

The agent matched the measured peaks to Bay Area FM assignments:

Measured peak FM channel Likely station
88.498 MHz 88.5 KQED-FM
94.899 MHz 94.9 KYLD
95.700 MHz 95.7 KGMZ
99.699 MHz 99.7 KMVQ-FM
106.901 MHz 106.9 KCBS-FM
91.101 MHz 91.1 KCSM
103.708 MHz 103.7 KOSF
96.501 MHz 96.5 KOIT
104.499 MHz 104.5 KNBR-FM
106.101 MHz 106.1 KMEL

Importantly, it also made the distinction that these were frequency-assignment matches, not confirmed station IDs decoded from the RF signal.

That is the correct distinction to make.

The TL;DR

I basically made a chatbot that you can tell to capture and analyze radio shit.

In this case it captured roughly 20 MHz of spectrum containing ten major FM stations simultaneously, ran an FFT against the recorded IQ, extracted the major peaks, generated a report, and then used the results later in the conversation.

That last part is probably the most interesting thing to me.

The capture is no longer just a file sitting on disk.

The agent knows:

  • what it captured
  • where the capture is stored
  • what analysis has already been performed
  • what peaks were detected
  • what additional questions I am asking about those results

So instead of manually moving between an SDR application, files, FFT scripts, Google searches, and ChatGPT, I can just continue the conversation.

Why this feels better than my normal SDR workflow

Normally I might be sitting around asking ChatGPT how to configure GNU Radio, then clicking and dragging blocks around in GNU Radio Companion, running something, looking at the output, copying values somewhere else, and then coming back to ChatGPT.

This is much easier.

The interaction becomes:

Capture this part of the spectrum.

Then:

What is in it?

Then:

What are those signals likely to be?

That is much closer to how I actually want to interact with radio tools.

To be clear, the AI is not replacing the DSP.

The FFT is still an FFT.

The SDR driver still controls the radio.

The interesting part is that the language model can decide when and how to use those capabilities and preserve the results as part of an ongoing investigation.

Why I am not giving it GNU Radio yet

Someone has already built a GNU Radio MCP server, which is obviously tempting.

I am deliberately holding off.

I want to understand what the smallest useful set of radio primitives looks like before I hand the agent an entire GNU Radio environment.

Right now I have:

capture_iq
fft_analysis

Leave a comment