An oil painting of a signed acoustic guitar leaning against a chair, its sticker-covered case open on the floor, by an open window at dusk, a framed photograph of a hawk on the wall above, and an open book with a handwritten inscription on the chair.

Partner in Multiple Google Adventures

I recently wrote about Theo of Golden, Allen Levi’s novel about a stranger who notices everyone in a small town. All the way through it I kept seeing my friend Luiz Barroso. One of the passages I highlighted explains why it’s taken me this long to write about him: “There is no virtue in advertising one’s sadness. But there is no wisdom in denying it either. And there is the beautiful possibility that great love can grow out of sadness if it is well-tended.”

Luiz died in September 2023. He was 59. Apart from a line in the post about leaving Google, I haven’t written about him at all. This is my attempt.

The Datacenter as a Computer

Luiz André Barroso was a Brazilian computer scientist and one of the most consequential engineers most people have never heard of. He led the small team that rebuilt Google’s data centers so they behaved like a single machine. He and Urs Hölzle laid out the idea in The Datacenter as a Computer. That change shaped how much of the internet gets built. He won the Eckert-Mauchly Award in 2020 and was elected to the American Academy of Arts and Sciences in 2022.

Failure Is an Option

I worked for Luiz for several years. Before Core, when he was running Google Maps infrastructure, an organization of about fifteen hundred people, I’d started a small project to build a maps augmented reality system. We didn’t know if it was possible. Luiz didn’t think it was possible at all, and he let a few of us work on it for a year anyway.

That was proportional scrutiny, one of his ideas I still use: spend your attention where the consequences are. A few people chasing a long shot didn’t carry the consequences of the big bets in his organization, so he let us run. In one of our one-on-ones, I told him I was worried we wouldn’t succeed. He told me, “Failure is an option.” It’s the reverse of the line everyone quotes from Apollo 13. He’d made the bet knowing it might not pay off, and he wanted me to know that he knew.

Later, when he was asked to build the Core organization, I became Core’s chief of staff. I held that job for two years, the first of them working directly for Luiz, and then I helped him create the role he moved into next. That’s where I learned how to think about large organizations.

The Days in Which I Wasted My Career

Luiz was also an artist. He played guitar nearly every day, at home and at the office, and brought it on every vacation. He photographed birds, and a framed picture of a hawk he gave me as a holiday gift hangs on my wall. The year he died, he released Before Bossa, an album of American jazz standards and Brazilian songs from before the bossa nova era.

He made chocolate, too, and roasted his own Brazilian coffee. At Christmas he’d bring little boxes of chocolate to the office and give them to people. Sometimes he’d give me a pound or two of lightly roasted Brazilian coffee, and I savored it.

When the third edition of his data center book came out, he gave me a signed copy. The inscription reads: “To my friend and partner in multiple Google adventures, in hopes that this will remind you of the days in which I wasted my career as an Engineer :-)”

He didn’t think his engineering was a waste. He knew exactly how much it mattered. The joke was about something he took seriously: a person should be more than their job. The guitar, the birds, the chocolate, and the friendships were the other half of a whole life, and he made room for them.

The Only Thing He Carried Was a Guitar

Luiz was one of the only executives I ever worked with who didn’t carry a laptop into meetings. He’d show up with his phone in his pocket, and it stayed there. He didn’t read email between speakers or skim his inbox during someone’s slides. He talked with his team. The only thing he tended to carry into a meeting room was a guitar.

Somehow he was also prompt with email. I knew him for years and never saw him with a computer, but his replies always came back fast. I still don’t know how he managed to be fully present all day and stay on top of his inbox.

After his death, Urs Hölzle said there are constant battles inside the company over what the future should look like. Luiz navigated them, he said, thanks to an endearing personality and his guitar. In a room full of smart, stubborn people, the person who’s actually listening is often the one who gets a decision to stick.

He brought the same attention everywhere. We traveled together a lot. One Saturday on a business trip to Zurich, we spent hours walking all over the city and along the lake. We ended up drinking beer in a park and talking. On another trip we went to Oktoberfest, decided the crowded tents weren’t for us, and found a smaller beer garden away from the main festivities. What I remember from both is his questions. He was interested in everything, and he asked about you because he wanted to know.

He was also the most fun person I’ve ever watched soccer with. During the 2018 World Cup we had TVs set up in the cafeteria of our Google Maps building, and Luiz made it to a lot of the games. Once I took him to a San Jose Earthquakes game, and the things he noticed were so typically Luiz. Someone would make a bad play and he’d say, “You see him, he’s looking at the coach to see if the coach saw his mistake.” Even at a soccer game, he was watching the people.

In the novel, Theo finds ninety-two pencil portraits on a coffeehouse wall and gives each one back to the person in it. Reading those scenes, I felt something catch in my chest, because Luiz did the same thing. The gifts were real, but they weren’t the main way he did it. He did it with time and attention. He listened fully. He was present. He saw you.

What Google Meant to Him

Luiz loved Google, and he loved what he thought it stood for. He’d come to Google from Digital Equipment Corporation, and he’d watched big technology companies decline as they grew and got acquired. DEC was the example he came back to most often. I think he felt a responsibility to help steer Google through its enormous growth, and to keep reminding the company what it meant to be itself.

His essays on engineering culture read to me as part of that work. In the latest edition of the data center book, his co-authors published a small collection of them. In The Eagle has Launched?, he argues that we celebrate the wrong moments. We throw parties for launches, when what matters is the landing: a product that measurably makes users happier, or a system that got simpler and more reliable. In the Roofshot Manifesto, he made the case for steady, mostly invisible 1.3x to 2x improvements. Stack enough of them and from far away it looks like a moonshot.

Both essays are about noticing work that’s easy to overlook. That’s a management problem as much as an engineering one, because what a leader recognizes is what a team learns to value. Luiz recognized the people everyone else walked past. In my review of Theo I told a story about telling a struggling engineer that their work mattered. I said I’d learned it from a boss who was also a close friend. That was Luiz.

Obvious in Foresight

Luiz was brilliant, and he was modest about it. He used to say that all he had was the ability to state the obvious. The catch was that things obvious to him in foresight were usually only obvious to the rest of us in hindsight. In Three Lessons from Three Decades in Engineering, he puts it as advice. Big, important problems tend to be easy to understand even when they’re hard to solve, so develop respect for the obvious.

Luck and the Help of Others

That same essay ends with a line I keep rereading. After listing the lessons of his career, he writes that he’s left out the effect of luck and the help of others. They had as much impact, he says, as any efforts of his own.

That’s one of the most decorated engineers of his generation saying he isn’t sure how much of it he can claim. I think about luck as a multiplier. Talent and preparation still have to be there, and success is still earned. But whether it comes out as a one or a ten depends on things nobody controls. People who see their own success like that tend to hold it loosely and give a lot of it away. Luiz was the most generous person I’ve known, and I think that’s where it came from.

That Last Summer

My mom died two months before Luiz did. When he heard, he reached out and offered to do anything I needed. We spent a morning at his house talking about my mom, and about his dad, who had died a few years earlier. Eventually we drifted into technology and work. He listened.

A few weeks before he died, he came to my house to play guitar. My son plays French horn and trumpet, and he brought his trumpet out and asked if he could join us. We put a few charts in front of him, and the two of them played old jazz standards together, Luiz on guitar and my son on trumpet. It’s one of my fondest memories of him.

At his memorial service we heard from many, many people who’d been close to him. We told stories and helped each other mourn a friend and mentor. The same things ran through the stories people told. Luiz listened, he was kind, and he was smart.

OM-01

When Luiz left Google Maps to build Core, we threw him a big goodbye party. I’d made him a guitar for it, had everyone on the team sign it, and covered the case in Google stickers. I’d built guitars in classes before, but this was the first one I made on my own, so I gave it the serial number OM-01. It’s the guitar in so many of the photographs of him playing.

After he died, his wife, Catherine, gave it back to me. It hangs within reach of my desk now. When I’m stuck on a hard problem, I take it down, play for a while, and ask myself what Luiz would do.

It’s been three years since my friend died. I still think about him every day.

A wooden desk at night with six overflowing paper inboxes, each connected by a copper wire to one neat stack of paper beside a notebook and pen.

Capture Everywhere, Think in One Place

I read a lot. News comes in through RSS feeds, ideas come in through podcasts, and the slower stuff comes in through books and magazines. A surprising amount of it ends up in what I write here and in the work I do at Vycari. An article I skimmed in March becomes the counterexample I need in a design discussion in August. A talk I half-watched on a Saturday becomes the seed of a blog post.

That only works if I can find the thing again. Two years ago I had the same problem with podcasts, and I built a search system over my listening history to solve it. This time the shape was different. My notes live in plain markdown files in Obsidian, and that vault is where I think. The problem was that my reading didn’t live there. It lived everywhere else.

Six Inboxes and No Desk

Readwise held my RSS feeds, my Kindle highlights, and my Twitter bookmarks. Karakeep, the self-hosted bookmark manager on my homelab, held the links I saved from my phone. GitHub stars were an input I cared about as much as any article, and they lived in GitHub. Each of those places was a fine place to capture something and a terrible place to find it three months later.

YouTube was the worst of them, and it’s what started this. I watch a lot of talks and technical videos, and almost none of that made it into my notes. I wanted a thumbs-up on a video to mean something, the way a highlight in a book does. I tried IFTTT and Zapier first, and neither would do the simple thing I wanted, which was to take a liked video and put it somewhere I could triage it. I’d forgotten that detail until I sat down to write this. The whole system grew out of one missing integration.

I’d built the capture habit. Starring a repo, liking a video, or bookmarking a page costs nothing, which is exactly why I did it constantly. The idea is borrowed from David Allen’s Getting Things Done: get everything out of your head and into an inbox, then process the inbox on a schedule. The inbox half stuck with me. The processing half never did. I have never once had the discipline to sit down for the weekly review, and so the highlights and stars piled up in their silos. When I sat down to write I worked from memory and a few frantic searches.

Last November I wrote about personal software, software written for an audience of one. The thing I noticed then was that I’d stopped searching for tools and started building them. This problem was the next test of that idea, and it showed me something about how the idea is changing. That post was about small utilities and one-off scripts. What I built this time is a service, with a scheduler, a status page, secrets management, and a CI pipeline, and I built it the same way I’d build a twenty-line script. The tools I write for myself are getting more sophisticated, and the cost of that sophistication hasn’t gone up. I want to walk through what I built, because the shape of it says something about where this is going.

