Database Agent with OpenClaw
A database agent translates natural language questions into parameterised SQL queries, executes them safely on your chosen database, and returns structured or narrative results — without exposing raw connection strings to the model.
Supported Databases
- PostgreSQL / Amazon RDS / Aurora
- MySQL / MariaDB / PlanetScale
- SQLite (local development)
- Google BigQuery
- MongoDB (via aggregation pipeline)
Agent Configuration
# agents/db-agent.yaml
name: db-agent
model: gpt-4o
temperature: 0.0
tools:
- sql_query # parameterised execute only
- schema_explorer # read table/column names, no data
system: |
You are a database analyst. Translate user questions to SQL.
Rules:
- NEVER write DROP, DELETE, UPDATE, or INSERT statements.
- Always use parameterised queries — never string-interpolate user input.
- Explain the query before running it.
- Limit result sets to 500 rows max.
- Format numbers with commas and round decimals to 2 places.Safe Connection Setup
openclaw_reader role.
import os
from sqlalchemy import create_engine, text
from openclaw import Agent
# Read credentials from environment — never hardcode
DB_URL = os.environ["DATABASE_URL_READONLY"]
engine = create_engine(DB_URL, pool_size=5, max_overflow=2, pool_pre_ping=True)
agent = Agent.from_config("agents/db-agent.yaml")
def safe_query(question: str) -> dict:
"""Execute a natural language database query safely."""
# Agent generates SQL, then we execute it
sql = agent.run(
f"Write a READ-ONLY SQL query to answer: {question}\n"
"Return ONLY the SQL statement, nothing else."
)
# Reject any mutating statements before execution
forbidden = ("drop ", "delete ", "update ", "insert ", "alter ", "truncate ")
if any(sql.lower().startswith(kw) for kw in forbidden):
raise PermissionError(f"Refused to execute mutating statement: {sql[:80]}")
with engine.connect() as conn:
rows = conn.execute(text(sql)).fetchmany(500)
return {"sql": sql, "rows": [dict(r._mapping) for r in rows]}Natural Language to SQL
def query_with_schema_context(question: str) -> str:
"""Provide table schema to improve SQL generation accuracy."""
# Give the agent schema context without real data
schema_prompt = agent.run("List all tables and their columns as JSON")
full_prompt = (
f"Schema:\n{schema_prompt}\n\n"
f"Question: {question}\n"
"Write a parameterised SQL query. Explain briefly what it does."
)
result = agent.run(full_prompt)
return result
# Example usage
print(query_with_schema_context(
"Show me the top 10 customers by revenue in the last 30 days"
))Data Analysis Agent
def analyse_table(table_name: str) -> str:
"""Run a descriptive analysis on any table."""
return agent.run(
f"Analyse the '{table_name}' table. "
"Report: row count, date range, top categories, nulls per column, "
"and any anomalies. Use multiple queries if needed."
)Audit Logging for All Queries
import json, datetime, pathlib
LOG_FILE = pathlib.Path("db-agent-audit.jsonl")
def logged_query(question: str, user: str = "unknown") -> dict:
result = safe_query(question)
record = {
"ts": datetime.datetime.utcnow().isoformat(),
"user": user,
"question": question,
"sql": result["sql"],
"row_count": len(result["rows"]),
}
with LOG_FILE.open("a") as f:
f.write(json.dumps(record) + "\n")
return resultFrequently Asked Questions
How do I prevent SQL injection in natural language queries?
Use parameterized queries exclusively: never interpolate user input directly into SQL strings. The database agent should generate SQL with placeholders (? or $1) and pass user values as a separate parameters array. Add a validate_sql() function that parses the generated SQL with sqlparse or similar, and rejects queries containing suspicious patterns (e.g., ; DROP, UNION SELECT in unexpected positions).
Can the database agent write to the database or only read?
By default, configure read-only access: use a database role with SELECT privilege only, no INSERT/UPDATE/DELETE. For write operations, create a separate agent with elevated permissions and require explicit approval before execution. Use database transactions: wrap writes in BEGIN; ... COMMIT; and add a preview_changes() step that shows affected rows before committing.
Which databases work best with OpenClaw agents?
PostgreSQL (best LLM compatibility: rich schema introspection, JSON support), MySQL (widely used, simpler schema → easier for LLMs), SQLite (great for prototyping), BigQuery (analytics queries, but slower for small queries), Snowflake (enterprise data warehouses). Avoid NoSQL databases unless you add a translation layer, as SQL-generation models are not trained on MongoDB query syntax.
How accurate are LLM-generated SQL queries?
For simple queries (1–2 table joins, WHERE clauses), GPT-4 achieves ~90% correctness. Accuracy drops for complex analytics queries (window functions, CTEs, subqueries) to ~60–70%. Always validate generated SQL: run EXPLAIN first to check query plan, then execute with LIMIT 10 and ask the user to verify results before returning full data. Provide schema documentation (table names, column descriptions) in the agent's context to improve accuracy.