Flowing Water & Stuck Agents
A debugging methodology for when AI tells you it can't be done. Three patterns from one hard night of multi-card GPU debugging on consumer Windows — transferable to any session where the agent is confidently telling you to abandon the path.
There is a moment in any hard debugging session with an AI agent where the agent gets stuck. Not silently — confidently. It will catalog the reasons your approach won't work. It will list the failure modes. It will recommend you abandon the path. And it will sound right, because it is drawing on real evidence — the BSODs you both saw, the driver versions you both checked, the kernel error codes you both read.
The skill that matters isn't picking the right model or having the right hardware. It is knowing when to push back. And knowing how to push back productively, so the agent moves with you instead of digging deeper into its catalog of nos.
This article is about three patterns that worked during one hard night of debugging multi-card "shared" GPU memory on a Windows 10 box — a configuration most of the prevailing AI-engineering literature will tell you doesn't exist in a workable form. By the end of the night it did. The methodology is most of the article. But the category of hardware mattered enough to me to push past several "abandon the path" recommendations — and that part of the story belongs in here too.
I Came In With Conviction.
This wasn't a hardware review.
I have been working toward this kind of local-LLM setup ever since I first ran voice-to-text inference on an average gaming GPU and watched VRAM cap out before I had gotten anywhere interesting. The work didn't need to go fast. It needed to fit. And no matter how I sliced the CUDA option, I couldn't justify the price for the VRAM ceiling — not for the kinds of things I wanted to try.
I am a local Oregonian, and Intel is in my backyard. I have been watching Intel's discrete GPU program since Alchemist — through the rough launch, the driver stumbles, the public slappings as the team made the mistakes you make when you are becoming a serious player — and into the back half of 2023 when something clearly changed inside that org. Battlemage shipped with a different cadence. The Vulkan investment stopped looking like a hedge and started looking like a strategy. I read it as one of Intel's few real plays to stay relevant in an Nvidia-dominated AI space — almost certainly subsidized at the consumer/workstation end, almost certainly aimed at chipping back the market share Nvidia's pricing was making contested.
When the chance came to get two B70s, I was all in. Not because the marketing told me to. Because I had been watching long enough to believe Intel would push these into a working state even where the rest of the ecosystem hadn't gotten there yet.
The first night of debugging tested that belief hard. The setup looked exactly like the kind of "this should not work" configuration the engineering literature warns away from: Windows 10 (a vendor-dropped OS for most modern AI workflows), DDR4 RAM on a 6-year-old AM4 AMD platform, two cards from a vendor whose dGPU track record was still being written. Every framework I tried at first either didn't see the second card, or saw it and refused to use it, or used it and crashed the machine.
That is the context for the pushback that follows. I wasn't pushing back at the agent because I was being stubborn. I was pushing back because I had done the research on the bet before the debugging started, the bet was sound, and the agent's "this doesn't work" framing was missing context I had already factored in.
Stop Telling Me What Doesn't Work.
Somewhere mid-night, after the agent had spent an hour cataloging WSL2 SYCL bugs, driver-line incompatibilities, and Windows reporting blind-spots, I said something like:
That was the pivot. The agent was stuck in failure-cataloging mode. Failure-cataloging is useful — it is how you rule out variables — but it is not progress. Forward progress requires the agent to switch gears: from "here is why X failed" to "here is the smallest X we haven't tried."
"Flowing water" is the metaphor, and I want to dial in what I mean by it because most of what follows rides on it. The framing isn't zen-contemplative — not a stream meandering through a meadow. It is force-of-nature. The image is a trickle of water finding the one weak spot in a levy. Once a single thread of water gets through, it widens the channel, erodes the structure, and eventually carries the whole levy away. Plug the culverts under a road and the water doesn't give up; it finds another route, and where the water comes through is exactly where you built the road wrong — the flow shows you the weakest point as it finds another way. The ancients quarried stone by driving wooden wedges into hairline cracks and soaking them — the wedges expanded and split the stone clean. Water freezing in a sealed metal vessel will deform the metal. My background is physical sciences, my upbringing was lumberjack-adjacent, and the unstoppable power of water and weather isn't a literary device for me. It is something I learned to respect by watching it work.
The operational companion to that frame came from my mother, tutoring me in math after dinner. The line of hers I still use:
It sounds too simple to be useful. It is profoundly useful. The number of times it kept me from being overwhelmed by a problem-space — kept me incrementally moving until enough of the fog of war cleared to see the real shape — is uncountable. That is the how of flowing water in practice. You don't have to know how the levy is going to break. You just have to find one small forward problem you can actually solve, and keep solving forward problems until the blockage gives way.
The "smallest possible point where we can make this connection work" in the quote above is that instinct talking. There is always a problem you DO know how to solve right now. Find it. Solve it. The next one will be visible from there.
Three Moves That Unstick AI Agents.
1. Persona-Shifted Critics
When an agent settles into a mediocre local minimum, telling it to be someone else often forces a different level of engagement. Two personas earned their keep that night.
The NASA low-level debugger (working name: "NASA bro"). When the agent kept reasoning at the framework layer ("ollama can't see the second card"), instructing it to operate as a low-level C++ / drivers expert — strip the abstractions, work at the Vulkan / kernel-driver boundary, treat every layer's reporting as suspect until proven honest — produced a different class of suggestion. Suddenly the question stopped being "why doesn't ollama work" and became "what does the Vulkan API actually see when we enumerate devices, and how does that change when we set GGML_VK_VISIBLE_DEVICES=0,1?" The actual move wasn't going deeper — it was crossing layers and re-checking what each one was reporting. That reframing was the move that broke things open.
llama-server with what I thought were correct dual-card flags. The server returned /health: ok. The agent's framework-level reasoning said everything was working. But Intel Pro Graphics Software — which talks directly to the Intel driver, not via the DXGI path Windows Task Manager uses — showed one card at 0 GB allocated and the other holding the entire 27 GB model. Host RAM had collapsed from 21 GB free to 1 GB free. Two layers were agreeing on "everything is fine," one layer was telling the truth, and the NASA-bro move was treating the agreement as the suspicious thing. The actual cause turned out to be a less-documented flag: -fit off. Without it, the server's auto-fitter silently overrode the layer-split request. Two hours of misdiagnosis as "driver bug" or "Vulkan multi-GPU limitation" before the cross-layer move identified the real fix.
NASA bro isn't an abstract role to me. He is the spiritual ancestor of the people I worked next to in R&D at a software company in 2000. They wrote network drivers when the network stack didn't support what they needed — when a layer didn't do the job, they wrote the layer themselves. They had been trained by the masters of assembler; most of them could still write assembler when the situation called for it. They reviewed my PRs and called me out for using Vector when I already knew the size at compile time — use an array, save the dynamic resize, save the synchronization overhead. They built a distributed Java applet on 1.1.2 with AWT (Swing didn't exist yet), and they are where I learned what manual memory management actually costs. And before Java had thread-safe types in its standard library, I watched them write a multi-threaded server to host those applet updates — implementing the synchronization primitives the language didn't yet give them. Absolutely baller engineering. I was the baby on the team.
I don't practice that level of rigor day-to-day. But I know it exists, I have seen it in person, and the line I remember most was theirs: a problem is never unsolvable; it is just a matter of how much work it would be. The flowing-water frame in the section above is my version of that line — borrowed, re-phrased, but the stance is theirs originally. When I invoke "the NASA bro voice" with an agent that is stuck at the framework layer, I am reaching past the agent's default-helpful-mode and asking it to retrieve the discipline of those people — devs trained by people who had to write assembler, who treated unsolvability as a category error.
The MIT professor in applied AI. When the agent's explanations got hand-wavy, telling it to teach the result as if I were a graduate student — show the work, derive the formula, label the assumptions — forced a level of precision that exposed gaps. Several "it should work because [vague reason]" suggestions evaporated under "explain why using only what we have measured this session." A capacity-estimation math error that went off by 2700x later in the same arc would have been caught earlier under this discipline; that is the lesson.
These aren't magic prompts. They are retrieval-and-focus directives. Every community of experts whose practitioners talk publicly — NASA-class systems engineers, MIT applied-AI faculty, working drivers people on conference talks, half the open-source kernel mailing lists — has its tradecraft recorded somewhere on the web that the model trained on. The persona prompt doesn't conjure new capability; it tells the model which community's tradecraft to retrieve and apply as guardrails on its problem-solving breadth. Before you reach for a persona, do the meta-check: is there hours of public discourse on this role's craft? If yes, the prompt has something to retrieve. If no — if the tradecraft is mostly tribal or unwritten — the prompt has nothing to pull from and the persona won't take.
This pattern isn't first-use. The same retrieval-directive discipline cracked open a network-latency optimization problem in a prior project, where the expert YouTube/talk circuit had taught me the shape of the answer long before the agent collected and re-applied it. The dual-B70 night is the most recent iteration; it is not the proof-of-concept.
The shape of the prompt looks something like this — swap the role for whichever expert community has the discourse you want retrieved:
2. Pushback as a Structured Intervention
I had to push back at least three times that night when the agent confidently said the path forward wasn't viable. Each pushback opened space that the agent had closed too early.
The pattern that worked:
- Don't argue with the agent's evidence. It was usually right that the thing it tried didn't work.
- Reject the framing. The agent is describing one path; you are asking about the path-space.
- Demand the smallest forward step. Not "make it work end-to-end." "Find the smallest probe that would distinguish hypothesis A from hypothesis B."
- If the agent still won't budge, switch personas.
The hardest version of this is when the agent's failure-cataloging sounds correct because the failures were real. WSL2 SYCL really did have two distinct bugs. The Intel Arc driver really did BSOD on certain workloads. Those failures were genuine. But "X failed" is not the same as "X-adjacent paths must all fail." The agent collapses that distinction unless you actively prevent it.
The shape of the pushback prompt — the one I used variants of repeatedly that night:
3. Ask the Agent to Argue Against Itself in Your Voice
The third pattern is the one I think about the most: explicitly asking the agent to model my reaction to its own plan before committing to it.
This is asymmetric work. The agent can usually defend its own plan. What it is much weaker at, by default, is attacking its own plan from the perspective of someone who has worked the problem in a different domain. Forcing the role inversion surfaces issues the agent wouldn't notice on its own — usually around scope creep, hidden assumptions, or proposing infrastructure that already exists in the codebase.
The shape of the prompt is short:
Inside our session this got a working name — the lumberjack-Derek role (the agent's internal critic, wearing my voice, catching things the agent's helpful-mode wouldn't have caught).
The transferable version: name a critic. Give them voice. Make the agent run plans past them.
The Shared Move Underneath All Three
All three patterns are vectors on the same primitive: change whose voice the agent is speaking in.
- Persona-shifted critics change it to an expert community (NASA debugger, MIT professor — whatever role has hours of recorded tradecraft for the model to retrieve and apply).
- Pushback discipline changes the tone of the agent's voice — from confident-no back to small-step-yes — while leaving the role unchanged.
- Asking the agent to argue against itself in your voice changes whose voice the agent is speaking in entirely — to yours, the lumberjack-Derek shadow.
Same underlying move, three vectors on it. Once you see the shared primitive, picking the right one for the moment gets easier: am I stuck on what the agent is reasoning about (switch role)? Am I stuck on how the agent is concluding (switch tone)? Or am I about to ship something the agent hasn't critiqued from outside its own helpful-mode (switch to my voice)?
How to Tell When the Patterns Aren't Working
The cleanest failure test is the one this article lived through: did you have to switch modes to get past an otherwise unresolvable blockage, and did you then overcome it? If yes, the pattern is working as designed.
There are two ways for it to fail:
- You haven't switched and you are not getting unstuck. That is the diagnostic — if the agent has been cataloging failures for any length of time and you haven't redirected the voice, you are spending compute on a loop that isn't converging. Force a switch.
- You switched and the output didn't change. The persona didn't take. Try a more specific role (not "an engineer" but "a kernel-drivers maintainer with 10 years of upstream commits to Mesa"), or restart the conversation cleanly with the new persona seeded in the system prompt rather than retro-fitted into a long thread.
The pattern's success criterion isn't "no blockages." It is: when a blockage appears, switching modes resolves it. If you never had a blockage, you didn't need the pattern. If you have one and switching doesn't resolve it, the persona was wrong or the switch didn't take.
From High Level Down to the Driver.
The breakthrough didn't come from one clever insight. It came from a sequence:
- High-level planning first. We started by writing what we wanted in plain English ("two cards. one model. shared memory. native Windows. no WSL2.") and only descended into details after the planning was solid.
- Build the testing harness early. A PowerShell
Assert-CleanStategate that verified host RAM, VRAM residual on both Vulkan devices, pagefile pressure, and Memory Compression footprint before any model swap. Cost: an hour to write. Saved: every model swap from then on, because we never again wasted a launch on a thrashing system. - Improve the logging layer-by-layer. When the agent said "the second card isn't loading," we instrumented the actual Vulkan device enumeration, the in-server VRAM accounting, and the Intel Pro Graphics Software readout in parallel. Three different sources for the same question — that is how we discovered Windows Task Manager was lying about Vulkan allocations on Intel Arc.
- Drill lower with confidence. Each layer of instrumentation let us swap a variable and watch what changed. Driver line.
-fit off.GGML_VK_VISIBLE_DEVICES. Each variable swap was now cheap because the gates and the logging held the state stable.
That last point is the one I want to underline. Variable isolation is impossible without state-isolation infrastructure. If your debugging session is fighting state drift in parallel with the actual bug, you will exhaust yourself on noise. Pay the harness tax up front; it pays back in the second hour.
The work compounded. The harness + the logging + the persona-shifted critics + the pushback discipline = an environment where the agent could drill down with me, instead of away from me.
What Landed By Morning.
Four open-weights frontier labs running on the same Windows 10 box. Two Intel Arc Pro B70s, ECC off on both, 64 GB of pooled VRAM. AMD Ryzen 9 5900X / 32 GB DDR4 / NVMe scratch. No WSL2, no CUDA, no Linux dual-boot. llama.cpp Vulkan b9305.
| Lab | Model | Verified result |
|---|---|---|
| Meta | Llama-3.3-70B Q4 | 11.7 t/s gen, 152 t/s prompt-eval — dual-card layer-split |
| DeepSeek | V2.5-1210 (236B MoE / 21B active) IQ2 | 5.7 t/s gen — coherent output, overnight-batch territory |
| Alibaba | Qwen3-30B-A3B MoE | 12 t/s gen at 28K cached — 3.16x per-token vs same-class dense |
| Mistral | Small-3.2-24B + dual-card + cache | 638 t/s prompt-eval, 19.8 t/s gen at 4K cached — daily-driver territory |
Three cache primitives that compose on the same box: a single-slot prefix cache that turns batch follow-ups into chat (50x speedup on the cheapest cached query), MoE active-params compounding with that cache for 3.16x per-token throughput at long cached context vs the same-class dense model, and a persistent disk-cache that restores 4.75 GB of KV state in 2.35 seconds for a 6.1x faster CI-workflow restart. The recipe is mundane (a handful of environment variables and one non-default server flag); the substrate that lets the recipe run on consumer Windows is the work.
Three Unlocks Worth Saying Out Loud
These three unlocks together — native Windows, MSRP-available, dual-purpose — are the actual story most of the AI-on-budget-hardware narratives miss. The hardware is incidental to the methodology, but the category of hardware (an MSRP-available workstation GPU that doesn't ask you to wipe your dev box) opens this work to people the prior literature kept locked out.
What This Means If You Work With AI Agents.
You don't need a budget to use these patterns. You don't need exotic hardware. You don't need a specific model family. The three moves — persona-shifted critics, structured pushback, and asking the agent to argue against itself in your voice — work in any AI-collaboration session where you are trying to dig out of a hard problem.
What you need is the belief that the path exists. The flowing-water frame: there is always a smallest-possible-step that makes forward progress. Your job is to keep the agent looking for that step instead of cataloging the steps that didn't work.
If you are new to working with AI agents on hard technical problems: push back more than feels comfortable. Reject premature negative conclusions. Switch personas when the agent is stuck. And ask the agent, before it ships a plan, to model the version of you that would reject it hardest.
Credit where it is due: Intel's Vulkan investment has gone from a hedge to a strategy. The Alchemist generation took the public hits and the team kept shipping. Through every other thing breaking around this build, Vulkan was the layer that never blinked. Battlemage plus the workstation-driver line is the payoff.