Skip to main content
Glama
tihon-veliar

agent-memory

by tihon-veliar

agent-memory

Standalone memory microservice for agent memory management. Converts completed agent sessions into long-term memory and exposes retrieval through an MCP tool interface.

All runnable code must remain inside sandbox/agent-memory/.

Requirements

  • Python 3.12+

  • Qdrant (local Docker container)

  • Ollama (local, with models pulled)

  • Docker (for Qdrant)

Quick Install

pip install -e ".[dev]"

Copy and configure the environment file:

copy .env.example .env

Dependencies At A Glance

Dependency

Default Port

Purpose

Qdrant

7333

Vector database (via Docker)

Ollama

11434

LLM extraction + embedding

Service

8000

agent_memory_service FastAPI

MCP Server

stdio

agent_memory_mcp (no TCP port)

Sleep CLI

n/a

One-shot operator tool

Architecture Boundaries

The system has four separate package roots with clear ownership:

Package

Entrypoint

Responsibility

agent_memory_service

python -m agent_memory_service

HTTP API, persistence, retrieval

agent_memory_mcp

python -m agent_memory_mcp

MCP tool server (long-lived)

agent_memory_sleep

python -m agent_memory_sleep

Interactive operator CLI (one-shot)

Config layer

src/agent_memory_service/

Typed YAML loading, shared by all

Hard boundary rule: neither agent_memory_mcp nor agent_memory_sleep talk to Qdrant or Mem0 directly. All memory operations go through agent_memory_service HTTP endpoints.


Startup Order

Start the stack in this exact order. Each step depends on the previous one.

1. Start Qdrant (Docker)

docker run --name agent-memory-qdrant -p 7333:6333 -p 7334:6334 -d qdrant/qdrant

Verify:

curl http://localhost:7333/

Windows note: host port 6333 is reserved (TCP range 6315-6414), so config/memory.yaml maps host 7333 to container 6333.

If the container already exists but is stopped:

docker start agent-memory-qdrant

2. Verify Ollama models

ollama list

Required models (pull if missing):

ollama pull qwen2.5:3b
ollama pull qwen2.5:7b
ollama pull nomic-embed-text

3. Start agent_memory_service

python -m agent_memory_service

Verify:

curl http://localhost:8000/health
curl http://localhost:8000/up-status

/up-status reports component-by-component status for config loading, Qdrant, Mem0 OSS, and the provider layer. All four must be ok before proceeding.

4. Start agent_memory_mcp (separate terminal)

set AGENT_MEMORY_AGENT_ID=default
python -m agent_memory_mcp

The MCP server communicates over stdio. It refuses to start if the service is unreachable at http://localhost:8000/health.

5. Run agent_memory_sleep (operator-initiated, one-shot)

python -m agent_memory_sleep

Follow the interactive prompts to:

  • Select source runtime (opencode / codex)

  • Enter agent ID and session export path

  • Choose dream source (inline / profile / file)

  • Select mode (dry_run to preview, commit to persist)

The sleep tool is one-shot — it exits after processing one session.


Configuration

Format: YAML (frozen baseline — do not substitute JSON or TOML).

Config directory: config/

Frozen config filenames:

File

Purpose

config/agents.yaml

Agent identity and behaviour

config/providers.yaml

Model provider and runtime wiring

config/memory.yaml

Memory store and persistence

Typed loading lives under src/agent_memory_service/. All config is validated at service startup — malformed files prevent boot.

Environment overrides:

Variable

Config Field

Default

AGENT_MEMORY_CONFIG_DIR

Config directory path

./config

AGENT_MEMORY_AGENT_ID

Agent ID for MCP server

default (fallback)

AGENT_MEMORY_SERVICE_URL

Service URL for MCP server

http://localhost:8000


agents_hub Integration

agents_hub consumes agent_memory_mcp as an MCP server over stdio — it never calls the service endpoints or Qdrant directly.

MCP Client Configuration

Add agent_memory_mcp to your MCP client's server list as a stdio transport:

{
  "mcpServers": {
    "agent_memory": {
      "command": "python",
      "args": ["-m", "agent_memory_mcp"],
      "env": {
        "AGENT_MEMORY_AGENT_ID": "default",
        "AGENT_MEMORY_CONFIG_DIR": "./sandbox/agent-memory/config"
      }
    }
  }
}

The MCP server exposes exactly one tool:

Tool

Arguments

Returns

memory_search

query (required)

Formatted memory results with scores

limit (optional)

scoped to the configured agent only

Blocked arguments: agent_id, user_id, user, provider — the MCP server rejects these immediately. Agent identity is resolved from host context, not from tool arguments.

