Skip to main content

Official Python SDK for MME (Modular Memory Engine) — tag-graph memory for LLMs, built by Rail Tech.

Project description

railtech-mme

PyPI version CI Python License

Python SDK for MME — the Modular Memory Engine by Rail Tech.

Tag-graph memory for LLMs. Bounded retrieval. Hard token budgets. Learns from use. No vector DB.

pip install railtech-mme

Requires Python 3.9+.

Quick start

from railtech_mme import MME

mme = MME(api_key="mme_live_...")          # get one at https://mme.railtech.io

# Save a few facts — MME tags them automatically
mme.save("I prefer dark chocolate over milk chocolate.")
mme.save("I'm allergic to peanuts.")
mme.save("My favorite cuisine is Thai.")

# Recall them later — tag-graph activation matches keywords in the prompt
pack = mme.inject("What are my food preferences and allergies?", token_budget=1024)

for item in pack.items:
    print(f"- {item.title}: {item.excerpt}")

mme.feedback(pack_id=pack.pack_id, accepted=True)

That's the whole loop: save facts as they happen, inject them at prompt time, feedback to improve future packs.

Tip on prompt phrasing. MME's retrieval is tag-graph-based, not embedding-based: the prompt's keywords seed propagation across the tag graph. Prompts that share concrete words with your saved facts (food, chocolate, allergies) retrieve reliably even on a brand-new account; abstract paraphrases (dietary preferences) only start working after the graph has built up enough edges to bridge the gap. This is by design — it's why MME stays explainable and bounded.

Async

import asyncio
from railtech_mme import AsyncMME

async def main():
    async with AsyncMME(api_key="mme_live_...") as mme:
        await mme.save("hello")
        pack = await mme.inject("hello")
        print(pack.items[0].excerpt)

asyncio.run(main())

AsyncMME is a 1:1 mirror of MME. Same methods, same exceptions, same return types.

LangChain

pip install "railtech-mme[langchain]"
from railtech_mme import MME
from railtech_mme.langchain import MMESaveTool, MMEInjectTool

mme = MME(api_key="mme_live_...")
tools = [MMESaveTool(mme=mme), MMEInjectTool(mme=mme)]
# hand `tools` to your agent — see examples/langchain_agent.py for a runnable demo

The tools are LangChain BaseTool subclasses, so they drop into any agent that accepts tools (LangChain, LangGraph, AutoGen wrappers, etc.).

API surface

Method What it does
mme.save(content, *, tags=None, section=None, status=None, source=None) Persist a memory block. Returns SaveResult.
mme.inject(prompt, *, token_budget=2048, limit=None, filters=None, debug=False) Retrieve a token-budgeted Pack.
mme.feedback(*, pack_id, accepted, item_ids=None, tags=None) Mark a pack as useful or not — trains the edge graph.
mme.recent(*, limit=20, section=None) List the most recent memories as raw MemoryBlock objects (full content and structured tags).
mme.delete(memory_id) Remove a memory.
mme.tags() List all tags known for the org.

AsyncMME exposes the same surface with async def / await.

Filters

Narrow a retrieval to a section, a status, or a time window:

import datetime as dt
from railtech_mme import MME, InjectFilters

mme = MME()
pack = mme.inject(
    "what shipped this sprint?",
    filters=InjectFilters(
        section="work",
        since=dt.datetime(2026, 4, 1, tzinfo=dt.timezone.utc),
    ),
)

Auth

Get your mme_live_... API key at https://mme.railtech.io → API Key.

The SDK reads it from the RAILTECH_API_KEY environment variable if you don't pass it explicitly:

export RAILTECH_API_KEY=mme_live_...
from railtech_mme import MME
mme = MME()  # reads from env

The SDK exchanges your API key for a short-lived JWT on first use and caches it for the life of the client. Token refresh is automatic on 401.

Errors

All SDK errors inherit from MMEError:

import time
from railtech_mme import MME, MMEError, MMEAuthError, MMERateLimitError

mme = MME()
try:
    mme.save("...")
except MMERateLimitError as e:
    time.sleep(e.retry_after or 60)
except MMEAuthError:
    # API key is invalid or revoked — get a new one
    raise
except MMEError as e:
    print(e.status_code, e.response_body)

The full taxonomy: MMEErrorMMEAuthError, MMEClientError, MMERateLimitError, MMEServerError, MMETimeoutError, MMEBudgetExceeded.

Architecture — what MME does differently

MME does not use vector embeddings. It uses a bounded tag-graph that learns from pack accept/reject events. Retrieval is:

  1. Extract seed tags from the prompt
  2. Spread activation across the tag graph (bounded depth, beam width, decay)
  3. Score memories (activation + recency + importance + status − diversity penalty)
  4. Pack into a hard token budget greedily

Every pack respects the budget exactly. Every retrieval is explainable — seed tags, bounds, and activation paths come back in the response. Read the whitepaper for the full picture.

Examples

Runnable scripts in examples/:

Each one reads RAILTECH_API_KEY from the environment.

Links

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

railtech_mme-0.1.1.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

railtech_mme-0.1.1-py3-none-any.whl (25.1 kB view details)

Uploaded Python 3

File details

Details for the file railtech_mme-0.1.1.tar.gz.

File metadata

  • Download URL: railtech_mme-0.1.1.tar.gz
  • Upload date:
  • Size: 27.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for railtech_mme-0.1.1.tar.gz
Algorithm Hash digest
SHA256 50412da415a0eec0545294b583ea7c291ef18e38e56b85eac98d5b82b33c7400
MD5 6ba174a1e68cdd883b9b61a0e57f2785
BLAKE2b-256 0a86a2603c8c1a931e6ec98164ec0631ff6d3ba4621a7cf05bafa75c5b120262

See more details on using hashes here.

Provenance

The following attestation bundles were made for railtech_mme-0.1.1.tar.gz:

Publisher: publish.yml on gokulJinu01/railtech-mme-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file railtech_mme-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: railtech_mme-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 25.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for railtech_mme-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 15bbf613c0f8c61956713f54229aca80a0bce543700ae1b321def8018044432a
MD5 d072977aa9c23282153c235ab3e25a6f
BLAKE2b-256 c6cb99d391abc51bbe4d8fc84e96ea66a6178943ebdc1a95c4abfc136ab9e50e

See more details on using hashes here.

Provenance

The following attestation bundles were made for railtech_mme-0.1.1-py3-none-any.whl:

Publisher: publish.yml on gokulJinu01/railtech-mme-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page