Storage & Backends¶
Soulacy persists everything locally by default — zero external
dependencies. When you outgrow a single node, each layer (durable storage,
vector search, message queue) can be swapped independently via
config.yaml, including out-of-process sidecar backends that speak the
External Storage Protocol.
Durable storage (storage:)¶
The durable event-log and memory-archive backend.
| Key | Default | Description |
|---|---|---|
backend |
sqlite |
sqlite, postgres, or external |
postgres_dsn |
— | libpq connection string (postgres only) |
postgres_log_dir |
memory.dir |
Directory for per-agent .log mirror files (postgres only) |
command |
— | Sidecar executable (external only) |
args |
— | Sidecar arguments (external only) |
SQLite (default)¶
Embedded, zero-dependency, ideal for single-node deployments. Databases
live under the workspace data/ directory (see
Workspace Layout) — actions.db, archive.db,
knowledge.db, costs.db, workboard.db, and friends.
PostgreSQL¶
storage:
backend: postgres
postgres_dsn: "postgres://user:pass@host:5432/soulacy?sslmode=disable"
# postgres_log_dir: /var/lib/soulacy/logs # optional .log mirrors
Vector search (vector:)¶
Semantic memory search. When vector.backend is empty, the legacy
memory.vector_db setting is used for backwards compatibility.
| Key | Default | Description |
|---|---|---|
backend |
"" (inherits memory.vector_db) |
sqlite-vec, qdrant, or external |
url |
— | Qdrant base URL, e.g. http://localhost:6333 |
collection |
— | Qdrant collection name, e.g. soulacy_memory |
api_key |
— | Qdrant API key (optional) |
dims |
768 |
Embedding dimensionality — must match your embedder |
command / args |
— | Sidecar process (external only) |
# Built-in (default behaviour when memory.vector_db: sqlite-vec)
vector:
backend: sqlite-vec
# Qdrant
vector:
backend: qdrant
url: http://localhost:6333
collection: soulacy_memory
dims: 768
Qdrant is experimental
The qdrant vector backend has no automated tests and no known
production users. Enabling it logs a startup WARN. It is unsupported —
prefer sqlite-vec (the default) or an external sidecar for anything you
depend on.
Message queue (queue:)¶
Carries the event stream and internal work distribution.
| Key | Default | Description |
|---|---|---|
backend |
memory |
memory, nats, or external |
nats_url |
nats://localhost:4222 |
NATS server URL; comma-separated list for clusters |
nats_stream |
soulacy |
JetStream stream that owns Soulacy subjects |
nats_subject_prefix |
"" (= <stream>.>) |
Subject filter applied to the stream |
nats_ack_wait |
30s |
How long JetStream waits for an Ack before redelivering |
nats_max_deliver |
0 |
Max delivery attempts per message; 0 = unlimited |
command / args |
— | Sidecar process (external only) |
With the default memory backend, events exist in-process only (still
consumed by the webhook dispatcher). Switch to nats to consume events
from other processes or machines.
NATS is experimental
The nats queue backend has no automated tests and no known production
users. Enabling it logs a startup WARN. It is unsupported — the default
in-memory queue is the supported path; use an external sidecar if you need
cross-process durability.
External sidecars (External Storage Protocol)¶
Vector and queue backends can be served by a sidecar process speaking
the External Storage Protocol — JSON-RPC 2.0 over stdio — so third-party
database drivers plug in at runtime in any language, without recompiling
Soulacy. The gateway spawns the sidecar, negotiates capabilities, and
provisions a per-run shared scratch directory (data/scratch/…) so large
payloads move as files instead of stdio JSON. Full wire spec and
conformance kit (sdk/extstorage/storagetest): see
docs/EXTERNAL_STORAGE_PROTOCOL.md.
vector:
backend: external
command: /usr/local/bin/my-vector-sidecar
args: ["--db", "/var/lib/mydb"]
queue:
backend: external
command: /usr/local/bin/my-queue-sidecar
Sidecar crash behaviour
Storage sidecars are not auto-respawned in v1 — a crashed sidecar fails calls with a clear error. Restart the gateway (or fix the sidecar) to recover.
Knowledge & embeddings (knowledge:)¶
RAG defaults used by knowledge bases:
| Key | Default | Description |
|---|---|---|
db_path |
<workspace>/data/knowledge.db |
Knowledge SQLite database |
embedding_provider |
ollama |
Embedding provider |
embedding_model |
nomic-embed-text |
Embedding model |
chunk_size |
1000 |
Chunk size in characters |
chunk_overlap |
200 |
Chunk overlap in characters |
knowledge:
embedding_provider: ollama
embedding_model: nomic-embed-text
chunk_size: 1000
chunk_overlap: 200
The default embedding model (nomic-embed-text) produces 768-dimension
vectors, matching the vector.dims / memory.vector_dims default of
768. If you change embedders, keep these in sync.
Memory settings (memory:)¶
| Key | Default | Description |
|---|---|---|
dir |
<workspace>/memory |
Base directory for file memory |
sqlite_path |
<workspace>/data/archive.db |
SQLite memory archive |
vector_db |
"" (disabled) |
Legacy vector toggle: sqlite-vec or empty |
vector_dims |
768 |
Embedding dimensions |
max_history |
50 |
Max messages kept in hot memory |
Choosing backends¶
| Deployment | storage | vector | queue |
|---|---|---|---|
| Laptop / single user | sqlite |
sqlite-vec |
memory |
| Single VPS, external observers | sqlite |
sqlite-vec |
external |
| Multi-instance / heavy traffic | postgres |
external |
external |
| Custom database stack | any | external |
external |
The qdrant and nats backends are experimental and unsupported (no
tests, no known users). For cross-process vector search or queueing, prefer an
external sidecar.