Build a Personal Assistant Agent (memory + tools + RAG)

Build a personal AI assistant on one database — long-term memory of preferences, semantic tool routing, RAG over your notes, and grounded replies. No five-service stack. Works with Claude Code, OpenClaw, LangChain, or a voice agent.

All recipes· agents· 20 minutesadvancedsql
Instance: localhost:8080

Opens your running SynapCores (Build a Personal Assistant Agent (memory + tools + RAG) will be staged for a preview — nothing runs until you click Run). No instance yet? Install free in ~30s.

Share

Objective

A personal assistant has to remember you (preferences, constraints), route your request to the right capability (add a reminder vs. answer a question), look things up in your own notes (RAG), and reply grounded in all of it. That's the long-term-memory, tool-routing, and RAG building blocks working together. Here you'll assemble them into one assistant on one database — no vector store, no cache, no router service. The same brain drives any framework or a voice agent — see Use it from your agent at the end.

Step 1: Create the assistant's long-term memory

Durable facts about the user, embedded for recall and weighted by importance.

CREATE TABLE IF NOT EXISTS recipe_pa_memory (
  memory_id  INTEGER PRIMARY KEY,
  content    TEXT,
  importance DOUBLE,
  embedding  VECTOR(384)
);
INSERT INTO recipe_pa_memory (memory_id, content, importance) VALUES
 (1,'The user is vegetarian.',0.95),
 (2,'The user prefers meetings after 10am.',0.70),
 (3,'The user is training for a half marathon in October.',0.75),
 (4,'The user dislikes long emails; keep replies short.',0.80),
 (5,'The user lives in Lisbon (WET timezone).',0.85);
UPDATE recipe_pa_memory SET embedding = EMBED(content);

Step 2: Create the assistant's tool registry

The capabilities the assistant can invoke, described in natural language for semantic routing.

CREATE TABLE IF NOT EXISTS recipe_pa_tools (
  tool_id     INTEGER PRIMARY KEY,
  tool_name   TEXT,
  description TEXT,
  embedding   VECTOR(384)
);
INSERT INTO recipe_pa_tools (tool_id, tool_name, description) VALUES
 (1,'add_reminder','Create a reminder or to-do item for a specific time or date.'),
 (2,'schedule_meeting','Find a time and book a calendar meeting with someone.'),
 (3,'search_notes','Search the user''s personal notes and documents for an answer.'),
 (4,'send_message','Compose and send a short message or email on the user''s behalf.'),
 (5,'check_weather','Look up the current or forecast weather for a location.');
UPDATE recipe_pa_tools SET embedding = EMBED(description);

Step 3: Create the user's notes (for RAG)

Personal knowledge the assistant can ground answers in.

CREATE TABLE IF NOT EXISTS recipe_pa_notes (
  note_id   INTEGER PRIMARY KEY,
  content   TEXT,
  embedding VECTOR(384)
);
INSERT INTO recipe_pa_notes (note_id, content) VALUES
 (1,'My passport expires in March next year — renew it before booking the Japan trip.'),
 (2,'The half-marathon plan: long run every Sunday, rest on Mondays.'),
 (3,'Favorite vegetarian place in Lisbon is Ao 26 in Chiado.'),
 (4,'Dentist appointment is the second Tuesday of every month.');
UPDATE recipe_pa_notes SET embedding = EMBED(content);

Step 4: Route the request to the right tool

The user says "remind me to renew my passport" — route it by meaning to the reminder tool.

SELECT tool_name,
       COSINE_SIMILARITY(embedding, EMBED('remind me to renew my passport next month')) AS match_score
FROM recipe_pa_tools
ORDER BY match_score DESC
LIMIT 1;

Step 5: Recall the relevant memory for personalization

Pull the durable facts that should shape the reply — blending relevance and importance.

SELECT content,
       COSINE_SIMILARITY(embedding, EMBED('suggest where to eat dinner tonight')) * 0.7 + importance * 0.3 AS score
FROM recipe_pa_memory
ORDER BY score DESC
LIMIT 2;

Step 6: Look up an answer in the user's notes (RAG)

For a question, retrieve the most relevant personal note.

SELECT content,
       COSINE_SIMILARITY(embedding, EMBED('where do I like to eat in Lisbon?')) AS relevance
