cd /news/ai-agents/agentkeeper-solved-the-goldfish-memo… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-17409] src=github.com pub= topic=ai-agents verified=true sentiment=↑ positive

Agentkeeper solved the Goldfish Memory problem in AI Agents.v1.1 out now

AgentKeeper released version 1.1 of its AI agent infrastructure, solving the "Goldfish Memory" problem by providing cognitive continuity across model switches, crashes, and restarts. The update introduces protected principles and constraints that survive compression cycles, TTL-based fact expiration for compliance, and an MCP server enabling any MCP-aware client to access the agent's cognitive layer without integration code.

read7 min publishedMay 29, 2026

Cognitive continuity infrastructure for long-lived AI agents.

Your agent survives model switches, crashes, context-window limits, and restarts β€” with the same identity, memory, and priorities it had before.

Agents don't fail because they forget facts. They fail because they lose cognitive continuity β€” their state, priorities, and identity drift the moment the model changes, the context window fills, or the process restarts.

AgentKeeper treats this as a systems problem, not a memory problem.

pip install agentkeeper-ai

Zero required dependencies. No external infrastructure. Storage defaults to local SQLite.

pip install 'agentkeeper-ai[anthropic]'   # Claude
pip install 'agentkeeper-ai[openai]'      # GPT + OpenAI embeddings
pip install 'agentkeeper-ai[gemini]'      # Gemini
pip install 'agentkeeper-ai[semantic]'    # Local embeddings (sentence-transformers)
pip install 'agentkeeper-ai[mcp]'         # MCP server (Claude Desktop, Cursor, Codex)
pip install 'agentkeeper-ai[encrypted]'   # Encrypted storage at rest
pip install 'agentkeeper-ai[all]'         # Everything

Principles and constraints are protected β€” exempt from every compression pass, injected into every reconstructed context, regardless of token budget. They survive decay, consolidation, contradiction arbitration, model switches, and process restarts.

import agentkeeper

agent = agentkeeper.create(agent_id="aria", provider="anthropic")
agent.set_identity(
    name="Aria",
    role="EU insurance broker copilot",
    principles=["never share PII without explicit consent"],
    constraints=["EU data residency only"],
)
agent.principle("always confirm budget changes in writing")
agent.fact("client: Acme Corporation", importance=0.95)
agent.event("contract signed", when="2026-05-15")
agent.save()

The cognitive state is reconstructed in the format each model expects. XML for Claude, labelled sections for GPT-4, narrative prose for Gemini, terse tokens for Ollama. One agent, four runtimes, zero rewrites.

agent = agentkeeper.load("aria", provider="anthropic")
response = agent.ask("What do we know about Acme?")

agent.switch_provider("openai").save()
response = agent.ask("Same question, different model.")

Facts and graph triples accept a TTL. When it lapses, purge_expired()

removes them. No manual cleanup. Compliant by default.

agent.fact("session token: abc123", ttl="1h")
agent.fact("audit log reference: Q1-2026", ttl="90d")
agent.link("Acme", "signed_contract", "ThinkLanceAI", ttl="2y")

agent.purge_expired()  # removes what's lapsed, keeps what's protected

Facts are prose. Triples are structure. Both live in the same agent, with their own retention and TTL policy.

agent.link("Acme", "owns", "Globex")
agent.link("Globex", "located_in", "BE")
agent.link("Alice", "works_at", "Acme", confidence=0.9)

related = agent.find_related("Acme", max_hops=2, direction="out")

AgentKeeper ships an MCP server. Any MCP-aware client β€” Claude Desktop, Cursor, Claude Code β€” gets full access to the agent's cognitive layer without writing a line of integration code.

agentkeeper-mcp --agent-id aria --provider anthropic

claude_desktop_config.json

:

{
  "mcpServers": {
    "aria": {
      "command": "agentkeeper-mcp",
      "args": ["--agent-id", "aria", "--provider", "anthropic"]
    }
  }
}

Available tools over MCP: add_fact

, recall

, set_identity

, link

, find_related

, compress

, health

, gdpr_export

, purge_expired

, checkpoint

, restore

, list_checkpoints

.

