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.

Python
"""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).

JavaScript
// 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:

Shell
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).

Python
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.md covers running your own installation.