I built an AI agent guardrail. Nobody downloaded it.
Four downloads a week. Zero upvotes on Hacker News. On the subreddits I got two or three comments that were pretty clearly AI generated, all sitting at zero points.
That is the scoreboard for owthorize, a library I spent weeks building and was completely sure people needed.
Everyone writes the win post. The launch that hit number one, the side project that got acquired, how I got my first 1,000 users. I have read a hundred of them and I have learned almost nothing, because success has too many parents and most of them are luck. So this is the other post. This is what actually happened, including the part where I was right about the problem and it did not help me at all.
The problem is real
I gave an AI agent access to a database. It worked fine, until one run where it decided the cleanest way to reset some test data was this:
DELETE FROM users
No WHERE. My system prompt said "you are careful, never run destructive queries."
Well, the prompt does not run the query. The tool call does.
That is the whole thing. Once you see it you cannot unsee it. By the time the model has emitted a tool call, every "please be careful" you wrote is already spent. The only place left to stop the damage is the gap between the model deciding and your code executing.
So you do the obvious thing and block the scary words:
if (sql.includes("DELETE") || sql.includes("DROP")) block();
This fails in both directions. It blocks SELECT * FROM audit_drops because the word "drop" is sitting inside a table name. And it lets through plenty of genuinely destructive queries, because a keyword match reads text, and SQL has structure. You are guessing what a query means by looking at its surface.
The fix is to stop matching strings and start reading the query:
const ast = parse(sql);
if (ast.type === "delete" && !ast.where) block();
if (ast.type === "drop") block();
Parse it into an AST and ask structural questions. Is this a DELETE with no WHERE clause? Is this an actual DROP TABLE, or just the letters d, r, o, p sitting in a string? You read the shape of the thing instead of grepping its spelling.
The same idea covers the other ways an agent hurts you. Is this URL quietly pointing at the cloud metadata endpoint? Does this shell command carry metacharacters that break out of what you intended? Is this file path climbing out of its directory with ../? Every one of them is the same question. Understand the call before you run it.
I still think all of this is correct. I would defend every line of it. That is what makes the rest of this post interesting instead of just sad.
So why did nobody want it?
Here is the thing that took me a while to admit, and it is the actual lesson.
The problem being real is not the same as your solution being wanted.
Everyone building agents that touch real systems does hit this. But when they hit it, they do not go looking for a library. They write twenty lines of validation around their own tool handler, ship it, and move on. It takes an afternoon. It is slightly wrong in ways they will not discover for months — a regex where an AST should be, a check sitting on the wrong layer — but it works well enough that the itch stops.
So the market for my library was never "people with this problem." It was "people with this problem who have also decided their own twenty line version is not good enough." That is a much smaller group. Right now it might be an empty one.
What I was selling was correctness and convenience. That is real value. It is just not urgent value. Nobody wakes up and searches for "how do I stop my agent dropping tables," because they already solved it, badly, three weeks ago, and they have not been burned yet.
You do not get adopted for being more correct than somebody's hack. You get adopted for solving something they cannot solve themselves.
That is the first reason, and it is the technical one.
And then there is the real reason
I am bad at distribution.
Not "I should learn some marketing" bad. Structurally bad. I have no audience. I have never had an audience. I built a thing, posted it into three rooms full of strangers who had no reason to care what I think, and then acted surprised when strangers did not care what I think.
Posting into a cold room is not a launch. It is a lottery ticket.
And this is not a one off. If I am honest with myself it is the pattern of everything I have built. Before this I built a monitoring app for a SaaS marketplace. It worked end to end, it was genuinely useful, and I had no way to reach the people who would want it. Before that, other things. The engineering was never the bottleneck. It has been distribution every single time, and I kept not noticing, because building is fun and distribution is not.
Here is the uncomfortable maths. A great product with no distribution gets four downloads. A mediocre product with distribution gets four thousand. I have spent years getting very good at the half of that equation that does not multiply.
What I would tell myself before starting
Being right about the problem earns you nothing. The question is never "is this a real pain." It is "are people actively trying to solve this and failing." Those are two completely different questions and only the second one has customers in it.
"They could build it themselves in an afternoon" is a death sentence, not a footnote. I knew this about owthorize and I built it anyway, because I wanted the version that was actually correct. That is fine, but then it is a craft project, and I should have called it that from day one.
Distribution is not a launch step. It is a prerequisite. You do not build the thing and then work out how to reach people. You have the way to reach people, and then you build the thing they told you they wanted. I have had this backwards my whole building life.
And post the loss, not just the win. This post will almost certainly do better than the library did. That tells you something about what people actually find useful, and it is not code.
The library still exists
It is MIT, it works, it is on npm. owthorize. Parse, do not match. If the day comes when agents routinely have write access to production and somebody's twenty line hack finally bites them hard enough, it will be sitting there.
Maybe I was early. Maybe I was just wrong in a way that took four weeks and one launch to find out. Honestly, from where I am standing, those two look identical. The only difference between them is whether anybody was listening when you said it.
Right now, nobody was. That is the part I am going to go fix.
— Ayush
← back to blog