One Pipe Into Readwise

The decision that made everything else simple was to pick one database and route everything into it. That database is Readwise Reader. A purist would say the daemon should write markdown straight into the vault and skip the middleman, but Readwise already held half my sources and did that job well, with good iOS and browser clients and a maintained Obsidian plugin that pulls everything into the vault on a schedule. Nothing there was broken, so I didn’t fix it. I built only the missing pipe: the three sources that had no way into Readwise at all.

So I opened a coding agent and described a small daemon. It polls a set of sources, pushes anything new into Reader, and dedups against what’s already there. The result is sync-to-readwise, about two thousand lines of Python that has been running in a Docker container on my homelab since May. It handles the three sources Readwise couldn’t reach on its own: YouTube likes, GitHub stars, and Karakeep bookmarks.

The core of it is an interface with one method.

class Source(ABC):
    name: str
    default_location: str = "later"
    default_tags: tuple[str, ...] = ()

    @abstractmethod
    def fetch_candidates(self) -> Iterable[Item]:
        """Yield candidate items. The Syncer handles dedup."""

A source yields items with a URL, a title, and some metadata. The syncer asks Readwise whether it has already seen that URL and saves the ones it hasn’t. That’s the whole design. Adding a new source is one file and a line in a registry. That’s how the project went from YouTube likes on day one to GitHub stars the same afternoon, and Karakeep bookmarks over the summer.

The GitHub source is a good example of how little a source has to do. It pages through /user/starred, and for each repo it hands back the URL, the full name, the owner, and the description. Reader does the rest, fetching the README and filing it as an article tagged github. When I star a repo now, its README shows up in my reading queue within the hour.

The interesting engineering was all in the parts that touch Readwise, not the sources. Reader’s API allows twenty list requests a minute. A cold start that walks your entire library to build the dedup set runs straight into that limit. My first version had the two rate limits transposed, so it paced the generous endpoint carefully and hammered the strict one. Worse, it was walking my RSS feed items, which on a real account outnumber the things I’ve deliberately saved by orders of magnitude. The homelab deployment paged through 103,819 feed documents without reaching the end. The fix was to exclude the feed from the dedup cache entirely, persist the cache on disk, and warm it incrementally on each run. None of that was hard, but it was the kind of thing you only learn by running the tool against your own account.

It’s also a reminder that the agent didn’t notice either problem. I did, because I was reading the logs and knew what my account looked like, and then I had to ask for the cache. There’s a whole post in that, about what the job of an engineer becomes when the agent writes the code, and I’ll get to it soon.

Secrets live in Doppler, the same shape we use for Pepper at Vycari, so the only thing on the host is a service token. There’s a small status page that shows each source’s last sync, its counters, and whether the YouTube OAuth token has expired. If it has, there’s a link to re-authorize from the browser. I added that after the second time I had to SSH in to fix a token, and because I wanted a way to glance at the service and know what it was doing. Since then the token has stayed put and the service has just hummed along.

Claude Files It

Readwise’s plugin lands new documents in a Readwise folder in my vault throughout the day. That solved the finding problem, but it created a filing problem. A folder with a few hundred articles, videos, and repo READMEs is a pile, not a system.

That is where Claude comes in. I have a skill in the Claude desktop app that runs on a schedule and sweeps the new Readwise material into the projects it serves. Each project in my vault has a landing note that summarizes what the project is about. The skill reads those, reads the new documents, and appends each one to the right project’s sources note with a line or two on why it belongs there. When enough unfiled items cluster around a theme that isn’t a project yet, it proposes one. The sources note for this blog as a whole, not for any one post, now has an entry for an IEEE Spectrum piece on skill atrophy under automation. Next to it is a note that it pairs with a draft I’m working on about agents and code review. I didn’t file that. I read the article on my phone, it flowed through Readwise into the vault, and Claude worked out where it belonged. I wrote about scoping an agent to a project’s context earlier this year, and this is the same idea applied to intake rather than writing.

The most common miss is that Claude can’t place something and leaves it in an inbox for me to sort by hand, which is still a fraction of the sorting I’d be doing if I did all of it by hand. The other miss is that it attaches an article to a project where it doesn’t really belong. When that happens I delete the line while I’m reviewing the sources for that project, which I do every time I sit down to write from them. I’d rather have a few sources misfiled than never see them at all, which is where I was before this project. That review is the human check, and it’s the part of GTD I could never sustain on my own. The agent does the weekly review as my research assistant, and I do the reading when it matters.

The effect is that capture is effortless and organization is close to free. I star a project, thumbs-up a video, bookmark a page, or highlight a paragraph, and I don’t think about it again. When I open a project to write, the reading I did for it is already there, with notes on why I saved it.

What I Didn’t Do

I did look for an existing tool, briefly. IFTTT and Zapier were the obvious candidates and neither fit. A year ago that’s where the evening would have gone: reading comparisons of read-it-later services, trying two of them, and settling for the one that covered four of my six sources. Instead I sat down one Saturday, described exactly what I wanted to a coding agent, and let it build. A second Saturday over the summer added Karakeep. A few hours each time, and I learned something on both of them, which felt like a fair trade. Between those two sessions the tool has cost me almost nothing to run. It covers the three sources I was missing and nothing else, and the whole system now covers all six.

The audience of one keeps paying off. The tool has no settings I don’t use, no features waiting for someone else’s roadmap, and no update that quietly changes how it works. When Readwise’s rate limits bit me, I fixed it that afternoon, which is the responsibility I signed up for when I stepped outside managed software. That trade has been worth it every time.

The Part That Worries Me

Lately I’ve noticed the same attitude creeping toward software I already use and pay for. I run a window manager that does ninety percent of what I want and is missing one feature I care about. More than once I’ve thought about having an agent rewrite the whole utility so it does exactly what I want and nothing else. I haven’t done it yet, but the fact that it’s a live option is new, and I don’t think it’s entirely good.

To be clear, my private rewrite wouldn’t hurt anyone. I have no desire to sell or support any of my tools, and most of them aren’t even open source, because I don’t want to field issues or review pull requests for something that was only ever meant for me. This sync tool is public because I wanted to write about it, not because I want anyone else to run it. What worries me is the pattern, not my copy of it. As building for an audience of one gets easier, more people will reach for it first, before they look for the thing that already exists and does most of the job. The people who build those ninety-percent tools are mostly small independent developers, and a world where their potential customers default to rolling their own is a harder world for them to make a living in. I don’t have an answer for that. I notice that I’m part of it.

What I get back is time. I spend almost none of it organizing and much more of it thinking, and the thinking is better because the raw material is at hand. This is the first post in what I expect to be a series on the personal software I actually run. The next one will be about a tool I built for a very different kind of problem.

An overhead view of a wooden desk holding two laptops side by side. The left laptop is closed and covered in old stickers with a security badge on top. The right laptop is open with fresh stickers and a code editor on screen. A sheet of dated notes lies between them.

Writing My Way Out

I started writing this blog two years ago because I wanted to share what I was learning about AI, and the projects it kept pushing me to take on. A year ago I wrote the first anniversary post, and it ended with a plan. Two thoughtful posts a month instead of the weekly pace that had already beaten me once. More explainer series, because the embeddings posts had been the most-read thing I published. Some shorter pieces in the spirit of Simon Willison. And permission, finally, to write about the woodworking and the guitars instead of quietly worrying that they were off topic.

I had no idea, when I wrote it, that by the time I sat down to write the next one I would not be at Google anymore.

The plan mostly worked

I published fifty seven posts between that anniversary and this one, which is a little under five a month against a goal of two. I am not sure that counts as keeping a promise so much as failing to keep it in the more enjoyable direction.

I had been afraid that I would run out of things to say. The opposite happened. If I look at my drafts and ideas folders right now, there are close to fifty posts in there that I still want to write and have not found the time for.

The explainer series happened. The Agentic Shift was planned as twelve parts, and it came in at twelve parts, thirteen if you count the introduction, running from September through April. The structure held up almost exactly as I outlined it. What I did not anticipate was how much the ground would move underneath it. I thought I was writing a textbook, assembled in public. What I actually wrote was a journal of a landscape that would not hold still long enough to be documented. I outlined Part 9 as speculation about a future problem and published it as reporting on a present one. I am really proud of that series, and I think it has stood up well.

The shorter pieces happened too, though this one is still a work in progress. Eight Reading Lists, which started as an experiment in whether I could publish something in under an hour and turned into the format I reach for when an idea is real but not yet a post. I never got to the point of posting one every week, and that is something I want to get better at this year.

And the hobbies made it in. A bill in the California legislature that wanted my 3D printer to police itself. A French band I could not stop listening to. A Starlink dish on the roof of a car. The Köln Concert, as an argument about creative constraints in software. Nobody unsubscribed, as far as I can tell, which suggests the worry was mine and not my readers’. There is more of that to come, I hope.

The post that turned out to be about something else

In April I counted my GitHub contributions for the year. There were 4,255 of them, and the post was supposed to be a light piece about the shape of a year of building in the open.

The interesting number was not the total. It was that my most productive day of the week was Saturday, by a wide margin, and the reason was not discipline. It was that Saturday was the day nobody had scheduled anything. I wrote at the time that this was a diagnosis rather than a brag, and I meant it more casually than it turned out to deserve. Given time and no meetings, I build things compulsively, and I am happier. That is a useful thing to learn about yourself. It is also the kind of thing that, once you know it, quietly reorganizes every other question you were asking.

Four months later I left, after twenty one years, most of a career, and about half my life. Twenty One Years is the post about that. Not Everyone Wants a Hobby is the post about what I left to go do, which is a company called Vycari that I am building with Chris Perry. Chris was the product lead for Colab when I ran the AI Developer organization, we were both on the founding team of Gemini CLI, and somewhere in there he became the person I most wanted to build with. He is the CEO, I am the CTO, and our first product, Pepper, is a personal assistant for your life. And Thousands of Goodbyes is the post about pointing an agent at twenty one years of my own sent mail because I could only remember about a hundred and fifty of the several thousand people I had worked with.

I did not plan any of those as a trilogy. Reading them back to back, they are obviously one thing.

What the blog was for, and what it is for now

