Vayl

io.github.ac12644Published by GitHub account ac12644v0.10.0Updated Oct 30, 2026

Reconciling memory for AI agents: a changed fact retires the old value, with history and approval.

Overview

AI-generated overview

Local persistent memory for AI agents that reconciles changed facts, keeps history, and gates high-stakes changes behind approval.

What you can do
  • Store, recall and retract facts: remember, recall, safe_recall, forget, recall_related
  • Inspect and correct memory: list_memories, get_memory, update_memory, history
  • Record and audit agent decisions: record_decision, explain_decision, check_before_act, attest, verify_receipt, verify_audit, export_public_key
  • Review confirm-required changes: pending_changes, confirm_change, reject_change, set_reconcile_policy, get_reconcile_policy
  • Administer principals and data rights: create_principal, list_principals, revoke_principal, export_memory, delete, delete_all, purge_expired, audit_log
  • Check health, stats and license status
When to use it
Useful when an assistant must track facts that change over time — project stacks, account states, preferences, medications — and must not answer from stale values. Also fits agents that need an auditable record of why they acted and human sign-off on sensitive changes.
Requirements
Runs locally as a Python package (pip install vayl-mcp) over stdio. Needs an LLM/embedding provider: OPENAI_API_KEY, or a local Ollama model if unset; the README also mentions other OpenAI-compatible, Anthropic and Groq models. VAYL_DB sets the SQLite database path. Desktop client only.
Before you install
Memory is written, superseded and can be permanently erased: delete, delete_all and purge_expired are irreversible and purge flags can extend beyond a single user. Principal API keys are shown once and revocation is irreversible. The OPENAI_API_KEY secret is sent to the configured model endpoint. The vendor states it is not certified for clinical use and has not been third-party audited.

Installation

In SourceWeft

  1. Open Vayl in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

Vayl

The reconciling memory layer for AI agents.

[PyPI] [Python] [License] [OpenSSF Scorecard] [Docs]

When a fact changes, most agent memory keeps both versions and lets the model guess which is current. Vayl replaces the old value, keeps it in history, and can hold high-stakes changes until a person approves them. It runs locally on SQLite and works with any MCP client: Claude Code, Cursor, Claude Desktop, or your own agent.

[A real run with a fictional patient: warfarin is recorded, then replaced by apixaban. The change waits in pending_changes until a clinician confirms it. Recall then answers apixaban now, warfarin before, and refuses amoxicillin because of the recorded penicillin allergy.]

A real run with gpt-6-luna and the clinical preset. The patient is fictional. Script: assets/demo/clinical_demo.py

Features

  • Reconciles changes. A new value supersedes the old one, and "we stopped X" retracts X. A retired fact is never returned as current.
  • Keeps history. Ask what is true now or what was true before. Every change goes on a signed, tamper-evident audit chain.
  • Human approval where it matters. Mark slots such as medications as confirm-required, and changes wait in a queue. check_before_act blocks an action that depends on a disputed, stale or just-changed fact.
  • Small and local. SQLite by default, Postgres for teams. One model call to store a fact and one to answer. Any OpenAI-compatible model, Anthropic, Groq or a local Ollama model.
  • Built-in presets for clinical, support, finance, sales, coding and assistant memory.

Install

bash
pip install vayl-mcp

Add it to Claude Code:

bash
claude mcp add vayl -e LLM_PROVIDER=openai -e OPENAI_API_KEY=sk-... -e VAYL_DB=$HOME/.vayl/vayl.db -- vayl-mcp

For Cursor, Claude Desktop and other clients, see the quickstart. Run vayl-demo to try reconciliation with no API key.

Use it from code

python
from vayl import Vayl
with Vayl(user_id="cust_5521") as m:    m.remember("Acme's invoice bounced. Account suspended until payment clears.")    print(m.recall("Is Acme's account in good standing?"))    # No. Acme's account is suspended until payment clears.

