Databases
Give an agent a SQL database: upload a SQLite file or connect a PostgreSQL server.
| SQLite | PostgreSQL | |
|---|---|---|
| Use it when | Your data fits in one file and changes rarely | Your data lives in a running server and changes often |
| How you connect | Upload the .db file with FileUploader and pass the download link it returns | Pass a connection string |
| Writes | commit action; your local file is unchanged | query action; changes the live database |
| Asset path | aixplain/sqlite/aixplain (Marketplace card) | aixplain/postgresql/aixplain (Marketplace card) |
Try it with SQLite
Build a small database, upload it, and query it through the tool.
import sqlite3
from aixplain import Aixplain
from aixplain.v2 import FileUploader
aix = Aixplain(api_key="YOUR_API_KEY")
conn = sqlite3.connect("shop.db")
conn.execute("CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)")
conn.executemany("INSERT INTO products VALUES (?, ?, ?)", [
(1, "Laptop", 999.99), (2, "Monitor", 249.00), (3, "Keyboard", 79.50),
])
conn.commit()
conn.close()
db_url = FileUploader(api_key="YOUR_API_KEY").upload("shop.db", return_download_link=True)
db = aix.Tool(
name="Shop database",
description="Products table: id, name, price.",
integration="aixplain/sqlite/aixplain",
config={"url": db_url},
).save()
result = db.run(action="query", data={"query": "SELECT name, price FROM products WHERE price < 300"})
print(result.data)
Connect PostgreSQL
Keep the connection string in an environment variable, then create the tool and run a query.
import os
pg = aix.Tool(
name="Customer database",
description="Read-only access to the customer database.",
integration="aixplain/postgresql/aixplain",
config={"url": os.environ["POSTGRES_URL"]},
).save()
result = pg.run(action="query", data={"query": "SELECT version()"})
print(result.data)
Rows come back as a string of Python tuples without column names, so select columns in the order you want to read them.
The connection string uses the standard format, postgresql://USER:PASSWORD@HOST:5432/DATABASE?sslmode=require. URL-encode special characters in the password. save() does not test the connection, so a wrong host or password shows up on the first run().
Actions
| Action | SQLite | PostgreSQL |
|---|---|---|
query | Runs a read statement and returns the rows as a Markdown table. | Runs any statement, including writes, and returns the rows as a string of Python tuples. |
commit | Runs a statement that changes data, such as INSERT or UPDATE. | Not available; use query. |
schema | Returns the CREATE TABLE statements for every table. | Returns the tables and column names. |
Run queries
Pass the SQL in a dict under query; a bare string is rejected. The schema action returns the table definitions, which you can paste into an agent's instructions.
result = db.run(action="schema")
print(result.data)
Write data
In SQLite, run INSERT, UPDATE and DELETE through commit; the query action does not apply changes. Later queries on the same tool see the change, and your local shop.db stays as it was.
db.run(action="commit", data={"query": "INSERT INTO products VALUES (4, 'Mouse', 25.00)"})
result = db.run(action="query", data={"query": "SELECT COUNT(*) AS products FROM products"})
print(result.data)
In PostgreSQL, query runs writes with the permissions of the user in the connection string. Add RETURNING to see the rows you changed. This example writes to a temporary table, so it leaves the database unchanged:
result = pg.run(action="query", data={"query": """
CREATE TEMP TABLE notes (id serial, body text);
INSERT INTO notes (body) VALUES ('hello') RETURNING id, body
"""})
print(result.data)
Use with an agent
Agents currently work with the SQLite tool; for PostgreSQL, call pg.run from your code. Put the table schema in instructions so the agent writes correct SQL without guessing column names.
db.allowed_actions = ["query", "schema"]
agent = aix.Agent(
name="Shop analyst",
description="Answers questions about the shop's products.",
instructions="Query the products table (id, name, price) to answer.",
tools=[db],
).save()
result = agent.run("Which products cost less than $300?")
print(result.data.output)
An agent's first call to the SQLite tool can arrive without the SQL statement and fail, and the agent does not always retry. Check result.data.steps for a failed query step before you trust an answer.
Use a read-only user
When a PostgreSQL tool only needs to read, connect it as a user that can only read:
CREATE USER readonly_user WITH PASSWORD 'CHANGE_ME';
GRANT CONNECT ON DATABASE mydb TO readonly_user;
GRANT USAGE ON SCHEMA public TO readonly_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user;
Put readonly_user in the connection string, and load the string from an environment variable or a secrets manager, never from version control.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Could not validate inputs for 'query' | data was a string. | Pass data={"query": "..."}. |
Missing database url in data object | config["url"] is empty, for example an unset environment variable. | Pass the FileUploader link or set the variable before you create the tool. |
Invalid file type. Only .db files are supported | The SQLite URL does not point to a .db file. | Save the database with a .db extension before you upload it. |
could not translate host name, connection refused or timeout | The PostgreSQL host is wrong or does not accept connections from aixplain. | Fix the host, open port 5432 to aixplain, then create the tool again. |
permission denied for table | The PostgreSQL user lacks a grant. | Grant SELECT, and USAGE on the schema, to the user. |
| The agent's SQL names the wrong columns | The agent does not know the schema. | Add the output of the schema action to instructions. |
Clean up
agent.delete()
db.delete()
pg.delete()
Next steps
- Knowledge base: search documents by meaning instead of with SQL.
- Files: attach files such as CSVs directly to an agent.
- API reference: tool: every parameter and method.