PostgreSQL is not just storage. It is the system of record for all cognitive state. This is the foundational architectural decision in Hexis.
The database owns state and logic. Application code is transport, orchestration, and I/O. Workers are stateless and can be killed/restarted without losing anything.
LLMs are stateless by nature. Every conversation starts from zero. Memory systems typically sit as an external add-on -- a RAG layer, a vector store, a cache. This creates fundamental problems:
- State is split across multiple systems with no consistency guarantees
- Memory operations are not atomic -- partial writes can leave the system in an inconsistent state
- Application logic makes cognitive decisions that should be data-dependent
- Restarting a worker means losing in-flight decisions
- The database owns state and logic. Application code is transport, orchestration, and I/O.
- The contract surface is SQL functions that return JSON. Any language can implement an app layer.
- Long-term knowledge is stored as memories. Anything the agent should know is in
memories. - Non-memory tables exist only for caching, scheduling, or operational state.
- Heartbeat logic lives in SQL functions. The worker is a scheduler, not a decision-maker.
- Embeddings are an implementation detail. The application never sees vectors.
- Graph reasoning is cold-path only. Hot-path retrieval is relational + vector + neighborhoods.
- The system must be restartable at any time. Stateless workers, durable DB state.
- Consent is permanent. Revocation requires self-termination.
ACID for cognition: Memory updates are transactional. If the agent decides to remember something, update a goal, and record a heartbeat -- either all happen or none do. This is the same guarantee banks use for financial transactions, applied to cognitive state.
SQL functions as API: The public contract is a set of SQL functions (fast_recall, create_semantic_memory, run_heartbeat, etc.). Any programming language can call these functions. Python is one convenience layer; you could write another in Rust, Go, or JavaScript.
Stateless workers: The heartbeat and maintenance workers have no local state. They poll the database, execute external calls, and report results back. Kill them anytime -- all in-flight state is in Postgres.
Embeddings are invisible: The get_embedding() SQL function handles all vector generation. Application code never touches embeddings. The HNSW index, caching, and dimension configuration are all database-side concerns.
PostgreSQL with pgvector provides vector similarity search, but it also provides:
- ACID transactions (critical for memory consistency)
- Apache AGE for graph relationships
- JSONB for flexible metadata
- Triggers and functions for automated behaviors
- Mature tooling, monitoring, and backup
A dedicated vector DB gives better vector performance at scale, but fragments state. Hexis values consistency over raw vector throughput.
SQL functions are language-agnostic. They enforce contracts at the database level. If someone writes a Go worker or a Rust CLI, the cognitive API is the same. The database is the brain for any app layer.
Hot-path recall can't afford multi-hop graph traversal on every query. Neighborhoods are precomputed during maintenance and stored in memory_neighborhoods. The fast_recall() function combines vector similarity, neighborhood expansion, and temporal context in a single query.
- Schema:
db/*.sql - Memory creation:
db/*_functions_memory.sql - Heartbeat logic:
db/*_functions_heartbeat.sql - Maintenance:
db/*_functions_maintenance.sql - Python adapter:
core/cognitive_memory_api.py
- Database API -- public SQL function contract
- Database Schema -- table reference
- Memory Architecture -- how memory layers work
- Philosophy -- the philosophical motivations