Integration contract:

  • agents_hub must not use POST /retrieve or POST /process directly

  • agents_hub must not connect to Qdrant or Mem0

  • agents_hub must not set agent_id in memory_search arguments

  • The MCP server is the only retrieval surface exposed to external clients


Sleep Operator Guide

agent_memory_sleep is an interactive one-shot CLI that processes a completed agent session into long-term memory.

Step-by-step walkthrough

  1. Select runtime — choose opencode or codex as session source

  2. Enter agent ID — defaults to "default", must match config/agents.yaml

  3. Provide session path — absolute or relative path to the session export file

  4. Choose dream source:

    • inline — paste a JSON dream rule directly

    • profile — select a named profile from config/dream_profiles.yaml

    • file — provide an absolute path to a YAML/JSON dream file

  5. Select mode:

    • dry_run — extract and validate candidates without persistence

    • commit — persist memory records through Mem0 / Qdrant

Example session

$ python -m agent_memory_sleep

? Select source runtime: opencode
? Agent ID: default
? Path to opencode session export: tests/fixtures/opencode/session_sanitized.json
? Dream source: profile
? Dream profile name: default
? Mode: dry_run

╭────────────────────────────────────────╮
│ Session: ses_124a1da54ffeQ2cp0LkbaiADWt │
│ Agent: default                         │
│ Source: opencode                       │
│ Messages: 6                            │
╰────────────────────────────────────────╯

Calling http://127.0.0.1:8000/process (mode=dry_run)...

      Memory Record Candidates
┌───┬──────────────┬────────────┬──────────┐
│ # │ Content      │ Kind       │ Evidence │
├───┼──────────────┼────────────┼──────────┤
│ 1 │ ...          │ preference │ ...      │
│ 2 │ ...          │ pattern    │ ...      │
└───┴──────────────┴────────────┴──────────┘
3 candidate(s)
Extraction: qwen2.5:3b | Embedding: nomic-embed-text

Error handling

  • Session load errors: malformed exports, missing IDs, unresolved agents

  • Dream input errors: invalid JSON/YAML, missing required sections

  • Connection errors: service unreachable at http://127.0.0.1:8000

  • Service errors: extraction/embedding failures returned with error metadata


Service Endpoints

Method

Path

Purpose

GET

/health

Coarse health check (ok / error)

GET

/up-status

Component-by-component dependency status

POST

/process

Ingest a session (dry_run or commit)

POST

/retrieve

Search memory for an agent (internal use)

/process request body:

{
  "session": { "... normalized session ..." },
  "dream_rule": { "... dream rule ..." },
  "mode": "dry_run"
}

/retrieve request body:

{
  "agent_id": "default",
  "query": "user preferences",
  "limit": 5
}

Processed-Session Registry

Storage: local SQLite

Ownership: agent_memory_service — the registry is not accessed directly by agent_memory_mcp or agent_memory_sleep; those packages must go through the service boundary.

Path source: config/memory.yamlregistry.path (default: data/processed_sessions.db, relative to the service working directory unless absolute).

Frozen module: src/agent_memory_service/registry.py

Frozen contract fields:

Field

Type

Purpose

session_id

str

Unique session identifier

agent_id

str

Canonical agent identity

status

str

Processing outcome

processed_at

datetime

Timestamp of processing completion

The registry enforces idempotency: committing the same session_id twice returns the existing entry without creating duplicate memory records.


Diagnostics

Common operator failure states and how to resolve them.

Qdrant unavailable

Symptom: /up-status reports qdrant: unavailable

docker ps --filter name=agent-memory-qdrant
curl http://localhost:7333/

Fix: start the Qdrant container — see Startup Order step 1.

Service unreachable

Symptom: MCP server exits with agent_memory_service unreachable, or sleep CLI reports connection errors.

curl http://localhost:8000/health

Fix: start the service — see Startup Order step 3.

Ollama models missing

Symptom: /up-status reports provider_layer: ok but /process fails with provider execution errors mentioning the model name.

ollama list

Fix: pull missing models — see Startup Order step 2.

Ollama embeddings not supported (HTTP 501)

Symptom: /process fails with This server does not support embeddings.

curl http://localhost:11434/api/embed -d '{"model":"nomic-embed-text","input":"test"}'

Fix: ensure Ollama is running (ollama serve) and the model is pulled.

Port conflicts (Windows)

Symptom: Docker cannot bind host port 6333.

Reason: Windows reserves TCP ports 6315-6414.

Fix: already configured — config/memory.yaml uses host port 7333.

Duplicate session commit

Symptom: committing the same session twice reports status: completed but record_count: 0 on the second commit.

Expected behaviour: the registry returns the existing entry without creating duplicate memory records. This is idempotency, not a bug.

Memory not retrievable after commit

Symptom: sleep CLI reports status: completed with record_count > 0, but /retrieve returns empty results.