When I started writing here, the blog had a job inside a larger job. I said as much in the first anniversary post: building in the open and writing about it was how I contributed while my calendar was still too unpredictable for mission critical work, and it let me lead by example, demonstrating the kind of developer engagement I was hoping to inspire in an organization I was running.

That is a perfectly good reason to write, and it is gone now. There is no organization. There is no example to set for anyone but Chris and me. The blog is no longer a thing I do alongside the work, and it is not marketing for the work either. It is the only continuous artifact I have from before to after, which I did not appreciate until I went looking for a through line and found that the writing was the only place one existed.

There is an obvious hazard in this, and I would rather name it now than have you notice it in six months. Founder blogs decay into product announcements. It happens gradually and the person writing them is always the last to see it. So let me be clear about what you should expect. I am going to write about Vycari and Pepper, because they are the most interesting things happening to me right now. We are building a new kind of agent harness and a new kind of agent, and there are a lot of stories in that. Some of them will be technical, like the recent post about what happened to our issue backlog once agents were filing most of the issues. Some of them will be about philosophy, like why the chat window is the wrong interface for most people and why almost nothing a consumer agent does needs a frontier model, and a few of them will be things I did not feel I could say while I worked at Google. What I can promise is that everything I write here is here because I think it is useful to share, because I think you will enjoy reading it, and because I think it articulates why Chris and I, and the company we are building, are different.

The people who read this blog are people who will happily install a CLI, configure an API key, and read a changelog for fun. They are the reason it exists. I am aware that I have just started a company premised on the argument that requiring all of that is a failure of product design, and I do not think those two things are in tension, but I understand why it might look that way. Working out loud on that confluence is most of what I expect year three to be about.

Year Two, By the Series

The Agentic Shift

Twelve parts and a retrospective, September 2025 through April 2026. The series that ate the year, and the work on this site I am proudest of.

Building the Things I Write About

The Reading Lists

Eight of them, starting in April. Short, fast, and the closest thing this blog has to a running commentary.

The Work Itself

Building Vycari

The first three posts of the next chapter. None of them is a launch announcement, which is the point.

Everything Else

The promise I made last year to stop worrying about staying on topic.

Year Three

More of the same, with one change I am now a month into.

For two years I wrote about agents from inside a company with essentially unlimited access to models, infrastructure, and the people who build them. Everything I published came with that thumb on the scale, whether or not I acknowledged it. For the past month I have been building the same class of system with two people and a budget. In the first thirty days of that, the two of us merged 657 pull requests, our agents filed most of the 449 issues that came out of them, and something like a hundred and fifty million tokens went through the product for about forty dollars. Those are not numbers I could have written from inside Google, and they are the constraints almost all of my readers have always lived with. I expect that to make the writing better, and the series on how the two of us build, which started with the issue tracker, is where I intend to find out.

I also want to keep doing what Thousands of Goodbyes turned out to be, which was the first time in two years of writing about agents that I pointed one at something that was not work and had the output make me feel something. There is a great deal more of that available, and almost nobody is writing about it, because we are all still busy benchmarking.

Beyond that, my goals are simple. I want to keep sharing what I learn. Last year I said a weekly pace was not sustainable, and then published nearly five posts a month, so this year I am going to say it out loud: at least one real piece a week, with shorter things sprinkled in on the other days. I am trying to be more active on X and LinkedIn as well, so if you see me there, say hi. I will keep bringing more of my outside interests into this space, though it will almost always have a technical angle. There are more management posts planned, a tribute to a friend who is gone, some book reviews, and more.

Two years ago I hit publish on the first one of these with no idea where it would lead. I have a much better idea now, and I am still not going to tell you it is a plan. I am looking forward to what comes next, and I am glad you have decided to come along.

An ordinary compact sedan in a driveway at dawn, sharply in focus, with a covered exotic sports car blurred in a showroom behind it.

Not Everyone Needs Superintelligence

Every morning, while my family gets ready for the day, we have KQED on throughout the house. Proud members since 2000. Then I listen to podcasts while I work out. Either way I am half listening, the way you do, attention drifting between whatever is playing and planning for the day in front of me.

Last week I caught a segment about frontier models, and I could not tell you now whether it was the radio or one of the podcasts. The speaker was talking about pricing and performance, I think in relation to the new GLM model. Then he started talking about cars, and I stopped half listening. These frontier models are Ferraris, the argument went. Most people don’t drive a Ferrari. Most people drive a Corolla.

I have spent a lot of time over the last few years building agents that run on Corollas. Last year I built a coding agent on Gemini Flash 2.5, mostly to find out whether I could get really good performance on a lightweight, less expensive, and faster model. Lately I have been working with Chris on Pepper, a personal assistant for your life. Pepper runs on Corollas too.

That line stuck with me throughout the day. I mentioned it to Chris on a call the next morning, and he tied it back to one of my previous posts, the chat box is a detour. He was right: they are the same argument at two different layers. That post said we handed consumers the wrong interface because a chat window was the honest expression of what models could do in 2022, and then we never revisited it. This is the same mistake one layer down. We build on the frontier tier because that is where the attention is, not because the work requires it.

What Our Product Actually Runs On

At Vycari we are building agents that handle the day to day, and Pepper is the first one. Almost all of its agentic work runs on the cheapest models the big labs sell. Orchestration goes overwhelmingly to Gemini Flash Lite 3.5, with small slices of Claude Haiku 4.5 and GPT-5.6 Luna routed alongside it to keep us honest about vendor lock-in, and to give us a baseline for our own evals. Somewhere around a hundred and fifty million tokens have gone through the system for about forty dollars, which starts looking like a rounding error once you notice that an Opus-class harness can spend forty dollars in minutes.

The work those models do is not exotic. Look at a calendar. Read an email and decide whether it needs a response. Manage my exercise log, or find my to-dos. When I wrote about how everything becomes an agent, the point underneath was that an agent brings value by deciding in the moment, with real input in front of it. Most of those decisions are small. If you were hiring a person for this job, you would not start out looking for a PhD.

That changes the shape of the pricing conversation. For a lot of use cases we have been standing in the Ferrari showroom asking for a deal, when the better move is to walk down the street to the Toyota lot. The question was never how to get the frontier tier cheaper. It was why we were standing in that showroom at all, holding a list that reads: check the calendar, read the mail, log the workout.

The Objection I Keep Hearing

I have heard the objections. Small models hallucinate. They report success on work they never did. They narrate a tool call as prose instead of calling the tool, and the turn ends clean with fabricated content sitting in it. I have watched all of that happen in production.

The objections come out of real experience, and they were true recently enough that I understand why people still reach for them. But this industry is moving so quickly that we often have to check our assumptions on the models that are available today. The cheap tier climbs about a rung a year. The lite model I run today does work that belonged to the mid tier a year ago, and that mid tier was doing work the frontier owned the year before that. The objections have not been updated since the last time they were correct.

So we ran a quick eval. Nine recorded production turns, one for each failure shape our nightly reflection kept filing, replayed against three tiers: the lite model we ship on, the mid Flash model, and Pro. Fixed thinking budget, three samples per arm, and a grader from a different vendor so we were not asking Gemini to mark Gemini’s homework. I expected a ladder. What came back was flatter than that.

That is a small eval and I am not going to pretend otherwise. What I can say is that we have now watched the platform across thousands of model calls, and what the eval showed is holding up. We are not a public product yet, so the data is thin and I would not ask anyone to take it as settled. But every time I take one of our failing cases from Flash Lite and hand it up the ladder, the results refuse to move the way I expect them to.

The headline in our own experience is that this is mostly about how a model handles missing data, not how big it is. When a tool returns real data, all three tiers ground correctly and nobody invents anything. When the data is not there, behavior splits on how the absence gets signalled. Replay a turn with a vague instruction to proceed with whatever it already has, and all three fabricate confident content, with the bigger models producing the more polished fabrication. Signal the absence clearly, and every tier including lite says it cannot see the calendar instead of inventing events.

That reorganized how I think about the problem. The fabrication I had been charging to running cheap was mostly a property of how we told the model it had nothing. Our first recommendation to ourselves was to stop shopping for a bigger model and go fix the signal.

Which puts the weight on the harness instead. The harness manages the context, decides what the model sees, and decides what it is told when a tool comes back empty. Its entire job is to put the model in a position to succeed. Get that wrong and no amount of model will save you.

Two other results fell out of it. The first is a failure where the answer is correct and well-grounded all the way through, and then comes apart in its last few words. A phrase repeats itself, or a contraction mangles. One of ours signed off with “while he recovers today while he recovers.” We call it a garbled tail, and nothing in the logs flags it, because the model finished cleanly and the turn reads as a success. It showed up on every model we tested including Pro. Low rate, stochastic, and scaling did nothing to it.

The second is that the middle is not the safe middle it looks like. On empty tools the mid tier invented more concrete detail, weather numbers and times, than either the model above it or the one below.

There is one clean exception. False completion, where the agent answers after step two of a five-step procedure and reports back as though it had finished, does improve with model size. Our own notes call it the one real model-size win, and it is the only one on the list.

I want to be careful not to oversell this, because we do pay a tax for running small. Ten modules in Pepper’s agent harness exist mostly to catch models behaving badly, roughly 2,500 lines of production code and about the same again in tests. A detector for tool calls narrated as prose. A repair pass for garbled text. A guard for the case where a tool returns a success status with a zero success count buried in the JSON, which we wrote after a model read the status, believed its own plan, and invented the record IDs out of its own request.

Six of those ten ship detect-only. They watch, they report, and they change nothing a user sees, because we do not ship a pass that suppresses model output until nightly grading proves it is effective. The failures they watch for are not exclusive to the tier we run on. Most of that code is the cost of building an agent at all, and we would be writing a version of it at any price.

None of that machinery came out of a design document. It came out of watching. Every night a high-capability model, a Ferrari, reads back every task Pepper took on that day and grades it. It correlates failures to bugs, files the issues, sometimes reproduces a failure as a failing test, and sometimes opens a pull request to fix it. That process deserves its own post and it will get one. The short version is that almost every guard in our harness exists because we watched the model fail in one specific way and wrote a defense against that one failure.

So the Ferrari does have a job here. It is just not the one that answers you.

We Don’t Have a Word for These Models

This is a naming problem, and I think it matters more than it sounds. “Small” is wrong, because the capability is not small. “Cheap” is pejorative and smuggles in the assumption I have spent this post arguing against. “Flash Lite class” is a product SKU, not a category. Nobody has named this tier because nobody is positioning for it.

