This section uses the Use Chinook SQLite Data library to encapsulate a SQL query tool, allowing the Agent to generate SQL based on natural language questions, execute the query, and organize the final answer.
A lot of business data already exists in relational data libraries. Rather than putting the entire table into the prompt, it is better to give the Agent a controlled SQL query tool and let it query on demand.
| Way | advantage | risk |
|---|---|---|
| PutData copied into prompt | Simple and direct | The context is limited and the data is easily expired. |
| Let the Agent adjust the SQL tool | Query real data on demand | Need to restrict permissions and handle error SQL |
Let the Agent start from the natural language question, generate SQL query Chinook.db, and then use the query results to answer "Which artist starting with S is the most popular?"
Notebook uses LangChain Community's SQLDatabase tool class to connect local SQLite files.
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///resources/Chinook.db")Chinook is a common sample music database with tables such as Artist, Album, Track and InvoiceLine, making it useful for SQL Agent demos.
The tool receives a SQL string and executes db.run(query). If the SQL fails, the tool returns the error so the model has a chance to correct the query.
@tool
def sql_query(query: str) -> str:
"""Obtain information from the database using SQL queries"""
try:
return db.run(query)
except Exception as e:
return f"Error: {e}"
sql_query.invoke("SELECT * FROM Artist LIMIT 10")The course tool does not enforce permissions. In production, restrict it to read-only queries, limit table access, add timeouts and row limits, and prevent dangerous SQL generation.
Give sql_query to the Agent as its only tool. The model decides what SQL to write from the question and passes that SQL as the tool argument.
agent = create_agent(
model=deepseek_model(),
tools=[sql_query],
)
question = HumanMessage(
content="Who is the most popular artist beginning with 'S' in this database?"
)
response = agent.invoke({"messages": [question]})The model does not directly know the database answer. It first infers which tables and fields to query, then calls sql_query to get the result.
The notebook deliberately prints the tool-call arguments from the third-to-last message to inspect the SQL the model actually sent to the database.
print(response["messages"][-3].tool_calls[0]["args"]["query"])
print(response["messages"][-1].content)The debugging focus for a SQL Agent is whether the query is correct. A plausible final answer does not prove the SQL used the right table, join or ordering.
SELECT statements.LIMIT, timeouts and error classification at the tool layer.SQL tools let Agents access structured business data, but SQL correctness and safety must be handled at the tool boundary rather than relying on the model's judgment alone.