AML Memory MVP

August 6, 2026 · View on GitHub

A reproducible, evidence-only memory system for the Textual Memory / Academic Methods track of the 2026 Agent Memory Challenge. Version 0.3 adds typo-tolerant semantic retrieval, conversation-neighbor expansion, verbatim evidence windows, and bounded output while keeping the deployment surface intentionally small.

The service implements the current synchronous Add and Search contract. It stores every source message with strict user_id isolation, indexes English and CJK text with SQLite FTS5 plus character n-grams, and returns ranked source evidence. It deliberately does not generate final answers.

Design goals

  • Contract correctness before leaderboard optimization.
  • Original source evidence in every Search result.
  • Exact user_id isolation with no cross-sample state.
  • Idempotent Add requests.
  • Reproducible Docker deployment with no external database.
  • Optional, auditable gpt-4o-mini indexing cues for the current Full-run rule.

Architecture

Add messages
    ├─ optional per-message gpt-4o-mini index cues (no answer generation)
    ├─ deterministic English/CJK lexical features
    └─ SQLite records + FTS5 index, partitioned by user_id

Search query
    ├─ optional gpt-4o-mini facets, query expansion, and time intent
    ├─ Porter FTS5 BM25 with English typo fragments and CJK n-grams
    ├─ generic concept and adjacent-turn candidate expansion
    ├─ informative-term, option, date/number, and correction scoring
    ├─ incremental MMR for complementary multi-hop evidence
    └─ top_k timestamped, bounded, verbatim conversation windows

API

The evaluator may configure either the short paths or aliases:

  • GET /health
  • POST /add or POST /v1/memory/add
  • POST /search or POST /v1/memory/search

Add

{
  "request_id": "eval:run:dataset:sample:chunk-0",
  "messages": [
    {
      "role": "user",
      "timestamp": 1704067200000,
      "content": "memory text"
    }
  ],
  "user_id": "eval:run:dataset:sample",
  "session_id": "eval:run:session:0"
}

The response is sent only after every message is persisted and immediately searchable:

{
  "success": true,
  "request_id": "eval:run:dataset:sample:chunk-0",
  "user_id": "eval:run:dataset:sample",
  "session_id": "eval:run:session:0"
}
{
  "query": "Which answer best matches the memory?",
  "options": ["A. First", "B. Second"],
  "user_id": "eval:run:dataset:sample",
  "top_k": 100
}
{
  "data": [
    {
      "id": "mem_...",
      "content": "[user | 2026-07-01T12:00:00Z] original source evidence",
      "score": 0.91,
      "created_at": "2026-07-01T12:00:00Z"
    }
  ]
}

Run with Docker

Local deterministic mode, with no model credential:

docker build -t aml-memory-mvp:0.3.0 .
docker run --rm -p 8000:8000 \
  -e AML_LLM_MODE=off \
  -v aml-memory-data:/data \
  aml-memory-mvp:0.3.0

Resilient formal-evaluation mode. It uses gpt-4o-mini when a runtime credential is injected and otherwise falls back to the deterministic retriever:

docker run --rm -p 8000:8000 \
  -e AML_LLM_MODE=best_effort \
  -e OPENAI_MODEL=gpt-4o-mini \
  -e OPENAI_API_KEY \
  -v aml-memory-data:/data \
  aml-memory-mvp:0.3.0

Do not put credentials in the image, repository, URL, screenshots, or logs.

Run without Docker

Python 3.10 or later is required.

python -m venv .venv
. .venv/bin/activate
pip install -r requirements-dev.txt
AML_LLM_MODE=off uvicorn app.main:app --host 0.0.0.0 --port 8000

In another terminal:

python scripts/smoke.py
pytest

Configuration

VariableDefaultPurpose
AML_DATABASE_PATHdata/memory.dbSQLite database path
AML_LLM_MODEoffoff, best_effort, or required
AML_API_KEYemptyOptional Add/Search authentication
OPENAI_API_KEYemptyRuntime-only model credential
OPENAI_MODELgpt-4o-miniModel locked for current Full rule
OPENAI_BASE_URLOpenAI v1Compatible API base URL
AML_CANDIDATE_LIMIT400Retrieval candidates before reranking
AML_MAX_OUTPUT_CHARS240000Evidence-output safety budget for the shared Answer context

The model path makes at most one bounded JSON call per Add request and one per Search request. Search analysis is capped at 256 output tokens; Add indexing is capped dynamically between 256 and 1024 tokens according to batch size. For the challenge run, use a dedicated OpenAI API project with a monthly budget no higher than USD 50. The application does not embed credentials or silently switch to another model.

When AML_API_KEY is set, both Authorization: Bearer, Authorization: Token, and X-Api-Key are accepted. /health stays public.

Reproducibility

GitHub Actions runs unit tests and a Docker-level Add/Search smoke test on every push. The system uses a single worker by default because SQLite coordinates all concurrent requests through WAL and a 60-second busy timeout. The evaluator may still call the service concurrently.

Optional retrieval-only development checks can be run against separately downloaded public datasets. They use evidence/session annotations only, never answer labels, and the datasets are not packaged with the service:

python scripts/eval_locomo_retrieval.py /path/to/locomo10.json
python scripts/eval_longmemeval_retrieval.py /path/to/longmemeval_s_cleaned.json --per-type 5

For a formal submission, bind the score to the public Git commit and the image tag 0.3.0. Do not change that version after a Full run is accepted.

Originality and disclosure

This submission is original glue and retrieval code created for the 2026 Agent Memory Challenge. It does not copy an existing memory-system repository or reproduce a paper implementation. It uses standard information-retrieval techniques:

  • SQLite FTS5 BM25 candidate retrieval;
  • deterministic Unicode normalization, Porter stemming, typo fragments, and CJK character n-grams;
  • general concept expansion and source-order-safe adjacent-turn retrieval;
  • informative-term coverage, exact date/number anchors, and option-aware scoring;
  • latest/earliest/sequence intent with correction-aware temporal governance;
  • incremental maximal-marginal-relevance selection for complementary multi-hop evidence;
  • bounded verbatim conversation windows with stable source identifiers;
  • optional per-message indexing cues and query facets that are never returned as answers.

See DISCLOSURE.md for the complete statement and SUBMISSION.md for the prepared submission material.

Data handling

Evaluation memories are stored only in the configured SQLite database. Delete the database or Docker volume within 30 days after the run, unless the organizer gives written permission to retain it longer.

License

MIT