End-to-end examples
Complete programs you can copy and run — a scheduled report, a backend endpoint that keeps your key server-side, and a chart from an answer.
Each example is a whole program. Set DATABASE_AGENT_API_KEY and DATABASE_AGENT_ID (see the Quickstart) and run it as is.
A scheduled report
Ask a fixed list of questions and write the answers, the SQL behind each one and the result rows to a Markdown file. Run it from cron, a CI schedule or any job runner, then mail or post the file.
"""daily_report.py: ask the same questions every day and write report.md."""
import datetime
import os
import requests
API_ROOT = "https://futuresmart.ai/database-agent/api"
AGENT_ID = os.environ["DATABASE_AGENT_ID"]
HEADERS = {"X-API-Key": os.environ["DATABASE_AGENT_API_KEY"]}
QUESTIONS = [
"How many orders were placed in total?",
"Which 3 product categories had the most revenue?",
]
def ask(question):
r = requests.post(
f"{API_ROOT}/v1/agents/{AGENT_ID}/chat",
headers=HEADERS,
json={"query": question, "debug_info": True, "chart_output": False},
timeout=180,
)
r.raise_for_status()
return r.json()
def table(result):
if not result or not result.get("rows"):
return ""
names = [c["name"] for c in result["columns"]]
lines = ["| " + " | ".join(names) + " |", "|" + "---|" * len(names)]
lines += ["| " + " | ".join(str(row.get(n, "")) for n in names) + " |" for row in result["rows"]]
return "\n".join(lines)
sections = [f"# Daily report — {datetime.date.today():%d %B %Y}"]
for question in QUESTIONS:
answer = ask(question)
debug = answer.get("debug_info") or {}
sections.append(f"## {question}\n\n{answer['response']}")
if debug.get("sql_query"):
sections.append(f"```sql\n{debug['sql_query']}\n```")
sections.append(table(debug.get("db_result")))
with open("report.md", "w", encoding="utf-8") as f:
f.write("\n\n".join(s for s in sections if s) + "\n")
print(f"Wrote report.md with {len(QUESTIONS)} answers")Each question counts toward your daily question limit (see Errors and limits), so keep scheduled lists short.
A backend endpoint for your own app
Browsers must never hold your key. Put a small endpoint in front of the agent: your frontend posts the question to it, and it adds the key on the server. This one uses only Node.js built-ins (Node 18 or later).
// server.mjs: POST {"question": "...", "session_id": "..."} to http://localhost:3000/ask
import { createServer } from "node:http";
const API_ROOT = "https://futuresmart.ai/database-agent/api";
const AGENT_ID = process.env.DATABASE_AGENT_ID;
const API_KEY = process.env.DATABASE_AGENT_API_KEY;
async function readJson(req) {
let body = "";
for await (const chunk of req) body += chunk;
return JSON.parse(body || "{}");
}
createServer(async (req, res) => {
if (req.method !== "POST" || req.url !== "/ask") {
res.writeHead(404).end();
return;
}
try {
const { question, session_id } = await readJson(req);
if (!question) {
res.writeHead(400, { "Content-Type": "application/json" }).end(JSON.stringify({ error: "question is required" }));
return;
}
const upstream = await fetch(`${API_ROOT}/v1/agents/${AGENT_ID}/chat`, {
method: "POST",
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ query: question, session_id, chart_output: true }),
});
const data = await upstream.json();
// Pass on only what the page needs; never echo the key or raw errors.
const body = upstream.ok
? { answer: data.response, session_id: data.session_id, chart: data.chart_output }
: { error: typeof data.detail === "string" ? data.detail : "The agent could not answer" };
res.writeHead(upstream.ok ? 200 : upstream.status, { "Content-Type": "application/json" }).end(JSON.stringify(body));
} catch (err) {
res.writeHead(500, { "Content-Type": "application/json" }).end(JSON.stringify({ error: String(err) }));
}
}).listen(3000, () => console.log("Listening on http://localhost:3000/ask"));Start it with node server.mjs, then try it:
curl -sS -X POST http://localhost:3000/ask \
-H "Content-Type: application/json" \
-d '{"question": "How many customers are there?"}'Send the returned session_id back with the next question to keep the conversation going. Add your own sign-in check in front of /ask before you deploy it — the endpoint spends your question allowance for whoever calls it.
A chart from an answer
chart_output.chart_data.data is a list of {category, value} points, so it plots directly. This writes a PNG with matplotlib (pip install requests matplotlib).
import os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import requests
API_ROOT = "https://futuresmart.ai/database-agent/api"
AGENT_ID = os.environ["DATABASE_AGENT_ID"]
r = requests.post(
f"{API_ROOT}/v1/agents/{AGENT_ID}/chat",
headers={"X-API-Key": os.environ["DATABASE_AGENT_API_KEY"]},
json={"query": "How many orders were placed in each month of 2025? Show a bar chart.", "chart_output": True},
timeout=180,
)
r.raise_for_status()
chart = r.json()["chart_output"]
if not chart:
raise SystemExit("No chart for this answer; ask for one explicitly or check the agent's chart setting.")
points = chart["chart_data"]["data"]
meta = chart["chart_data"]["metadata"]
plt.figure(figsize=(10, 4))
plt.bar([str(p["category"]) for p in points], [p["value"] for p in points])
plt.title(meta.get("title", ""))
plt.xlabel(meta.get("x_axis", {}).get("label", ""))
plt.ylabel(meta.get("y_axis", {}).get("label", ""))
plt.xticks(rotation=45, ha="right")
plt.tight_layout()
plt.savefig("chart.png")
print("Saved chart.png:", chart["chart_suggestion"], len(points), "points")More
- Use the agent from Claude Code with the MCP server.
- The open-source repository's
docs/api.mdcovers running your own installation.