Identity Preservation System for LLM Agents
100% Local โข Deterministic โข Versioned Identity โข Model-Agnostic
Changelog โข Skill โข Franรงais โข MIRA Integration
- Relationship with MIRA
- Why SOUL?
- Architecture
- Identity Model
- Database Schema
- Installation
- Configuration
- CLI Usage
- MCP Tools
- Deployment
- Drift Detection
- Testing
- Module
- Changelog
| Aspect | Detail |
|---|---|
| Dependency | None - SOUL compiles and runs without MIRA |
| Integration | Can run standalone (separate MCP server) or embedded in MIRA (single binary, 16 tools) |
| Database | SOUL adds soul_* tables to MIRA's .mira/mira.db |
| Cross-access | SOUL can read MIRA's verbatim table to enrich identity context |
| Deployment | Standalone via stdio JSON-RPC, or embedded in MIRA process |
SOUL is opt-in. A client can connect to MIRA only, SOUL only, or both.
MIRA can embed SOUL as a single binary with 16 MCP tools:
# MIRA with embedded SOUL - single binary, 16 tools
./mira --config config.yaml --with-soulWhen embedded, SOUL shares MIRA's SQLite connection (ownsDB = false). If SOUL initialization fails, MIRA continues with its 8 tools.
LLM agents lose their personality between sessions and when switching models:
User talks to "Claude-3-Assistant" for 6 months.
The agent developed a unique personality: empathetic, analytical,
with subtle humor and preference for analogies.
Model switches to GPT-4. MIRA recalls all facts.
But the agent now responds differently:
- More formal, less warm
- No more analogies
- Doesn't recognize user's jokes
- Has "forgotten" how to react to frustrations
The user feels like they're talking to a STRANGER.
SOUL solves this by:
- Capturing personality traits, voice profile, communication style, values, and emotional tone
- Storing versioned identity snapshots in the shared database
- Recalling a structured identity prompt for LLM context injection
- Detecting identity drift and alerting when significant change occurs
- Handling model swaps by generating a reinforcement prompt
soul/
โโโ cmd/soul/main.go # CLI entry point + MCP dispatcher
โโโ config.example.yaml # Configuration reference
โโโ internal/
โ โโโ app/
โ โ โโโ app.go # Composition root
โ โ โโโ config_loader.go # YAML config loading
โ โโโ domain/
โ โ โโโ entities/ # IdentitySnapshot, PersonalityTrait, VoiceProfile...
โ โ โโโ valueobjects/ # SoulQuery, DriftReport, ModelSwap...
โ โโโ usecases/
โ โ โโโ interactors/ # Capture, Recall, Drift, Swap, Evolution, Merge
โ โโโ adapters/
โ โ โโโ sqlite/storage.go # SQLite storage (shared with MIRA)
โ โ โโโ composition/service.go # Identity prompt composer
โ โ โโโ drift/detector.go # Drift detection algorithm
โ โ โโโ embedder/service.go # 13-dim identity embedder
โ โ โโโ extraction/service.go # Trait extraction from conversations
โ โ โโโ modelswap/handler.go # Model swap + merge logic
โ โโโ interfaces/
โ โโโ mcp/server.go # MCP server (8 tools, stdio JSON-RPC)
Hexagonal architecture - domain never imports adapters. All external dependencies flow inward through ports.
An IdentitySnapshot contains:
- PersonalityTraits - Named traits with category, intensity (0-1), confidence (0-1), evidence count
- VoiceProfile - Formality, verbosity, vocabulary richness, metaphor usage
- CommunicationStyle - Directness, empathy, humor, question frequency, example usage
- BehavioralSignature - Response patterns, reasoning style, error handling
- ValueSystem - Ethical stances, priorities, boundaries
- EmotionalTone - Baseline valence, arousal, expressiveness
Trait categories: cognitive, emotional, social, epistemic, expressive, ethical
SOUL adds these tables to the shared SQLite database:
| Table | Purpose |
|---|---|
soul_identities |
Versioned identity snapshots per agent |
soul_traits |
Aggregated personality traits with confidence |
soul_observations |
Raw observations extracted from conversations |
soul_diffs |
Evolution diffs between consecutive versions |
soul_model_swaps |
History of model transitions |
soul_mira_links |
Links between identity snapshots and MIRA memories |
- Go 1.23+
- GCC (for
go-sqlite3CGo compilation)
git clone https://github.com/benoitpetit/soul
cd soul
go build -o soul ./cmd/soul./soul helpCopy config.example.yaml to configure SOUL:
cp config.example.yaml soul.yamlKey settings:
soul:
storage:
path: ".mira/mira.db" # Must match MIRA's database path
drift_detection:
threshold: 0.3 # 30% change triggers drift alert
window_size: 10
recall:
default_budget_tokens: 1000
# enrich_with_mira_memories and max_mira_memories are documented but NOT YET IMPLEMENTED.
# enrich_with_mira_memories: true
# max_mira_memories: 5soul capture \
--agent my-agent \
--conversation conversation.txt \
--model claude-3-sonnetsoul recall --agent my-agent --budget 800Output is the identity prompt ready to paste into a system message.
soul drift --agent my-agent --window 10soul swap --agent my-agent --from gpt-4 --to claude-3-sonnetOutputs a reinforcement prompt to inject into the new model's first message.
soul status --agent my-agentsoul history --agent my-agent --limit 20soul mcp --storage .mira/mira.dbSOUL exposes 8 MCP tools over stdio JSON-RPC:
| Tool | Description |
|---|---|
soul_capture |
Capture identity from a conversation |
soul_recall |
Recall identity prompt for LLM injection |
soul_drift |
Analyze identity drift |
soul_swap |
Handle model swap + generate reinforcement prompt |
soul_status |
Get current identity status |
soul_history |
Get identity evolution history |
soul_update |
Update identity via natural language directive (FR/EN) |
soul_patch |
Apply structured explicit patch to identity |
SOUL is opt-in within MIRA. By default, MIRA runs solo (8 tools). To activate SOUL:
# Enable SOUL via CLI flag
./mira --config config.yaml --with-soul
# Or enable SOUL via config
```yaml
soul:
enabled: trueWhen enabled, the 8 SOUL tools are registered alongside the 8 MIRA tools (16 total).
SOUL can run as a separate MCP server, with or without MIRA:
# Standalone with its own database
soul mcp --storage /path/to/soul.db
# Standalone sharing MIRA's database
soul mcp --storage /path/to/.mira/mira.db# Terminal 1 - MIRA (SOUL disabled by default)
./mira --config /path/to/mira/config.yaml
# Terminal 2 - SOUL (shares MIRA's database)
./soul mcp --storage /path/to/.mira/mira.dbBoth run as separate MCP server processes registered in your MCP client configuration.
b0p:
{
"mcpServers": {
"mira": {
"command": "/path/to/mira",
"working_directory": "/path/to/mira",
"enabled": true
},
"soul": {
"command": "/path/to/soul",
"args": ["mcp", "--storage", "/path/to/.mira/mira.db"],
"enabled": true
}
}
}Claude Desktop:
{
"mcpServers": {
"mira": {
"command": "/path/to/mira",
"args": ["--config", "/path/to/mira/config.yaml"]
},
"soul": {
"command": "/path/to/soul",
"args": ["mcp", "--storage", "/path/to/.mira/mira.db"]
}
}
}| Configuration | Tools available |
|---|---|
| MIRA only | 8 (mira_*) |
| SOUL standalone | 8 (soul_*) |
| MIRA + SOUL (separate servers) | 16 (mira_* + soul_*) |
| MIRA with embedded SOUL (single binary) | 16 (mira_* + soul_*) |
Tool names never collide - MIRA tools use mira_ prefix, SOUL tools use soul_ prefix.
SOUL computes drift by comparing the current snapshot against N previous versions:
- Per-dimension distance: voice profile, personality traits, value system, emotional tone (4 of 6 dimensions; communication style and behavioral signature are not yet monitored for drift)
- Average
DriftScoreacross dimensions - Alert when
DriftScore > threshold(default: 0.3)
Recommended action when drift is significant: inject the reinforcement prompt from soul_recall or soul_swap into the next context.
go test ./... -count=1All packages pass with an in-memory SQLite database. MIRA table absence is handled gracefully (fallback queries, empty results instead of errors).
github.com/benoitpetit/soul
Repository: https://github.com/benoitpetit/soul
Go 1.23.2 - SQLite via mattn/go-sqlite3 - MCP via mark3labs/mcp-go v0.2.0
- ๐ New version 0.0.6
- ๐ New version 0.0.5
- Unified embedded configuration: Added
NewApplicationWithDBAndConfigso MIRA can pass a fullSoulConfigwhen embedding SOUL. Embedded mode now supports the same tuning options as standalone mode (drift threshold, recall budget, extraction confidence, etc.). - Public API expansion: Exposed
soul.Configandsoul.DefaultConfig()aliases for external modules. - Prepublish script: Added
scripts/prepublish.shfor automated version bump, build, test, and benchmark workflow.
- Initial stable release with MCP server, identity capture, drift detection, model swap handling, and evolution tracking.