Integrations

Agent frameworks. Backends plug into the framework's own memory, so facts are stored and recalled on every turn. Tool adapters give the agent memory tools to call.

FrameworkInstallUse
Google ADKpip install 'vayl-mcp[adk]'from vayl.integrations.adk import VaylMemoryService (memory backend)
LlamaIndexpip install 'vayl-mcp[llamaindex]'from vayl.integrations.llamaindex import VaylMemory (memory block)
AutoGenpip install 'vayl-mcp[autogen]'from vayl.integrations.autogen import VaylMemory (memory backend)
LangGraph / LangChainpip install 'vayl-mcp[langgraph]'from vayl.integrations.langgraph import VaylMemory (tools)
OpenAI Agents SDKpip install 'vayl-mcp[openai-agents]'from vayl.integrations.openai_agents import VaylMemory (tools)
CrewAIpip install 'vayl-mcp[crewai]'from vayl.integrations.crewai import VaylMemory (tools)
Pydantic AIpip install vayl-mcp 'pydantic-ai-slim[openai,mcp]'MCPToolset over MCP, no adapter
Agnopip install vayl-mcp agno openaiMCPTools over MCP, no adapter
Vercel AI SDKnpm i @vayl.dev/client ai zodimport { vaylTools } from "@vayl.dev/client/vercel"
Mastranpm i @vayl.dev/client @mastra/core zodimport { vaylTools } from "@vayl.dev/client/mastra"

Examples for each are in Agent frameworks.

MCP clients. Install vayl-mcp, then add it to your client: Claude Code · Cursor · VS Code · Windsurf · Zed · Cline · Continue · Codex CLI · Gemini CLI. For a shared team memory, run vayl-server and call it over MCP or REST.

Documentation

QuickstartInstall and connect a client
How Vayl worksExtraction, reconciliation and retrieval
Tutorial: a hospital medication assistantClinical preset, critical facts and approval
Tutorial: a customer-support assistantAccount state and safety checks
MCP toolsAll 30+ tools
Deploying vayl-serverTeam server, auth, Docker, Postgres
BenchmarksStale-value and retraction results against Mem0 and Graphiti

Contributing

See CONTRIBUTING.md. The unit tests run offline, with no API key. Good starting points are labeled good first issue.

Security

Data is encrypted at rest by default, and Vayl sends nothing anywhere except to the model endpoints you configure. Vayl is not certified for clinical use and has not been audited by a third party. Report vulnerabilities as described in SECURITY.md.

License

Apache-2.0

Source: README.md at commit 675cc5d

Tools

32

remember

Remember (extract & reconcile facts)

Store fact(s) from a statement. Reconciles automatically: a new value SUPERSEDES the old one (not appended), removals are RETRACTED, and multiple facts in one message are all captured. Optional `metadata` tags the facts stored in this call. `source` records WHO/WHAT asserted the fact (an agent id, a person, a connector) — belief provenance, and the basis for source-aware reconciliation in a shared space (see set_reconcile_policy). Examples: 'We switched from Zustand to Redux Toolkit', 'Alice is the new team lead'.

Parameterstextrequiredrun_idsourceuser_idagent_idmetadata

recall

Recall from current memory

