Arb Series, Part 3 — the agent that almost cost me money by being too confident
A few days ago, someone asked me a question on LinkedIn that I’ve been chewing on ever since:
“Is the blocklist manual for now or are you planning to flag emission patterns on the fly? New tickers show up faster than any list can keep up 🤔”
That question was really about Agent 2 — the Yield Hunter, the agent that decides which pools are trustworthy enough to even look at. My answer was honest: right now it’s a hardcoded BLOCKED_TOKENS list plus a hard ceiling (MAX_APY_TO_TRUST = 300) that auto-flags anything too good to be true, whether or not it’s on the list yet.
But that only covers half the system. Before a play gets evaluated for trust, it has to be found in the first place. That’s Agent 3’s job. And while I was fact-checking my own answer to write this article, I found out the story I thought I knew wasn’t quite right either.
That’s kind of the point of this series. I’m not trying to be the guy who posts “look what I built, everything works perfectly.” I’d rather show the real catches — including the ones I thought I’d already fixed and hadn’t.
Meet the Gap Scout
Agent 3 is the arbitrage scout. Its job is simple to describe: look at the same token across different pools, find where the price disagrees with itself, and report the gap.
Simple to describe. Not simple to get right.
The Night Everything Looked Too Perfect
By late May, all five agents were running as systemd services on the Raspberry Pi, 24/7, feeding a shared signal bus. I checked the scorecard after a week away and saw something that should have made me suspicious immediately instead of happy:
45,288 signals logged. 100% of them marked EXECUTE.
If you’ve built anything that filters or scores data, you know where this goes: a filter that lets everything through isn’t a lenient filter. It’s a broken one.
The CBBTC Moment
One flagged play looked especially juicy — a CBBTC arbitrage between two pools, a reported 5.0% gap (hitting the system’s own ceiling), and a projected profit of roughly $50 per $1,000 traded.
Before trading it, I checked it manually against DexScreener.
The real numbers:
-
One pool: ~$73,329
-
The other pool: ~$73,403
-
Real gap: about $73, or roughly 0.1%
Not 5%. The bot wasn’t finding a jackpot. It was finding a rounding error and reporting it as one.
What Was Actually Broken
Here’s the actual code, straight from agent3_arb_scout.py:
python:
# Estimated price gap from APY spread (rough proxy)
# Real implementation uses actual token prices from DEX contracts
gap_pct = min(apy_spread * 0.01, 5.0)
Agent 3 on the Dashboard created with flask, live data stream from browser.
That’s the whole bug in two lines. Agent 3 was never comparing real prices at all. It was taking the spread between APY rates across pools and treating that number as a stand-in for a price gap — then capping the result at 5.0%. That’s exactly why the CBBTC signal showed a suspiciously round 5.0%: it wasn’t measuring a real price difference. It was hitting a ceiling because the APY spread happened to be large. The code even has a comment admitting it’s a placeholder: “Real implementation uses actual token prices from DEX contracts.”
No capital was lost. Manually verifying before trading — a habit I almost skipped that tired night — is the only reason this is a bug story and not a loss story.
Here’s Where I Was Wrong Yesterday
When I first wrote about this, I assumed that once the bug was found, it got fixed — normalize everything to USD, done, move on. That’s not what happened, and I only know that because I went and checked git history instead of trusting my memory.
The real timeline, straight from git log:
The line I quoted above — the actual proxy math — is still live in production right now. It never got replaced.
What I actually built on June 9th wasn’t a fix. It was damage control: if the APY spread between two pools is above 200%, treat it as an emission trap or data anomaly and skip it outright, rather than let the broken math turn it into a fake “opportunity.” That’s a real, useful safeguard. It’s just not the same thing as making the gap calculation correct.
Why I’m Telling You This Part
It would’ve been easy to write this article as “found a bug, fixed a bug, moving on” — and honestly, that’s what I believed until I ran git log while writing this. The real answer is messier: I caught the symptom, patched around the worst of it, and the actual root cause — comparing APY spread instead of real on-chain prices — is still sitting there, un-replaced, months later.
That’s the honest state of a lot of software people ship, mine included. A mitigation that reduces risk is genuinely good work. It’s just not the same claim as “fixed,” and I’d rather say which one it actually is.
Where This Connects Back to Agent 2
This is also the fuller, more honest answer to that original LinkedIn question. Agent 2’s blocklist and APY ceiling only mean something if Agent 3 is feeding it real, trustworthy gap numbers. Right now, the >200% guardrail is doing real work catching the worst cases — but the underlying gap number itself still isn’t a true reflection of price reality. The real fix — on-chain price feeds instead of an APY proxy — is still ahead of me, not behind me.
What Started as 4 Agents Is Now 7
This project’s been running about four months. I thought four agents would be the whole system. Every time I think I’ve built the last one, live data shows me another gap — literal and figurative — that needs its own dedicated logic. Four agents became seven. I don’t expect that number’s final either.
Next up: Agent 4, the Coordinator — the agent that takes everything Agents 1 through 3 report and decides whether to actually act on it.
Whatever you’re building today, keep goin’! 🚀🔥 — Voytek.ai
More articles at:
https://askvoytek.substack.com
If you enjoy following this build, consider supporting it: ko-fi.com/askvoytek
Follow me on:
Instagram: https://instagram.com/askvoytek
TikTok: https://tiktok.com/@askvoytek
I will be glad to follow others interested in same work.
