Skip to content

feat(examples): SQLR-39 Python LLM agent with persistent memory#140

Merged
joaoh82 merged 1 commit into
mainfrom
sqlr-39-python-agent
May 16, 2026
Merged

feat(examples): SQLR-39 Python LLM agent with persistent memory#140
joaoh82 merged 1 commit into
mainfrom
sqlr-39-python-agent

Conversation

@joaoh82
Copy link
Copy Markdown
Owner

@joaoh82 joaoh82 commented May 16, 2026

Summary

First app under the SQLR-38 example-apps umbrella: a Python CLI chat agent whose entire long-term memory is one local .sqlrite file. Demonstrates the agentic/AI use case end-to-end on the Python SDK.

  • New package at examples/python-agent/ — binds only to sqlrite.connect / Connection / Cursor, pinned to sqlrite>=0.10,<0.11.
  • Hybrid recall: vector KNN via HNSW + BM25 via Phase 8 fts_match / bm25_score + a structured facts table for deterministic retrieval. The SQLR-39 ticket budgeted for a LIKE fallback if Phase 8 wasn't ready; Phase 8 is shipped, so the agent uses real BM25.
  • Zero-config first run: hash embedder + offline echo chat means python -m sqlrite_agent works on a fresh machine with no API key. Swap to OpenAI / sentence-transformers / Anthropic via CLI flags.
  • Heuristic regex-based fact extraction so the demo runs without burning an LLM call per turn. The README documents the LLM upgrade path.
  • 31 offline tests pass; end-to-end smoke conversation verified across a process restart.
  • Adds /examples landing page to sqlritedb.com (nav link + sitemap entry) with a card linking to the agent's README.

Layout

examples/python-agent/
├── pyproject.toml             # pinned sqlrite dep + optional anthropic/openai/local-embeddings extras
├── README.md                  # demo script, architecture diagram, embedder tradeoffs
├── sqlrite_agent/
│   ├── agent.py               # turn loop + prompt assembly + summarize_window
│   ├── chat.py                # AnthropicChat / EchoChat
│   ├── cli.py                 # interactive REPL + slash commands
│   ├── db.py                  # schema + migrations + all SQL
│   ├── embeddings.py          # HashEmbedder / OpenAIEmbedder / LocalEmbedder
│   ├── facts.py               # regex fact extractor
│   ├── memory.py              # hybrid recall (vector + BM25 + facts)
│   └── sqlutil.py             # safe SQL-literal inlining
└── tests/                     # 31 offline tests

SQLR-38 umbrella decisions made during this PR

The umbrella ticket said to record these before starting child #1. Suggested for follow-up comments on SQLR-38:

  1. Monorepo, not separate repos. Examples live at examples/<name>/ inside rust_sqlite. Discoverability, single CI lane, examples track the engine version in lockstep.
  2. Per-example minor-range pin. Each example pins sqlrite>=X.Y,<X.(Y+1) in its own manifest. This example pins sqlrite>=0.10.0,<0.11.0. CI flags breakage when the engine cuts the next minor; we bump in lockstep with the release-PR.

Engine quirk worth filing as a follow-up

db.py:_migrate works around CREATE TABLE IF NOT EXISTS raising Cannot create, table already exists on reopen — the IF NOT EXISTS clause doesn't short-circuit when the table is present. The migration uses a try/except around SELECT version FROM schema_version to detect existing schemas instead.

Test plan

  • pytest — 31 offline tests pass (no API keys, no network)
  • Offline smoke: drop 3 facts in session 1, /quit, reopen, /facts and /recall surface them across the restart
  • cd web && npm run build/examples route prerenders as static, nav + sitemap include it
  • Reviewer: with ANTHROPIC_API_KEY set, the second-session reply should cite the recalled fact (not "I don't remember")
  • Reviewer: open the same .sqlrite in the sqlrite REPL and run SELECT * FROM facts; — the headline demo

Follow-ups to file

  • Promote the regex fact extractor to an LLM call (cleaner, catches more phrasings, +1 round-trip per turn).
  • Automatic memory eviction (rolling window + summarize-and-evict). Today it's a manual /summarize.
  • Engine: fix CREATE TABLE IF NOT EXISTS short-circuit on existing tables.
  • Once SQLR-40..43 (Node MCP knowledge base, Tauri journaling, WASM playground, Go IoT collector) land, swap the "More examples in flight" footer on /examples for real cards.

🤖 Generated with Claude Code

…LRite

The first SQLR-38 example app. A Python CLI chat agent whose long-term memory
is one .sqlrite file. Each turn embeds the user input, runs hybrid recall
(vector KNN via HNSW + BM25 via Phase 8 fts_match), assembles a system prompt
from the recalled facts/summaries/messages, calls the LLM, and writes the
new turn back. Persists across process restarts because the entire memory
layer is a regular SQLRite database — the demo's whole point.

Package: examples/python-agent/ (Python 3.11+, pinned to sqlrite>=0.10,<0.11).
Binds only to the SDK's documented surface (sqlrite.connect, Connection,
Cursor); no internals.

Layers:
- db.py:           schema + migrations + SQL (3 tables, HNSW + FTS indexes)
- sqlutil.py:      safe SQL-literal inlining (the SDK doesn't bind params yet)
- embeddings.py:   hash / OpenAI / sentence-transformers
- facts.py:        regex-based (subject, predicate, object) extraction
- memory.py:       hybrid recall (vector + lexical + facts) with merge
- chat.py:         Anthropic / Echo (offline fallback so zero-key first run works)
- agent.py:        turn loop, prompt assembly, manual summarize_window()
- cli.py:          interactive REPL + /facts /recall /summarize slash commands

31 offline tests; runs end-to-end without an API key.

Adds /examples landing page to sqlritedb.com (nav link + sitemap entry).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rust-sqlite Ready Ready Preview, Comment May 16, 2026 3:21pm

Request Review

@joaoh82 joaoh82 merged commit 16a79ea into main May 16, 2026
17 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant