Reading Simon Willison’s Blog at 11 PM
I was catching up on Simon Willison’s blog late last night when I saw he shipped Datasette Agent — an AI assistant that answers natural-language questions about your SQLite databases. The demo sold me: “When did Simon most recently see a pelican?” The agent queried his personal database and returned the answer. No SQL, no schema knowledge. Just a question.
I couldn’t sleep after reading it. Not because of pelicans. Because this is exactly the problem our procurement team faces every week.
The Problem: Same Questions, Same SQL, Same Bottleneck
Our ERP runs on PostgreSQL — dozens of tables, years of purchase orders, supplier records, QC results. The questions are predictable: “Which vendor had the highest rejection rate last quarter?” “Show me all POs over budget by more than 20%.” “How much did we spend on expedited shipping?”
Every answer requires a SQL query. Every SQL query requires someone who knows the schema. And that someone is usually me.
I get pinged on Slack. I context-switch. I write the query. I send back results. Repeat. This doesn’t scale when you’re also building Angular frontends and maintaining CI/CD pipelines.
What Datasette Agent Actually Does
Willison built the agent on his LLM Python library — a project he’s maintained for over three years. It uses Claude as the model (cheap, fast, reliable with SQLite) and connects to a Datasette instance. You type a question in plain English, and the agent:
- Generates SQL from your question
- Runs it against the database
- Returns the result
- Retries with corrections if the query fails
The plugin system is what makes it interesting. Install datasette-agent-charts and suddenly the agent can generate charts from your data. The architecture is intentionally thin — new capabilities come from plugins, not from a monolithic system prompt.
My Sunday Morning Experiment
I don’t use SQLite in production. Our stack is PostgreSQL, and switching databases isn’t an option. So I spent Sunday morning building a lightweight equivalent.
The core loop is the same: user asks a question → LLM generates SQL → query runs against PostgreSQL → result is formatted → if error, retry. I used LangChain’s SQL agent as a base but stripped out most of the framework bloat. The whole agent is about 200 lines of Python.
One thing I learned immediately: the LLM needs schema context. Not the full DDL dump — just table names, column names, and a one-line description per column. I wrote a small extractor that queries information_schema.columns and formats it as a compact block. That alone cut hallucinated column names by roughly 90%.
The model I used was deepseek-v4-pro — it handles SQL generation well and is generous enough with context windows to include a full schema summary.
Real Questions, Real Answers
Once I had the agent running against a read-only replica, I shared it with the procurement team. The questions surprised me:
- “Which vendor has the highest rejection rate on incoming QC?” (joins across 4 tables)
- “Show me the 5 most reordered SKUs this month, with lead times.”
- “How much did we spend on expedited shipping last quarter?”
All real questions. All previously required someone to wait for me. Now they type the question and get a table back in seconds.
The agent isn’t perfect. It still generates wrong JOIN conditions about 15% of the time, especially on tables with ambiguous foreign key names. I added a verification step — before returning results, the agent explains in plain English what the query does. If the explanation doesn’t match the user’s question, they can reject it and the agent retries.
Verdict: Own the Pipeline
Don’t start with a framework. I looked at LangChain’s SQL agent, Vanna.ai, and a few others. They’re all designed for generic use cases and add complexity you don’t need. The simplest approach — prompt + schema + function calling — handles 80% of use cases.
Also, never run this on your production database. I set up a read-only replica with a dedicated user that has zero write permissions. The worst it can do is run a slow query against the replica, and that’s easy to kill.
Simon’s approach of building on his own library gives him full control over model interaction. That’s the lesson I’m taking away with me: own the pipeline, don’t outsource it to a framework. If you’re maintaining a PostgreSQL database that gets regular ad-hoc questions, try building a lightweight SQL agent yourself. Approach it like you’d approach any AI coding task — persona first, tool second, framework last.
Related: Post 4: Building the Agent Team — Supervisor, Coder, Reviewer, QC.
Related: One Markdown File Made My AI Agent 23 Points Smarter.
Discover more from Susiloharjo
Subscribe to get the latest posts sent to your email.