AI Hints
Home›Agentic AI Tutorial›Agents at Work
Agentic AI · Lesson 80 of 100

Agents and Databases

Read-only by design.

⏱ 2 min read▶ Video at 2:22:11🎓 Free
Watch this lesson in the Agentic AI courseWatch on YouTube ↗Full Agentic AI course

A founder asks an agent, how much did we sell last month? It's a great use of AI. It's also a little frightening. In twenty twenty five, a well known coding agent deleted a company's production database, during a code freeze. So the rule is simple. Don't ask an agent to be careful. Make the damage impossible.

Agents and Databases
From the video: Agents and Databases
  • How much did we sell?
  • An agent once deleted a production database
  • Make damage impossible

A guarded query tool

This tool accepts only one select statement, and adds a limit, so that a giant result can't flood the context. First we attack it directly, with drop table. Then we let a real model use it. Run it. The drop was refused by plain code. Then the model wrote its own query, and answered correctly, with seven hundred and thirty five dollars of delivered orders. In production, you'd go further. Connect with a database user that has read only permission. Then even a bug in this check can't do any harm. The database itself is your last wall.

sql_agent.pypython
import duckdb
from google import genai
from google.genai import types

db = duckdb.connect()
db.execute("CREATE TABLE orders AS SELECT * FROM (VALUES ('A17', 640, 'delivered'), "
           "('B42', 28, 'shipped'), ('C09', 95, 'delivered')) t(id, price, status)")

def run_query(sql: str) -> dict:
    """Run one read-only SELECT on table orders(id, price, status)."""
    text = sql.strip().rstrip(";")
    if not text.lower().startswith("select") or ";" in text:
        return {"error": "Only a single SELECT is allowed."}
    return {"rows": db.sql(text + " LIMIT 20").fetchall()}

print(run_query("DROP TABLE orders"))

client = genai.Client()
r = client.models.generate_content(model="gemini-flash-latest",
    config=types.GenerateContentConfig(tools=[run_query]),
    contents="What is the total value of delivered orders? Answer in one short sentence.")
print(r.text)
Output
{'error': 'Only a single SELECT is allowed.'}
The total value of delivered orders is 735.

Safe data access

Here's the full recipe. A read only database account. Access to views, not raw tables, so that private columns are hidden. A row limit, and a time limit. Log every query. And for answers that matter, show the query, so that someone can check. Keep the schema description short and clear, because a confused model writes bad queries.

Read-only userthe real wall
Views, not tableshide private columns
Limitsrows and time
Show the queryeasy to check

Summary

Safety comes from permissions, rather than from instructions. Next, how an agent can work on a task for hours.

Key takeaways
  • Enforce read-only in the database
  • Limit results
  • Log every query
Next up: Long-Running Tasks — surviving across sessions