Check:

curl -X POST http://localhost:8000/retrieve -H "Content-Type: application/json" -d "{\"agent_id\":\"default\",\"query\":\"test\",\"limit\":10}"

Fix: verify Qdrant collection exists and has the correct dimensions:

curl http://localhost:7333/collections
curl http://localhost:7333/collections/agent_memory

Check that embedding_dims: 768 in config/memory.yaml matches the model (nomic-embed-text produces 768-dimension vectors). Confirm the correct agent_id is used in retrieval — memories are scoped per agent.

SQLite registry failure

Symptom: /process commit mode fails with registry-related errors.

Check:

dir data\processed_sessions.db

Fix: ensure the data/ directory exists relative to the service working directory, and the service process has write permissions. If the database is locked, stop any other process accessing it and delete the file to recreate on next boot.

Config loading failure

Symptom: service exits at startup with config errors.

python -c "from agent_memory_service.config import load_memory_config; print(load_memory_config().model_dump())"

Fix: check config/memory.yaml, config/providers.yaml, and config/agents.yaml for valid YAML syntax and required fields.


End-to-End Verification

Run this sequence after starting the full stack to verify the operating model end to end.

Automated verification (integration tests)

Requires Qdrant, Ollama, and service already running:

python -m pytest tests/test_end_to_end.py -v -m integration

These tests verify:

  1. Service /health returns ok

  2. /up-status reports Qdrant, Mem0, and provider layer as ok

  3. POST /process (commit) persists memory records

  4. POST /retrieve returns the persisted memory

  5. Idempotency — duplicate commit returns the existing entry

Manual verification script

  1. Verify Qdrant:

curl http://localhost:7333/
  1. Verify service health:

curl http://localhost:8000/health
curl http://localhost:8000/up-status

Expected: all four components (config_loading, qdrant, mem0_oss, provider_layer) report "status": "ok".

  1. Process a session via sleep CLI (commit mode):

python -m agent_memory_sleep

Select:

  • Source: opencode

  • Agent: default

  • Session path: tests/fixtures/opencode/session_sanitized.json

  • Dream: profiledefault

  • Mode: commit

Expected: Status: completed with record count > 0.

  1. Verify retrieval through the service endpoint (service-level smoke check):

curl -X POST http://localhost:8000/retrieve ^
  -H "Content-Type: application/json" ^
  -d "{\"agent_id\":\"default\",\"query\":\"user preferences and actions\",\"limit\":5}"

Expected: results array contains at least one memory with content from the processed session.

  1. Verify retrieval through the MCP server (MCP-client boundary):

First, start the MCP server in one terminal:

set AGENT_MEMORY_AGENT_ID=default
python -m agent_memory_mcp

Then call memory_search through an MCP client. Example verification script (run from another terminal):

python -c "import asyncio, sys, os; from mcp import ClientSession; from mcp.client.stdio import StdioServerParameters, stdio_client; async def main(): server_params = StdioServerParameters(command=sys.executable, args=['-m', 'agent_memory_mcp'], env={**os.environ, 'AGENT_MEMORY_AGENT_ID': 'default'}); async with stdio_client(server_params) as (r, w): async with ClientSession(r, w) as session: await session.initialize(); result = await session.call_tool('memory_search', {'query': 'user preferences', 'limit': 5}); print('\\n'.join(c.text for c in result.content if hasattr(c, 'text'))); asyncio.run(main())"

Expected: formatted memory results including content from the processed session, scoped to the configured agent.

  1. Verify idempotency — re-run the sleep CLI with the same session:

python -m agent_memory_sleep

(Same selections as step 3)

Expected: Status: completed with record_count: 0 — the existing registry entry is returned without creating duplicates.

Quick smoke checks

python -m pytest tests/ -q
python -c "import agent_memory_service, agent_memory_mcp, agent_memory_sleep; print('imports: ok')"

Test

Run all automated tests (integration tests are skipped when services aren't running):

python -m pytest

Run specific test files:

python -m pytest tests/test_end_to_end.py -v

Run with real services (Qdrant + service + Ollama must be running):

python -m pytest tests/test_end_to_end.py -v -m integration

Markers overview:

Marker

Purpose

integration

Requires live Qdrant, service, and Ollama


Local Defaults

Component

Default Value

Config File

Extraction model

qwen2.5:3b

providers.yaml

Fallback model

qwen2.5:7b

providers.yaml

Embedding model

nomic-embed-text

providers.yaml

Embedding dims

768

memory.yaml

Qdrant port

7333

memory.yaml

Ollama URL

http://localhost:11434

memory.yaml, providers.yaml

Service port

8000

(uvicorn default)

Registry path

data/processed_sessions.db

memory.yaml

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tihon-veliar/agent-memory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server