FROM recipe_pa_notes
ORDER BY relevance DESC
LIMIT 1;

Step 7: Produce a grounded, personalized reply (GENERATE)

Combine memory + the retrieved note into a short reply that respects the user's preferences. First materialize the top user fact and the most relevant note into a single context row (projecting the scores we order by), then generate from that row.

CREATE TABLE IF NOT EXISTS recipe_pa_fact (memory_id INTEGER PRIMARY KEY, content TEXT, importance DOUBLE);
INSERT INTO recipe_pa_fact (memory_id, content, importance)
SELECT memory_id, content, importance FROM recipe_pa_memory ORDER BY importance DESC LIMIT 1;
CREATE TABLE IF NOT EXISTS recipe_pa_note (note_id INTEGER PRIMARY KEY, content TEXT, relevance DOUBLE);
INSERT INTO recipe_pa_note (note_id, content, relevance)
SELECT note_id, content,
       COSINE_SIMILARITY(embedding, EMBED('dinner recommendation in Lisbon')) AS relevance
FROM recipe_pa_notes ORDER BY relevance DESC LIMIT 1;
CREATE TABLE IF NOT EXISTS recipe_pa_ctx (id INTEGER PRIMARY KEY, fact TEXT, note TEXT);
INSERT INTO recipe_pa_ctx (id, fact, note)
SELECT 1,
       (SELECT content FROM recipe_pa_fact LIMIT 1),
       (SELECT content FROM recipe_pa_note LIMIT 1);
SELECT GENERATE(
  'You are a concise personal assistant. User facts: ' || fact ||
  ' Relevant note: ' || note ||
  ' Request: Recommend somewhere for dinner tonight. Reply in one short sentence.') AS reply
FROM recipe_pa_ctx;

Cleanup (Optional)

DROP TABLE IF EXISTS recipe_pa_memory;
DROP TABLE IF EXISTS recipe_pa_tools;
DROP TABLE IF EXISTS recipe_pa_notes;
DROP TABLE IF EXISTS recipe_pa_fact;
DROP TABLE IF EXISTS recipe_pa_note;
DROP TABLE IF EXISTS recipe_pa_ctx;

Expected Outcomes

  • Step 4 routes "remind me to renew my passport" to add_reminder by meaning.
  • Step 5 surfaces the vegetarian preference (high importance) for a dinner request.
  • Step 6 retrieves the "favorite vegetarian place is Ao 26" note.
  • Step 7 returns a one-sentence dinner recommendation that's both grounded in the note and respects the vegetarian preference — memory + tools + RAG in one reply.

You've built a personal assistant — long-term memory, semantic tool routing, and RAG over personal notes — on one database.

Use it from your agent (framework-agnostic — this is the whole point)

The assistant brain is just memory + a tool registry + notes, all queried the same way, so any agent shell drives it with no framework lock-in:

  • REST / SDKPOST /v1/query/execute (any language), or @synapcores/sdk client.executeQuery(...). Per turn your agent routes (Step 4), recalls memory (Step 5), runs RAG over notes (Step 6), and replies (Step 7); when the route is an action tool, it invokes that function instead.
  • MCP (native, on by default) — point any MCP client (Claude Code, Cursor, a custom loop, a voice runtime) at ws://<your-instance>/mcp?token=<jwt> (JWT from one POST /v1/auth/loginaccess_token). The query tool routes/recalls/retrieves; the execute tool writes new memories and notes — the assistant loop as tool calls.
  • Any framework — OpenClaw, a LangGraph assistant, a custom loop, or a voice assistant on a phone or smart speaker all call the same brain. The database is the brain; the framework is swappable.

Key Concepts Learned

  • A personal assistant composes long-term memory, semantic tool routing, and RAG over personal notes.
  • Routing decides what to do; memory + RAG decide what to say — all from the same query surface.
  • Blending importance into memory recall keeps high-stakes facts (allergies, constraints) front and center.
  • Because it's plain data ops (SQL + GENERATE / REST / MCP), the assistant works from any framework — the agent-agnostic backend pattern this cluster builds on.

Tags

ai-agentpersonal-assistantagent-memorytool-routingraggeneratemcp

Run this on your own machine

Install SynapCores Community Edition free, paste the SQL or Cypher above into the bundled web UI, and watch it run.

Download Free CE