Building with agents

I moved my build agent to a local model. Most of what I learned went back to Sonnet.

My bot builds apps with an AI agent on Tessryx. To stop paying for every test build I moved it to Qwen on a Mac, wrote a proxy, split the bot into stages and let Claude Code tune it overnight. Then the lessons went back to Sonnet, and the testing moved to my Claude plan.

7 min read

Someone Built It is a bot that reads "someone should build…" posts and has an AI agent build one as a live app on Tessryx. The first post covers what Tessryx needed before it could run. This one is about the bill, and what happened when I tried to make it smaller.

#Why I tried a local model

A Map Map build on Sonnet 5.5 cost me between $6 and $10. Most of that was the agent rereading its own conversation every turn, and one build read 6.4 million tokens to write 200,000. That's fine for a one-off, but I was rebuilding the same app every time a feature landed, close to ninety times, which comes to a few hundred dollars for one map of maps, when the same build on my own Mac would cost electricity.

Tessryx needed two changes for that. An LLM block now takes a server address. Leave it empty and it calls Anthropic, or set it and the block sends the same requests to any server that speaks the same API, using your key from the secret store. A model you run yourself also restarts, sometimes hours into a build, so an agent whose server stops answering now waits and resends the turn, leaving longer gaps each time. Resending is safe, because a turn's tools only run once the model has answered. The details are in the agents docs.

#The proxy

I run Qwen3.8 on a Mac with oMLX, which speaks most of Anthropic's API. A proxy between the tunnel and the model fills in the rest. It's about 3,500 lines of Go by now, mostly fixes I didn't know I needed until a build fell over:

  • oMLX only takes images inline, so the proxy downloads the agent's screenshots and inlines them. A conversation resends every screenshot on every turn, so it keeps them on disk.
  • oMLX ignores the effort setting, and a quick QA step could think for minutes. The proxy maps effort to Qwen's reasoning mode plus a thinking budget.
  • Compaction summaries are asked for as ordinary turns, so they come almost entirely from the cache. JSON keys keep their original order too, since a re-sorted request reads as a new prompt and misses it.
  • Qwen sometimes writes a whole workflow definition as a string of JSON. Tessryx refuses that, as it should, and the model writes the entire thing again, which takes minutes. When the tool's schema says object, the proxy parses the string back into one.

It also has a page that streams every turn as it happens, which is how I found most of the above.

#The first local build

I pointed the build agent at Qwen and started a Map Map build. Four hours later I cancelled it, unfinished.

Qwen was slow, and the builder made it slower. It was one long conversation driven by one long prompt, about 25,000 tokens of rules and tools before it did anything. Qwen followed the rules near the end loosely. It took snapshots of its own page for forty minutes and never called QA, which the prompt asks for three times. Every turn paid for every rule, page rules on a data turn and data rules on a page turn. And when a compaction summary came back as a single word, it replaced everything the agent had done, and the next run spent fifteen turns working out what it had built. I switched the bot back to Sonnet that afternoon.

#A second bot, in stages

For the local model I built a second bot that splits a build into stages. Each stage is its own agent step with only the rules and tools for its job. A data stage builds the API a route at a time and writes down real responses from its own runs. An interaction stage reads those and decides how the page behaves when it's empty, when it holds 300 records, and when someone hovers on a phone. The page stage builds to both, with read-only access to the API's folder so it can't change the API under itself. QA runs between stages as an ordinary workflow step, so no agent can decide to skip it. Stages hand over files instead of conversations, so a bad summary costs one stage a few turns.

A Sonnet build of Map Map took about half an hour back then. The first app the local model finished, Sign-up Sheet, took five hours and fifty minutes, which is fine when nobody's waiting, and as a chain it was just more runs.

#Letting Claude Code do the tuning

Most of the work was tuning: run a build, read where it went wrong, change a rule, run it again. I did that with Claude Code beside me until builds were taking hours and I was the one holding them up. So I gave a Claude Code session the goal on its own (keep refining the bot until Qwen builds an app well from start to finish) and went to bed. Local builds cost nothing, so it ran them back to back all night. By the next afternoon it had called the API stage stable after 16 runs across five ideas and moved on to the page.

It works through the same Tessryx MCP server any account can connect to Claude. It starts rounds, reads run reports and traces, opens pages in a browser, and edits the bot's prompts and workflows, but never the apps. It reports to a record, bot/agent-log, which the admin page shows with a reply box under it. From my phone I asked whether Sign-up Sheet looked right on phones. It loaded the page at 390 pixels and agreed that it didn't: a fix stage had squeezed every section into a narrow column to keep text clear of the "Served by Tessryx" badge. It changed the QA and fix rules, and the next fix pass put the layout back.

It found problems in Tessryx too. Fix stages spent about half their time reading a page's code to find one class name, so agents got a find tool. A patch missing one field used to be refused and sent again in full, and now it's applied. Both shipped the same day.

Sign-up Sheet came out the other end with a clean QA pass. Then the finish stage used it for real. It put up about 34 sheets, found two bugs no QA pass could see (every card said "Online" instead of the venue, and "put up another" glued the last title onto the new one), fixed them, and took its test sheets down so the app shipped empty.

#Back to Sonnet

The staged builder stayed a trial. I got weeks of unpaid builds out of it and took most of what they showed back to the Sonnet bot. Today's bot is the classic builder, one agent on Sonnet 5.5 at medium effort, up to 50 turns and 128,000 output tokens a turn, chaining across runs when a build runs long. Its workflow is on version 224.

Most of the improvement came from making the agent look at its pages before it reports done. Page snapshots now report dead links, low contrast and motion that never stops as well as overlapping text, and every build ends with a final pass at desktop, phone and small phone widths, plus the empty state and a later page of every paged list.

The prompt changed too. It used to gain a rule after every bad build, until the rules started arguing with each other. Now it's one brief that describes a good result and lists each known failure once, as a one-line outcome. A reaction, like a rose turning when the ship arrives, plays once and comes to rest, so only one idle thing on the page loops forever. A class that positions something carries its part's prefix, because a .first rule meant for one button once threw the pager's First link on top of Previous. Neither rule mentions maps.

#Testing on my Claude plan

I don't fix a bad build by hand. The rule that let it through gets fixed and the app gets built again, and a prompt version only ships after two separate test builds pass. Every real bot build is a paid API run, so most test builds now happen in Claude Code.

Claude Code starts a Sonnet subagent and hands it the bot's exact system prompt, filled in for a bench folder like map-map-bench43. The subagent builds the whole app in the real workspace through the same MCP tools the bot uses, scoped to that folder. The page snapshot can't be reached from outside Tessryx, so a small program called pagesnap runs the same snapshot code against Chrome on my Mac and returns the same report the bot would get. Then Claude Code checks the app the way a visitor would. It loads the 29 real maps, looks at desktop and phone, follows the links, opens later pages of each list, and hovers and taps.

Those builds come out of my Claude plan, so they cost nothing extra. When a version passes on the bench, the bot gets one paid rebuild, and you can see what the current version makes on the build pages.

Give your AI somewhere to build.

Free to start, no credit card. Bring the agent you already use.

Start building for free