Building mew · 2026
Published · 5 min read
Harness engineering is not a joke. I have the failed runs to prove it.
I built a coding harness in six hours and it beat my tools on small tasks. Then I tried to shrink its context, lost, tried again, and gave it a bug that would take me two hours by hand, and lost that too. What I tried, what failed, what I did next, and what I still haven't won.
I built a coding harness in six hours, and on small tasks it was better than the tools I'd been using.
Then I started trying to make it good, and that's where it got humbling. I've lost more rounds than I've won, and this post is the honest account. I tried, I lost, and I went back in.
Small tasks flatter a harness
A task that runs for ten minutes hides almost every design mistake. The conversation is short, a few files are in play, and nothing has had time to rot.
A thirty-minute task is a different animal. The model has read dozens of files, formed three theories and dropped two of them. It's carrying its own history, and paying for that history again on every call. Most of what I'd built was tuned for the ten-minute case, and I couldn't see that until a long one broke it.
The thing I fought first: tokens
An agent run isn't one request. Every tool call is another API call, and every API call sends the whole conversation again. So a tool result isn't paid for once. It's paid for on every call that comes after it.
In one real mew run, a single file read cost 1,922 tokens and was re-sent 15 times, which is 28,830. Overall, 52% of that run's input was earlier tool results travelling along again. The price of reading a file is its size times the number of calls that follow.
That pushes you two ways at once. You want fewer calls, and you want less in each one.
- Fewer calls. Search, outlines and symbol reads let the model find a function without reading a whole file. A read-only scout on a cheap model investigates first, so the main model starts from findings.
- Less per call. mew remembers which lines of each file the model has already seen. Ask again and you get only what's new, or a diff if the file changed.
Those held up. Then I got ambitious.
Round one: the variable idea
If files are what fill the context, why keep them in the context at all?
My idea was a variable. Read a file, keep the contents somewhere else, and leave the model a handle. The data lives outside the conversation, so it can't be re-sent on every call.
On paper it was perfect. In practice, the same file was being read four or five times, the tokens were coming back as uncached, and the bill went up. That was the opposite of the point.
I still can't fully explain why they were uncached. I had a theory that prompt caching depends on the start of the conversation staying identical, so anything that rewrites an earlier message breaks it. I never confirmed that, and given what happened next, it may not be the explanation at all.
What did happen was dull. I removed one of the pieces I'd stacked on top of each other, and it behaved a bit better than before. Then I found one very small glitch in my Python and fixed it, and the variable approach now works. All that theory, and the thing standing in the way was a small bug in my own code.
I won't turn that into a lesson about clever design. The lesson is to check the bill, because the bill was the only thing that told me the idea was failing. What gave me something to check it against was the cost report. /cost now says why a call was billed in full: an idle gap, a model change, or a changed prefix. In the run I screenshotted, it reported 25,381 tokens re-billed because the prefix changed.
Round two: the thirty-minute bug
This is the one I'm least proud of.
I gave mew a bug I'd have found myself in an hour or two of digging in my own codebase, and let it plan and investigate. It failed badly. It wasn't designed for work like that, and I tried a few things on the spot that didn't rescue the run.
A long investigation isn't a bigger version of a short task. It needs things a short one never asks for. So I went back and added what I thought was missing:
- Memory that survives compaction. When the context fills up, something has to go, and a paraphrase of the whole history loses the facts the investigation stands on. mew now keeps the newest ~20k tokens word for word, folds only older turns into a running summary, and adds a plain list of the files read and changed.
- A way to stop reading in circles. The prompt now teaches hypothesis-first investigation: say what you think is wrong, then look for where the real behaviour differs from the expected behaviour. Loop detection catches repeated actions and escalates to a stronger model instead of burning the budget.
- A budget that ends cleanly. At 70% mew warns, and when the budget is gone it makes one last call with no tools, so the work so far becomes an answer.
I'm not going to tell you that fixed it. I built those because that run showed me what was missing, and I haven't shown that mew now beats me at a two-hour bug.
The scoreboard
| Attempt | Result |
|---|---|
| Search first, outlines, symbol reads, a scout | Kept |
| Line map and diffs instead of re-reading files | Kept |
| Variable handles instead of files in the context | Lost, then fixed a small glitch and it works now |
| A long, hard bug investigation | Lost, tried again, still not proven |
What I'd tell anyone starting
Measure before you optimise. A harness has too many moving parts to improve by feel, and the cost report told me things I'd never have guessed, like one file being re-sent 15 times.
Test long tasks early. Ten-minute runs tell you the loop works and nothing else. The design problems show up at thirty minutes, and by then the architecture is set.
Expect the boring answer. The variable idea sounded like a design problem, and a small Python glitch was in the way.
I started this in six hours and thought I understood it. The ten-minute runs agreed with me. The thirty-minute one didn't, and it was right.