Freeze the full cognitive state into an immutable, content-hashed snapshot. Restore it after a crash, a context-window overflow, a model switch, or a process restart. Attach an opaque execution_state

payload (current file, pending task, todos) β€” AgentKeeper stores and returns it verbatim; it never interprets or runs it.

snap = agent.checkpoint(
    label="before refactor",
    execution_state={
        "current_file": "auth.py",
        "pending_task": "finish RS256 migration",
    },
)

agent = agentkeeper.load("aria").restore(snap.snapshot_id)

agentkeeper.diff(snap_a, snap_b)   # factual diff: facts added/removed/modified
agent.list_checkpoints()           # every snapshot, oldest first

Reconstruction is deterministic β€” the same snapshot always rebuilds the same cognitive state, verified by a content hash. Behaviour is not guaranteed: AgentKeeper restores the agent's state, not the model's next decision. The crash-recovery demo runs with no API key:

python examples/crash_recovery.py
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β”‚                  AgentKeeper Public API                       β”‚
       β”‚  agent.remember() Β· agent.recall() Β· agent.ask()             β”‚
       β”‚  agent.compress() Β· agent.link() Β· agent.find_related()      β”‚
       β”‚  agent.set_identity() Β· agent.purge_expired() Β· agent.save() β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β”‚           Cognitive Reconstruction Engine (CRE)              β”‚
       β”‚  Identity injection Β· importance ranking Β· semantic boost    β”‚
       β”‚  Token budget Β· profile-driven rendering                     β”‚
       β””β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚           β”‚            β”‚            β”‚
   β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ Memory    β”‚ β”‚ Semantic   β”‚ β”‚ Cognitive β”‚ β”‚ Cross-Model   β”‚
   β”‚ Hierarchy β”‚ β”‚ Recall     β”‚ β”‚ Compress  β”‚ β”‚ Translation   β”‚
   β”‚           β”‚ β”‚            β”‚ β”‚           β”‚ β”‚               β”‚
   β”‚ working   β”‚ β”‚ embeddings β”‚ β”‚ decay     β”‚ β”‚ XML (Claude)  β”‚
   β”‚ episodic  β”‚ β”‚ vector idx β”‚ β”‚ consol.   β”‚ β”‚ sections (GPT)β”‚
   β”‚ semantic  β”‚ β”‚ sqlite-vec β”‚ β”‚ contradic β”‚ β”‚ narrative (G.)β”‚
   β”‚ archival  β”‚ β”‚            β”‚ β”‚           β”‚ β”‚ minimal (Oll.)β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                            β”‚
   β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  Graph Layer             Storage (pluggable)                   β”‚
   β”‚  Triple, TTL, BFS        SQLite Β· Encrypted SQLite Β· Postgres* β”‚
   β”‚  agent.link()            AGENTKEEPER_DB, AGENTKEEPER_ENC_KEY   β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  MCP Server Β· LangChain Β· CrewAI         β”‚
              β”‚  agentkeeper-mcp Β· langchain_system_promptβ”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

*Postgres stub available; full implementation in v1.2.

agent.fact("budget: 50k EUR", importance=0.9)          # stable semantic fact
agent.event("contract signed", when="2026-05-15")      # episodic, time-anchored
agent.principle("never share PII")                     # protected, survives all compression
agent.remember("favourite colour: blue")               # tier inferred automatically
results = agent.recall("money allocated to the project", top_k=5)
for fact, score in results:
    print(f"{score:.2f}  {fact.content}")

Pluggable backends: local sentence-transformers

(default, free, offline), OpenAI, or your own. Persistent index via sqlite-vec

β€” survives process restarts without rebuild.

report = agent.compress()

Three independent passes: decay (exponential half-life on unused facts), consolidation (embedding-based clustering, optional LLM synthesiser), contradiction arbitration (key-value divergence + polarity detection, deterministic winner). Protected facts are immortal.

agent.link("Acme", "owns", "Globex", confidence=1.0)
agent.link("Acme", "signed_contract", "ThinkLanceAI", ttl="2y")

related = agent.find_related("Acme", max_hops=2, direction="out")

