Published Aug 9, 2026, 7:30 AM EDT I’m Adam Conway, an Irish technology fanatic with a BSc in Computer Science and I'm XDA’s Lead Technical Editor. My Bachelor’s thesis was conducted on the viability of benchmarking the non-functional elements of Android apps and smartphones such as performance, and I’ve been working in the tech industry in some way or another since 2017. In my spare time, you’ll probably find me playing Counter-Strike or VALORANT, and you can reach out to me at adam@xda-developers.com, on Twitter as @AdamConwayIE, on Instagram as AdamConwayIE, or u/AdamConwayIE on Reddit. Sign in to your XDA account Tines launched 3B at the end of July, and its entire pitch is that you can vibe code safely, as credentials never touch generated code. API keys live in connectors and get injected by a proxy outside the execution environment, so the model writing your workflow can't read them even if you ask it to. I said I'd be testing this with a local model, and providing your own model is what the free tier expects after you use your $50 credit allowance. I suspect that most will bring their own cloud-based subscription, but I was especially curious how a local LLM would handle it instead. Armed with Qwen 3.6 27B Q4_K_M with multi-token prediction on a Radeon RX 7900 XTX and deployed with llama.cpp, I was ready to go. I exposed my setup to the cloud through a reverse proxy, and I configured 3B to use it as a model provider. I typically get 40-50 tokens per second, which is more than enough, but 3B uses a unique architecture of multiple steps that involves giving each step its own container that feeds into another container, so I expected it to fail. Once connected, I asked it to build me a website that merges the RSS feeds from a few subreddits and XDA into one page. However, where it failed is arguably less to do with the model and more to do with the limited context window I could provide it. It built a working three-step web app, from one prompt and two errors I highlighted, and it got the platform's own conventions right almost every time. It wasn't perfect, though, and it introduced a couple of bugs where the answers were sitting in its context window. It found and fixed both later on, and even talked itself into a proper architectural rewrite. It's genuinely impressive, but it wasn't a hands-off experience. Occasionally it stopped and I had to prod it to continue, and as I'll get to, I had to create new context windows as I kept filling it up. 3B gives the model over 4000 words of rules to start Qwen has seen nothing like it 3B builds workflows out of steps, where each step is a directory with a config.toml and a Dockerfile and one step's stdout becomes the next one's stdin. Route steps get a raw RFC 7230 HTTP request on stdin and have to write a full HTTP response back out, and persistent state lives in named volumes declared in the Dockerfile with access modes like VOLUME ["feed-config:ro"]. The platform was only a few weeks old when I ran this, and public for even less time, so Qwen 3.6 27B has never seen anything like it. The best starter package Qwen gets instead of training data is the included AGENTS.md, a file 3B drops into every workflow that runs to 4,586 words and covers everything from route_auth modes to cron syntax to how to write a step's README. Next to it sits a CLAUDE.md containing one line, @AGENTS.md, so a coding assistant working locally (if you fetch the code) reads the same rulebook the builder does, plus five step templates and eighteen loadable skills. Thanks to 3B's tools, a model can run a step and read its logs, execute throwaway code to test an idea, and control a rendered page in a real browser. It can also research before it writes, with a webSearch powered by Parallel.ai and a webFetch that takes a URL plus an objective rather than dumping an entire page at you. That's an especially big deal for a small local model whose knowledge of any given API is a lot smaller than a frontier model's. Getting the cloud to my LAN was the only difficult part. I used Pangolin, which I already run for everything else, with an exposed endpoint and an API key on it. 3B ships its own tunnel and it's free on the Explore tier, which is the zero-setup path if you don't already have a reverse proxy, though I couldn't get it working for the model connection specifically. Everything else I've pushed through that tunnel has been fine, so it may well be something on my end. All 3B needs is an endpoint that speaks the OpenAI chat completions schema and supports streaming and tool use. It built the whole thing from one prompt and two bug reports Terminal green on near-black, because it decided to My prompt was pretty simple: "build a website that combines RSS feeds from different subreddits like r/esp32, r/homeassistant, and XDA's RSS feed as well." The first thing it did was fetch all three feeds to learn their shapes, with objectives like "get the RSS feed structure, item titles, links, pubDate, content:encoded or description," which is how it knew XDA uses content:encoded and dc:creator while Reddit doesn't. Then it copied the templates into separate steps the way AGENTS.md tells it to, loaded the frontend design skill unprompted, and told me it was going for a terminal aesthetic with phosphor green on near-black because it suited the maker audience. It split the workload into three separate steps: A TypeScript step that pulls the feeds, parses both RSS and Atom, dedupes and sorts and caches the result A CRUD API for adding and removing feeds, persisted to a named volume, complete with an api.json OpenAPI fragment because AGENTS.md asks for one A 457-line React front end with source filter tabs, search, relative timestamps and an add-a-subreddit panel. That came to under an hour of token generation time across three sessions. The platform-specific stuff it mostly got right the first time. It caught itself mid-build with "the Fetch Feeds step is a route step, so it receives an HTTP request and needs to output a full RFC 7230 response." It worked out that a React step shouldn't sit downstream of a data-fetching step because that blocks the page, and rewired it to fetch client-side. It also gave the reader a read-only mount on the shared volume and the writer an exclusive one, which is specific to 3B and not something you'd guess from general TypeScript knowledge. Reddit posts weren't appearing at first, which was caused by three problems stacked on top of each other. The first was a rather trivial error, in that old Reddit serves Atom rather than RSS. Secondly, fast-xml-parser held the keys behind XML namespace prefixes, and finally, a workaround it had written on the first pass was corrupting valid XML entities. It separated all three correctly, and once it stopped guessing at parser options and started running throwaway scripts to probe which ones existed, it had it right in minutes. Before that, it had invented an option called maxTotalExpansions, and wasted time trying to figure it out. The 100K context window was the biggest issue Reasoning traces aren't free The limitation here wasn't the model or its capabilities, it was how much space it had to think. My setup gives it a 100,000 token context window, which pushes the 24GB of VRAM in my 7900 XTX to its limit. It also doesn't help that I keep reasoning traces preserved because the model performs better that way, and those account for approximately 20 percent of my chat transcripts. All of that is why it took three passes just to build the app; I had to fork a draft once I reached that limit as a sort of manual context compaction, but it means that every fork starts with it reading the whole workflow back in to work out where it is. More importantly, every fork loses whatever it had already figured out. To give you an idea of how much of a problem this was, a step with a route needs "output = true" in its config.toml for its stdout to become the HTTP response, and AGENTS.md says that without it, the request returns a 202 Accepted with no body. The feed management step didn't have it, so the browser got nothing, res.json() threw "Unexpected end of JSON input," and adding a feed just didn't work. The model learned this on the first pass, pulled it from the documentation, and added the flag to the fetch step. However, because I had to change to a new context, it built the management step without knowledge of that earlier fix, and left it switched off. When I pasted the error it looked at the config.toml, but described a theory about volume isolation instead. Its own test tool didn't catch it either, as running a step directly outputs the normal stdout without ever testing the pipeline that turns stdout into an actual response. I'd also argue that this is partially a flaw of 3B as well, even if the model was instructed to watch for it in the first place. The GET path for feed management was broken in the same way, but it went unnoticed as the frontend hid the error and fell back to working out the source list from the feed items. As a result, a single missing config key produced three separate attempts at a fix and generated a chunk of code that merely treated the symptom rather than the cause. Treating the symptom rather than the cause is all too common, and it's a big reason why many AI-built projects are bloated. In a final fourth pass focused on bug fixing, though, things went differently. It immediately found most of the problems, stating "Manage Feeds missing output = true. Without it, the step writes JSON to stdout but the runtime returns a 202 Accepted with an empty body." It also volunteered a second bug I hadn't asked about, correctly working out that the retry backoff plus the delays between Reddit feeds could exceed the step's 90-second timeout. The only difference was a fresh context window focused on a bug fix, rather than bug fixing after a feature addition. And it did a phenomenal job here. It talked itself into the right architecture, and never mentioned concurrency once Taking the long way to the right solution Its first fix for the timeouts was to cut the retry delays, which works but fixes nothing, because Fetch Feeds still did all its network work inside a request. So I told it that it was still timing out, and it went around in circles for a couple of turns. It tried starting the refresh in the background, then caught that "once process.stdout.write fires and main() returns, Bun exits immediately, the background refresh promise never resolves." At this point, it switched to awaiting the refresh, then caught that the step could overrun its timeout and have the stdout it already wrote thrown away. Seeing this, it added per-request timeouts once it worked out that Bun's fetch doesn't have a default. It slowly dissected the problem in front of me, piece by piece, essentially concluding that 3B buffers stdout until the process exits. It stated that it likely does, meaning that awaiting anything blocks the response regardless. It ran the gamut of every option it could run inside of a single step, then stepped back, stating "Actually, I'm overcomplicating this. The cleanest fix: split concerns. Fetch Feeds just serves cache instantly and exits. A separate cron step keeps the cache fresh on a schedule." Then it built it, with Fetch Feeds going from 272 lines to 39 while doing nothing but reading a file, and it built a new Refresh Cache step that fetches every 5 minutes. Finally, it moved the volume mounts to match, so the reader takes no lock at all. Surprisingly it even warned me that the cron would only fire on the published version, so I'd need to push live for it to start populating automatically. Reading back through those steps is the interesting part, as it never once mentions the exclusive lock, or concurrent requests, or a second browser tab queueing behind the first. Every step of its reasoning is about a single execution, which is correct, and it got there purely by eliminating constraints that have nothing to do with concurrency at all: Bun exiting before a background promise can resolve, Bun's fetch having no default timeout, stdout being buffered until the process exits. To be fair, that's also the architecture 3B's own skills describe, and the model had been working inside it already. But it never went back to AGENTS.md, which had the answer, and reasoned its way there regardless. That's arguably more impressive, even if it's inefficient. The finished code still has rough edges. Refresh Cache writes whatever it fetched straight to the cache without checking it, so a failed fetch overwrites a perfectly good one. That's worth fixing, but look at when it happened: by the time the rewrite was done, the model was about 82% of the way through its context window. Every bug that got caught was caught in a fresh context, and every bug that slipped through was written in a full one. I'd put this one in the second category, and I suspect it would have spotted it with room to spare. All in all, this is the most fun I've had with a local model in a while, and the reason isn't the model. Qwen 3.6 27B is a phenomenal model, and with a platform that told it the rules, let it run its own code, and read its own logs, it was able to demonstrate just how capable it was. You do need to be attentive to it in a way that 3B's default models, Opus 5 and GPT-5.6-Sol, don't need you to be. But it still worked, and that's the most impressive part.
I vibe coded with Qwen 3.6 on a platform it had never seen, and the model was never the bottleneck
Full Article
Original Source
Read the full article at Xda-developers →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.