Skip to main content

soul-framework

Persistent AI souls — memory, personality, and identity for any LLM agent.

Most agents forget everything between runs. soul-framework gives yours a soul: a persistent identity with an OCEAN personality, a memory that survives restarts, and the ability to reflect on what it learned — in ~2 minutes, zero configuration.

import asyncio
from soul_framework import Soul

async def main():
    async with Soul.create("Maya", ocean={"O": 0.8, "C": 0.9, "E": 0.6, "A": 0.7, "N": 0.2}) as agent:
        await agent.memory.store("User prefers concise technical answers", importance=7)
        context = await agent.boot()        # ready-to-use system-prompt context
        print(context)                      # -> "## Identity: Maya  OCEAN Profile: ..."
        await agent.reflect("First session went well; the user values brevity")

asyncio.run(main())

Command line

Prefer a terminal? soul-framework ships a soul CLI. Each soul lives in ~/.soul/<name>.db.

soul create Maya --ocean "0.8,0.9,0.6,0.7,0.2"   # give Maya a personality
soul remember Maya "William prefers short answers" --importance 8
soul recall Maya "how should I answer?"           # lexical by default (see note below)
soul boot Maya                                    # print the system-prompt context
soul reflect Maya "the session went well" --mood satisfied
soul snapshot Maya                                # compact view of the soul's state

Install

pip install soul-framework              # base: identity + memory + boot + reflect, SQLite, zero config
pip install soul-framework[embeddings]  # add TRUE semantic memory search (sentence-transformers)
pip install soul-framework[ann]         # add portable graph-ANN search for large SQLite souls
pip install soul-framework[integrity]   # add signed integrity checkpoints
pip install soul-framework[postgres]    # add PostgreSQL + indexed pgvector storage

No database to set up — SQLite by default.

PostgreSQL + pgvector

For a larger persistent store, install both production extras and pass the DSN at runtime (never commit it):

pip install 'soul-framework[postgres,embeddings]'
import os
from soul_framework import Soul
from soul_framework.config import SoulConfig

config = SoulConfig(
    backend="postgres",
    backend_url=os.environ["SOUL_POSTGRES_DSN"],
    embedding_provider="sentence-transformer",
)

async with Soul.create("Maya", config=config) as agent:
    await agent.memory.store("The user enjoys astronomy")
    matches = await agent.memory.search("favorite stargazing hobby")

The database administrator must enable CREATE EXTENSION vector once. SOUL then applies an idempotent schema migration and uses a cosine HNSW index. The embedding model defines meaning: pgvector scales retrieval, while the default simple provider remains lexical by design. At scale, PostgreSQL first takes the nearest memory_search_candidate_limit vectors and then applies SOUL's importance/recency scoring; raise that limit when those secondary signals must consider a wider candidate set.

The soul CLI intentionally remains the zero-config SQLite path in v0.4.2; PostgreSQL is configured through the Python API shown above.

Five-year SQLite path (local and sovereign)

For a large local soul, BGE-M3 runs through the loopback-only Ollama API and Graph ANN avoids scanning every memory. Linux/macOS use HNSW; Python 3.13 on Windows uses USearch because hnswlib does not publish a compatible wheel there:

ollama pull bge-m3
pip install 'soul-framework[ann]'
from soul_framework import Soul
from soul_framework.config import SoulConfig

config = SoulConfig(
    backend_url="maya.db",
    embedding_provider="bge-m3",
    embedding_dimensions=1024,
    memory_vector_index="auto",
)

async with Soul.create("Maya", config=config) as agent:
    matches = await agent.memory.search(
        "¿qué medicina debo evitar?",
        context="Estoy revisando mis antecedentes médicos",
    )

Existing 128-dimensional SQLite souls are migrated into a separate candidate; the source is never overwritten and the checkpoint supports resume/rollback:

python -m soul_framework.embedding_migration run maya.db \
  --candidate maya.bge-m3.db --source-dim 128 --target-dim 1024 \
  --provider bge-m3

The five-year engineering gate used 54,750 synthetic memories: all 8 fixed contextual anchors appeared in the top 5 (7/8 ranked first), and end-to-end retrieval measured 280 ms p50 on the test host. This validates the candidate path, not a universal "never forgets" claim; natural corpora and broader probes remain application gates. The HNSW/USearch sidecar is bound to the SQLite source fingerprint and is rebuilt fail-closed if stale or corrupt.

Signed Ed25519 checkpoints are available through soul_framework.integrity. Strong rollback protection additionally requires an external monotonic witness; an in-process witness is useful for tests but is not a security boundary.

What you get

  • Persistent identity + OCEAN personality — the agent is the same agent across runs.
  • Memory that survives restarts — store facts with importance; recall them on boot.
  • Boot context — one call returns a system-prompt block with the agent's identity, traits, and salient memories.
  • Self-reflection — the agent records what it learned and its emotional state.

A note on memory search (honest by design)

  • The base install ranks memories with lexical token-hash matching — zero downloads. It's strong when the query shares words with the memory (e.g. "short answers" → high), but a purely semantic query with no shared words (e.g. "what does the user like?") scores near 0.00. It's word-overlap search, not meaning search.
  • True semantic search — "find by meaning, not keywords" — needs the embeddings extra: pip install soul-framework[embeddings] and SoulConfig(embedding_provider="sentence-transformer").

We'd rather tell you this up front than have you discover a 0.00 similarity on your first meaning-based query.

Why soul-framework vs a general agent framework

soul-framework typical agent framework
Persistent identity across runs ✅ built-in (OCEAN) ✗ / bring-your-own
Memory that survives restarts ✅ SQLite by default usually external store
Boot-context for the system prompt ✅ one call
Self-reflection / learning trace
Zero-config to first run ✅ ~2 min varies
Memory search — lexical (base) / semantic ([embeddings]) ✅ both varies

soul-framework is not a full agent orchestrator — it's the soul layer you drop into any LLM loop (LangChain, your own, whatever). It answers one question well: how does this agent remember who it is and what it learned?

Docs

Status

Alpha (v0.4.2) — local BGE-M3 + portable HNSW/USearch ANN + reversible embedding migration, with optional signed integrity checkpoints. API may still shift before 1.0.

License

Apache-2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

soul_framework-0.4.2.tar.gz (112.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

soul_framework-0.4.2-py3-none-any.whl (96.4 kB view details)

Uploaded Python 3

File details

Details for the file soul_framework-0.4.2.tar.gz.

File metadata

  • Download URL: soul_framework-0.4.2.tar.gz
  • Upload date:
  • Size: 112.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for soul_framework-0.4.2.tar.gz
Algorithm Hash digest
SHA256 43cebc414d9c356ca738071a986f544ba350cdb41846b06240e99406d1644f2d
MD5 ca0d41ba1005c8d8e28d3297ce4adda1
BLAKE2b-256 436e1894b650fa508cbc15e2d88b1dd613ff256f02e754ec7be14381b02beda5

See more details on using hashes here.

Provenance

The following attestation bundles were made for soul_framework-0.4.2.tar.gz:

Publisher: release.yml on sknaider/soul-framework

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file soul_framework-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: soul_framework-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 96.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for soul_framework-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8dc18db0ccbdb2b00968d3dfc41651e09d7371bf3a501f791aaab1ee23475bf0
MD5 a98b0748647f760e40783268ccfb174f
BLAKE2b-256 bb4b192095c7488bbfc5dc202bbe281f1e588109cb07bb92f6cb1c75e65306e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for soul_framework-0.4.2-py3-none-any.whl:

Publisher: release.yml on sknaider/soul-framework

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page