for triple in agent.triples:
    print(triple)  # Triple('Acme' -[owns]-> 'Globex', conf=1.00)
agent.fact("session token: abc123", ttl="1h")
agent.fact("temp context: negotiation", ttl="30d")
agent.link("Project Phoenix", "uses_provider", "Anthropic", ttl="P90D")

agent.purge_expired()  # returns count of removed items
python
from agentkeeper.storage.encrypted_sqlite import EncryptedSQLiteStorage

key = EncryptedSQLiteStorage.generate_key()
storage = EncryptedSQLiteStorage(encryption_key=key)

AES-128-CBC + HMAC-SHA256 at rest. Progressive migration β€” plain SQLite rows are upgraded on next save.

import asyncio, agentkeeper

async def main():
    agent = agentkeeper.create_async(agent_id="aria", provider="anthropic")
    agent.set_identity(name="Aria", role="copilot")
    agent.fact("budget: 50k EUR", importance=0.95)

    answers = await asyncio.gather(
        agent.ask("status?", provider="anthropic"),
        agent.ask("status?", provider="openai"),
    )

asyncio.run(main())

Sync and async agents share the same storage. Save with one, load with the other.

from agentkeeper.integrations.langchain import LangChainCognitiveProvider
from langchain_core.prompts import ChatPromptTemplate

provider = LangChainCognitiveProvider(agent, model="gpt-4o")
prompt = ChatPromptTemplate.from_messages([
    ("system", provider(message="What's our budget?")),
    ("human", "{input}"),
])
python
from agentkeeper import CognitiveProfile, PromptFormat, register_profile

register_profile(CognitiveProfile(
    provider="my-llm",
    format=PromptFormat.SECTIONS,
    effective_context_tokens=10_000,
))
export = agent.gdpr_export()   # all facts, triples, identity β€” JSON-serialisable
agent.purge_expired()          # remove anything whose TTL has elapsed
agent.forget(fact_id)          # remove a single fact by id
agentkeeper.delete("aria")     # permanently remove an agent from storage
snapshot = agent.health()

Type-safeβ€”py.typed

shipped, mypy-strict compatible.Typed exceptionsβ€”AgentKeeperError

root, subclasses for every failure mode.Structured loggingβ€” namespaced underagentkeeper.*

, opt-in,NullHandler

default.Retriesβ€” exponential backoff + jitter viawith_retry

/with_async_retry

.Testedβ€” 491 tests, CI on Python 3.10 / 3.11 / 3.12.** Zero breaking changes from v0.1**β€”agent.remember(content, critical=True)

still works.

Variable Default Purpose
OPENAI_API_KEY
β€” OpenAI provider
ANTHROPIC_API_KEY
β€” Anthropic provider
GEMINI_API_KEY
β€” Gemini provider
OLLAMA_HOST
http://localhost:11434
Ollama server
AGENTKEEPER_DB
agentkeeper.db
SQLite path
AGENTKEEPER_ENCRYPTION_KEY
β€” Fernet key for encrypted storage
AGENTKEEPER_EMBEDDING_PROVIDER
auto sentence-transformers β€Ί openai β€Ί mock
pip install agentkeeper-ai
python examples/demo.py

The demo runs entirely on provider="mock"

and AGENTKEEPER_EMBEDDING_PROVIDER=mock

. No keys. No network. Shows identity hardening, compression, cross-model translation, and async β€” in one file.

v1.1βœ… β€” TTL, graph layer, encrypted storage, MCP server, LangChain + CrewAI integrations, persistentsqlite-vec

index, GDPR export, health snapshot, cognitive checkpoints (snapshot / restore / diff), 491 tests.v1.2β€” Postgres storage backend (full implementation), TypeScript SDK.** v1.3**β€” AgentKeeper Cloud (managed sync). OSS stays feature-complete.

Issues, ideas, and PRs welcome. See CONTRIBUTING.md.

MIT. See LICENSE.

ThinkLanceAI β€” Tom Anciaux Berner β€” cognitive infrastructure for AI systems.

tom@thinklanceai.com

── more in #ai-agents 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/agentkeeper-solved-t…] indexed:0 read:7min 2026-05-29 Β· β€”