I want to call them daily drivers.

A daily driver is not a lesser car. It is the car you actually chose, judged on what matters when you drive it every morning. It starts. It’s cheap to run. It does the trip. Nobody apologizes for driving one, and nobody seriously believes the Ferrari owner is having a better time getting the groceries home.

The capability question is already settled, and I published the evidence three months ago while thinking I was writing about something else. When I built a scoreboard for Gemini Scribe, my Obsidian plugin, the point was to stop grading my own agent on vibes. It scores reliability the way τ-bench does, so a task counts only if every one of five runs succeeds. The headline result, which is still published, was that the newer gemini-3.1-flash-lite solves 74.1% of that suite at solve^5 and the older gemini-2.5-flash, supposedly a tier up, solves 57.4%. Same tasks, same judge, about seventeen percentage points apart, and the lite model costs about three quarters as much per run.

Speed is part of this too, and it does not show up anywhere in a solve rate. The daily driver starts talking sooner, and the gap in time to first token is not subtle. For an assistant you are holding a conversation with, that is not a nice-to-have. It is most of what the thing feels like to use.

The Price Gap Is Widening, Not Closing

The objection I take most seriously is that all of this evaporates when frontier prices fall. If the Ferrari costs Corolla money, what is left of the argument?

Watch what actually happened this summer. OpenAI cut Luna’s price by 80% on July 30 and took 20% off the mid tier. Those are their numbers, and the same announcement adds one more line: Sol pricing remains unchanged. Three weeks later they cut Sol too, and on their own product page that second cut is described as running for the next three months.

Read the two together. The cut at the bottom is the price. The cut at the top is a sale with an end date on it. At launch the flagship cost five times what the cheap tier cost, on input and on output alike. Take the promotion out and it now costs twenty-five times, which is where the ratio lands again when the sale lapses in November.

The gap widened because the floor dropped, not because the ceiling rose. The research says to expect that. An MIT FutureTech analysis of the price-performance frontier puts the decline at five to ten times a year for a fixed level of capability, with roughly three of that coming from algorithms rather than hardware. A five-dollar subscription does not need the gap to hold still. It needs the floor to keep falling, and the floor is where the competitive energy is.

Where Cheap Doesn’t Save You

Inference is not the whole bill, and this is the part I would have wanted someone to tell me a year ago.

Grounding costs real money and it does not follow the same curve. Google gives you 5,000 free search requests a month shared across all the Gemini 3.x models, then charges $14 per thousand after that. Anthropic and OpenAI both charge $10. On a deep research task, where the agent fires dozens of queries to answer one question, the search line can run past the inference line. That inversion gets worse as tokens get cheaper, not better.

The other place the rule breaks is writing skills. A lightweight model asked to author its own procedure does it badly, and the failure is subtle. It writes instructions a smarter model could infer its way through. So our skill-authoring tool runs on a bigger model than the runtime it writes for, and the skill’s own instructions spell the asymmetry out to whatever is drafting. What you write will be executed by a lower-capability model than the one drafting it now. So be pedantic. Name the exact tool and its arguments, and do not leave a judgment call implicit. Vague instructions are instructions a smaller model will fumble.

That is the boundary in general. Reach up a tier where the output is a plan that gets reused, and stay down where the output is one decision that gets made and thrown away.

The Part I’m Most Excited About

The strategic argument for running this low is that it eventually stops depending on the labs at all. At this size there is a real path to fine-tuned open weights, and past that you are substantially immune to price hikes and can buy your own hardware.

I believe that, and I have not proved it. The abstraction is there: Pepper’s model layer is provider-neutral and already routes three vendors through one interface, so a fourth backend is a translation adapter and a route key rather than a rewrite. What is not there is a single line of code pointing at a local runtime.

When I did measure it, the answer was no, and I published that too. The local gemma4:e4b running on my own hardware clears the easy tier at 100% and then collapses: 15% on T2, 7% on T3, 11% on T4. Flash Lite stays above 65% on every tier. It almost always finishes without erroring. It just gets the answer wrong.

That is one very small model, well under what a single consumer GPU could hold, and I have not put the larger variants through the same gradient. With capable dense models now shipping in the 30-billion-parameter range, that gradient is the next thing I want to run.

A Different Company, Not a Cheaper Bill

Cheap orchestration is what makes a five-dollar subscription possible. A five-dollar subscription is what makes Pepper reachable by the people I had in mind when I wrote that not everyone wants a hobby. That is the whole thesis, and the model tier is critical to it in a way a line item on an infrastructure bill never is.

Chris’s read on the field is that most people building here run on higher-grade models, which is a large part of why they need venture money. They are burning tokens on work that does not require them. I don’t think anyone made that choice on purpose. The frontier is where the demos are, where the benchmarks are, and where the attention is. It takes a deliberate act to go shopping somewhere else.

There is an argument running right now about whether we are heading for superintelligence and what it will mean when we get there. It is a real argument and I am not dismissing it. It also has almost nothing to do with the software most people will actually use, which needs to read a calendar, check the weather, and then get out of the way. That job was solved a while ago. We just kept pricing it as though it were not.

Whoever it was I was half listening to had it right, and did not go far enough. Nobody needs a Ferrari to get to work. What nobody says out loud is that the Corolla gets faster every year while we are all reading the reviews of the Ferrari.

A mostly empty library card catalog with a few cards left in one open drawer, lit by morning light.

The Backlog Was a Coping Mechanism

We gave our coding agents a rule that sounded obviously correct. No follow-up left behind. It went into our agent context files in roughly those words: anything a pull request doesn’t fully address gets filed as an issue before the review closes. No deferred cleanup sitting in a comment nobody reads again, no “we should probably handle this properly at some point” evaporating the moment the branch merges. Every loose thread becomes a tracked one, and the agents were good at following it.

The rule worked exactly as designed. That was the problem. Take the last month, which is the first real stretch where I’ve been full time on the product. In those 30 days the two of us merged 657 pull requests on our main repository, close to 30 on a typical weekday. Every one of them came out the other end of review with its own small pile of follow-ups. Honest ones, well written, entirely legitimate.

Over the same 30 days we opened 449 issues. Fifteen a day, most of them filed by our own agents rather than typed by us. Nothing in the system closed the loop. The list only grew, and it grew faster the more time I gave it.

This is the first post in a series about how the two of us actually build Vycari, which I promised when I wrote about why we started the company. I want to start here, with the issue tracker, because it’s the piece of the toolchain I had thought about the least and had to change the most. Almost everything I believed about what belongs in a bug database turned out to be a belief about human limitations rather than about software.

What We Were Really Doing When We Filed a Bug

Think about why you file an issue. You have an idea for something the project should do, and you write it down so it doesn’t fall out of your head. You’re deep in one file and you spot a bug in another, and you write it down so you don’t lose your place. You’re cleaning up a module and you notice three more that need the same treatment, so you write those down too.

The common element in all of it is that you couldn’t do the thing right then. Filing was the second best option. The tracker was a memory prosthesis, a place to park work your hands were too busy or too few to pick up, and it was built for exactly that. Bugzilla went public on a mozilla.org server in 1998, replacing Netscape’s in-house system. The shape it established is still the one we use. A durable record, an owner, a state, a conversation attached to it. Durable because the gap between noticing and fixing was measured in weeks.

The failure mode is just as old. Avery Pennarun makes the point plainly in his treatise on bug tracking and triage. Bugs pile up when filing outpaces fixing. Declaring bug bankruptcy doesn’t change the slope of that line. Every engineer I know has worked in a tracker where the honest read on most open issues was that nobody would ever look at them again. We tolerated it because the alternative was forgetting, and forgetting felt worse.

The second thing we used trackers for was breaking work apart. The vocabulary comes from the agile world. Mike Cohn defines an epic as, simply, a large user story, one you decompose into smaller stories when a team is ready to work on it. Big thing arrives, big thing gets chopped into two-week pieces, pieces get distributed across people, tracker becomes the coordination surface. That’s project management wearing an issue tracker as a costume, and for humans it works well.

Both of those jobs assumed constraints that agents removed. We spent the last few weeks stress testing that, finding out which parts of the practice were load bearing, and came out the other side with a different idea of what a tracker is for.

The Follow-Up That Doesn’t Need to Wait

Start with the follow-ups, because that’s where the pain showed up first.

Our code reviews are agentic. We run Greptile on every pull request and I’ve been genuinely happy with what it catches. An agent reads the diff against the project’s own conventions and writes up what it finds. The good ones find real things. A missing test case, an error path that swallows a failure, a helper that should have been extracted. Under the old rule, each of those became an issue. Faithful record keeping, and a queue that grew every single day.

What we’re experimenting with now is skipping the record entirely. When the review turns up a follow-up, the reviewing agent forks its own context into a subagent and hands it the problem immediately. The fork inherits the conversation that produced the finding, so it already knows the file, the convention that was violated, and why the reviewer cared. It goes off and opens its own pull request while the original review continues uninterrupted. If the pull request that spawned it hasn’t merged yet, the fork stacks its work on top of that branch.

The economics are almost embarrassing. Writing a good issue means describing context that is already loaded in the window right in front of you. Then, later, some other agent pays to rebuild that context from scratch by re-reading the same files and re-deriving the same reasoning, assuming anyone ever picks the issue up at all. Forking the context costs a fraction of that and produces a pull request instead of a promise. It reuses the cached context from the original thread, which saves real money and skips the whole bootstrapping conversation. The cache is already warm. The reasoning is already done.

I want to be careful not to oversell it. This doesn’t work for everything. Some findings send me off to do research first. Some need me to sit with the consequences, or go take a walk and figure out how I actually want to handle the situation. Some need a conversation between me and Chris about whether a feature is the right fit for the product at all. Those still get filed, and I’ll come back to what that queue looks like now. But the default flipped. Filing an issue used to be what you did with a follow-up. Now it’s what you do when the follow-up needs a person to think first.

Epics Assume a Constraint That Left

The second habit took longer to give up, because breaking work into pieces feels like professionalism itself.

An agent can produce a five thousand line pull request in ten minutes. When that’s true, the reason for chopping a large feature into eleven tracked sub-issues mostly disappears. You weren’t decomposing because the work was inherently separable. You were decomposing because a person can only hold so much in their head at once, because a sprint is two weeks long, and because four people needed to work in parallel without colliding. Those are real constraints. None of them are the agent’s.