Answer a question from CURRENT memory — the active value ('what state library do we use?') or a multi-hop question over current facts. Returns 'I don't know' rather than guessing, and NEVER answers from a retired/retracted fact. For the timeline of a subject, use `history`. Set `include_history=True` ONLY for questions explicitly about the past — 'what did we use before?', 'when did we switch?' — where retired facts are the answer. It is off by default because with it off, superseded values are never loaded at all, so a stale value cannot be returned as current regardless of how the model behaves. Leaving it off is the guarantee; turning it on trades that for reach into the timeline. `critical_categories` (comma-separated) names fact categories that must ALWAYS reach the answer regardless of ranking — 'allergy,active_medication' in a clinical deployment. Ordinary recall is semantic top-k, so a fact that does not rank is invisible, not merely deprioritised; for some categories that is a safety failure rather than a quality one. Leave empty to use the deployment-wide VAYL_CRITICAL_CATEGORIES; an empty value never means 'none'. Set `explain=True` to also get the PROVENANCE — the exact facts used to answer, each with who asserted it, its confidence, and what it superseded. That's the truthful basis for an audit of why the agent believes what it does (and it's what `record_decision` snapshots).

Parametersrun_idexplainuser_idagent_idquestionrequiredinclude_historycritical_categories

forget

Forget / retract (kept in history for audit)

Retract a fact — a removal with no replacement. Unlike additive stores, this actually retires it so it stops being returned as current (kept in history for audit). Examples: 'We dropped Sentry', 'Alice left the Platform team', 'we no longer support IE11'.

Parameterstextrequiredrun_iduser_idagent_id

get_memory

Get one memory by id

Fetch one memory by its id (the `#id` shown by `list_memories`) — its value, status, scope, confidence, what it supersedes, and any metadata.

Parametersrun_iduser_idagent_idmemory_idrequired

update_memory

Update a memory (audit-preserving)

Correct a memory by id (the `#id` from `list_memories`). Audit-preserving: the old value is retired to history and the new value becomes active — so the change still shows up in `history`.

Parametersrun_iduser_idagent_idmemory_idrequirednew_valuerequired

history

Change history for a subject

The change-log for a subject — every value it has held, oldest → newest, with status. The 'what did we use first vs now' view that additive stores can't give you. The `subject` is the key shown by `list_memories`.

Parametersrun_idsubjectrequireduser_idagent_id

record_decision

Record a decision + the beliefs behind it

Log a decision an agent is about to take, bound to the EXACT facts it consulted. Atomically recalls `question` with provenance and snapshots those beliefs (value, source, confidence, what they superseded) alongside `action_summary`. The snapshot is immutable and signed, so 'why did the agent do X?' stays answerable even after the facts later change. Returns the decision id and a verifiable receipt hash. Example: action_summary='Issued refund to order #91', question='what is the refund policy and this customer's tier?'.

Parametersrun_iduser_idagent_idquestionrequiredaction_summaryrequired

explain_decision

Explain a past decision (why the agent acted)

Reconstruct why an agent acted: the recorded action and the exact beliefs it held at that moment — even if those facts have since been superseded, retracted, or erased. Also verifies the decision's signed receipt so you know the record itself wasn't altered.

Parametersuser_iddecision_idrequired

check_before_act

Safety check before acting on a fact

Ask whether it's SAFE to take an autonomous action based on what memory knows about `subject`. Returns SAFE, or BLOCKED with explicit reasons — an unresolved conflict, confidence below the bar, a value that's gone stale, or one that just changed. Call this before any irreversible action (a payment, an email, a config change) so the agent never silently acts on bad memory. Tune the policy via the params (e.g. min_confidence=0.9, max_staleness_days=90 for high-stakes actions).

Parametersrun_idsubjectrequireduser_idagent_idmin_confidencerequire_activeblock_on_flaggedmax_staleness_daysblock_on_recent_change_days

safe_recall

Gated recall — answers only if safe to act on

Like `recall`, but for when the agent will ACT on the answer. It answers only if every current fact behind the answer passes the safety policy; otherwise it withholds the answer and returns the reasons (disputed value, low confidence, stale, or nothing current). Use this instead of `recall` on the path to an irreversible action. `critical_categories` behaves as in `recall`, and matters more here: this gate can only judge the facts it was handed, so a critical fact ranked out of context would be invisible to the check as well — it would pass, on an answer it never knew was incomplete.

Parametersrun_iduser_idagent_idquestionrequiredmin_confidencerequire_activeblock_on_flaggedmax_staleness_dayscritical_categoriesblock_on_recent_change_days

delete

Erase a subject permanently (GDPR erasure)

PERMANENTLY erase every record of a subject — including history and tombstones — for a user. Unlike `forget` (which retires but retains for audit), this is a hard delete for right-to-be-forgotten / GDPR erasure. The `subject` is the key shown by `list_memories`.

Parametersrun_idsubjectrequireduser_idagent_id

delete_all

Erase ALL memory for a user permanently (GDPR erasure)

PERMANENTLY erase memory (history included). With no agent_id/run_id, erases ALL of the user's memory across every space (account deletion / GDPR); pass them to erase just one space. Irreversible — not the same as `forget`, which retains history for audit.

Parametersrun_iduser_idagent_id

attest

Attest the current value of a subject (signed proof)

Issue a signed, third-party-verifiable attestation of what memory currently holds for `subject` — 'as of now, the active value is X', anchored to the tamper-evident audit-log head. Use it to prove what was known at a point in time. Verify later with verify_receipt, or independently with export_public_key.

Parametersrun_idsubjectrequireduser_idagent_id

verify_receipt

Verify a signed receipt / attestation

Verify a persisted erasure receipt or knowledge attestation: recompute its canonical body and check the Ed25519 signature. Confirms the artifact is authentic and unaltered — the same check a third party can run with only the public key.

Parametersreceipt_idrequired

verify_audit

Verify the audit log is untampered

Verify the tamper-evident audit chain end-to-end. Recomputes every row's hash and (if signed) signature; reports INTACT, or the exact row where the chain breaks — so you can prove the accountability log wasn't edited, reordered, or truncated.

Takes no parameters.

export_public_key

Export the public key for third-party verification

Return Vayl's Ed25519 public key (hex). Anyone can use it to verify erasure receipts, attestations, and the signed audit chain WITHOUT the secret key or access to the database.

Takes no parameters.

set_reconcile_policy

Configure how a shared space reconciles conflicting sources

Configure how a SHARED space resolves conflicts between DIFFERENT contributors (sources). A shared space is any space (e.g. user_id='org:acme') that multiple agents/people write to with a `source` on each remember. Modes: • RECENCY — newer assertion wins (default; contributors equally trusted). • AUTHORITY — a higher-ranked source wins; a lower-ranked source contradicting it is FLAGGED, not overwritten. Pass `authority` as {source: rank} (higher = more authoritative). • REVIEW — any cross-source conflict is FLAGGED for a human. A source correcting its OWN earlier fact always supersedes, regardless of mode.

Parametersmoderun_iduser_idagent_idauthority

get_reconcile_policy

Show a shared space's reconciliation policy

Show the source-aware reconciliation policy configured for a space (default RECENCY if unset).

Parametersrun_iduser_idagent_id

pending_changes

List changes awaiting human approval

List proposed changes to confirm-required slots that have NOT been applied. Slots declared with "confirm" in the slot schema do not auto-apply a replacement or removal — the current value stands until a person approves. This is the queue of what is waiting.

Parametersrun_iduser_idagent_id

confirm_change

Approve a pending change

Approve a proposed change to a confirm-required slot, applying it. Needs the `approve` capability (admin and member roles; agents lack it, so an agent can't approve its own proposal). The approver recorded is the authenticated caller; `decided_by` is an optional note.

Parametersrun_iduser_idagent_idmemory_idrequireddecided_by

reject_change

Discard a pending change

Discard a proposed change. The current value stands. The proposal is kept as history — that someone proposed it is itself worth being able to audit. Needs `approve`, like confirm_change: an agent quietly discarding proposals would empty the review queue just as surely as approving them. `decided_by` is an optional note beside the authenticated caller.

Parametersrun_iduser_idagent_idmemory_idrequireddecided_by

create_principal

Create a principal (user/agent) + API key

Admin only. Create a principal (a human user, agent, or service) and issue its API key. Roles: admin, member, agent, viewer, auditor. The key is shown ONCE — store it securely; it can't be recovered (reissue by creating a new principal). `scopes` is a comma-separated list of user_ids this principal may access, e.g. "cust_5521,cust_7788". Leave empty for unrestricted (the default, and correct for a single-tenant deployment). Set it for any multi-tenant deployment: without it, a valid key can read any space by passing that space's user_id. An admin role is unrestricted regardless, since org control implies reaching every space. `tenant` is the org partition this key belongs to (default: the caller's own tenant). It is a HARD boundary: every store query is filtered by it, so a key for one tenant cannot reach another tenant's memory even under the same user_id. Set it per org in a shared multi-tenant deployment. Only the deployment operator (an admin of the "default" tenant) may name a different tenant.

Parameterskindnamerequiredrolescopestenant

list_principals

List principals of this deployment

Admin only. List your tenant's principals — id, name, roles, and whether disabled (the deployment operator sees every tenant's). Never shows API keys (only their hashes are stored).

Takes no parameters.

license_status

Show the license / edition status

Show the deployment's edition and entitlements — Community or a licensed edition, seats used vs allowed, expiry, and unlocked features. If a license was rejected (tampered/expired/wrong key), this says so and reports the Community fallback it's running under.

Takes no parameters.

revoke_principal

Revoke a principal's access

Admin only. Disable a principal — its API key stops working immediately. Irreversible (create a new principal to restore access). With `erase=True`, the principal row is HARD-deleted (Art. 17 for team members) instead of retained as disabled. A tenant admin can only revoke its own tenant's principals; another tenant's id reads as unknown.

Parameterseraseprincipal_idrequired

list_memories

List current memories

List the current active facts (the reconciled current beliefs) for a user, plus a history block of what was superseded / retracted / archived. Active rows show the `#id` for get/update.

Parametersrun_iduser_idagent_id

export_memory

Export all memory as JSON (GDPR access/portability)

Export everything held about a user/space as machine-readable JSON — data-subject access & portability (GDPR Art. 15/20). A complete DSAR answer: statements (active + full history), PLUS what the append-only records hold about them — decision snapshots, audit entries, and receipts.

Parametersrun_iduser_idagent_id

purge_expired

Purge records older than N days (retention)

Retention / storage-limitation (GDPR Art. 5(1)(e)): permanently delete records written more than `older_than_days` ago. Statements are scoped to the user/space. The optional flags extend the same window to the append-only tables — NOTE these are not per-user: `include_decisions` and `include_receipts` purge those tables for your whole tenant, and `include_audit` purges the audit log from the head of the chain (a signed retention anchor keeps the remaining chain verifiable). There is one chain per deployment, shared by every tenant, so `include_audit` is DEPLOYMENT-WIDE and only the deployment operator may use it.

Parametersrun_iduser_idagent_idinclude_auditolder_than_daysrequiredinclude_receiptsinclude_decisions

audit_log

Audit log (accountability trail)

The accountability trail (GDPR Art. 5(2)) — recent data operations: who / what / when. Optionally filter by user_id. Not affected by memory erasure.

Parameterslimituser_id

stats

Usage stats & KPIs

Operational KPIs for this Vayl instance — on-device, nothing leaves the machine: per-tool call counts, average latency and error counts, plus the distribution of reconciliation actions the engine has taken (SUPERSEDE / RETRACT / FLAG / SKIP / ADD / …).

Takes no parameters.

health

Health check

Check that Vayl is configured and its dependencies are reachable — database, embedder, LLM, and graph (if enabled). Run this to diagnose setup before relying on memory; it makes one small LLM/embed call, so it costs a few tokens.

Takes no parameters.

Version history

3
  1. v0.10.0LatestOct 22, 2026
  2. v0.9.1Oct 22, 2026
  3. v0.9.0Oct 21, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts