[build-system] requires = ["setuptools>=61"] build-backend = "setuptools.build_meta" [project] name = "inspeximus" version = "2.44.0" description = "The agent memory that takes it back: correct a fact once and the retired value stops coming back, by key, with no LLM in the loop. Long-term memory for AI agents in a zero-dependency single file + MCP server, with value-ranked recall, per-type decay, consolidation, revert, and tamper-evident erasure." readme = "README.md" requires-python = ">=3.9" license = { text = "MIT" } # Chosen by frequency in how developers actually describe this problem, not by how we describe it. # Measured 2026-08-25 over 837 agent-memory documents from 2026: stale 24.1%, forget 14.2%, # conflict 12.5%, delete 10.8%, contradict 9.7%, outdated 8.7%, supersede 4.4%. Not one of those # words was in this list; four that were -- rag, embeddings, consolidation, second-brain -- are # terms nobody types when a corrected fact comes back. "stale" alone is five times more common # than "supersede", and it appeared nowhere in our metadata. keywords = [ "stale-data", "outdated", "forget", "supersede", "conflict-resolution", "llm", "agent", "memory", "agent-memory", "ai-agent-memory", "recall", "mcp", "model-context-protocol", "claude-code", "rag", "erasure", "data-erasure", "gdpr", "right-to-be-forgotten", "provenance", "audit-log", "tamper-evident", "revert", "retention", "compliance", "witness", "attestation", ] authors = [{ name = "Rastislav Drahoš (Agora)" }] # PyPI's own browse and filter surface runs on these, and we shipped three. Every entry below is a # claim we can back: the Python versions are the ones CI actually runs (3.9, 3.11, 3.12), not the # ">=3.9" the metadata declares, which is now what CI proves; Beta rather than Stable because this ships several # releases a week; no "Typing :: Typed" because there is no py.typed; OS Independent because the base # package has no dependencies. classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Database", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", ] [project.urls] # PyPI renders each of these as a link in the project sidebar. Until now they pointed only back at this # package, so the research the design rules actually come from -- the replication ledger, the benchmark, # the measured receipts -- was unreachable from the one high-authority page most people land on first. Homepage = "https://dancenitra.github.io/inspeximus/" Source = "https://github.com/DanceNitra/inspeximus" Repository = "https://github.com/DanceNitra/inspeximus" Changelog = "https://github.com/DanceNitra/inspeximus/blob/main/CHANGELOG.md" Issues = "https://github.com/DanceNitra/inspeximus/issues" "Replication ledger" = "https://dancenitra.github.io/agora/public/crucible/" "Benchmark (RAMR)" = "https://github.com/DanceNitra/ramr" Research = "https://dancenitra.github.io/agora/" [project.optional-dependencies] # The five examples that sign anything need Ed25519. The base package deliberately has no # dependencies, so this is the extra a reader is told to install -- and `inspeximus[crypto]` # is the form everyone guesses first, which until 2.0.2 silently installed nothing. crypto = ["cryptography>=41"] # Upper bound is load-bearing, not caution. mcp 2.0 removed `mcp.server.fastmcp`, which is what # inspeximus/mcp_server.py imports, so with an unbounded `>=1.0` a fresh `pip install "inspeximus[mcp]"` # resolved to 2.0.0 and the MCP server raised ImportError on import -- every tool, unusable. Measured in a # clean venv on 2026-07-30; CI never saw it because the dev image already had 1.28.1 pinned by its lockfile. # Supporting 2.x is a real port (the module was reorganised, not renamed in place) and is not attempted here. # The cap has a MEASURED cost, recorded so it is not forgotten: adding it changed pip's search order in # the nine-extra CI install and pip settled on google-adk 1.14.1 (ten majors back, no # google.adk.cli.service_registry) even though google-adk 2.5.0 with mcp 1.29.0 satisfies every # constraint. Realistic installs are fine -- `.[mcp,google-adk]` resolves to 2.5.0 -- and CI now states # google-adk>=2 explicitly so a real conflict fails loudly. This is the documented downside of a library # upper bound; it is carried deliberately, because without it the MCP server does not start at all. # The FLOOR is measured too, not inherited. ">=1.0" was never a tested claim; a resolver under an older # interpreter, a conflicting co-dependency, or a --resolution=lowest CI run can hand you mcp 1.0.0, where # FastMCP exists but the surrounding API does not match this code -- a subtler failure than the clean # ImportError the ceiling fixes. 1.28.1 and 1.29.0 are the versions this code has actually been imported # and tested against. mcp = ["mcp[cli]>=1.28,<2"] # Agent-framework integrations (inspeximus.integrations.*) — opt-in; the core library stays zero-dependency. langchain = ["langchain-core"] langgraph = ["langgraph"] llamaindex = ["llama-index-core"] # `>=0.4` is a FLOOR for the same reason as google-adk below, but the failure it prevents is # nastier: declared unbounded, the nine-extra solve on 2026-08-24 backtracked from 0.7.5 all the # way down and settled on `autogen-core-0.0.2` -- a placeholder release that satisfies the NAME # and ships no `autogen_core` module. pip printed "Successfully installed", exit 0, and the only # thing that noticed was ci.yml's `import autogen_core` line. A resolver that can reach a stub # will reach it, so a floor here turns a silent no-op install into a loud resolution error. autogen = ["autogen-agentchat>=0.4", "autogen-core>=0.4"] # `>=2` is a FLOOR, not a cap, and it is measured: integrations/google_adk.py's register() imports # google.adk.cli.service_registry, which exists in 2.5.0 and does NOT in 1.14.1. Declared unbounded, the # mcp<2 cap changed pip's search order enough that a nine-extra install resolved to 1.14.1 and the # integration was untestable. Stating the floor fixes every install site at once -- CI and users alike -- # instead of patching each pip line, which is how the release workflow kept a copy of the bug after ci.yml # was fixed. google-adk = ["google-adk>=2"] openai-agents = ["openai-agents"] pydantic-ai = ["pydantic-ai"] crewai = ["crewai"] # `haystack-ai` had NO extra at all, though the adapter, its parity script (haystack_audit.py) and two # test modules have shipped for months: `pip install "inspeximus[haystack]"` failed, and CI installed the # package by hand in one job so nothing surfaced it. A documented adapter with no supported install path # is a broken adapter for anyone who did not read the CI file. # `>=2` is a FLOOR and it is the API GENERATION the adapter targets: the 2.x reorganisation is where # `haystack.document_stores.types.DocumentStore` / `DuplicatePolicy` live, and 1.x has neither. No upper # bound -- haystack-ai 3.0.0 is what the conformance round trip is verified against # (docs/integration_conformance.json) and it passes, so there is no observed breakage to cap on. The # version named here is HAYSTACK'S, not ours. It once matched this package's own version exactly, a # release bump rewrote it as though it were a carrier of ours, and the warning added afterwards was # rewritten by the NEXT bump because the warning itself spelled out the numbers. So this paragraph # now contains no dotted version at all: a search-and-replace has nothing here to catch. haystack = ["haystack-ai>=2"] [project.scripts] inspeximus = "inspeximus.cli:main" inspeximus-mcp = "inspeximus.mcp_server:main" # Hermes Agent discovers a memory provider from this entry-point group, so `pip install inspeximus` # is the whole install and no file is copied under $HERMES_HOME. The bundled provider directory in # that project is closed to new entries; this route is not, and needs nobody's permission. # # THE NAME ON THE LEFT IS WHAT A USER PUTS IN `memory.provider`. Hermes activates a provider by name, # so it must equal `hermes_agent.PROVIDER_NAME`; a mismatch is a provider that can be discovered and # never selected, and `tests/test_the_hermes_provider_answers_its_own_contract.py` pins the pair. [project.entry-points."hermes_agent.memory_providers"] inspeximus = "inspeximus.integrations.hermes_agent:register" [tool.setuptools] packages = ["inspeximus", "inspeximus.integrations"]