This is not an argument against testing, or against reviewing carefully, or against building a large feature in stages you can actually validate. Every one of those matters more now, not less. Simon Willison put it well recently. Using agents well takes two skills, instructing them clearly and verifying that what came back is right. He also points out that eyeballing every line was never the best way to do the second one. The chunking that survives is the chunking that helps you verify. The chunking that dies is the chunking that existed to schedule humans.

The testing instincts I picked up early in my career are paying dividends now more than ever. I can load our project into a browser inside the coding agent and start poking at it. When something behaves wrong, the agent is sitting right there with the context already loaded, so I can just ask about it. I can drive the thing from the terminal and then go verify what actually happened in my local database or against my local copy of the service. None of that is new. It’s the same work I’ve been doing for my whole career, and agents didn’t change it.

So we stopped using issues as project management. The agent doesn’t need a burndown chart, and neither do the two of us. We did try. We briefly put the work into a GitHub project built on our issues, kanban columns and all. It fell out of date faster than either of us was willing to maintain it.

Aspirational Issues Are a Trap

The third category is the one I’d defend the longest and was most wrong about. “Someday we should support real-time collaboration.” “It’d be nice if this thing had a plugin system.”

An agent cannot reliably act on an issue like that. It doesn’t have the product context, the customer conversations, or the constraints that would make one implementation right and another one a waste of a week. What it has is enough capability to build something confidently, quickly, and wrong. Aspirational issues are the ideal input for producing exactly that.

Worse, they poison the queue around them. If a tracker is a work list something else pulls from overnight, every unbuildable item in it is a small trap laid for a system that can’t tell the difference. Those ideas are still worth keeping. They just belong somewhere that isn’t the tracker: a document, a spreadsheet, a future-features markdown file checked into the repo. Somewhere a person browses on purpose, rather than somewhere an agent shops.

What Actually Belongs in the Tracker Now

Here’s the test we use. Could a cheap, fast model with the repository’s context in hand fix this tonight, correctly, without asking me anything?

I mean cheap literally. Sonnet 5, Gemini Flash, GPT Terra. If the issue is well defined and the project’s conventions are written down where an agent can read them, the frontier model isn’t buying you much. That’s a strong forcing function on how you write the issue. It’s also the same forcing function that made issues good for humans.

Three kinds of work pass the test. Bugs I found while using the product away from my desk, which I can describe well because I just watched it happen. Most of those reach the tracker through a feedback path rather than through my hands, and the nightly reflection that turns them into issues is a post of its own. Follow-ups from review that resisted being forked. Small features that are well scoped, well understood, and simply not a priority this week. That’s it. Everything in the tracker is something a low-cost agent could pick up and drive to a pull request, prioritized so it knows which one to pick.

We have a pipeline that does exactly that. It doesn’t wait for night. It runs continuously, picking up whatever is ready whenever it becomes ready. That’s the next post in this series, and it’s the reason the discipline in this one matters so much. A pipeline that works through an unfiltered backlog is a machine for generating plausible garbage at scale.

I’m also experimenting with a task that sweeps every issue opened during the week and spawns an agent to fix the ones that qualify. That habit is new enough that I don’t know yet whether the tracker ever actually reaches empty.

Where the Big Work Goes Instead

None of this means we stopped doing big things. It means the big things stopped living in the tracker.

For a substantial feature, I work with an agent to write a product document first. That might be a short document, a mock, or a piece of a design system, whatever makes the idea concrete enough to argue about. Then Chris and I talk it through until we agree it’s actually right for the product. Only then does it become the input to a technical design document, which gets reviewed the way any other design gets reviewed and then checked into the repository alongside the code. After the design doc lands we create an issue, and the issue says one thing. Implement this design.

That issue is not food for the overnight pipeline, and it’s labeled so the pipeline leaves it alone. It’s a marker. It exists so that a person sitting down with an agent has a place to start, and so both of us can see what’s planned but not yet built. When someone picks it up, the first move is to point the agent at the design doc for context, and then build the feature end to end. Not in phases the issue dictated in advance, because an issue written before the work started is a bad predictor of how the work will actually decompose. In reasonably sized chunks of working functionality, with a lot of manual testing along the way, laddering up to the whole thing. That doesn’t mean one enormous pull request either. I’m about fifteen pull requests into a feature right now, several days of work, all of it pointed at a single issue.

The design document does the job the epic used to do, and does it better. It holds the reasoning, not just the task list, which is what an agent needs to build something faithfully. And it’s version controlled next to the code it describes, so it goes stale visibly instead of quietly. We have an agent that runs nightly to compare the claims in those documents against the code and update the ones that have drifted, which is a story for another day.

Taking Inventory

Last week I stopped adding and took inventory instead. 300 open issues on that same repository, every one of them read against the actual code rather than against its own title, then sorted by what it would really take to close.

15 were already dead. Fixed by some other pull request, obsoleted by a decision we’d since made, duplicated, or never actionable in the first place. 54 were real work an agent could simply do, so I let it. The sweep spawned subagents in waves and merged 54 pull requests over the following days. That’s 69 issues, most of a quarter of the backlog, that a machine could resolve without me in the room.

The rest is the part that stuck with me. 101 needed a decision from me. 54 needed one from Chris. 67 were epics or deliberately parked, and I left them alone on purpose. Three quarters of what we had filed wasn’t work at all. It was a queue of decisions wearing work’s clothing, and it had been sitting there looking like a backlog the whole time.

That number moved me further than any argument in this post did.

Three Jobs Instead of One

What we’ve landed on is a tracker with three purposes. It holds things we found and can’t fix right now but an agent can fix later. It holds pointers to planned work whose real content lives in a design document. It holds the follow-ups from review that weren’t worth forking a subagent to solve on the spot.

Look at what fell out. The tracker stopped being a filing cabinet for human memory. Everything in it is now addressed to a machine that will read it, act on it, and open a pull request. That makes an issue much closer to a function call than to a note to self. I’ve argued before that prompts are code and deserve the same rigor. An issue an agent will execute is the same claim, arriving from a direction I didn’t expect.

The part I’m still sitting with is how much of my old practice was compensation. Filing a bug so I wouldn’t forget it. Breaking an epic into pieces so a team could carry them. Keeping a wishlist because writing it down felt like progress. Those were all coping mechanisms for being a human with one pair of hands and a bad memory. I still have both of those things. I just have fewer reasons to build my tools around them.

Next time, the pipeline that works through this queue on its own, and what happens when it wanders into a public repository and starts talking to strangers.

An empty, glowing chat window floating apart from a cluster of worn analog interface objects like a door handle, light switch, and rotary phone, rendered as a warm painterly illustration.

The Chat Box Is a Detour

When ChatGPT launched in November 2022, we got a simple chat window, following a few months behind Google’s own preview of LaMDA 2 through AI Test Kitchen at Google I/O 2022, itself a chat window layered over a model. Type something in, get something back. That was the right call, and not because anyone had done deep interface research. A transformer model is trained to do one thing: predict the next token given everything before it. Feed it a prompt, get a completion, feed it more, get another. A chat window is close to the most direct expression of that loop made visible. It was an honest match for what those models were good at, an admission of what the technology could do yet, not a considered design choice.

Models have gotten more capable and efficient since, and what we ask of them has gotten far more complex. Somewhere in that gap, the chat window stopped being an honest match and became a habit. We have spent the years since watching agentic AI show up everywhere: code editors, browsers, the operating system itself, the enterprise tools people already had open. Through all of it, we kept handing people the same box. Our reluctance to move past it is a real drag on adoption, and it is one of the bedrocks of our point of view at Vycari.

Anyone who works in this technology every day already knows a specific version of this problem: the blank box itself is hard. Staring at an empty chat window and guessing how to phrase what you want, what the agent can do, which words trigger the behavior you’re after, is its own skill. It is hard for people who spend all day in this field. It is much harder for someone who does not, who has no reason to have built a mental model of what an agent can do from looking at an empty rectangle.

My co-founder Chris Perry made a version of this same argument last week, coming at it from adoption and product history rather than the interface argument here. Ours is a two person company, and we did not coordinate this; we just keep running into the same wall from different angles. It is part of why I like building with him: he thinks about a problem from the side I don’t, and by the time we compare notes we have usually converged without meaning to. His post is worth reading alongside this one.

Agents outgrew the box

Last January I wrote about how everything becomes an agent; the argument underneath was really about decision making. An agent earns its keep when the input is hard to predict ahead of time, when the alternative is branch logic encoding what a developer guessed the user would need, written months before that user showed up. Treat an agent as a piece of your program that makes the call in the moment, with the actual input in front of it, and it looks like a much bigger part of how software gets built than a chat window would suggest.

None of that requires typing into a box. An agent deciding which tool to call inside a checkout flow, a support queue, or a scheduling tool does not need a text field to do its job well. In a lot of what we build at Vycari, the agent takes a backseat to the interface on purpose. Nothing beats a solid interface that is familiar and delightful to use, and an empty chat box waiting to be filled is neither of those things for most people.

Chat is the hobbyist’s interface

I wrote a few weeks ago about why not everyone wants a hobby, and this is where that argument meets this one. A chat interface rewards people who already know how to prompt, who enjoy the back and forth, who get a small thrill from coaxing a good answer out of a model. That is real and worthwhile. It is also a hobby, and most people do not want one. They want the thing handled.

This is not a new problem for our industry. Unix was a command line. So was DOS, VMS, Ultrix, and SunOS, the whole family of operating systems that ran the serious computing of their era. Knowing the right incantation, the right flags, the right order of operations was a hobby in its own right, and it kept computers in the hands of people willing to learn that hobby. The graphical interface Xerox PARC prototyped, and that the Macintosh and then Windows brought to everyone else’s desk, did not make computers more powerful. In most ways it made them less flexible than a shell. What it did was let someone finish a task without first learning a syntax and a vocabulary of magic commands, as Chris put it. Nobody wants to read a manual to cross the next thing off their list. That was true of computing in 1984, and it is true of agents now.

Look at the products getting the most attention right now, open source projects like OpenClaw and Hermes, or the frontier lab flagships like Gemini Spark, Claude Cowork, and ChatGPT Work. Nearly all of them are built on the same premise: you will chat with the agent. My own Gemini Scribe started the same way, a chat window bolted onto Obsidian. Sometimes the chat happens over voice instead of text, but underneath the voice layer is the same box, just one you talk to instead of type into.

