A lightweight TypeScript/Node.js server that mimics Opengeni's core agent routing
Welcome to another official UVF IT guide! In this quick‑fire tutorial we’ll build a minimal AI‑agent‑server inspired by Opengeni, using only free‑tier Node.js, TypeScript and SQLite. The result is a tiny HTTP API that accepts a prompt, stores it, and returns a canned “agent” response – enough to prototype and extend later.
We’ll keep the stack simple: Node 18+, express, better-sqlite3, and TypeScript. No external AI APIs are called, so you can run everything locally in about 45 minutes.
Create a fresh npm workspace and add TypeScript, Express and SQLite dependencies. This gives us a typed Node environment and a lightweight HTTP server ready to talk to a local database.
We also add development tools (ts-node-dev) so we can run the TypeScript code without a manual compile step, keeping the workflow fast for beginners.
mkdir minimal-ai-agent && cd minimal-ai-agent
npm init -y
npm i express better-sqlite3
npm i -D typescript @types/node @types/express ts-node-dev
npx tsc --init --rootDir src --outDir dist --esModuleInterop true --resolveJsonModule true
mkdir srcSet up a tiny SQLite DB with a prompts table and helper functions to insert and fetch records. SQLite lives in a single file, so no external service is required and the data persists between runs.
The wrapper abstracts the raw SQL calls, exposing simple addPrompt and getAllPrompts functions that the rest of the server can use without worrying about connections.
src/db.ts
import Database from 'better-sqlite3';
// Initialise (or create) a SQLite file called `prompts.db`
const db = new Database('prompts.db');
// Ensure the table exists – id auto‑increments, prompt stores the raw text, created_at timestamps the entry
db.exec(`
CREATE TABLE IF NOT EXISTS prompts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prompt TEXT NOT NULL,
created_at TEXT DEFAULT (datetime('now'))
);
`);
/** Insert a new prompt and return its generated id */
export function addPrompt(text: string): number {
const stmt = db.prepare('INSERT INTO prompts (prompt) VALUES (?)');
const info = stmt.run(text);
return Number(info.lastInsertRowid);
}
/** Retrieve all stored prompts ordered by newest first */
export function getAllPrompts(): {id: number; prompt: string; created_at: string}[] {
const stmt = db.prepare('SELECT id, prompt, created_at FROM prompts ORDER BY created_at DESC');
return stmt.all();
}In this step we create a tiny Express server that will act like the AI‑agent router. The /agent endpoint accepts a JSON payload with a prompt, stores it in memory, and immediately returns a fake reply so you can see the round‑trip working. We also add a /prompt/:id GET route so you can fetch any saved prompt later, which mimics how a real system might retrieve conversation history.
src/server.ts
import express from 'express';
import bodyParser from 'body-parser';
const app = express();
app.use(bodyParser.json());
// simple in‑memory store
let nextId = 1;
const prompts: Record<number, string> = {};
// POST /agent – store prompt and return mock reply
app.post('/agent', (req, res) => {
const {prompt} = req.body;
if (typeof prompt !== 'string') {
return res.status(400).json({error: 'prompt must be a string'});
}
const id = nextId++;
prompts[id] = prompt;
const mockReply = `Echo: ${prompt}`; // static mock response
res.json({id, reply: mockReply});
});
// GET /prompt/:id – retrieve stored prompt
app.get('/prompt/:id', (req, res) => {
const id = Number(req.params.id);
const stored = prompts[id];
if (!stored) return res.status(404).json({error: 'not found'});
res.json({id, prompt: stored});
});
const PORT = 3000;
app.listen(PORT, () => console.log(`🚀 Server listening on http://localhost:${PORT}`));Now that the code is ready we’ll start the server with hot‑reloading so any changes to src/server.ts instantly restart the process. ts-node-dev compiles TypeScript on the fly and watches the files, giving you a fast feedback loop during development.
npx ts-node-dev src/server.tsWith the server running, use curl to hit the new endpoints and see the mock behavior in action. Once you’re comfortable, you can replace the static mockReply with a real call to an open‑source LLM or external API, turning this scaffold into a functional AI agent.
# Test POST /agent
curl -X POST http://localhost:3000/agent \
-H 'Content-Type: application/json' \
-d '{"prompt":"Hello AI"}'
# Assuming the response gave id 1, fetch it back
curl http://localhost:3000/prompt/1| Check | Command / Why it matters |
|---|---|
| npm install completes without errors | npm i |
| Server starts and logs listening message | npx ts-node-dev src/server.ts |
| POST /agent returns JSON with id and reply | curl -X POST http://localhost:3000/agent -H 'Content-Type: application/json' -d '{"prompt":"test"}' |
| GET /prompt/:id returns stored prompt | curl http://localhost:3000/prompt/1 |
Replace the static reply with a call to an open‑source LLM (e.g., llama.cpp) or a free API, add authentication, rate‑limiting, and a simple UI to evolve this minimal clone into a full‑featured AI‑agent platform.