10 Things I Learned from Vibe Coding (or: How I Let an AI Agent Write My Audio Library)

Published: (January 16, 2026 at 04:40 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

TL;DR — The finished result is here

I hope it helps someone else too.

I recently finished a small side‑project and decided to handle one required feature differently than usual.

The task was simple on the surface: accept an uploaded audio file in almost any format, then resample and convert it to PCM 16‑bit signed, mono, 8 kHz WAV.

In the telecom world this ultra‑low‑spec format is still the standard you must support — most class‑4 and class‑5 PBXs expect (or silently convert everything to) exactly G.711‑compatible PCM: 8000 Hz, mono, 16‑bit linear. Anything else usually gets transcoded anyway, or the call just fails.

Normally I would just shell out to ffmpeg and be done with it. This time I wanted pure native Go code — no external binaries.

A few years ago I wrote a tiny Go package that took raw PCM samples and wrapped them into a .wav file. That was it — no decoding, no resampling, no format conversion. When I tried to extend the idea to real resampling and multi‑format input I quickly ran into trouble.

After a week of one‑hour evening sessions the code was still:

  • crashing on several inputs (bad buffer logic)
  • producing noticeably worse audio quality than ffmpeg or Audacity (naïve linear resampling)
  • supporting only PCM .wav files (no RIFF metadata handling, no other containers)
  • taking forever to make progress

At that point I decided to see whether free non‑agent AIs could help. I tried:

  • 🟡 Claude
  • 🔵 Grok
  • 🟢 GitHub Copilot
  • 🟣 ChatGPT
  • 🟠 Gemini

Copilot gave by far the most useful starting point. It produced code that could:

  • read and write RIFF WAVE files
  • decode Ogg Vorbis
  • decode MP3

…all attempting to share roughly the same interface.

Still — lots of crashes, memory corruption, infinite loops, bad buffer management, and the interface was mostly ignored in practice.

I cleaned it up by hand until I reached this early commit — still very fragile, but at least the abstractions were starting to hold.

On January 9th I switched to Claude with agent/computer‑use capabilities — and that made a huge difference. The rest of this post is what I learned during that second, agent‑driven phase.

What I learned

1. Be clear

Modern AIs — even agents — almost never tell you “this design is wrong” or suggest a completely different approach unless you explicitly ask them to critique it.

If you don’t already have a mental model of what you want (boundaries, failure modes, safety, layering), the AI will happily generate code that compiles but misses the point.

Solution: start with tiny, very concrete tasks.

Example: instead of “fix this crash”, I started asking “look at this backtrace — why do you think it crashed, and what would you change to prevent it?”.

Very often the first answer was wrong (e.g. “the buffer isn’t initialized” when the real issue was missing bounds checks). I had to stop the agent many times because it was heading in a useless direction.

2. Always check what was offered

Claude frequently wrote outdated or non‑idiomatic Go:

// outdated
interface{} // instead of any

Only a few times was I actually wrong, and even then the agent’s version was usually over‑complicated.

for i := 0; i 90 % of the memory leaks, slice‑shadowing bugs, uninitialized values, and off‑by‑one errors myself — usually faster than waiting for another iteration.

5. Write code as if a human will have to maintain it later

Avoid “write‑only” code — even when the first draft comes from an AI.

KISS still applies. Clear names > clever tricks.

Future readers (including yourself in six months) will thank you.

6. Demand proper unit tests and benchmarks — with modern Go idioms

Early on the agent wrote:

  • benchmarks named TestSomething instead of BenchmarkSomething
  • unit tests without the Test prefix
  • classic for i := 0; i < … loops that caused memory leaks, slice‑shadowing bugs, uninitialized values, and off‑by‑one errors

That’s basically what a strong coding agent is — an extremely fast, very knowledgeable code monkey.

  • It can produce huge amounts of code quickly.
  • It cannot take architectural responsibility.
  • It won’t warn you about future maintenance pain unless you force the topic.

If you don’t steer tightly, you get working‑but‑awful code.

Use it like a very junior‑but‑fast pair programmer: you supply the thinking and the taste, it supplies the typing.

And just for fun — here’s the song that gave the section its name:

Code Monkey loves you

Code Monkey — the unofficial anthem of every developer who’s ever pair‑programmed with an AI 😄

Happy coding — and don’t trust the robot too much. 😉


Have you had similar (good or terrible) experiences vibe‑coding with AI agents?

Drop a comment — I’d love to hear your war stories!

Back to Blog

Related posts

Read more »

Rapg: TUI-based Secret Manager

We've all been there. You join a new project, and the first thing you hear is: > 'Check the pinned message in Slack for the .env file.' Or you have several .env...

Technology is an Enabler, not a Saviour

Why clarity of thinking matters more than the tools you use Technology is often treated as a magic switch—flip it on, and everything improves. New software, pl...