Meeting people where they already are

I do not think most people want to learn a new modality to get value out of AI, and I do not think they will, even though some of us genuinely enjoy it. Agentic AI is a shift on the scale of the ones we have already lived through: personal computers, the internet, the web, mobile, and now AI. I made a version of this list once before, and each of those transitions asked people to change how they worked. The ones that won met people with an interface they already understood, not the ones that made them learn a new vocabulary first. I want to be careful here: I am not arguing for skeuomorphism, for software that pretends to be the paper or the switch it replaced. I am arguing for good, intuitive design, interfaces that borrow the mental model people already carry and build the new capability on top of it. Every time this industry has moved toward a more familiar interface and a design language people already recognized, it created more value, not less, because it stopped spending people’s attention on the tool and let them spend it on the task.

That is the standard I want agent products held to. Not “does the model perform,” because at this point almost all of them do. The question is whether the software finds you where you already are, understands what you are actually trying to accomplish, and gets you back to your day.

Did you have to come back

Early in my career at Google, one of the metrics we watched for search was whether you came back. If you searched, clicked a result, and never returned, that meant you had found what you needed and moved on. I think agents deserve the same measurement. Did you get the thing done? Did you have to come back and try again? The best outcome is that you do not come back, not because the product failed you, but because you already had what you wanted and were on to the next thing.

In our own applications at Vycari, that translates into something concrete. It means the agent understood the request on the first try, without a round of clarifying questions, without asking you to drop into a chat window to add detail it should already have had. Better still, it means the agent acted on your behalf and you never had to watch it happen. In my ideal world, people using what we build will know this is agentic AI about as much as they know it is written in Python: not at all, not because we are hiding it, but because it will not be a fact that matters to them.

We should not be building toward the box. We should be building toward wherever the user already is, and toward what they are actually trying to get done. Agents are not a hobby. They are here to help people get through their day, and the sooner our interfaces act like it, the sooner more people will actually use them.

A laptop on a dark desk with thousands of small glowing blue points of light rising from the screen and spreading outward like a constellation, connected by faint threads, with a small bright cluster near the screen and the rest fading into darkness.

Thousands of Goodbyes

There is a problem with leaving a job you held for twenty one years, and nobody warns you about it. You cannot remember who you worked with.

Not in the sense of having forgotten them. In the sense that the list does not exist anywhere, including in your head. I left Google earlier this month after twenty one and a half years across Search, Maps, ads, mobile, Core, Core ML, and DeepMind, in roles that ranged from running large organizations to writing code with three people. Somewhere in there I met, argued with, mentored, was mentored by, shipped alongside, and occasionally annoyed several thousand people. When I sat down to write my goodbye note, I could produce maybe a hundred and fifty names from memory, and I knew with total certainty that the hundred and fifty were wrong. They were the recent ones and the loud ones. The person I had one extraordinary conversation with in a London conference room in 2008 was nowhere near that list.

This is the sort of problem that used to have exactly one answer, which is that you accept it. There is no roster of everyone who mattered to you, no internal system that will hand you the list. What you actually do is type out the names you can think of, send the note, and add a line asking people to please forward it to anyone you missed. It works, in the sense that something gets sent. It is also a sloppy solution that quietly hands the entire decision to your recency bias. The people you saw last month get a goodbye. The people who changed how you work, fifteen years ago, on a team that no longer exists, do not.

I did not want to accept it. So I did the other thing.

Letting the machine do the remembering

The tool I reached for was Antigravity, paired with the Google Workspace MCP server I had originally built as a Gemini CLI extension. That extension exists because I wanted my terminal to be able to see my calendar. It turns out that giving an agent access to your mail and calendar for ordinary convenience also gives it access to the complete archaeological record of your working life, which is not something I had thought carefully about until I needed it.

The first pass was mail. I had the agent go through twenty one years of sent messages and pull out every address I had ever written to individually. Not mailing lists, not the thirty person threads, not the announcements. One to one mail, or close enough to it, on the theory that if I had bothered to type your name into the To field, we had a relationship worth closing properly. That produced a very large and very stale list, because a lot of those people left Google years ago. So the second pass compared the addresses against an internal directory and kept only the ones still active, which cut it down considerably and also produced a small, unexpected inventory of people I had lost track of.

The second source was calendar. Mail catches the people you write to, but it misses the ones you only ever talked to in a room. So the agent went through twenty one years of my calendar looking for anything that was genuinely a one to one: a recurring weekly, a single mentoring session someone booked in 2017, a skip level, a coffee that got a calendar entry because that is how Google works. Every one of those has a person on the other side of it, and a surprising number of them never once appeared in my sent mail.

Then it merged the two. I had expected this to be the hard part and it was not, for a boring reason: Google email addresses are stable. People change teams constantly and the address follows them, so deduping on the address alone does nearly all of the work. What I was not prepared for was reading the result. Whole eras came back. I would hit a cluster of addresses and remember an entire project I had not thought about in a decade.

The last problem was purely mechanical and almost funny after all that. Gmail will not let you put several thousand addresses on a BCC line. The agent did not raise this, which is worth saying in a post that is otherwise about how capable these things are. I had to notice it and ask. Once I did, it split the list into batches that fit under the limit and drafted the same message across all of them, and I sat there and hit send, over and over, until the list was gone.

What came back

I expected silence. You send a goodbye to someone you shared one project with in 2011 and you expect it to land in an archive folder, if it lands anywhere.

One person wrote back to tell me, politely, that he had no idea who I was. I liked that reply enormously. I assume he was not the only one who felt that way and just the only one honest enough to say it, and I would rather have sent that mail and been forgotten than not sent it at all.

But most of what came back was not that, and the volume of it caught me completely off guard. A solutions engineer in Japan wrote about a Street View collaboration with Nintendo that had been his very first project at Google, and told me I was probably the first real engineer he ever encountered. We were born the same year. He had turned fifty a month earlier and was finding the number about as strange as I am. Someone I managed for only a few months thanked me for trusting him and called it one of the most engaging windows of his career. A former colleague opened by saying he had just been telling someone we both used to work with how much he missed working with me, and then reported that he still has not gotten his motorcycle license because his friends staged an intervention dinner about it. A director in Munich offered a beer if I ever make it back and reminded me of work we did together that I had honestly stopped thinking about. Someone I have known for close to twenty years said he had been meaning to call, and instead of trading contact details we ended up at lunch off campus the following Friday, which is the best possible version of what one of these notes can do.

That is the part I keep turning over. Not one of those replies exists if I send the note from memory.

A hundred and fifty, the number of names I could produce on my own, is roughly Dunbar’s number, the size of a stable social group a human can actually maintain. I do not think that is a coincidence, and I have stopped treating it as a personal failing. My recall of my own career landed almost exactly where the research says it should, which means the ceiling was never effort or affection. It was architecture. Twenty one years builds a network many times larger than the one a head is designed to hold, and the overflow is not forgotten so much as never retrievable in the first place. The agent was not being clever here. It simply was not subject to the constraint.

The people who wrote the most moving things back to me were, almost without exception, the ones my brain had not surfaced. They were on the list because software read my calendar from 2013 and did not care that it was 2013.

The gap this points at

I have spent two years writing about what agents can do, and most of my examples have been about work. Code, pipelines, research, the machinery of building software. This is the first time I have used one for something that was purely about people, and it is the only agentic project I have run where the output made me feel something.

It is also, and I want to be honest about this, a completely unreasonable thing to ask a normal person to do. To get here I needed an agent platform, an MCP server I wrote myself, OAuth credentials, a working mental model of what a tool call is, and enough patience to iterate on the approach a few times when it came back wrong. The capability was extraordinary. The cost of access was absurd.

That gap is the whole reason I am doing what I am doing next. I wrote last week that using agents today is effectively a hobby, and this is the cleanest example I have of why that matters. Everyone leaving a long job has this problem. Almost nobody gets to solve it, because solving it currently requires you to invest in the hobby first. Closing that distance, so that an ordinary person on an ordinary Tuesday can ask for something like this and simply get it, is the work.

Twenty one years of colleagues got a goodbye from me because software remembered what I could not. I would like that to be an unremarkable thing to say.

And to everyone who wrote back: I replied to every thread I could, and I am sure I still missed some. I want all of you to know how deeply your words and your wishes landed. Thank you for that.

An overhead illustration of a cluttered hobbyist workbench with soldering iron, parts drawers and a notebook of diagrams, and a single plain phone resting apart from it all at the edge of the bench.

Not Everyone Wants a Hobby

Yesterday I wrote about leaving Google after twenty one years and said there was a next chapter I would tell you about today. This is it.

Chris Perry and I are starting a company. It is called Vycari, we are building agents, and we are looking for people to test what we make. I want to spend most of this post on the problem rather than the product, because the problem is the interesting part and because the product is not ready for you yet.

Using agents today is a skill

Here is what it currently takes to get real value out of an agent.

You curate your skills, your triggers, and your extensions. You pick the right model for the task and make sure it is wired to the right API key. You keep the right software installed and updated on your machine. You have a sandbox configured, because obviously you have a sandbox configured. You learn which failures are the model’s fault and which are yours. You read changelogs, because the thing you learned last month is already wrong.

That is not using a tool. That is adopting a hobby.

I want to be careful here, because I do not mean that as a complaint. There is nothing wrong with AI as a hobby. A great many of the real sea changes in personal computing were driven by people who treated the work as an avocation first and a profession second, and the current moment is no different. I count myself among those people. They are my people. This blog exists because of them, and I am not going to stop writing for them.

But it is worth being honest that this is what we have built so far, and about who it excludes.

Most people do not want a hobby

Not everyone wants their tool to become a pastime. Not everyone wants to marvel at the stack, or to feel the small thrill of watching software take an action in the real world on their behalf. Plenty of capable, curious, technically fluent people simply want to get something done, and they want to use whatever makes that easiest.

I am friends with a lot of these people. They are not incurious and they are not afraid of technology. They carry a supercomputer in their pocket and use it fluently all day. They have just never been given a reason to believe that an agent is for them, because every agent they have encountered asked them to become a hobbyist first.

Chat apps are the exception that proves the point. They reached enormous audiences because there was nothing to adopt: you type, it answers, and the entire interface is a thing you already knew how to use. Step outside that box and agents are still close to magic for most people, and magic is not a compliment when you are trying to get through a Tuesday. Agent products remain genuinely hard to use, and the difficulty has very little to do with how good the models have become.

