Persistent identity, continuous emotion, governed memory, and auditable context for long-running AI personas.
SoulLink is an open-source runtime for agents that should feel like the same person over time, not a fresh prompt on every turn. It combines a layered persona engine, continuous emotional state, governed long-term memory, exact context evidence, and reversible host integration.
A memory is not automatically an instruction. An emotion is not only a style adjective. A summary is not the latest user request. SoulLink makes those distinctions executable and auditable.
The screenshot uses synthetic public demo data rendered by the real read-only SoulLink WebUI. It contains no private persona, memory, or conversation data.
| Capability | Observable behavior |
|---|---|
| Continuous persona | Stable identity stays anchored while work, daily, intimate, or crisis posture changes expression without replacing the person. |
| Dynamic emotion | Affection, trust, possessiveness, and patience change tone, distance, initiative, and boundaries with intensity and aftereffects instead of resetting each turn. |
| Governed memory | PCLTM separates the persistent archive, recall candidates, policy judgment, and records that actually influence the final model input. |
| Exact evidence | The WebUI distinguishes exact host capture from sidecar reconstruction; missing evidence is shown as unavailable, never invented. |
| Reversible integration | Host adapters follow detect → backup → apply → verify → receipt → byte-exact rollback. |
git clone https://github.com/miyamoriaoi1997-del/Soul-Llink.git
cd Soul-Llink
uv sync --group dev
uv run soullink init
uv run soullink doctor
uv run soullink webuiThe dashboard opens at http://127.0.0.1:8765/. Core runtime use does not require Hermes or Codex; both are optional, explicit adapters.
For a packaged install, download the wheel from the latest GitHub Release, verify SHA256SUMS.txt, then run:
python -m pip install soullink_public-2.1.0-py3-none-any.whl
soullink init
soullink doctor
soullink webuiLong-running persona agents commonly fail in ways that short demos hide:
- identity, behavior, and task instructions collapse into one unauditable prompt;
- retrieved memories and compressed summaries gain accidental authority;
- tool results leak across turns as stale evidence;
- emotional state is computed but softened away before the final response;
- host integration becomes an undocumented, irreversible local patch;
- model routing cannot be correlated with the state that requested it.
SoulLink treats persona, memory, emotion, context, tools, and routing as separate governed layers. The result is a runtime that can remain expressive without surrendering factual discipline or operator control.
User / Host Adapter
|
v
Persona Engine <---- runtime mode, emotion state, task scene, style layer
|
v
PCLTM Context Assembly <---- pinned memory, approved records, episodic recall, compaction boundaries
|
v
Model Router <---- explicit metadata, provider policy, model selection
|
v
Upstream Model
The reusable runtime packages are host-independent. This repository also carries optional reference adapters and
versioned host patchsets under adapters/. They are explicit integration surfaces, not hidden dependencies of the core.
Host adaptation must detect capabilities, create a backup, verify the installed result, and support rollback.
packages/persona_engine/— persona runtime and mode/state orchestration.packages/pcltm/— memory/context governance primitives, audit helpers, and safe context assembly.packages/model_router/— OpenAI-compatible routing proxy and example configuration.adapters/— optional, host-specific integration assets kept outside the reusable package boundary.tests/— public regression tests for the extracted runtime.
The Persona Engine is responsible for assembling the active behavioral layer of the agent. It keeps identity, mode, emotion, task framing, and style as separate inputs instead of flattening them into an uncontrolled prompt.
Its design goals are:
- Layered priority — higher-priority identity and boundary layers cannot be rewritten by lower-priority style or task layers.
- Mode-aware behavior — daily, work, intimate, crisis, or other runtime scenes can change expression without replacing identity.
- Emotion-aware output — emotion state can influence tone, distance, initiative, and softness while preserving factual discipline.
- Host independence — the reusable engine does not require a specific chat platform, file layout, or deployment process.
This lets a persona remain stable while still reacting dynamically to the current relationship, task, and conversation state.
PCLTM is SoulLink's exclusive memory and context-governance architecture. It is not just a vector search layer and not just a summarizer. It is the control plane that decides which continuity records may influence the model, how they are typed, how they are bounded, and how they are assembled into the active prompt.
The name emphasizes the design goal: long-term memory is centered on the persona runtime. Memory is not allowed to be a loose pile of retrieved text. It must respect identity, user preference, runtime boundaries, approval state, and the current conversation's actual latest request.
PCLTM owns the memory/context boundary for long-running agents:
- Typed memory records — memory is treated as structured records with state, bucket, provenance, and intended use.
- Pinned continuity — stable identity, user preferences, and architecture invariants can be pinned without becoming noisy chat history.
- Progressive recall — older or larger records can remain searchable without being injected into every turn by default.
- Compaction governance — summaries and handoff blocks are reference-only unless explicitly promoted by policy.
- Tool-result hygiene — tool output is only valid inside the current assistant-tool chain and should not leak into future turns as fresh evidence.
- Active-context assembly — final prompt materialization is a deliberate assembly step, not an accidental concatenation of everything remembered.
- Auditability — memory candidates and context decisions can be inspected with read-only audit helpers.
A typical PCLTM deployment separates memory into several layers:
- Runtime invariants — rules that define non-negotiable behavior of the memory system itself.
- Pinned records — approved facts and preferences that should be available across sessions.
- Episodic records — conversation-derived memories that may be recalled when relevant.
- Compaction capsules — compressed continuity blocks that preserve context but remain reference-only.
- Tool-chain evidence — current-turn tool outputs that expire when the active tool chain closes.
- Host/runtime state — deployment-specific files, logs, databases, and adapters that must not be committed into source.
This separation prevents a common failure mode in long-context agents: treating every remembered string as equal. PCLTM requires memory to carry intent. A durable user preference, a stale tool result, a summary of an old task, and the current user request are not the same kind of information and should not have the same authority.
The public package includes context-engine invariants that encode this philosophy:
- Compaction and handoff blocks are background reference material, never the latest user request.
- Tool results are valid only inside the currently open assistant-tool chain.
- User, system, and developer turns close the current tool chain.
- Orphaned, late, duplicate, or historically reused tool results are removed from model/context copies.
- Runtime data is kept outside package source and outside public examples.
These rules make the active context safer and easier to reason about. The model should answer the user's current request, not a stale handoff, a duplicated tool log, or an old compressed summary that happens to be nearby.
PCLTM is built around governance, not retrieval alone.
A plain memory system asks, "what text is similar to this turn?" PCLTM asks additional questions before anything reaches the model:
- What type of memory is this?
- Who approved it, and what is its lifecycle state?
- Is it a durable preference, an episodic fact, a runtime invariant, or temporary evidence?
- Can it affect the current turn, or should it remain searchable background context?
- Does injecting it risk overriding the latest user request?
- Is the record safe for this host, mode, and deployment boundary?
That is why PCLTM is the distinctive architecture inside SoulLink. It gives a persona agent continuity without surrendering control of the active prompt to untyped memory retrieval or opaque compression.
The Model Router is an OpenAI-compatible routing proxy. It allows runtime metadata to participate in provider/model selection without hardcoding routing behavior inside the persona or memory layers.
Its goals are:
- route requests based on explicit metadata rather than hidden side effects;
- keep upstream provider configuration separate from persona logic;
- support public tests with synthetic configs;
- make model choice auditable and replaceable.
This repository intentionally does not include:
- private memories, state files, logs, evidence dumps, or local operator data;
- deployment configuration for a specific private host;
- private host configuration or unversioned host modifications;
- real API keys, provider secrets, or
.envfiles; - private role/persona content;
- copyrighted or private character presets.
The public edition is meant to demonstrate the reusable architecture, not to publish a private running instance.
- Python 3.11 or newer
- Git, when MemFS history or host patch application is used
uvis recommended for development and reproducible environments- An OpenAI-compatible endpoint is optional and needed only when using the model router or an LLM-backed semantic classifier
- PyTorch and Transformers are optional; install the
mldependency group only when local neural emotion inference is required
SoulLink does not require Hermes or Codex for its core runtime. Host support is provided through explicit, optional adapters.
Download both the wheel and SHA256SUMS.txt from the latest release, verify the checksum, then install into a fresh environment:
python -m venv .venv
# Linux/macOS
. .venv/bin/activate
# Windows PowerShell
# .venv\Scripts\Activate.ps1
python -m pip install soullink_public-2.1.0-py3-none-any.whl
soullink init
soullink doctor
soullink webuigit clone https://github.com/miyamoriaoi1997-del/Soul-Llink.git
cd Soul-Llink
uv sync --group dev
uv run pytest -qOptional local neural inference dependencies:
uv sync --group mlDo this for deployments, CI, and tests so runtime data never lands in the source tree accidentally:
soullink init --db /srv/soullink/pcltm.db --memfs /srv/soullink/memfs --json
soullink doctor --db /srv/soullink/pcltm.db --memfs /srv/soullink/memfs --jsonEquivalent environment variables:
export HERMES_PCLTM_DB=/srv/soullink/pcltm.db
export HERMES_PCLTM_MEMFS_ROOT=/srv/soullink/memfsThe wheel installs the core commands plus managed Hermes and Codex adapter commands:
| Command | Purpose |
|---|---|
soullink |
Initialize, inspect, govern, and monitor the PCLTM runtime |
pcltm |
Alias of soullink |
soullink-continuity-gate |
Evaluate pinned continuity artifacts using deployment-owned baselines and policy |
soullink-host-adapt |
Detect, apply, verify, and roll back a versioned host patchset |
soullink-hermes-deploy |
Managed Hermes deployment lifecycle |
soullink-codex-deploy |
Detect, apply, verify, and byte-exactly roll back a Codex installation |
soullink-codex-mcp |
SoulLink/PCLTM STDIO MCP server used by Codex |
soullink-codex-hook |
Codex lifecycle hook entrypoint |
Useful health and evidence commands:
soullink doctor --json
soullink index stats --json
soullink index doctor --json
soullink live-context smoke --mode work --query "current task" --json
soullink live-context evidence-smoke --json
soullink governance run --jsonlive-context evidence-smoke uses synthetic tool evidence and verifies that context remains bounded, contains one outer PCLTM block, and does not expose the synthetic secret marker.
SoulLink source code and runtime state have separate ownership. A default local initialization creates:
var/
├── pcltm-prod.db # authoritative SQLite event and memory store
└── memfs/
├── system/ # runtime invariants and system continuity
├── pinned/ # approved durable records
├── episodic/ # recallable episodic records
├── transient/ # short-lived or retrieve-only material
└── skills/ # procedural memory exports
The repository ignores runtime databases, MemFS state, logs, backups, .env files, keys, and generated evidence. Do not publish a runtime directory as source code.
Hermes integration is optional and deliberately separated from the core packages. SoulLink owns its required host adaptations as versioned assets under adapters/hermes/ rather than relying on undocumented manual edits.
A host-adapter lifecycle is:
soullink-host-adapt detect \
--manifest adapters/hermes/compatibility.yaml \
--host-root /path/to/hermes
soullink-host-adapt apply \
--manifest adapters/hermes/compatibility.yaml \
--host-root /path/to/hermes \
--receipt /safe/path/soullink-adapter-receipt.json
soullink-host-adapt verify \
--manifest adapters/hermes/compatibility.yaml \
--host-root /path/to/hermes
soullink-host-adapt rollback \
--manifest adapters/hermes/compatibility.yaml \
--receipt /safe/path/soullink-adapter-receipt.jsonImportant rules:
- Run
detectbefore mutation. - Test against an isolated host copy or worktree first.
- Keep the receipt until post-install verification is complete.
- A failed verification triggers rollback; do not delete backup evidence manually.
- Host compatibility is version-specific. Never apply a patchset to an unknown host revision merely because paths look similar.
The reference memory-provider and plugin manifests are examples of explicit integration boundaries. They do not silently activate themselves during package installation.
The Codex adapter uses supported Codex extension surfaces only: a local STDIO MCP server in
$CODEX_HOME/config.toml and lifecycle command hooks in $CODEX_HOME/hooks.json. It does not patch
Codex source. Existing config and hook entries are retained; a pre-existing foreign
[mcp_servers.soullink] table is treated as an incompatibility instead of being overwritten.
soullink-codex-deploy detect --codex-home ~/.codex
soullink-codex-deploy apply \
--codex-home ~/.codex \
--db /srv/soullink/pcltm.db \
--memfs /srv/soullink/memfs \
--receipt /safe/path/soullink-codex-receipt.json
soullink-codex-deploy verify --codex-home ~/.codex
codex mcp get soullink
soullink-codex-deploy rollback \
--receipt /safe/path/soullink-codex-receipt.jsonThe MCP server exposes governed search, open, exact recall, remember, identity-status, and
runtime-status tools. SessionStart and UserPromptSubmit hooks provide bounded developer context;
other registered hooks are audit-only. Codex lifecycle hooks do not expose an exact final-model-input
boundary, so the adapter reports final_forward_observation = unavailable_host_boundary and never labels
hook output or retrieval previews as captured final-forward evidence.
Treat the generated hook commands as executable local code and review them before granting hook trust. The installer creates a receipt and hash-checked backup before mutation. Failed apply/verify/receipt writes restore the original managed file set automatically; explicit rollback restores pre-existing files byte for byte and removes the receipt.
model_router is an OpenAI-compatible routing proxy. Start from the synthetic configuration:
cp packages/model_router/config.example.yaml packages/model_router/config.yaml
# edit the local copy; never commit credentials or private endpoints
python -m model_router.app --config packages/model_router/config.yamlThe router accepts only HTTP(S) upstream URLs with a hostname, rejects embedded credentials and query/fragment data, strips SoulLink/Hermes routing metadata before forwarding, and avoids recording raw prompts or authorization headers in audit logs.
Neural emotion analysis is optional and never authoritative by default. The rule/state transition path remains available when PyTorch, Transformers, or model weights are absent.
Supported model IDs have pinned default revisions in sentiment_analyzer.py. Override them explicitly when auditing a different checkpoint:
export SOULLINK_SENTIMENT_MODEL_ID=tabularisai/multilingual-emotion-classification
export SOULLINK_SENTIMENT_MODEL_REVISION=<audited-commit-sha>Model downloads may be large. Production deployments should prefetch and review weights rather than allowing an unexpected first-request download.
Run the public root suite:
uv run pytest -qRun the Persona Engine source-tree suite, whose historical imports require the package roots on PYTHONPATH:
# Linux/macOS
PYTHONPATH="packages/persona_engine:packages:adapters" uv run pytest -q packages/persona_engine/tests
# Windows Git Bash
PYTHONPATH="packages/persona_engine;packages;adapters" uv run pytest -q packages/persona_engine/testsBuild distributions:
uv buildBefore publishing, run the fail-closed public release audit after all tests and after cleaning generated logs:
python scripts/public_release_audit.py --root . --jsonThe audit rejects private identity markers, host-local absolute paths, runtime databases, logs, backups, key material, private production reports, and missing release-policy files. Release archives should be scanned independently as well; a clean source tree does not prove a clean wheel or sdist.
SoulLink assumes that retrieved memory, compaction text, host messages, and tool output may be untrusted. Important boundaries include:
- the latest real user request is not replaced by a summary or handoff capsule;
- tool evidence expires when the active assistant-tool chain closes;
- memory candidates carry lifecycle, provenance, target, and scope information;
- promotion gates bind to independently configured baseline and policy digests;
- monitoring binds to loopback and exposes read-only methods by default;
- runtime logs and model-router audits do not intentionally store raw prompts or credentials;
- host adaptation rejects paths that escape the selected host root and preserves rollback evidence.
See SECURITY.md for responsible disclosure and trust-boundary details.
Run:
soullink doctor --fix --db /path/to/pcltm.db --memfs /path/to/memfsThe operation creates missing scaffolding and does not intentionally delete existing runtime data.
Use the documented source-tree PYTHONPATH. Installed wheel imports use persona_engine.persona_orchestrator.
Install the ml dependency group, verify the model cache and pinned revision, or continue with the rule-based fallback. Do not claim neural inference is active merely because configuration exists.
Stop. Verify the host root, host revision, required paths, and patchset version. Do not force-apply the patch. An incompatible result is a safety boundary, not an inconvenience to bypass.
This is intentional. The bundled monitor is designed as a local read-only surface and rejects external binding by default.
This repository is an open-source reference runtime, not a copy of a private running persona. It is suitable for development, review, controlled integration, and experimentation. Production adoption still requires deployment-specific threat modeling, persistence/backup policy, provider configuration, and host-version validation.
Public templates are intentionally neutral. Configure your own lawful persona identity, relationship labels, and content policies in deployment-owned overlays; do not commit private overlays or user memories back into the public repository.
- Keep examples generic and synthetic.
- Keep host-specific adapters explicit and outside the reusable packages.
- Do not commit runtime databases, memory exports, logs,
.envfiles, or provider credentials. - Treat tests as the public contract for the extracted runtime behavior.
- Prefer explicit metadata and typed records over implicit prompt concatenation.
SoulLink's public value comes from its boundaries. Contributions should preserve those boundaries:
- no private state or secrets in source;
- no real user memory dumps in tests;
- no copyrighted/private persona preset in examples;
- no hidden coupling between host adapters and core packages;
- no behavior that allows stale tool output or compaction summaries to override the latest user request.
Runtime data is created locally after installation and is not committed to the repository. The public defaults are:
- DB:
var/pcltm-prod.db - MemFS root:
var/memfs - MemFS directories:
system,pinned,episodic,transient,skills
Initialize a fresh checkout or installed environment with:
soullink init
# equivalent alias:
pcltm initCheck readiness without modifying existing runtime data:
soullink doctorCreate missing DB/MemFS scaffolding before checking:
soullink doctor --fixBoth commands are idempotent. They create missing parents, bootstrap the SQLite
schema through EventStore, and create the MemFS directory layout without
deleting or overwriting runtime data. Use --db and --memfs for explicit
paths, or set HERMES_PCLTM_DB and HERMES_PCLTM_MEMFS_ROOT.
Hermes integration is optional. The core runtime exposes initialization,
context governance, MemFS, and host-neutral adapter primitives. Reference Hermes
adapter and patchset assets live under adapters/; using them does not make the
core packages depend on Hermes. Treat host compatibility as version-specific and
run detect, apply, verify, and rollback against an isolated host before production use.
This repository builds standard Python source and wheel distributions:
uv run --with build python -m build
uv run --with twine python -m twine check dist/*The released wheel contains the reusable host-neutral packages:
soul_linkpcltmpersona_enginemodel_router
Runtime-specific adapter examples remain in the source tree but are not included
as hidden core dependencies. The soullink-host-adapt command applies only an
explicit manifest and records a rollback receipt.
Before publishing, run:
python scripts/public_release_audit.py --root .SoulLink Public 2.1 is released under the MIT License. See LICENSE.
