One of the first things you discover when you begin doing agentic development is just how astonishingly capable these systems can be at writing code. You can describe surprisingly elaborate things in ordinary language, work through the problems iteratively, and watch the agent tie together libraries, databases, APIs, interfaces, and infrastructure into actual working software.
But one of the next things you discover—or at least one of the next things I discovered—is that this extraordinary competence can be accompanied by a certain kind of naïveté.
I do not necessarily mean hallucination in the conventional sense of the agent simply making something up. The problem is often subtler than that. Unless you force the agent to ground its assumptions in the particular reality you are dealing with, it will quite happily reason from generalized knowledge and approximate conditions. And because it communicates those approximations with the same fluency and confidence it uses when it actually knows something, a reasonable estimate can sound an awful lot like an informed judgment.
This is something I have become much more careful about over the past year. The agent can help you reason through a problem. It can tell you what is typical. It can construct a plausible architecture. It can even build the thing. But at the end of the day, you are still the person responsible for determining whether the assumptions underneath its recommendations correspond to reality.
What I eventually learned was to stop treating an agent’s estimate as evidence until I could identify the assumptions underneath it—and verify that those assumptions actually applied to the system I was building.
One of the first ways I learned that lesson was an expensive one.
During the first couple of weeks I spent thinking seriously about Skysquare, I repeatedly asked my agents some version of the same question: What is this thing actually going to cost me?
At the time, the numbers I was getting back seemed remarkably manageable. Even the more pessimistic scenarios generally landed somewhere in the neighborhood of a few hundred dollars a month to operate the application on AWS.
Two hundred dollars? Three hundred dollars? Well, hell. I could afford to experiment with that.
My own experience with AWS up to that point did not give me much reason to doubt the estimate. I had been using AWS for years, but mostly to host open-source applications I had spun up for clients. In those situations, somebody else had already designed the application. Somebody else had already figured out how its pieces fit together. My job was largely to provision a server, configure the software, connect the necessary services, and keep the thing running.
Building an application from scratch turned out to be a rather different proposition.
And building this application turned out to be considerably more complicated than anything I had imagined when I watched that first prototype appear on my screen.
At the product level, Skysquare sounds almost comically simple: somebody opens a webpage, Skysquare finds the Bluesky posts associated with it, and those posts appear alongside the page.
That is more or less what the prototype did.
But once I started asking what would have to exist underneath that experience for it to work reliably for other people, I began discovering an enormous amount of machinery hiding inside that seemingly simple sentence.
For roughly the first six weeks of the project, during the summer of 2025, I investigated and experimented with what that machinery would need to look like. It is worth remembering that the agentic models I was working with then were considerably less capable than the systems available today, and I was learning how to work with them at the same time they were helping me learn how to build the application.
Every answer seemed to reveal another question.
If Skysquare was going to show people Bluesky posts about the pages they were reading, where were those posts going to come from? How would I know when somebody shared a new page? How would I collect that information continuously? How much of the Bluesky network did I need to watch? Which records did I need to keep? Where would I put them? How long would I keep them? What happened when somebody deleted a post? What happened when two different URLs actually pointed to the same article? How quickly did the information need to come back when somebody opened a page?
And, lurking underneath all of those questions: How much is this going to cost?
This was where I began to understand the distance between having a working application on my screen and having a working application in the world.
The jump from a prototype working in my own browser, powered by a quickly assembled ingestion of the Bluesky Jetstream—which, almost literally as I write these words, has itself been substantially reworked in the newly announced Jetstream v2—to something other people could actually use was going to be much larger than I had initially appreciated.
One of the first limitations I confronted was history.
Jetstream was extremely useful for telling me what was happening on Bluesky now. But at the time I was building these early versions of Skysquare, it only gave me a relatively short window into the recent stream. If I discovered an interesting writer today and decided I wanted Skysquare to understand everything that person had shared in the past, I could not simply ask Jetstream to hand me their entire history.
That presented a fairly obvious problem for the product I had imagined. Skysquare was supposed to show you the Bluesky conversation around the things you were reading. But if I had only begun watching a particular person yesterday, what happened to the hundreds or thousands of useful links they might have shared before I started listening?
Somehow, eventually, I was going to need a historical record.
For a while I treated that as a problem for the future. Maybe I would buy access to some existing archive. Maybe I would devise my own backfill process. Maybe there was some other part of the ATProto infrastructure I had not yet discovered. I did not know. I only knew that, if Skysquare was ever going to become the application I had in my head rather than merely an interesting live demo, I was eventually going to have to solve it.
Then, as 2025 was coming to a close, the AT Protocol team released something called Tap.
Tap was almost uncannily well suited to the problem I had been staring at. Instead of merely listening to new events as they passed through the firehose, I could tell Tap which repositories I wanted to follow. Tap would go back to the user's PDS, fetch the existing repository, deliver that historical data to my application, and then transition cleanly into delivering the new events arriving in real time. It also handled a bunch of synchronization machinery I barely understood at the time—verification, ordering, recovery, buffering live events while the historical backfill was underway.
Suddenly, one of the biggest unanswered questions in the Skysquare architecture had an answer.
If I identified a Bluesky account that mattered to Skysquare, I no longer had to accept that I would only know what that person shared from the moment I discovered them onward. I could begin backfilling the existing records in the repositories I cared about and then keep them synchronized as the network changed.
Of course, there was another way of looking at this development. I had just discovered a way to acquire considerably more data.
I understood immediately that incorporating Tap was going to be a serious project. But by this point I had already spent months building, and thinking about what Skysquare ought to become, and the architecture suddenly offered me a way to build out the historical depth I had wanted from the beginning. If I was going to do this, I reasoned, I might as well do it correctly.
So I committed to it.
And somewhere around that decision, the pleasant little infrastructure model I had been carrying around in my head—the one in which this experiment might cost me two or three hundred dollars a month—began to come apart.