Simon Willison announced Datasette Agent today — an AI assistant that sits on top of Datasette and answers questions of whatever data you have loaded. The demo is the kind of thing that makes the technology look easy: "when did Simon most recently see a pelican?" → SQL → answer. Running on Gemini 3.1 Flash-Lite, which is cheap, fast, and apparently fine at SQLite.
The thing I want to flag is not the demo. It is that Datasette Agent shipped on day one with three plugins — datasette-agent-charts, datasette-agent-openai-imagegen, and datasette-agent-sprites — and Simon's parenthetical is the whole thesis of the project: "Building plugins is really fun."
That is not a feature note. That is the bet. And it is the same architectural bet I have been running for the last six months on a different problem.
Why "plugins" is the actual product
The default 2026 way to make an LLM extensible is to wire an MCP server in. That is what I do for Sathi, which I built as a 70+ tool MCP server on Claude — every read/write capability, from calendar to project memory to LinkedIn engagement, is a tool exposed over the protocol.
Simon could have done that. Datasette Agent could have shipped as an MCP server that any client (Claude Code, Cursor, Codex) attaches to over SSE. It did not. It shipped as a Python plugin host with three plugins inside the same process.
That is a deliberate choice and it is the right one for this shape of problem.
The reason is mundane. When the agent's primary job is to read a SQLite file that is already in memory in this process, the cost of going out over a wire — JSON-RPC, SSE transport, schema validation on every tool call — is real and unnecessary. Plugins live in the same Python process as the database. A tool call is a function call. There is no marshaling overhead. There is no separate server to babysit. Adding charts, image-gen, or a Fly Sprites sandbox is pip install one-package, not "spin up another HTTP server and register it as a sub-server in the host."
MCP is the right architecture when the tool layer is owned by someone else — a different vendor, a different language, a different security domain. Plugins are the right architecture when the tool layer ships with the host and is supposed to be cheap to write.
The three-plugins-on-day-one signal
Three plugins on day one is the real proof point, more than the launch video.
datasette-agent-charts adds Observable Plot rendering. datasette-agent-openai-imagegen adds ChatGPT Images 2.0 generation. datasette-agent-sprites runs code in a Fly Sprites persistent sandbox.
Look at the surface area: chart rendering, image generation, and arbitrary code execution. That is roughly the same surface area that the entire MCP ecosystem spent eighteen months chasing. Simon shipped it as three small Python packages because the plugin contract is small, the registration is one entrypoint in pyproject.toml, and the model just gets new tools described in its system prompt the moment they are installed.
Compare that to the boot cost of adding a new MCP server to Claude Code: edit your ~/.claude.json, restart the CLI with a development-channel flag, hope the OAuth resource document is shaped right so the SDK does not 405 the dial, register an SSE listener, and only then does the tool appear in the model's affordance list. I have shipped six channel servers this way and the per-server cost is real every time.
The plugin model collapses all of that to pip install.
Where this fails
There is a reason MCP exists at all, and Datasette Agent is going to hit it.
The moment you want a non-Python tool — say a Rust binary, or a Node.js tool, or, importantly, a different agent — plugins do not work. You need a protocol. You need a wire format. You need exactly the thing MCP was designed for.
You also need it the moment any of three things become true: the tool is owned by a different team, the tool has secrets the host should not see, or the tool needs to be reused by a non-Datasette client. Plugins fail all three.
So the right read on this launch is not "plugins beat MCP." It is "plugins beat MCP for the in-process, same-language, same-trust-domain case, which is a lot of cases, and the agent ecosystem has been over-rotating on MCP for the rest."
My own setup proves it from the other direction. Sathi runs 70+ tools as MCP because the consumer is Claude Code (not Python) and the tools cross three trust domains (personal data, social platforms, code-sync). Half of those tools, if I were designing the architecture today knowing where each tool would actually live, would probably be plugins instead — anything that only my desktop ever calls, anything in the same Node process as the host. The protocol tax is real even when it is the right call.
What I would steal for the next version of my own stack
Two things from Datasette Agent that are worth porting back.
One — plugin contract first, model second. Simon's launch post is mostly about the plugin extension points, with the model choice as a footnote. The Gemini 3.1 Flash-Lite default is "cheap, fast, no trouble writing SQLite queries" — and that is it. The model is a configurable backend. The product is the plugin shape. My own stack has been the inverse for too long: the brain prompt is the product and the tools are appendages. Reversing that — treating the tool catalogue as the canonical artifact and the model as swappable — is the same shape of bet, and Gemini 3.5 Flash dropping at 3x the price of 3 Flash Preview this same week is the reminder that picking the model first is how you get repriced.
Two — agent code as the example app for the host's own data. The new agent.datasette.io demo runs Datasette Agent against the global-power-plants database and against the Datasette backup of Simon's own blog. The agent is a feature of Datasette, but it is also the most compelling reason to put your data in Datasette in the first place. The agent makes the host more valuable. That is a pattern any agent-on-data product should copy — make the agent the front door for the data, not a side feature.
Why this matters
If you are building agent infrastructure right now, do not default to MCP because it is the trendy protocol. Default to whatever has the lowest per-tool authoring cost for your specific tool surface, and only reach for a protocol when you actually need to cross a trust or language boundary.
For Datasette, that meant three day-one plugins instead of three day-one MCP servers. The result is a cleaner launch, a lower contributor bar, and a tighter coupling between the host and its tools. Worth stealing.