What I keep coming back to

The most useful thing I learned in two years of building agents has almost nothing to do with models. It is this: people do not bounce off AI because it is not smart enough. They bounce off because the cost of using it, all of it, the setup and the vocabulary and the remembering to go there, is higher than the problem they were trying to solve.

Which means the frontier I find interesting is not making these systems more capable. They are already more capable than almost anyone is extracting value from. The frontier is closing the enormous distance between what the technology can do and what an ordinary person can actually get out of it on a normal day, without a new app, a new habit, or a new hobby.

That gap is not a model problem. It is a product problem, a reliability problem, and a taste problem. It is also, as far as I can tell, wide open.

What we believe

We are early enough that I would rather tell you what we intend than what we have built. Four things we are holding ourselves to.

Meet people where they already are. If using the thing requires a new destination in someone’s day, we have already lost, no matter how good it is once they arrive.

Earn the trust the access requires. An agent worth having needs to see calendars, mail, and contacts, which is about as intimate as software access gets. There is no version of this business where that access to private data becomes an advertising product, and there is no version where you cannot take your data and leave.

Never make you learn our vocabulary. Nobody should have to know what a skill is, or which model answered, or that any of this is AI at all. Those are our problems. The user’s problem is that they asked for something and want it handled.

Be warm about it. An assistant you find pleasant is one you will actually use, and an assistant you actually use is the only kind that matters.

Who we are

My co-founder is Chris Perry. He is the CEO. I am the CTO. Chris used to report to me, and putting him in the CEO seat was one of the easier decisions either of us has made.

We have been circling each other for about a decade. We met when I was running Street View and imagery inside Maps and he was a PM on Google Photos, back when our two teams were trying to make those products understand each other’s pictures. Years later he turned up in the AI Developer organization I was running, as the product lead for Colab. Most recently we were both on the founding team of Gemini CLI and shipped its Workspace extension together. Somewhere in there he stopped being someone I had worked with and became someone I wanted to build with. He is writing his own version of this announcement, and his path here is different enough from mine that you should read both.

It is just the two of us right now, and we are both in the codebase. One of the underrated pleasures of leaving a large company is that you get to assemble the org chart from scratch, based on who is best at the job rather than on who has been there longest.

The part where I ask you for something

Twenty one years at Google taught me how to build systems where the hardest problems are problems of coordination. This is a different kind of hard. There are two of us, the feedback loop is measured in hours, and the person on the other end of a failure is someone who trusted us with something that mattered to them. I have not been this uncomfortable in a long time, and I have not enjoyed work this much since 2008.

We are opening to testers in the coming weeks, a few at a time and deliberately, because the failure I am most afraid of is someone relying on this and being let down. If you would like to be in that first group, put your name down here. What we want back is your honest experience, particularly the parts where it does not work.

And if the person who came to mind while you were reading this was not you but someone else, someone who would get enormous value from an assistant and would never in their life go looking for one, then you have understood exactly who we are building for.

I will keep writing about the engineering here as we go. It is going to be a good year.

A desktop 3D printer printing a small mechanical part in a home workshop, with filament spools blurred in the background.

The Bill That Wants My 3D Printer to Police Itself

There is a printer humming in my workshop right now, laying down a part one 0.2mm layer at a time. It is a slow, almost meditative machine. It does not know what it is making. It does not know if the object taking shape on the bed is a bracket for my garage shelving, a fidget toy for my son, a one-off template, a jig for my guitar building, or something I should not be making at all. It knows one thing: move the nozzle here, push out this much plastic, repeat a few hundred thousand times. That is the entire worldview of a 3D printer.

I bring this up because the California legislature has decided my printer should know more than that. Assembly Bill 2047 would require every 3D printer sold in the state to run a state-certified “detection algorithm” designed to recognize and refuse to print firearm components. I got into this hobby almost a decade ago on a Prusa, I still run one today, and I have spent enough of my career writing software to have a strong and specific reaction to this. It is not a political one. It is an engineering one. The bill asks for a piece of software that cannot reliably exist, and even if it could, it would have nowhere to run. On top of that imaginary foundation it then builds an entire regulatory apparatus.

What AB2047 Actually Asks For

The mechanics are worth understanding before we argue about them. The bill lays out a multi-year timeline. By July 2027, the California Department of Justice studies firearm detection technology. By January 2028, it certifies detection algorithms from vendors. By July 2028, manufacturers must submit an attestation for each printer model they sell. By September 2028, the state publishes a list of approved printers, updated quarterly. And starting in March 2029, selling a non-compliant printer in California becomes illegal. There are new criminal penalties for anyone who disables the detection technology.

Read that sequence again and notice what it assumes. It assumes that by 2028 there will be vendors selling reliable firearm-detection software, that the DOJ will be able to certify it, and that manufacturers can bolt it onto their machines. The entire structure depends on step one being possible. So let’s look at step one.

A Rifled Barrel Is Just a Grooved Cylinder

Here is the core problem, and it is the kind of thing that sounds solvable until you actually try to specify it. A 3D printer receives a model. The model is geometry: a mesh of triangles, sliced into a stack of two-dimensional paths. To detect a firearm part, the software would have to look at that geometry and decide whether it represents something dangerous.

But geometry does not carry intent. A rifled barrel, to a detection algorithm, is a grooved cylinder. So is a section of industrial screw thread. So is part of an optical instrument, a custom gear, a textile bobbin, a printable fidget toy, a thousand legitimate objects. The shape that makes a barrel a barrel is not unique to barrels. You cannot write a function that takes in a mesh and returns “this is a gun part” without either missing real firearm components or flagging an enormous number of innocent ones. In machine learning terms you are choosing between false negatives and false positives, and both failure modes here are catastrophic. Miss the real thing and the law accomplishes nothing. Flag the innocent thing and you have a printer that refuses to make a curtain rod bracket because it looks suspicious.

It gets worse once you remember that the person trying to evade detection gets a vote. Shape-based detection is defeated by the most trivial transformations imaginable. Rotate the model. Scale it slightly. Split a banned object into a handful of innocent-looking pieces, print them across separate jobs, and assemble them on the bench, which is how people print large or complex parts anyway. None of these change the function of the final object, and all of them defeat a classifier looking for a known silhouette. There is an old locksmith’s adage that locks only keep honest people honest. A detection algorithm is a kind of lock, and this one stops the honest while inconveniencing nobody who is actually a threat.

Where Would This Software Even Run

Suppose, against all of this, that someone ships a detection algorithm that actually works. There is a second wall waiting behind the first, and it is the part of this I find almost funny: even a perfect classifier would have nowhere to run.

Here is what most people, and I suspect most legislators, do not realize about how these machines work. By the time a design reaches my printer, it is no longer a 3D model. Software on my computer, called a slicer, has already flattened it into G-code, a dumb list of hundreds of thousands of instructions that say move here, extrude this much, heat to this temperature. The printer’s control board never sees the shape of the object at all. For the firmware on the printer to detect a gun, it would have to reconstruct a three-dimensional model out of raw toolpaths and run shape analysis on it, on a microcontroller with kilobytes of memory. My Prusa cannot do that. No consumer printer can. It is not a hard engineering problem so much as an absurd one.

So the detection has to live somewhere else, and there are really only two places it can go. The first is the slicer. But the popular slicers, PrusaSlicer, Cura, OrcaSlicer, are themselves open source. You fork the one with the block stripped out, or you simply use a different one, and nothing downstream ever checks what it produced. The second place is the only one that actually enforces anything: require every printer to refuse any G-code that is not cryptographically signed by a state-approved cloud slicing service. That version works, in the narrow sense that it would function. It also means the end of slicing your own files on your own computer, the end of open-source firmware, the end of the printer as a general-purpose tool. It turns an open machine into a locked appliance that prints only what a government-approved server allows.

That is the choice the bill quietly forces, even if its authors never say it out loud. Either the detection is real and trivially bypassed, or it is genuinely enforceable and the open ecosystem is dead.

And that open ecosystem is not incidental to how these machines work. The software that actually drives them, the two dominant projects Marlin and Klipper, is open source and free to download, and replacing the firmware on a printer is something the community does routinely, in minutes, to tune machines and add features. A state-mandated block sitting in that firmware is removable by definition. The whole community already holds the key to the proposed lock. The law is betting that criminals either do not know the key exists or will politely decline to use it. The bill’s response is criminal penalties for disabling the technology, which means the actual enforceable result is that an ordinary maker who updates their firmware becomes a potential criminal, while anyone with bad intent was always going to use a non-compliant machine bought out of state or built from parts.

Who Actually Pays

This is where the abstract engineering critique becomes a real-world one. The signatories on the opposition letter are not a fringe group. They include Prusa Research, Make Magazine, and VORON Design, alongside individuals like Josef Průša, Dale Dougherty, and Joel Telling of 3D Printing Nerd. The numbers they cite are the reason. More than 1.5 million California students reach 3D printing through their schools. More than 30,000 businesses depend on it, from dental labs to jewelers to small manufacturers. There is something on the order of $10.5 billion in investment riding on this ecosystem in the state.

The bill’s penalties, reportedly $25,000 per violation, do not land on the people it is nominally aimed at. They land on the school district, the maker space, the library, the small business owner running three printers in a garage. Those are the entities that buy from compliant vendors, register their equipment, and follow the rules. The person determined to manufacture an untraceable weapon was never in that group. They route around the law, because routing around the law is, as we just established, trivial. So you end up with the worst possible outcome: real cost imposed on the law-abiding, near-zero cost imposed on the dangerous, and a chilling effect on exactly the educational and small-business use that makes this technology worth having.

Compelled Speech and the First Amendment

There is a legal dimension I am less qualified to litigate but that I think any engineer should at least register. CAD files and the source code that drives these machines are, under a long line of cases, a form of protected expression. The bill requires manufacturers to attest to the behavior of an algorithm operating on that expression, which the opposition frames as compelled speech on a matter of public concern. I am not a lawyer, and I will not pretend the constitutional question is open and shut. But it should make us uncomfortable that the mechanism here is the state requiring a company to vouch for the output of detection software that, as far as anyone can demonstrate, does not actually work. Picture a law that required every typewriter manufacturer to certify, in writing and renewed every year, that their machines cannot be used to type a threatening letter. That is roughly the position AB2047 puts a printer company in. You are being compelled to attest to a fiction, under penalty.

