LangGraph SQL Agent
Natural language goes in. A stateful execution pipeline decides how to query the database safely.
- Role
- Sole engineer
- Year
- 2026
- Type
- Agentic pipeline
- Stack
- Python
- LangGraph
- OpenAI API
- SQLite
- Gradio
Architecture
- Schema
- Generate
- Execute
- Inspect
- Answer
Question
Which regions grew fastest last quarter?
01 — Introspected schema
- orders(id, region_id, amount, quarter)
- regions(region_id, name)
02 — Generated query
SELECT r.name, SUM(o.amount) AS revenue
FROM orders o
JOIN regions r USING (region_id)
WHERE o.quarter = ?
GROUP BY r.name
ORDER BY revenue DESC;
Parameterised · read-only · grounded in the introspected schema
03 — Returned rows
04 — Inspection before answering
- result non-empty
- column types match
- shape as requested
An empty or malformed result routes back into the graph instead of forward into a confident sentence.
05 — Answer
Composed from the returned rows, with the executed query retained alongside it so the answer can be checked rather than trusted.
Text-to-SQL is easy to demo and hard to trust. The value is in the steps either side of generation: knowing the schema first, and inspecting the result before answering.
Overview
An agent that answers questions about a relational database in natural language. Built on LangGraph as an explicit StateGraph so each stage of the process is a node with its own responsibility.
The interface is deliberately plain — a Gradio surface — because the work is in the pipeline, not the presentation.
The problem
A model asked to write SQL with no knowledge of the schema will invent table names with total confidence. A model that runs its own SQL with no inspection step will report an empty result set as a factual answer.
Both failures are invisible to the user, which makes them the interesting ones. The fix is structural: give the pipeline a stage to learn the schema, and a stage to look at what came back.
The pipeline
Five nodes in a StateGraph. Every node reads and writes the same run state, so a later stage can see exactly what an earlier one did.
- 01Inspect schemaIntrospect tables, columns, and relationships before a single token of SQL is written.
- 02GenerateCompose a query grounded in that real schema rather than an assumed one.
- 03ExecuteRun against SQLite with read-oriented, parameterised access.
- 04Inspect resultExamine the rows returned. Empty or malformed results route back rather than forward.
- 05AnswerTranslate rows into a natural-language answer, with the query available for verification.
Technical decisions
Schema inspection as a separate node
Rather than pasting a schema into the system prompt, the graph fetches it. The agent stays correct when the database changes, and the prompt stays small.
An inspection stage between execution and answer
This is the node that earns the architecture. Zero rows, a type mismatch, or an error becomes a routing decision instead of a confidently wrong sentence.
State as the interface between nodes
Nodes communicate through typed run state, not through nested function calls. Adding a stage means adding a node and an edge, which is why the extensions below were straightforward.
Extensions I have worked on
Directions I have explored on top of the core pipeline.
Memory
Carrying prior turns so follow-up questions resolve against the previous query’s context.
Caching
Reusing generated SQL for repeated questions instead of paying for regeneration.
Validation
Checking a query against the introspected schema before it is allowed to execute.
Safety
Constraining the generated statement surface so the agent cannot mutate data.
Interface
Captures from the Gradio interface.
What I learned
Reliability in an LLM pipeline comes from adding stages that verify, not from writing a longer prompt. Every improvement I made was structural.
Making state explicit also made the system teachable — I can point at a node and say what it is responsible for, which is not true of a prompt chain.