Simon Willison just published a small but instructive example of how to use an AI coding agent on a genuinely obscure technical problem. As Simon Willison reports, he wanted Datasette to look at any SQL query and figure out which table.column each result column actually came from, even through joins and CTEs. Rather than grind through the SQLite internals himself, he handed the problem to Claude Code (Opus 4.8) and let it surface the options. What stands out here is the workflow, not just the answer. This is a clean template for using AI to explore a solution space you don’t already know.
📋 Quick Start
You’ll learn how to point an AI coding agent at a hard, poorly documented problem and have it return multiple working approaches you can compare. What you need: an AI coding agent (Simon used Claude Code with Opus 4.8), a clearly stated problem, and a willingness to evaluate several candidate solutions instead of accepting the first one.
🛠️ The Problem Worth Framing First
Before touching the agent, Simon defined the goal precisely. He wanted arbitrary SQL like select users.name, orders.total from users join orders on orders.user_id = users.id to be traced back so each result column maps to its real source table and column. This matters because a vague request gets a vague answer. The more exactly you state the edge cases (joins, CTEs, complex syntax), the better the agent scopes its search.
🤖 Step 1: Hand the Problem to the Agent
Simon set Claude Code on the task using Opus 4.8. His aside on model choice is a useful reminder: pick the model you can actually run. He noted Fable was unavailable to him, so Opus 4.8 did the work. The practical lesson is to give the agent a self-contained problem statement and let it investigate rather than spoon-feeding it a single expected method.
🔍 Step 2: Let It Return Multiple Approaches
This is the core move. Instead of one answer, the agent came back with several promising solutions. According to Simon Willison, it found three distinct paths:
- The
apswroute. Using the alternative Python SQLite wrapper, which exposes lower-level capabilities than the standard library. - The
ctypesroute. Reaching into SQLite’s C layer to callsqlite3_column_table_name(), a function that isn’t otherwise exposed to Python. This is the clever one, because it taps native functionality most developers never see. - The
EXPLAINroute. Interrogating the output of SQLite’sEXPLAINcommand to deduce column origins.
Why this matters: each approach trades off differently on dependencies, portability, and fragility. An agent that hands you three options lets you weigh them instead of locking you into the first idea that compiled.
💡 Tips and Best Practices
- Ask for options, not an answer. The value here came from breadth. Three candidate solutions beat one, especially in unfamiliar territory.
- Name the hard cases up front. Simon called out joins and CTEs explicitly, which kept the agent honest about edge cases.
- Verify before you ship. Approaches like the
ctypescall into undocumented territory work, but they can break across versions. Treat agent output as a starting point to test, not a finished product. - Use the agent to find what isn’t documented. The
sqlite3_column_table_name()trick is exactly the kind of buried capability an agent surfaces faster than manual searching.
This is significant because it shows AI agents earning their keep on research-grade problems, not just boilerplate. The agent’s real contribution was reconnaissance across a space Simon would have had to map by hand.
🚀 Next Steps
Try the same pattern on your own stuck problem. Write a tight problem statement, list the tricky cases, and ask your agent for several distinct solutions rather than one. Then benchmark the candidates for dependencies, speed, and how likely each is to survive a library update. Pick the one you can maintain, not just the one that runs. Full technical detail is available at the original source from Simon Willison.