What This Pattern Should Teach Us

I want to be careful here, because it is easy to read a piece like this as “no regulation, ever.” That is not my position. Untraceable firearms are a genuine problem and a serious one. The objection is not that the goal is illegitimate. The objection is that the proposed mechanism is engineering fan fiction, and that mandating impossible software does not become possible because a statute says so.

It helps to remember what the law already does. California does not ignore homemade firearms. If you want to build your own, you must first apply to the Department of Justice for a serial number and engrave it on the receiver, and doing otherwise is itself a crime. The state already regulates the dangerous act, directly, where it belongs. What AB2047 does instead is reach past the act and conscript the tool. Nobody expects Home Depot to interrogate why I am buying a length of steel pipe or a box of fasteners, even though plenty of dangerous things can be assembled from ordinary hardware. We regulate the act, not the hardware store, because the hardware store cannot read minds. Neither can my printer.

This is a pattern worth recognizing, because 3D printers are not the last general-purpose tool a legislature is going to try to make smart enough to police its own users. Any time a law says “the tool must detect bad use and refuse it,” an engineer should ask the boring, deflating questions. Can the tool actually distinguish intent from form? What does the determined adversary do in response? Who absorbs the cost when the detection is wrong? For AB2047 the answers are no, they trivially route around it, and the schools and makers do. When those are your answers, you do not have a safety feature. You have a tax on the honest and a piece of theater for everyone else.

If you build things, and especially if you build things in California, this one is worth paying attention to. The opposition letter has a breakdown of where the bill stands and who to contact on the Senate Judiciary and Public Safety committees before it advances. I am writing to those committee members, and I am going to call my own state senator, Dave Cortese, because the gap between what the bill asks for and what software can actually do is not a close call, and that gap is precisely the kind of thing the people who build these machines are in a position to explain.

My printer is still running as I finish this. It still has no idea what it is making. And no statute, however well-intentioned, is going to change that.

A spotlight shines on a pianist intensely playing a small, worn piano on a large, dark stage.

The Koln Concert and Creative Constraints

This week I was reminded of a story I like to tell, and the value of constraints on creative work. When I’m working, I often set my constraints before I begin. For example, on an old agentic coding project, I set a few constraints: “The orchestration model must be Gemini Flash,” “All tool calls are through sub-agents,” and “Permissions and configurability are at the core of the agentic loop.” From that, I ended up with adh-cli, a policy-aware TUI for working with Gemini that inspired many of the features I worked on in Gemini CLI last year. The project itself is defunct now and not maintained, but the constraints gave me a great way to think about the project and forced creativity in other areas.

We run into constraints in many different ways. Maybe it’s time pressure: How many of you felt like you wrote your best papers 24 hours before they were due? Maybe it’s the environment, like you must integrate with a certain piece of software, or you have to design your system in a certain way. Maybe it’s self-imposed like my example with adh-cli.

Or maybe the constraint is philosophical. Take Mario Zechner’s Pi Agent, for example. In a blog post, Zechner expressed frustration with the bloat of modern AI coding assistants that try to do everything, describing them as “spaceships with 80% unused functionality.” In response, he built Pi around an “anti-framework” philosophy of radical minimalism. He intentionally constrained his default coding agent to just four fundamental tools: read, write, edit, and bash. By stripping away the hidden system prompts and unpredictable context injections, the tool forces developers to be intentional. It proves that you don’t need a massive, opaque framework to build highly capable AI workflows—sometimes, fewer tools create a sharper focus.

Whether it’s a self-imposed architectural rule or an anti-framework philosophy, these software constraints force us out of our default habits and into a space of deliberate, intentional design. Yet, in our day-to-day work, constraints are rarely celebrated. In fact, that is actually how I end up in constraint conversations the most often: people don’t like their constraints because the constraint has been imposed on them externally. They see it as a restriction instead of a way to channel their creativity. To me, a constraint means that we shut down a huge portion of the exploration space. I don’t have to worry about a million different architectural choices because the constraint has made the decision for me. It is incredibly freeing. Whenever I try to help someone turn around their mindset—from fearing or being frustrated by constraints to being excited by them—I inevitably end up telling them the story of Keith Jarrett and the 1975 Köln Concert.

In 1975, a 17-year-old jazz fan named Vera Brandes organized a late-night concert at the Cologne Opera House. She managed to book Keith Jarrett, one of the most notoriously perfectionist jazz pianists of his generation. It was an ambitious undertaking, and almost immediately, it turned into a disaster.

Due to a backstage mix-up, the venue provided the wrong piano. Instead of the premier concert grand Jarrett requested, he was presented with a small rehearsal model. It was horribly out of tune, the pedals stuck, the high notes sounded tinny and harsh, and the bass lacked any resonance. Jarrett, exhausted and suffering from back pain, flat-out refused to play. It was only when Brandes followed him out into the pouring rain and begged him that he relented, taking pity on the teenager. “Never forget,” he told her. “Only for you.”

What happened next is legendary. Forced to play an unplayable instrument, Jarrett had to completely abandon his usual style. Because the high and low registers were awful, he confined his playing strictly to the middle of the keyboard. Because the piano was too quiet to fill the 1,400-seat opera house, he stood up and hammered the keys with immense physical force. To make up for the lack of resonance, he relied on rolling, repetitive, hypnotic rhythmic patterns in his left hand.

He embraced the limitations, and in doing so, he produced absolute magic. The recording, The Köln Concert, went on to become the best-selling solo jazz album in history.

I think about the Köln Concert all the time, especially lately as we navigate the current landscape of Artificial Intelligence and software architecture.

The Bloat of Infinite Resources

In modern software engineering, we are rarely handed a broken piano. We operate in an era of perceived infinite resources. Cloud computing gives us endless horizontal scaling. Context windows for Large Language Models have ballooned from a meager 4K tokens to 1 million or more. If an application is slow or an agent isn’t performing well, the default instinct is to throw more compute, more memory, or a larger model at the problem.

But infinite resources often breed intellectual laziness. When you have a 1-million token context window, you don’t have to think critically about what information actually matters. You just dump the entire codebase or the entire library of documents into the prompt and hope the model figures it out. It’s the equivalent of having a perfect Bösendorfer grand piano and just mashing all the keys at once.

A pragmatic engineering manager might push back here: Developer time is expensive. If I can solve a problem today by dumping an entire codebase into a 1-million token context window, isn’t throwing compute at it just good business?

It’s a fair question, and engineering is always about tradeoffs. But the tools have evolved—building a RAG pipeline doesn’t take a week anymore; with the right utilities, it takes minutes. More importantly, relying on infinite resources often hides long-term costs. When I built adh-cli, I made an explicit tradeoff: by routing everything through tightly scoped sub-agents, I was actually consuming more total tokens than a single massive prompt would use. But because my constraint forced me to use a much cheaper model (Gemini Flash), my bet was that the overall system would be far more cost-effective and resilient. AI doesn’t remove the need for architectural judgment; it exponentially increases it. You have to exercise good judgment to know when throwing compute at a problem is a calculated business decision, and when it’s just masking a fragile design.

The Innovation of Constraints

The most interesting work in AI right now isn’t happening where resources are unlimited. It’s happening at the edges, where constraints are severe.

Take local models, for example. When you’re trying to run an LLM on a consumer laptop or a Raspberry Pi, you don’t have the luxury of a 70-billion parameter model. You are forced to use a smaller, quantized model. This constraint forces you to build better architectures. You can’t rely on the model to “know” everything, so you have to optimize at the edge. Maybe you build robust Retrieval-Augmented Generation (RAG) pipelines. Maybe you implement sophisticated memory retrieval systems to surface exactly the right historical context just-in-time. Or maybe you break complex workflows down into tiny, focused sub-agents, each operating with its own tightly constrained context window. You have to craft highly specific, deterministic prompts.

# Instead of one massive prompt, constraints force modularity
def evaluate_code_chunk(chunk: str, context: dict) -> EvaluationResult:
    """
    A tightly scoped function that uses a small, fast local model
    to evaluate a specific piece of code, rather than dumping
    the whole repo into a massive API call.
    """
    prompt = build_focused_prompt(chunk, context)
    response = local_model.generate(prompt, max_tokens=256)
    return parse_evaluation(response)

Just like Jarrett avoiding the tinny upper register, we learn to avoid the weak points of our tools. We build guardrails. We write cleaner code. We design systems that are elegant because they have to be.

Finding Your Broken Piano

Of course, there is a survivorship bias to the Köln Concert. For every broken piano that produces a masterpiece, there are a hundred broken laptops that just result in missed deadlines. Not all constraints are good constraints. You can’t change the laws of physics, and if a structural limitation is genuinely preventing the work from happening, you have to reevaluate. The goal isn’t to suffer for the sake of suffering. But by starting with strict constraints, you force yourself to explore the boundaries. If you prove a task is impossible under those conditions, you can always loosen the constraints and expand your resources. But if you start with infinite resources, you never learn where those boundaries actually are.

Constraints are not the enemy of creativity; they are its prerequisite. Yes, accepting a severe constraint—especially an external one you didn’t choose—can be incredibly painful in the moment. Keith Jarrett hated his broken piano. He didn’t feel freed; he fought against it until he was forced to adapt. But like exercise or eating your vegetables, the value isn’t in the immediate comfort. It’s about the mindset shift. You accept the constraint to build a muscle, to stay fit, to force yourself to find a new path when the easy one is blocked. When we are stripped of our ideal tools and infinite runways, we are forced to abandon our default habits. Whether it’s the self-imposed design rules of adh-cli, the radical minimalism of Mario Zechner’s Pi Agent, or the physical limitations of a broken rehearsal piano in Cologne, constraints force us into a space of deliberate, intentional action.

If you want to build a truly resilient, innovative system, don’t start with the biggest, most expensive tools available. Start with a broken piano. Artificially constrain your resources. Limit your context window. See what you can achieve with a 7B parameter model instead of a flagship API, or see what happens when you strip your agent’s toolkit down to the bare essentials.

You might just find that the limitations force you to build something far better than you would have otherwise—a system that is elegant not in spite of its constraints, but because of them.

So, look around your current projects. Where are you relying on infinite resources to mask lazy architecture? And more importantly: what constraints have you come across in your own work that felt like a frustrating restriction at first, but turned out to be a blessing in disguise? I’d love to hear your stories.