Same AI, Same Bug: The Effort Dial
The bug didn’t change. The AI didn’t change. I turned one dial.
We had a bug in our iOS VoIP app: AI-assisted phone calls failed on the Mac build. The call would connect… then die ~2–3 seconds later, every time. Regular calls were fine. Only the AI-assisted ones broke.
I put Claude Code on it. At its normal setting, here’s the trap it fell into — the same trap I’d have fallen into:
The Xcode console was flooded with terrifying Apple audio errors. failed to run downlink DSP (state fault). VoiceProcessingIO aggregate timeouts. Hundreds of lines. So it concluded the Mac’s audio engine was fundamentally broken, wrote a fix, then another, then confirmed the SDK had no workaround — and recommended we either rewrite our audio layer or declare the Mac unsupported. It even drafted a GitHub issue to that effect.
All of it was wrong. Confidently, thoroughly wrong.
Then I switched it to maximum effort — Claude Code’s /effort command set to “max,” running Opus. Same model, same context, nothing added.
That alone reframed everything. At max effort it did what good debugging actually requires: it finally used a fact that had been in front of it the whole time — regular calls work fine on the same Mac, through the same audio stack — and asked whether those scary errors also appeared in the working case. They did. The audio “errors” were harmless noise present on every successful call. A red herring.
The real cause had nothing to do with audio. AI-assisted calls routed through CallKit; regular calls didn’t. On Mac — which can’t receive push notifications — CallKit was auto-ending the call a couple seconds after it connected. The fix was a handful of lines: skip CallKit on Mac. It worked on the first try.
The lesson isn’t “AI is smart now.” It’s that reasoning depth is a dial, not a constant — and the failure mode at low depth looks exactly like the failure mode of a rushed human engineer: latch onto the loudest signal, build a theory, defend it.
The discriminating fact was sitting there the whole time. It took more deliberate reasoning — and a human refusing to let a wrong answer stand — to honor it.
Two takeaways I’m keeping:
- Before you trust an error message, check whether it also shows up when things work.
- When your tools let you spend more reasoning on a hard problem, spend it. The cheap answer and the correct answer often look equally confident.