```
├── .github/
├── ISSUE_TEMPLATE/
├── bug_report.yml (400 tokens)
├── config.yml (100 tokens)
├── feature_request.yml (300 tokens)
├── hackathon_task.yml (400 tokens)
├── improvement_suggestion.yml (400 tokens)
├── PULL_REQUEST_TEMPLATE.md (200 tokens)
├── workflows/
├── build.yml (200 tokens)
├── pr-title.yml (200 tokens)
├── release-please.yml (900 tokens)
├── .gitignore (700 tokens)
├── .pre-commit-config.yaml (100 tokens)
├── .python-version
├── AGENTS.md (700 tokens)
├── CHANGELOG.md (4.1k tokens)
├── CONTRIBUTING.md (1400 tokens)
├── Cargo.lock (omitted)
├── Cargo.toml (100 tokens)
├── LICENSE.txt (2.2k tokens)
├── MANIFEST.in (100 tokens)
├── Makefile (100 tokens)
├── README.md (5k tokens)
├── assets/
├── banner.png
├── benchmark.png
├── memUbot.png
├── memorize.png
├── partners/
├── Clawdchat.png
├── LazyLLM.png
├── buddie.png
├── bytebase.png
├── jazz.png
├── openagents.png
├── xroute.png
├── qrcode.png
├── retrieve.png
├── star.gif
├── structure.png
├── usecase/
├── ai_companion-0000.jpg
├── ai_creation-0000.jpg
├── ai_edu-0000.jpg
├── ai_ip-0000.png
├── ai_robot-0000.jpg
├── ai_role_play-0000.jpg
├── ai_therapy-0000.jpg
├── docs/
├── HACKATHON_ISSUE_DRAFT.md (600 tokens)
├── HACKATHON_MAD_COMBOS.md (4.5k tokens)
├── adr/
├── 0001-workflow-pipeline-architecture.md (300 tokens)
├── 0002-pluggable-storage-and-vector-strategy.md (300 tokens)
├── 0003-user-scope-in-data-model.md (200 tokens)
├── README.md (100 tokens)
├── architecture.md (1300 tokens)
├── integrations/
├── grok.md (200 tokens)
├── langgraph_integration.md (700 tokens)
├── providers/
├── grok.md (400 tokens)
├── sealos-devbox-guide.md (2.4k tokens)
├── sealos_use_case.md (400 tokens)
├── sqlite.md (1300 tokens)
├── tutorials/
├── getting_started.md (1400 tokens)
├── examples/
├── example_1_conversation_memory.py (700 tokens)
├── example_2_skill_extraction.py (1800 tokens)
├── example_3_multimodal_memory.py (900 tokens)
├── example_4_openrouter_memory.py (700 tokens)
├── example_5_with_lazyllm_client.py (1600 tokens)
├── getting_started_robust.py (800 tokens)
├── langgraph_demo.py (500 tokens)
├── output/
├── conversation_example/
├── activities.md (100 tokens)
├── experiences.md (100 tokens)
├── goals.md (200 tokens)
├── habits.md (100 tokens)
├── knowledge.md (500 tokens)
├── opinions.md
├── personal_info.md
├── preferences.md (100 tokens)
├── relationships.md
├── work_life.md (200 tokens)
├── proactive/
├── memory/
├── config.py (700 tokens)
├── local/
├── __init__.py
├── common.py (200 tokens)
├── memorize.py (300 tokens)
├── tools.py (300 tokens)
├── platform/
├── __init__.py
├── memorize.py (200 tokens)
├── tools.py (400 tokens)
├── proactive.py (1200 tokens)
├── resources/
├── conversations/
├── conv1.json (600 tokens)
├── conv2.json (800 tokens)
├── conv3.json (800 tokens)
├── docs/
├── doc1.txt (1900 tokens)
├── doc2.txt (2.5k tokens)
├── images/
├── image1.png
├── logs/
├── log1.txt (1700 tokens)
├── log2.txt (1900 tokens)
├── log3.txt (2.9k tokens)
├── sealos-assistant/
├── README.md (300 tokens)
├── entrypoint.sh (100 tokens)
├── main.py (1700 tokens)
├── requirements.txt
├── sealos_support_agent.py (500 tokens)
├── test_nebius_provider.py (1500 tokens)
├── pyproject.toml (800 tokens)
├── readme/
├── README_en.md (5k tokens)
├── README_es.md (5.4k tokens)
├── README_fr.md (5.4k tokens)
├── README_ja.md (3.9k tokens)
├── README_ko.md (3.8k tokens)
├── README_zh.md (3.5k tokens)
├── setup.cfg (100 tokens)
├── src/
├── lib.rs (100 tokens)
├── memu/
├── __init__.py
├── _core.pyi
├── app/
├── __init__.py (100 tokens)
├── crud.py (5.5k tokens)
├── memorize.py (10.9k tokens)
├── patch.py (3.6k tokens)
├── retrieve.py (11.6k tokens)
├── service.py (3.5k tokens)
├── settings.py (2.7k tokens)
├── blob/
├── __init__.py
├── local_fs.py (600 tokens)
├── client/
├── __init__.py (200 tokens)
├── openai_wrapper.py (1700 tokens)
├── database/
├── __init__.py (100 tokens)
├── factory.py (300 tokens)
├── inmemory/
├── __init__.py (200 tokens)
├── models.py (300 tokens)
├── repo.py (500 tokens)
├── repositories/
├── __init__.py (100 tokens)
├── category_item_repo.py (400 tokens)
├── filter.py (200 tokens)
├── memory_category_repo.py (600 tokens)
├── memory_item_repo.py (1900 tokens)
├── resource_repo.py (400 tokens)
├── state.py
├── vector.py (1000 tokens)
├── interfaces.py (200 tokens)
├── models.py (1100 tokens)
├── postgres/
├── __init__.py (200 tokens)
├── migration.py (700 tokens)
├── migrations/
├── __init__.py
├── env.py (300 tokens)
├── models.py (1300 tokens)
├── postgres.py (900 tokens)
├── repositories/
├── __init__.py (100 tokens)
├── base.py (700 tokens)
├── category_item_repo.py (700 tokens)
├── memory_category_repo.py (1200 tokens)
├── memory_item_repo.py (2.9k tokens)
├── resource_repo.py (700 tokens)
├── schema.py (500 tokens)
├── session.py (200 tokens)
├── repositories/
├── __init__.py (100 tokens)
├── category_item.py (100 tokens)
├── memory_category.py (200 tokens)
├── memory_item.py (300 tokens)
├── resource.py (200 tokens)
├── sqlite/
├── __init__.py (200 tokens)
├── models.py (1700 tokens)
├── repositories/
├── __init__.py (100 tokens)
├── base.py (900 tokens)
├── category_item_repo.py (1200 tokens)
├── memory_category_repo.py (1800 tokens)
├── memory_item_repo.py (3.8k tokens)
├── resource_repo.py (1200 tokens)
├── schema.py (600 tokens)
├── session.py (300 tokens)
├── sqlite.py (1200 tokens)
├── state.py (100 tokens)
├── embedding/
├── __init__.py
├── backends/
├── __init__.py (100 tokens)
├── base.py (100 tokens)
├── doubao.py (500 tokens)
├── openai.py (100 tokens)
├── http_client.py (1100 tokens)
├── openai_sdk.py (300 tokens)
├── integrations/
├── __init__.py
├── langgraph.py (1300 tokens)
├── llm/
├── backends/
├── __init__.py (100 tokens)
├── base.py (200 tokens)
├── doubao.py (400 tokens)
├── grok.py (100 tokens)
├── openai.py (400 tokens)
├── openrouter.py (500 tokens)
├── http_client.py (2.3k tokens)
├── lazyllm_client.py (1200 tokens)
├── openai_sdk.py (1600 tokens)
├── wrapper.py (5.1k tokens)
├── prompts/
├── __init__.py (100 tokens)
├── category_patch/
├── __init__.py
├── category.py (200 tokens)
├── category_summary/
├── __init__.py (100 tokens)
├── category.py (2000 tokens)
├── category_with_refs.py (900 tokens)
├── memory_type/
├── __init__.py (300 tokens)
├── behavior.py (1600 tokens)
├── event.py (1600 tokens)
├── knowledge.py (1400 tokens)
├── profile.py (1900 tokens)
├── skill.py (4.3k tokens)
├── tool.py (900 tokens)
├── preprocess/
├── __init__.py (100 tokens)
├── audio.py (200 tokens)
├── conversation.py (300 tokens)
├── document.py (200 tokens)
├── image.py (200 tokens)
├── video.py (300 tokens)
├── retrieve/
├── __init__.py
├── judger.py (200 tokens)
├── llm_category_ranker.py (200 tokens)
├── llm_item_ranker.py (300 tokens)
├── llm_resource_ranker.py (200 tokens)
├── pre_retrieval_decision.py (300 tokens)
├── query_rewriter.py (300 tokens)
├── query_rewriter_judger.py (300 tokens)
├── utils/
├── __init__.py
├── conversation.py (600 tokens)
├── references.py (900 tokens)
├── tool.py (700 tokens)
├── video.py (2000 tokens)
├── workflow/
├── __init__.py (200 tokens)
├── interceptor.py (1400 tokens)
├── pipeline.py (1300 tokens)
├── runner.py (500 tokens)
├── step.py (700 tokens)
├── tests/
├── __init__.py
├── example/
├── example_conversation.json (3.9k tokens)
├── integrations/
├── test_langgraph.py (500 tokens)
├── llm/
├── test_grok_provider.py (400 tokens)
├── rust_entry_test.py
├── test_client_wrapper.py (900 tokens)
├── test_inmemory.py (700 tokens)
├── test_lazyllm.py (600 tokens)
├── test_openrouter.py (1100 tokens)
├── test_postgres.py (600 tokens)
├── test_postgres_migration_config.py (200 tokens)
├── test_references.py (1300 tokens)
├── test_salience.py (1500 tokens)
├── test_sqlite.py (600 tokens)
├── test_tool_memory.py (2.2k tokens)
├── utils/
├── test_conversation.py (800 tokens)
├── uv.lock (omitted)
```
## /.github/ISSUE_TEMPLATE/bug_report.yml
```yml path="/.github/ISSUE_TEMPLATE/bug_report.yml"
name: Bug Report
description: Report a bug or issue with memU
title: "[BUG] "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report a bug in memU! Please fill in the following details.
- type: textarea
id: description
attributes:
label: Description
description: A clear and detailed description of the bug.
placeholder: "Enter a clear and concise description of what the bug is."
validations:
required: true
- type: input
id: environment
attributes:
label: Environment
description: The environment where this bug occurred (e.g., operating system, CPU arch, etc.).
placeholder: "Enter details about the environment."
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: What are the steps to reproduce this issue?
placeholder: "Enter step-by-step instructions to reproduce the issue."
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: What should have happened instead?
placeholder: "Describe what you expected to happen."
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: What version of memU are you using?
placeholder: e.g., v1.0.0
validations:
required: true
- type: dropdown
id: severity
attributes:
label: Severity
description: How severe is the bug?
options:
- Critical
- Major
- Minor
validations:
required: true
- type: textarea
id: additional_info
attributes:
label: Additional Information
description: Any other context or screenshots related to the bug.
placeholder: "Enter additional context or information."
validations:
required: false
```
## /.github/ISSUE_TEMPLATE/config.yml
```yml path="/.github/ISSUE_TEMPLATE/config.yml"
blank_issues_enabled: false
contact_links:
- name: GitHub Discussions
url: https://github.com/NevaMind-AI/memU/discussions
about: For questions and general discussions about memU
- name: Documentation
url: https://github.com/NevaMind-AI/memU/blob/main/README.md
about: Check out the memU documentation
```
## /.github/ISSUE_TEMPLATE/feature_request.yml
```yml path="/.github/ISSUE_TEMPLATE/feature_request.yml"
name: Feature Request
description: Request a feature for memU
title: "[FEATURE] "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to request a feature for memU! Please fill in the following details.
- type: textarea
id: description
attributes:
label: Description
description: A clear and detailed description of the feature request.
placeholder: "Enter a clear and concise description of what the feature request is."
validations:
required: true
- type: textarea
id: motivation
attributes:
label: Motivation
description: Why do we need this feature? What problem does it solve?
placeholder: "Explain the use case and why this feature would be valuable."
validations:
required: true
- type: dropdown
id: platform
attributes:
label: Platform
description: Which platform(s) does this feature apply to?
options:
- Platform Independent
- Linux
- macOS
- Windows
validations:
required: true
- type: dropdown
id: priority
attributes:
label: Priority
description: How important is this feature?
options:
- Critical
- Major
- Minor
validations:
required: true
- type: textarea
id: additional_info
attributes:
label: Additional Information
description: Any other context or screenshots related to the feature request.
placeholder: "Enter additional context or information."
validations:
required: false
```
## /.github/ISSUE_TEMPLATE/hackathon_task.yml
```yml path="/.github/ISSUE_TEMPLATE/hackathon_task.yml"
name: Hackathon Task
description: The official designated task for the memU track in the 2026 New Year Challenge
title: "[2026NewYearChallenge] "
labels: ["hackathon-task"]
assignees: []
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to join the challenge, and best of luck!
- type: dropdown
id: label_hint
attributes:
label: Label
description: Pick the most appropriate label for this task.
options:
- hackathon-task
validations:
required: true
- type: input
id: assignees_hint
attributes:
label: Assignees
description: GitHub usernames to assign (comma-separated). If empty, maintainers will triage.
placeholder: "e.g., alice,bob"
validations:
required: false
- type: textarea
id: description
attributes:
label: Description*
description: What will this task implement?
placeholder: "Enter a clear and concise description of the task you want to implement."
validations:
required: true
- type: textarea
id: requirements
attributes:
label: Requirements (optional)
description: What will your planned pull request include? (APIs, modules, tests, docs, etc.)
placeholder: |
- [ ] Implementation details
- [ ] Tests
- [ ] Docs / examples
- [ ] Compatibility notes
validations:
required: false
- type: textarea
id: review_criteria
attributes:
label: Review Criteria (optional)
description: How will this task be evaluated?
placeholder: |
Example:
- Correctness (passes tests, no regressions)
- Quality (readability, modularity)
- DX (good docs / examples)
- Impact (useful for memU users)
validations:
required: false
```
## /.github/ISSUE_TEMPLATE/improvement_suggestion.yml
```yml path="/.github/ISSUE_TEMPLATE/improvement_suggestion.yml"
name: Improvement Suggestion
description: Suggest an improvement for memU
title: "[IMPROVEMENT] "
labels: ["enhancement", "improvement"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to suggest an improvement for memU! Please fill in the following details.
- type: textarea
id: description
attributes:
label: Description
description: A clear and detailed description of the improvement suggestion.
placeholder: "Enter a clear and concise description of what you'd like to improve."
validations:
required: true
- type: textarea
id: current_behavior
attributes:
label: Current Behavior
description: How does it work currently?
placeholder: "Describe the current behavior or implementation."
validations:
required: false
- type: textarea
id: proposed_improvement
attributes:
label: Proposed Improvement
description: How would you like it to work?
placeholder: "Describe your proposed improvement."
validations:
required: true
- type: textarea
id: benefits
attributes:
label: Benefits
description: What are the benefits of this improvement?
placeholder: "Explain why this improvement would be valuable."
validations:
required: false
- type: input
id: version
attributes:
label: Version
description: What version of memU are you using?
placeholder: e.g., v1.0.0
validations:
required: false
- type: textarea
id: additional_info
attributes:
label: Additional Information
description: Any other context or screenshots related to the improvement.
placeholder: "Enter additional context or information."
validations:
required: false
```
## /.github/PULL_REQUEST_TEMPLATE.md
## 📝 Pull Request Summary
Please provide a short summary explaining the purpose of this PR.
---
## ✅ What does this PR do?
- Clearly describe the change introduced.
- Mention the motivation or problem it solves.
---
## 🤔 Why is this change needed?
- Explain the context or user impact.
- Link any relevant issue or discussion.
---
## 🔍 Type of Change
Please check what applies:
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Refactor / cleanup
- [ ] Other (please explain)
---
## ✅ PR Quality Checklist
- [ ] PR title follows the conventional format (feat:, fix:, docs:)
- [ ] Changes are limited in scope and easy to review
- [ ] Documentation updated where applicable
- [ ] No breaking changes (or clearly documented)
- [ ] Related issues or discussions linked
---
## 📌 Optional
- [ ] Screenshots or examples added (if applicable)
- [ ] Edge cases considered
- [ ] Follow-up tasks mentioned
## /.github/workflows/build.yml
```yml path="/.github/workflows/build.yml"
name: build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
strategy:
matrix:
python-version: ["3.13"]
steps:
- uses: actions/checkout@v6
- name: Install uv & set Python
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
cache-python: true
- name: Ensure Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Sync dependencies
run: |
uv sync --frozen
uv run pre-commit install
- name: Run style checks
run: uv run make check
- name: Run tests
run: uv run make test
```
## /.github/workflows/pr-title.yml
```yml path="/.github/workflows/pr-title.yml"
name: pr-title
on:
pull_request_target:
types:
- opened
- edited
- reopened
- synchronize
permissions:
contents: read
statuses: write
jobs:
validate:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
build
chore
ci
docs
feat
fix
perf
refactor
revert
style
test
- name: Disallow trailing ellipsis
shell: bash
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
if [[ "$PR_TITLE" == *... ]]; then
echo "::error title=Invalid PR title::PR title must not end with an ellipsis (...)"
exit 1
fi
```
## /.github/workflows/release-please.yml
```yml path="/.github/workflows/release-please.yml"
on:
push:
branches:
- main
permissions:
contents: write
issues: write
pull-requests: write
name: release-please
jobs:
release-please:
runs-on: ubuntu-latest
outputs:
releases_created: ${{ steps.release.outputs.releases_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
release-type: python
target-branch: main
build-wheels:
name: build wheels (${{ matrix.label }})
runs-on: ${{ matrix.os }}
needs: release-please
if: ${{ needs.release-please.outputs.releases_created == 'true' && needs.release-please.outputs.tag_name != '' }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
label: linux-x86_64
target: x86_64-unknown-linux-gnu
extra-args: "--compatibility manylinux_2_39"
python-version: "3.13"
- os: ubuntu-latest
label: linux-aarch64
target: aarch64-unknown-linux-gnu
extra-args: "--compatibility manylinux_2_39"
python-version: "3.13"
- os: macos-15-intel
label: macos-x86_64
target: ""
extra-args: ""
python-version: "3.13"
- os: macos-latest
label: macos-aarch64
target: ""
extra-args: ""
python-version: "3.13"
- os: windows-latest
label: windows-x86_64
target: ""
extra-args: ""
python-version: "3.13"
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
- name: Install maturin
run: uv tool install maturin
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Setup cross-compilation for Linux ARM64
if: matrix.label == 'linux-aarch64'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
- name: Build wheel
run: uvx maturin build --release --out dist ${{ matrix.extra-args }} ${{ matrix.target && format('--target {0}', matrix.target) || '' }}
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
- name: Upload wheel artifact
uses: actions/upload-artifact@v6
with:
name: wheels-${{ matrix.label }}
path: dist/*.whl
if-no-files-found: error
build-sdist:
name: build sdist
runs-on: ubuntu-latest
needs: release-please
if: ${{ needs.release-please.outputs.releases_created == 'true' && needs.release-please.outputs.tag_name != '' }}
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.13"
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Install maturin
run: uv tool install maturin
- name: Build sdist
run: uvx maturin sdist --out dist
- name: Upload sdist artifact
uses: actions/upload-artifact@v6
with:
name: sdist
path: dist/*.tar.gz
if-no-files-found: error
publish:
name: publish release artifacts
runs-on: ubuntu-latest
needs:
- release-please
- build-wheels
- build-sdist
if: ${{ needs.release-please.outputs.releases_created == 'true' && needs.release-please.outputs.tag_name != '' }}
environment: pypi
permissions:
id-token: write
contents: write
steps:
- name: Download wheel artifacts
uses: actions/download-artifact@v7
with:
pattern: wheels-*
merge-multiple: true
path: dist
- name: Download sdist artifact
uses: actions/download-artifact@v7
with:
name: sdist
path: dist
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/*
tag: ${{ needs.release-please.outputs.tag_name }}
file_glob: true
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
```
## /.gitignore
```gitignore path="/.gitignore"
data/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.env.*
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be added to the global gitignore or merged into this project gitignore. For a PyCharm
# project, it is common to ignore sensitive information such as project configurations.
.idea/
# Database files
*.db
*.sqlite
*.sqlite3
persona_memory.db
persona_conversations.db
basic_memory_demo.db
demo_memory.db
demo_conversations.db
chatbot_memory.db
chatbot_conversations.db
integration_memory.db
integration_conversations.db
conversation_demo.db
# Log files
*.log
# Temporary files
tmp/
temp/
.tmp/
# OS specific
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# IDE
.vscode/
*.swp
*.swo
*~
# Model files (if using local models)
models/
*.bin
*.pt
*.pth
*.onnx
# API keys and secrets
.env.local
.env.*.local
secrets.txt
api_keys.txt
.cursor
```
## /.pre-commit-config.yaml
```yaml path="/.pre-commit-config.yaml"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v6.0.0"
hooks:
- id: check-case-conflict
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
- id: check-json
- id: pretty-format-json
args: [--autofix, --no-sort-keys]
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.14.3"
hooks:
- id: ruff
args: [--exit-non-zero-on-fix]
- id: ruff-format
```
## /.python-version
```python-version path="/.python-version"
3.13
```
## /AGENTS.md
# AGENTS.md
Guidance for AI coding agents working in this repository.
## Goal
Implement features and fix bugs with minimal regression risk, while preserving memU's architecture:
- `MemoryService` as composition root
- workflow-based execution (`memorize`, `retrieve`, CRUD/patch)
- pluggable storage backends (`inmemory`, `sqlite`, `postgres`)
- profile-based LLM routing (`default`, `embedding`, custom profiles)
See `docs/architecture.md` for the current architectural view.
## Where to Change Code
- Service/runtime wiring: `src/memu/app/service.py`
- Memorize flow: `src/memu/app/memorize.py`
- Retrieve flow: `src/memu/app/retrieve.py`
- CRUD/Patch flow: `src/memu/app/crud.py`
- Config models/defaults: `src/memu/app/settings.py`
- Workflow engine: `src/memu/workflow/*`
- Storage abstraction/factory: `src/memu/database/interfaces.py`, `src/memu/database/factory.py`
- In-memory: `src/memu/database/inmemory/*`
- SQLite: `src/memu/database/sqlite/*`
- Postgres: `src/memu/database/postgres/*`
- LLM clients/wrappers/interceptors: `src/memu/llm/*`
- Integrations: `src/memu/integrations/*`, `src/memu/client/*`
- Tests: `tests/*`
## Implementation Rules
- Keep changes small and localized.
- Do not change public API signatures unless explicitly required.
- Preserve async behavior and existing workflow step contracts (`requires`/`produces` keys).
- If adding a new capability, prefer integrating through an existing pipeline step or a new clearly named step.
- Maintain backend parity where appropriate (if a repository contract changes, update all relevant backends).
- Validate `where`/scope behavior against `UserConfig.model`; do not bypass scope filtering.
- Keep type hints and mypy compatibility intact.
## Feature Work Checklist
1. Locate affected flow(s): memorize, retrieve, CRUD, or integration layer.
2. Update config models/defaults if behavior is configurable.
3. Wire behavior through `MemoryService` pipelines and step config (LLM profiles/capabilities).
4. Implement backend/repository changes for all impacted providers.
5. Add/extend tests for happy path and edge cases.
6. Update docs when behavior changes (`README.md`, `docs/*`, examples if needed).
7. If the change is architectural, add/update ADRs under `docs/adr/`.
## Bug Fix Checklist
1. Reproduce with an existing or new failing test.
2. Implement the smallest safe fix at the correct layer.
3. Add a regression test that fails before and passes after.
4. Check cross-backend effects (`inmemory`, `sqlite`, `postgres`) and retrieval modes (`rag`, `llm`) when relevant.
5. Verify no unintended API/output shape changes.
## Testing and Validation
Use `uv` for all local runs.
- Setup: `make install`
- Run all tests: `make test`
- Run focused tests: `uv run python -m pytest tests/<target_test>.py`
- Full quality checks: `make check`
At minimum, run targeted tests for touched code. Run `make check` for broad or cross-cutting changes.
If you cannot run a required check, state it explicitly in your final summary.
## Done Criteria
Before finishing, ensure:
- Code compiles and tests for changed behavior pass.
- New behavior is covered by tests.
- Docs are updated for user-visible or architectural changes.
- No unrelated files were modified.
## /CHANGELOG.md
# Changelog
## [1.5.1](https://github.com/NevaMind-AI/memU/compare/v1.5.0...v1.5.1) (2026-03-23)
### Bug Fixes
* use correct interpolation in alembic url ([#390](https://github.com/NevaMind-AI/memU/issues/390)) ([fd87ceb](https://github.com/NevaMind-AI/memU/commit/fd87ceb558eaa800aeb694b045847971958f23a3))
## [1.5.0](https://github.com/NevaMind-AI/memU/compare/v1.4.0...v1.5.0) (2026-03-17)
### Features
* add non-propagate option for memory patch ([#386](https://github.com/NevaMind-AI/memU/issues/386)) ([3b67458](https://github.com/NevaMind-AI/memU/commit/3b67458c6325b4fcdaccbc34f6e0fea491b7ba96))
* **http:** add HTTP proxy support for LLM & embedding clients ([#310](https://github.com/NevaMind-AI/memU/issues/310)) ([a3d45e2](https://github.com/NevaMind-AI/memU/commit/a3d45e2f4174702fd8fd83cd13862285cd47cad9))
### Bug Fixes
* httpx base_url path discarded when endpoint starts with / ([#328](https://github.com/NevaMind-AI/memU/issues/328), [#336](https://github.com/NevaMind-AI/memU/issues/336), [#341](https://github.com/NevaMind-AI/memU/issues/341), [#329](https://github.com/NevaMind-AI/memU/issues/329)) ([#344](https://github.com/NevaMind-AI/memU/issues/344)) ([9e31ef2](https://github.com/NevaMind-AI/memU/commit/9e31ef235d46317f383613825090c52943cb55a2))
### Documentation
* add architecture explanation and adrs ([#353](https://github.com/NevaMind-AI/memU/issues/353)) ([8676a27](https://github.com/NevaMind-AI/memU/commit/8676a2721917f4e0baee6d01a9d6b95bd642be97))
* add pull request template to improve contribution quality ([#261](https://github.com/NevaMind-AI/memU/issues/261)) ([2256119](https://github.com/NevaMind-AI/memU/commit/2256119fb2d177890c7f738c926f437a355e7359))
* Update Discord link in README.md ([#377](https://github.com/NevaMind-AI/memU/issues/377)) ([163d050](https://github.com/NevaMind-AI/memU/commit/163d050299b77143226e9727f67d4826c9a69f92))
* update memU Bot section with GitHub reference and "Now open source" ([#366](https://github.com/NevaMind-AI/memU/issues/366)) ([dc6880a](https://github.com/NevaMind-AI/memU/commit/dc6880a793d40b04cd599298a110af5f0f0b9cb5))
## [1.4.0](https://github.com/NevaMind-AI/memU/compare/v1.3.0...v1.4.0) (2026-02-06)
### Features
* Add inline memory item references in category summaries ([#202](https://github.com/NevaMind-AI/memU/issues/202)) ([#205](https://github.com/NevaMind-AI/memU/issues/205)) ([5213571](https://github.com/NevaMind-AI/memU/commit/5213571b218d85784e0771f7a721eafd7da1c1ff))
* Add salience-aware memory with reinforcement tracking ([#186](https://github.com/NevaMind-AI/memU/issues/186)) ([#206](https://github.com/NevaMind-AI/memU/issues/206)) ([2bdbcce](https://github.com/NevaMind-AI/memU/commit/2bdbcce1a87ae1017d5930901fb0ae8d2924dcee))
* Add Tool Memory type with specialized metadata and statistics ([#247](https://github.com/NevaMind-AI/memU/issues/247)) ([4e8a035](https://github.com/NevaMind-AI/memU/commit/4e8a03578641afd0e07f9700629dff8d91d2b3fb))
### Bug Fixes
* add chat() API and stop misusing summarize() ([#208](https://github.com/NevaMind-AI/memU/issues/208)) ([be0a5c7](https://github.com/NevaMind-AI/memU/commit/be0a5c73250f0a21ad5e0d39b0e66e3018809e0f))
* remove unused type: ignore comment and add lazyllm mypy override ([#275](https://github.com/NevaMind-AI/memU/issues/275)) ([0e490f7](https://github.com/NevaMind-AI/memU/commit/0e490f7333feecffaef0901cccb1c9a5dbb7bafb))
* **video:** cleanup temp files on extraction failure ([#295](https://github.com/NevaMind-AI/memU/issues/295)) ([16b65e5](https://github.com/NevaMind-AI/memU/commit/16b65e54aef69dfe617835ca534c12752e06eda8))
### Documentation
* file system in readme ([#301](https://github.com/NevaMind-AI/memU/issues/301)) ([ee27d8a](https://github.com/NevaMind-AI/memU/commit/ee27d8aa5e42d249963b08d5775338080b0255f8))
* fix name ([#291](https://github.com/NevaMind-AI/memU/issues/291)) ([fd0d179](https://github.com/NevaMind-AI/memU/commit/fd0d17998f6c0c9ba5c7e91964c39ee909f2b366))
* fix readme lint ([#290](https://github.com/NevaMind-AI/memU/issues/290)) ([a7a5516](https://github.com/NevaMind-AI/memU/commit/a7a55169ecbc1579ae87dc68c5e09b1d62f07b56))
* lint error ([#287](https://github.com/NevaMind-AI/memU/issues/287)) ([7f61dc7](https://github.com/NevaMind-AI/memU/commit/7f61dc72ffbadf849f227cf314bba7ce7964761b))
* readme memubot ([#289](https://github.com/NevaMind-AI/memU/issues/289)) ([2f30798](https://github.com/NevaMind-AI/memU/commit/2f30798367e3591107e1e66a184d0dd4ad6c2f93))
* Update README.md ([#300](https://github.com/NevaMind-AI/memU/issues/300)) ([1075d7c](https://github.com/NevaMind-AI/memU/commit/1075d7c9ec3a272846c9fdb8c22ec58ff73cf6e7))
## [1.3.0](https://github.com/NevaMind-AI/memU/compare/v1.2.0...v1.3.0) (2026-01-29)
### Features
* add happened at and extra fields to memory item ([#262](https://github.com/NevaMind-AI/memU/issues/262)) ([77938e9](https://github.com/NevaMind-AI/memU/commit/77938e9c282e1c0eda11088675c35975d85c4ff0))
* add proactive example ([#268](https://github.com/NevaMind-AI/memU/issues/268)) ([d3d1de1](https://github.com/NevaMind-AI/memU/commit/d3d1de1d9b0f45d9b14479cbaa4462458b172005))
* add Sealos support agent use case (Track G) ([#255](https://github.com/NevaMind-AI/memU/issues/255)) ([8fbdf3c](https://github.com/NevaMind-AI/memU/commit/8fbdf3c301f74f2aa85604837e00bb305b8801ec))
* integrate LazyLLM to provide more llm services ([#265](https://github.com/NevaMind-AI/memU/issues/265)) ([c03f639](https://github.com/NevaMind-AI/memU/commit/c03f639677d6c897b75dfe28d0cd92d5b5270957))
* **integrations:** Add LangGraph Adapter for MemU (Track A) ([#258](https://github.com/NevaMind-AI/memU/issues/258)) ([50b5502](https://github.com/NevaMind-AI/memU/commit/50b5502ebcacd86401f98b1bb7e5a6577fab7126))
* **llm:** add Grok (xAI) integration ([#179](https://github.com/NevaMind-AI/memU/issues/179)) ([#236](https://github.com/NevaMind-AI/memU/issues/236)) ([1e16309](https://github.com/NevaMind-AI/memU/commit/1e1630948af535f8ed9d608e6c4f9d2748d4ce8e))
* Openrouter integration as backend provider ([#182](https://github.com/NevaMind-AI/memU/issues/182)) ([cba667a](https://github.com/NevaMind-AI/memU/commit/cba667a56daca5093c9b79a598c7d2ffda813756))
### Bug Fixes
* memory type & proactive example ([#272](https://github.com/NevaMind-AI/memU/issues/272)) ([710f14d](https://github.com/NevaMind-AI/memU/commit/710f14d4b171c5cde609a9dc2caf454681ab94b3))
* proactive examples ([#273](https://github.com/NevaMind-AI/memU/issues/273)) ([603ae12](https://github.com/NevaMind-AI/memU/commit/603ae122b94741bb350656086960c4e2bb868c2a))
### Documentation
* Add link to memU bot ([#276](https://github.com/NevaMind-AI/memU/issues/276)) ([2f84231](https://github.com/NevaMind-AI/memU/commit/2f842311ed592c1a45cdb9e24f7a128da97a0a39))
* multilingual readme ([#271](https://github.com/NevaMind-AI/memU/issues/271)) ([200f47a](https://github.com/NevaMind-AI/memU/commit/200f47a15ff7d05fc435abe1d2cefbb3774548fe))
* Update memU bot link to include full URL ([#277](https://github.com/NevaMind-AI/memU/issues/277)) ([6874eaf](https://github.com/NevaMind-AI/memU/commit/6874eaf278e910d07a4427dd4c06f9c4c21283ce))
* update readme ([#266](https://github.com/NevaMind-AI/memU/issues/266)) ([16ae534](https://github.com/NevaMind-AI/memU/commit/16ae534675a5e0711256a5e2147b9190fd8b2524))
* update README ([#270](https://github.com/NevaMind-AI/memU/issues/270)) ([b531d39](https://github.com/NevaMind-AI/memU/commit/b531d39e5538449b31cb212aea1deea24e12180f))
## [1.2.0](https://github.com/NevaMind-AI/memU/compare/v1.1.2...v1.2.0) (2026-01-14)
### Features
* clear memory ([#239](https://github.com/NevaMind-AI/memU/issues/239)) ([7da36da](https://github.com/NevaMind-AI/memU/commit/7da36da57d7013df213e537b1f238f5a526e69d9))
* **database:** add SQLite storage backend ([#201](https://github.com/NevaMind-AI/memU/issues/201)) ([4b899d7](https://github.com/NevaMind-AI/memU/commit/4b899d7b768fcd48b6456234800033e3b2e3173c))
* improve issue template ([#199](https://github.com/NevaMind-AI/memU/issues/199)) ([abe0f1b](https://github.com/NevaMind-AI/memU/commit/abe0f1b77d5f8294ff45c9f57f5aeb6de33977d6))
* optimize topk pick function ([#196](https://github.com/NevaMind-AI/memU/issues/196)) ([b474c54](https://github.com/NevaMind-AI/memU/commit/b474c54a7eea06ba56844d6482d5e78b3cb3f020))
* workflow step interceptor ([#240](https://github.com/NevaMind-AI/memU/issues/240)) ([bf2ac96](https://github.com/NevaMind-AI/memU/commit/bf2ac96f1cb26b196f27b543d4c3e157f408f343))
### Bug Fixes
* allow nullable resource_id in Postgres items ([#232](https://github.com/NevaMind-AI/memU/issues/232)) ([ae2ffbb](https://github.com/NevaMind-AI/memU/commit/ae2ffbb0bcd69170875a47cebf322b71a15f4bd3))
* correct coverage source to track memu package instead of tests ([#220](https://github.com/NevaMind-AI/memU/issues/220)) ([2460bbd](https://github.com/NevaMind-AI/memU/commit/2460bbd2a2c4df5b3664db81d89886b926b51031))
* correct typo in PromptBlock class label attribute ([#231](https://github.com/NevaMind-AI/memU/issues/231)) ([d69053c](https://github.com/NevaMind-AI/memU/commit/d69053cece3467dd7c8cbf0634e72447649095f7))
* default embed size ([#192](https://github.com/NevaMind-AI/memU/issues/192)) ([144fd32](https://github.com/NevaMind-AI/memU/commit/144fd32cfd6917b08f29cf56f251f239c360d2ae))
* readme partners link & github issue link ([#198](https://github.com/NevaMind-AI/memU/issues/198)) ([849f881](https://github.com/NevaMind-AI/memU/commit/849f881f004b0772f372069e40f937731c114c89))
### Documentation
* add Chinese translation of README ([#212](https://github.com/NevaMind-AI/memU/issues/212)) ([d15ecf9](https://github.com/NevaMind-AI/memU/commit/d15ecf97647d8fd9f1d2ae95008a08bbba93a44a))
* add How to Contribute section to README ([#215](https://github.com/NevaMind-AI/memU/issues/215)) ([bf44de7](https://github.com/NevaMind-AI/memU/commit/bf44de722965fd611c0dc585712eac587caa9e6c))
* **readme:** update Chinese README with fixes and improvements ([#221](https://github.com/NevaMind-AI/memU/issues/221)) ([75a8f65](https://github.com/NevaMind-AI/memU/commit/75a8f651bb4b491ab5b0363de789c0dcd0291287))
## [1.1.2](https://github.com/NevaMind-AI/memU/compare/v1.1.1...v1.1.2) (2026-01-08)
### Bug Fixes
* custom memory type default prompt ([#169](https://github.com/NevaMind-AI/memU/issues/169)) ([5a0032f](https://github.com/NevaMind-AI/memU/commit/5a0032fc0f29229524d0356d454a3f5991e04f7b))
* prompt & item fallback ([#183](https://github.com/NevaMind-AI/memU/issues/183)) ([bc95ade](https://github.com/NevaMind-AI/memU/commit/bc95adeb26789104c0bbe199e126cf05def27941))
### Documentation
* add docs folder ([#181](https://github.com/NevaMind-AI/memU/issues/181)) ([919d2ca](https://github.com/NevaMind-AI/memU/commit/919d2caef23107d539c36f30c44d4fb5aa38b324))
* fix issue template dropdown ([#167](https://github.com/NevaMind-AI/memU/issues/167)) ([14d0333](https://github.com/NevaMind-AI/memU/commit/14d03331ed14f1e593fdebbf561189a3775651be))
* issue template fix ([#165](https://github.com/NevaMind-AI/memU/issues/165)) ([5d91237](https://github.com/NevaMind-AI/memU/commit/5d912372e1bf70d7ff573cd5b92e917118048e25))
## [1.1.1](https://github.com/NevaMind-AI/memU/compare/v1.1.0...v1.1.1) (2026-01-07)
### Bug Fixes
* ensure both Linux x86_64 and ARM64 wheels are built ([#162](https://github.com/NevaMind-AI/memU/issues/162)) ([51c9ea4](https://github.com/NevaMind-AI/memU/commit/51c9ea4335a1e9eac227c79783d7aa8cca2b883b))
### Documentation
* add custom LLM and embedding configuration guide ([#160](https://github.com/NevaMind-AI/memU/issues/160)) ([29c414a](https://github.com/NevaMind-AI/memU/commit/29c414a84d1c9c2f989e2165d0b6508c3fe62862))
* add template ([#158](https://github.com/NevaMind-AI/memU/issues/158)) ([b79a78d](https://github.com/NevaMind-AI/memU/commit/b79a78d25b96e670888c18b8f09277db33803865))
## [1.1.0](https://github.com/NevaMind-AI/memU/compare/v1.0.1...v1.1.0) (2026-01-07)
### Features
* add Linux ARM64 (aarch64) build target ([#156](https://github.com/NevaMind-AI/memU/issues/156)) ([0c90fcf](https://github.com/NevaMind-AI/memU/commit/0c90fcfb19fc3e91b951f4ba7454798e4b83e42c))
### Bug Fixes
* llm client profile & wrapper ([#157](https://github.com/NevaMind-AI/memU/issues/157)) ([e55c668](https://github.com/NevaMind-AI/memU/commit/e55c66847eac3ceaf276587d58b76d953d7be9f8))
### Documentation
* remove legacy docs ([#154](https://github.com/NevaMind-AI/memU/issues/154)) ([11fda41](https://github.com/NevaMind-AI/memU/commit/11fda41dda8a5c38b790d3c2fb7053b57b16606e))
## [1.0.1](https://github.com/NevaMind-AI/memU/compare/v1.0.0...v1.0.1) (2026-01-06)
### Bug Fixes
* get embedding client ([#152](https://github.com/NevaMind-AI/memU/issues/152)) ([76716a4](https://github.com/NevaMind-AI/memU/commit/76716a4f00127a3cc21444996f32a9cf810c9282))
* Readme incomplete ([#148](https://github.com/NevaMind-AI/memU/issues/148)) ([f8bc748](https://github.com/NevaMind-AI/memU/commit/f8bc748b9ebfb652ca8a5e06edbbe7eb648ed4f6))
## [1.0.0](https://github.com/NevaMind-AI/memU/compare/v0.9.0...v1.0.0) (2026-01-05)
### ⚠ BREAKING CHANGES
* v1.0.0 ([#147](https://github.com/NevaMind-AI/memU/issues/147))
### Bug Fixes
* v1.0.0 ([#147](https://github.com/NevaMind-AI/memU/issues/147)) ([23f37ee](https://github.com/NevaMind-AI/memU/commit/23f37ee403ecaf88b48af0144e3d701c22ccfddd))
### Documentation
* add readme cloud api ([#144](https://github.com/NevaMind-AI/memU/issues/144)) ([42fd5ba](https://github.com/NevaMind-AI/memU/commit/42fd5babe6748ef54254cf114a54bdefea304f07))
* fix api doc link ([#146](https://github.com/NevaMind-AI/memU/issues/146)) ([23ce7d1](https://github.com/NevaMind-AI/memU/commit/23ce7d19b1d68f4fd0a5a5ac6b756f69fede8d09))
## [0.9.0](https://github.com/NevaMind-AI/memU/compare/v0.8.0...v0.9.0) (2026-01-04)
### Features
* add GitHub issue templates (bug report, designer feedback, feat… ([#132](https://github.com/NevaMind-AI/memU/issues/132)) ([aee22ee](https://github.com/NevaMind-AI/memU/commit/aee22ee94f275749f69367b83a02a2e819cfd001))
* add LLM wrapper and interceptors for LLM calls ([#131](https://github.com/NevaMind-AI/memU/issues/131)) ([416e102](https://github.com/NevaMind-AI/memU/commit/416e1029e7752f173c133ebc83bc42801a313059))
* patch & crud workflows ([#127](https://github.com/NevaMind-AI/memU/issues/127)) ([3cd3dc6](https://github.com/NevaMind-AI/memU/commit/3cd3dc65ae9488207ff8fb0c81e4adb0d22c0f91))
### Bug Fixes
* category summary & category user scopes ([#125](https://github.com/NevaMind-AI/memU/issues/125)) ([a24efd5](https://github.com/NevaMind-AI/memU/commit/a24efd57df2e305fa3eae8622ea889318979c2f7))
* config & resource caption ([#142](https://github.com/NevaMind-AI/memU/issues/142)) ([ea4be13](https://github.com/NevaMind-AI/memU/commit/ea4be1396c0f55b02d706819f6c2b4d5c6e68be8))
* remove duplicate and unnecessary issue templates ([#133](https://github.com/NevaMind-AI/memU/issues/133)) ([559ec14](https://github.com/NevaMind-AI/memU/commit/559ec14d2561ac09162bbb93f178e0f74cc58b23))
### Documentation
* fix README and CONTRIBUTING to match actual codebase ([#130](https://github.com/NevaMind-AI/memU/issues/130)) ([65d7ef4](https://github.com/NevaMind-AI/memU/commit/65d7ef414563395c6cfa0a75343864671c11b62d))
* modify readme.md 0102 ([#136](https://github.com/NevaMind-AI/memU/issues/136)) ([f114ee4](https://github.com/NevaMind-AI/memU/commit/f114ee46c8639b256472a8e989695b2f2215f4d4))
## [0.8.0](https://github.com/NevaMind-AI/memU/compare/v0.7.0...v0.8.0) (2025-12-24)
### Features
* add configurable batch_size for embedding API calls ([#114](https://github.com/NevaMind-AI/memU/issues/114)) ([060067a](https://github.com/NevaMind-AI/memU/commit/060067a5ebe8ad36c4ca4ad2cc6033303c3f1a36))
* add conversation created at ([#120](https://github.com/NevaMind-AI/memU/issues/120)) ([825df56](https://github.com/NevaMind-AI/memU/commit/825df5640037fa2345c3153c3df89174059551b3))
* add workflow implementation and postgres store ([#122](https://github.com/NevaMind-AI/memU/issues/122)) ([a175811](https://github.com/NevaMind-AI/memU/commit/a1758110f859f3725960d308fa0344a1056be52c))
### Bug Fixes
* example 3 output ([#117](https://github.com/NevaMind-AI/memU/issues/117)) ([65ef7c6](https://github.com/NevaMind-AI/memU/commit/65ef7c6a497047f0f86938cf77ee4602a630216b))
* postgres model definitions & database initialization ([#124](https://github.com/NevaMind-AI/memU/issues/124)) ([7d5e0cb](https://github.com/NevaMind-AI/memU/commit/7d5e0cb02837a6e2071d3c3344ef6dad613f9a43))
### Documentation
* Add memU-experiment link to README ([#119](https://github.com/NevaMind-AI/memU/issues/119)) ([2d908e1](https://github.com/NevaMind-AI/memU/commit/2d908e17ee2e15b95d4eb2f35dd09f924d57f8cf))
* clearer introduction and new agent examples ([#115](https://github.com/NevaMind-AI/memU/issues/115)) ([da27875](https://github.com/NevaMind-AI/memU/commit/da2787536d91490f7a96a0c7379abd1ad1c6d9ac))
## [0.7.0](https://github.com/NevaMind-AI/memU/compare/v0.6.0...v0.7.0) (2025-12-05)
### Features
* add user model and user context store ([#113](https://github.com/NevaMind-AI/memU/issues/113)) ([7c37fb1](https://github.com/NevaMind-AI/memU/commit/7c37fb166b0a85bf7c89d0b109cbaa882fa80064))
* add valcano model support ([#110](https://github.com/NevaMind-AI/memU/issues/110)) ([704c302](https://github.com/NevaMind-AI/memU/commit/704c3024946e8d4a1d1b13ffef33126bb68bd9c4))
### Bug Fixes
* resource caption miss problem ([#111](https://github.com/NevaMind-AI/memU/issues/111)) ([85586f5](https://github.com/NevaMind-AI/memU/commit/85586f52d6bd6355ae440ad06d8cc6779c689ce8))
### Documentation
* fix example file path ([#105](https://github.com/NevaMind-AI/memU/issues/105)) ([21aad6a](https://github.com/NevaMind-AI/memU/commit/21aad6a7f070e7666ac6a41c91980a4fa9696918))
* fix readme test case ([#107](https://github.com/NevaMind-AI/memU/issues/107)) ([228306c](https://github.com/NevaMind-AI/memU/commit/228306c897402c633f57c7aa31e8c6cd4e995d5d))
* highlight OpenAI key ([#106](https://github.com/NevaMind-AI/memU/issues/106)) ([5b6ce54](https://github.com/NevaMind-AI/memU/commit/5b6ce54def5aa7743a85bec629da65bfa9d8333b))
* highlight readme openai key ([#103](https://github.com/NevaMind-AI/memU/issues/103)) ([fc4154a](https://github.com/NevaMind-AI/memU/commit/fc4154a707220ced4359e7296218451c43cf0681))
## [0.6.0](https://github.com/NevaMind-AI/memU/compare/v0.5.0...v0.6.0) (2025-11-20)
### Features
* retrieve args change conversation_history to queries ([#98](https://github.com/NevaMind-AI/memU/issues/98)) ([6370c6e](https://github.com/NevaMind-AI/memU/commit/6370c6e968c9d0922120bf2a41e8b4206bab87cb))
## [0.5.0](https://github.com/NevaMind-AI/memU/compare/v0.4.0...v0.5.0) (2025-11-18)
### Features
* add usecase examples ([#94](https://github.com/NevaMind-AI/memU/issues/94)) ([47b5b39](https://github.com/NevaMind-AI/memU/commit/47b5b390e065ccac1cd2173fa2d6c41549e01063))
## [0.4.0](https://github.com/NevaMind-AI/memU/compare/v0.3.0...v0.4.0) (2025-11-18)
### Features
* add non-RAG retrieve solution ([#84](https://github.com/NevaMind-AI/memU/issues/84)) ([fb96e54](https://github.com/NevaMind-AI/memU/commit/fb96e5405f1c0e3477929b7d9874e624dd0453cb))
### Bug Fixes
* correct binary name after making a release ([#91](https://github.com/NevaMind-AI/memU/issues/91)) ([0fa721a](https://github.com/NevaMind-AI/memU/commit/0fa721aaae294c6f230221af11084a0a6c1f478d))
### Documentation
* fix several words in README ([#89](https://github.com/NevaMind-AI/memU/issues/89)) ([1e3baf9](https://github.com/NevaMind-AI/memU/commit/1e3baf92d5a08ec51a7eda3249bbd4b40530f56c))
* revise README for clarity and roadmap inclusion ([#86](https://github.com/NevaMind-AI/memU/issues/86)) ([2235b09](https://github.com/NevaMind-AI/memU/commit/2235b099acc7e92ac52b2613fa731f85259d58fd))
* update images and refine punctuation in README ([#88](https://github.com/NevaMind-AI/memU/issues/88)) ([cc375e8](https://github.com/NevaMind-AI/memU/commit/cc375e89a9b49bda0b7057eee696d74c4c1d9cee))
## [0.3.0](https://github.com/NevaMind-AI/memU/compare/v0.2.2...v0.3.0) (2025-11-17)
### Features
* initialize the memorize and retrieve workflows with the new 3-layer architecture ([#81](https://github.com/NevaMind-AI/memU/issues/81)) ([4a2e86c](https://github.com/NevaMind-AI/memU/commit/4a2e86c0e8bc3e50c82c4fde33d07ad741c8a65e))
### Documentation
* add German translation for README ([f6d6ab1](https://github.com/NevaMind-AI/memU/commit/f6d6ab1a51b76bd4312542422aebac89410b8da9))
* add German translation for README ([76c3fc4](https://github.com/NevaMind-AI/memU/commit/76c3fc4227a8e349fbcf1e5bfec29d68e984ff7a))
## /CONTRIBUTING.md
# Contributing to MemU
Thank you for your interest in contributing to MemU! This document provides guidelines and information for contributors.
## 🌟 Ways to Contribute
We welcome all types of contributions:
- 🐛 **Bug Reports** - Help us identify and fix issues
- 💡 **Feature Requests** - Suggest new capabilities and improvements
- 📝 **Documentation** - Improve guides, examples, and API docs
- 🔧 **Code Contributions** - Add features, fix bugs, optimize performance
- 🧪 **Testing** - Write tests, improve coverage, test edge cases
- 🎨 **UI/UX** - Enhance user experience and interface design
- 🌐 **Translations** - Help make MemU accessible globally
- 📢 **Community** - Help others in discussions and support channels
## 🚀 Quick Start for Contributors
### Prerequisites
- Python 3.13+
- Git
- [uv](https://github.com/astral-sh/uv) (Python package manager)
- A code editor (VS Code recommended)
### Development Setup
```bash
# 1. Fork the repository on GitHub
# 2. Clone your fork locally
git clone https://github.com/YOUR_USERNAME/MemU.git
cd MemU
# 3. Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# 4. Install development dependencies and pre-commit hooks
make install
# 5. Verify setup by running tests
make test
```
### Available Commands
```bash
make install # Create virtual environment and install dependencies with uv
make test # Run tests with pytest and coverage
make check # Run all checks (lock file, pre-commit, mypy, deptry)
```
## 🔧 Development Guidelines
### Code Style
- Follow **PEP 8** Python style guidelines
- Use **Ruff** for code formatting and linting (line length: 120)
- Use **type hints** for all functions and methods
- Write **docstrings** for public APIs
### Code Quality Standards
- Maintain **test coverage > 80%**
- All code must pass **linting** (ruff, mypy)
- Use **meaningful variable and function names**
- Keep functions **focused and small**
- Follow **SOLID principles**
### Testing
```bash
# Run all tests with coverage
make test
# Run tests directly with pytest
uv run python -m pytest
# Run with coverage report
uv run python -m pytest --cov --cov-config=pyproject.toml --cov-report=html
# Run specific test file
uv run python -m pytest tests/rust_entry_test.py
# Run tests with specific marker
uv run python -m pytest -m "not slow"
```
## 📝 Submitting Changes
### Before You Start
1. **Search existing issues** to avoid duplicates
2. **Create an issue** for new features or major changes
3. **Discuss your approach** in the issue before implementing
### Creating Issues
When reporting bugs, please include:
- **Environment details** (Python version, OS, MemU version)
- **Reproduction steps** with minimal code example
- **Expected vs actual behavior**
- **Error messages** or stack traces
For feature requests, please describe:
- **The problem** you're trying to solve
- **Proposed solution** or approach
- **Alternative solutions** you've considered
- **Use cases** and examples
### Pull Request Process
1. **Create a feature branch**
```bash
git checkout -b feature/amazing-feature
# or for bug fixes
git checkout -b bugfix/fix-memory-leak
```
2. **Make your changes**
- Write clear, descriptive commit messages
- Keep commits focused and atomic
- Add tests for new functionality
- Update documentation as needed
3. **Test your changes**
```bash
make test
make lint
make coverage
```
4. **Submit pull request**
- Use descriptive title and description
- Reference related issues (e.g., "Fixes #123")
- Include testing instructions
- Add screenshots for UI changes
### Commit Message Format
Use conventional commit format:
```
type(scope): description
Examples:
feat(memory): add semantic search functionality
fix(llm): resolve OpenAI timeout issues
docs(readme): update installation instructions
test(agent): add unit tests for memory retrieval
refactor(core): restructure memory storage logic
```
**Types:**
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation changes
- `test`: Adding or fixing tests
- `refactor`: Code restructuring without feature changes
- `perf`: Performance improvements
- `chore`: Maintenance tasks
## 🎯 Current Priorities
We're currently focusing on:
| Priority | Area | Description |
|----------|------|-------------|
| 🔥 **High** | Multi-modal Support | Images, audio, video memory processing |
| 🔥 **High** | Performance | Memory retrieval optimization, caching |
| 🔥 **High** | LLM Providers | Additional provider integrations |
| 🟡 **Medium** | Enterprise Features | SSO, RBAC, audit logging |
| 🟡 **Medium** | Mobile SDKs | React Native, Flutter support |
| 🟢 **Low** | UI Improvements | Dashboard, memory visualization |
## 🏷️ Issue Labels
| Label | Description |
|-------|-------------|
| `good first issue` | Perfect for newcomers |
| `help wanted` | Extra attention needed |
| `bug` | Something isn't working |
| `enhancement` | New feature request |
| `documentation` | Improvements to docs |
| `performance` | Performance optimization |
| `breaking change` | Requires version bump |
| `priority:high` | Urgent issues |
| `priority:medium` | Important issues |
| `priority:low` | Nice to have |
## 📋 Code Review Process
### For Contributors
- Be open to feedback and constructive criticism
- Respond promptly to review comments
- Make requested changes in new commits (don't force push)
- Ask questions if feedback is unclear
### For Reviewers
- Be constructive and respectful in feedback
- Focus on code quality, maintainability, and project goals
- Suggest improvements with explanations
- Approve when ready, request changes when needed
## 🔒 Security
**Reporting Security Issues:**
- **DO NOT** create public issues for security vulnerabilities
- Email security issues privately to [contact@nevamind.ai](mailto:contact@nevamind.ai)
- Include detailed reproduction steps and impact assessment
- We'll acknowledge receipt within 24 hours
## 📄 License and Attribution
By contributing to MemU, you agree that:
- Your contributions will be licensed under the **Apache License 2.0**
- You have the right to contribute the code/content
- Your contribution doesn't violate any third-party rights
## 🌍 Community Guidelines
- Be respectful and inclusive
- Follow our [Code of Conduct](CODE_OF_CONDUCT.md)
- Help others learn and grow
- Share knowledge and best practices
- Celebrate diverse perspectives and experiences
## 📞 Getting Help
| Channel | Best For |
|---------|----------|
| 💬 [Discord](https://discord.gg/memu) | Real-time chat, quick questions |
| 🗣️ [GitHub Discussions](https://github.com/NevaMind-AI/MemU/discussions) | Feature discussions, Q&A |
| 🐛 [GitHub Issues](https://github.com/NevaMind-AI/MemU/issues) | Bug reports, feature requests |
| 📧 [Email](mailto:contact@nevamind.ai) | Private inquiries |
## 🎉 Recognition
Contributors are recognized in:
- README.md contributors section
- Release notes for significant contributions
- Our [Contributors](https://github.com/NevaMind-AI/MemU/graphs/contributors) page
Thank you for helping make MemU better! 🚀
## /Cargo.toml
```toml path="/Cargo.toml"
[package]
name = "memu"
version = "0.1.0"
edition = "2024"
[lib]
name = "_core"
# "cdylib" is necessary to produce a shared library for Python to import from.
crate-type = ["cdylib"]
[dependencies]
# "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so)
# "abi3-py313" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.13
pyo3 = { version = "0.27.1", features = ["extension-module", "abi3-py313"] }
```
## /LICENSE.txt
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(which shall not include communication that is conspicuously
marked or otherwise designated in writing by the copyright owner
as "Not a Contribution").
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based upon (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and derivative works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control
systems, and issue tracking systems that are managed by, or on behalf
of, the Licensor for the purpose of discussing and improving the Work,
but excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution".
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to use, reproduce, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Work, and to
permit persons to whom the Work is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Work.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, trademark, patent,
attribution and other notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright notice to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Support. You may choose to offer, and to
charge a fee for, warranty, support, indemnity or other liability
obligations and/or rights consistent with this License. However, in
accepting such obligations, You may act only on Your own behalf and
on Your sole responsibility, not on behalf of any other Contributor,
and only if You agree to indemnify, defend, and hold each Contributor
harmless for any liability incurred by, or claims asserted against,
such Contributor by reason of your accepting any such warranty or
support.
END OF TERMS AND CONDITIONS
Copyright 2024 MemU Team
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## /MANIFEST.in
```in path="/MANIFEST.in"
include README.md
recursive-include memu *.py
prune example
include setup_postgres_env.sh
exclude .env
exclude .env.example
exclude setup.py.backup
exclude */__pycache__/*
exclude *.pyc
exclude *.pyo
exclude .git/*
exclude .github/*
exclude server/*
exclude docs/*
exclude scripts/*
exclude docker-compose.yml
exclude Dockerfile
exclude .dockerignore
exclude PROJECT_RELEASE_SUMMARY.md
exclude Makefile
exclude .pre-commit-config.yaml
```
## /Makefile
``` path="/Makefile"
.PHONY: install
install:
@echo "🚀 Creating virtual environment using uv"
@uv sync
@uv run pre-commit install
.PHONY: check
check:
@echo "🚀 Checking lock file consistency with 'pyproject.toml'"
@uv lock --locked
@echo "🚀 Linting code: Running pre-commit"
@uv run pre-commit run -a
@echo "🚀 Static type checking: Running mypy"
@uv run mypy
@echo "🚀 Checking for obsolete dependencies: Running deptry"
@uv run deptry src
.PHONY: test
test:
@echo "🚀 Testing code: Running pytest"
@uv run python -m pytest --cov --cov-config=pyproject.toml --cov-report=xml
```
## /README.md

<div align="center">
# memU
### 24/7 Always-On Proactive Memory for AI Agents
[](https://badge.fury.io/py/memu-py)
[](https://opensource.org/licenses/Apache-2.0)
[](https://www.python.org/downloads/)
[](https://discord.com/invite/hQZntfGsbJ)
[](https://x.com/memU_ai)
<a href="https://trendshift.io/repositories/17374" target="_blank"><img src="https://trendshift.io/api/badge/repositories/17374" alt="NevaMind-AI%2FmemU | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
**[English](readme/README_en.md) | [中文](readme/README_zh.md) | [日本語](readme/README_ja.md) | [한국어](readme/README_ko.md) | [Español](readme/README_es.md) | [Français](readme/README_fr.md)**
</div>
---
memU is a memory framework built for **24/7 proactive agents**.
It is designed for long-running use and greatly **reduces the LLM token cost** of keeping agents always online, making always-on, evolving agents practical in production systems.
memU **continuously captures and understands user intent**. Even without a command, the agent can tell what you are about to do and act on it by itself.
---
## 🤖 [OpenClaw (Moltbot, Clawdbot) Alternative](https://github.com/NevaMind-AI/memUBot)
<img width="100%" src="https://github.com/NevaMind-AI/memU/blob/main/assets/memUbot.png" />
**[memU Bot](https://github.com/NevaMind-AI/memUBot)** — Now open source. The enterprise-ready OpenClaw. Your proactive AI assistant that remembers everything.
- **Download-and-use and simple** to get started (one-click install, < 3 min).
- Builds long-term memory to **understand user intent** and act proactively (24/7).
- **Cuts LLM token cost** with smaller context (~1/10 of comparable usage).
Try now: [memu.bot](https://memu.bot) · Source: [memUBot on GitHub](https://github.com/NevaMind-AI/memUBot)
---
## 🗃️ Memory as File System, File System as Memory
memU treats **memory like a file system**—structured, hierarchical, and instantly accessible.
| File System | memU Memory |
|-------------|-------------|
| 📁 Folders | 🏷️ Categories (auto-organized topics) |
| 📄 Files | 🧠 Memory Items (extracted facts, preferences, skills) |
| 🔗 Symlinks | 🔄 Cross-references (related memories linked) |
| 📂 Mount points | 📥 Resources (conversations, documents, images) |
**Why this matters:**
- **Navigate memories** like browsing directories—drill down from broad categories to specific facts
- **Mount new knowledge** instantly—conversations and documents become queryable memory
- **Cross-link everything**—memories reference each other, building a connected knowledge graph
- **Persistent & portable**—export, backup, and transfer memory like files
```
memory/
├── preferences/
│ ├── communication_style.md
│ └── topic_interests.md
├── relationships/
│ ├── contacts/
│ └── interaction_history/
├── knowledge/
│ ├── domain_expertise/
│ └── learned_skills/
└── context/
├── recent_conversations/
└── pending_tasks/
```
Just as a file system turns raw bytes into organized data, memU transforms raw interactions into **structured, searchable, proactive intelligence**.
---
## ⭐️ Star the repository
<img width="100%" src="https://github.com/NevaMind-AI/memU/blob/main/assets/star.gif" />
If you find memU useful or interesting, a GitHub Star ⭐️ would be greatly appreciated.
---
## ✨ Core Features
| Capability | Description |
|------------|-------------|
| 🤖 **24/7 Proactive Agent** | Always-on memory agent that works continuously in the background—never sleeps, never forgets |
| 🎯 **User Intention Capture** | Understands and remembers user goals, preferences, and context across sessions automatically |
| 💰 **Cost Efficient** | Reduces long-running token costs by caching insights and avoiding redundant LLM calls |
---
## 🔄 How Proactive Memory Works
```bash
cd examples/proactive
python proactive.py
```
---
### Proactive Memory Lifecycle
```
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ USER QUERY │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌────────────────────────────────────────┐ ┌────────────────────────────────────────────────┐
│ 🤖 MAIN AGENT │ │ 🧠 MEMU BOT │
│ │ │ │
│ Handle user queries & execute tasks │ ◄───► │ Monitor, memorize & proactive intelligence │
├────────────────────────────────────────┤ ├────────────────────────────────────────────────┤
│ │ │ │
│ ┌──────────────────────────────────┐ │ │ ┌──────────────────────────────────────────┐ │
│ │ 1. RECEIVE USER INPUT │ │ │ │ 1. MONITOR INPUT/OUTPUT │ │
│ │ Parse query, understand │ │ ───► │ │ Observe agent interactions │ │
│ │ context and intent │ │ │ │ Track conversation flow │ │
│ └──────────────────────────────────┘ │ │ └──────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌──────────────────────────────────┐ │ │ ┌──────────────────────────────────────────┐ │
│ │ 2. PLAN & EXECUTE │ │ │ │ 2. MEMORIZE & EXTRACT │ │
│ │ Break down tasks │ │ ◄─── │ │ Store insights, facts, preferences │ │
│ │ Call tools, retrieve data │ │ inject │ │ Extract skills & knowledge │ │
│ │ Generate responses │ │ memory │ │ Update user profile │ │
│ └──────────────────────────────────┘ │ │ └──────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌──────────────────────────────────┐ │ │ ┌──────────────────────────────────────────┐ │
│ │ 3. RESPOND TO USER │ │ │ │ 3. PREDICT USER INTENT │ │
│ │ Deliver answer/result │ │ ───► │ │ Anticipate next steps │ │
│ │ Continue conversation │ │ │ │ Identify upcoming needs │ │
│ └──────────────────────────────────┘ │ │ └──────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌──────────────────────────────────┐ │ │ ┌──────────────────────────────────────────┐ │
│ │ 4. LOOP │ │ │ │ 4. RUN PROACTIVE TASKS │ │
│ │ Wait for next user input │ │ ◄─── │ │ Pre-fetch relevant context │ │
│ │ or proactive suggestions │ │ suggest│ │ Prepare recommendations │ │
│ └──────────────────────────────────┘ │ │ │ Update todolist autonomously │ │
│ │ │ └──────────────────────────────────────────┘ │
└────────────────────────────────────────┘ └────────────────────────────────────────────────┘
│ │
└───────────────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────┐
│ CONTINUOUS SYNC LOOP │
│ Agent ◄──► MemU Bot ◄──► DB │
└──────────────────────────────┘
```
---
## 🎯 Proactive Use Cases
### 1. **Information Recommendation**
*Agent monitors interests and proactively surfaces relevant content*
```python
# User has been researching AI topics
MemU tracks: reading history, saved articles, search queries
# When new content arrives:
Agent: "I found 3 new papers on RAG optimization that align with
your recent research on retrieval systems. One author
(Dr. Chen) you've cited before published yesterday."
# Proactive behaviors:
- Learns topic preferences from browsing patterns
- Tracks author/source credibility preferences
- Filters noise based on engagement history
- Times recommendations for optimal attention
```
### 2. **Email Management**
*Agent learns communication patterns and handles routine correspondence*
```python
# MemU observes email patterns over time:
- Response templates for common scenarios
- Priority contacts and urgent keywords
- Scheduling preferences and availability
- Writing style and tone variations
# Proactive email assistance:
Agent: "You have 12 new emails. I've drafted responses for 3 routine
requests and flagged 2 urgent items from your priority contacts.
Should I also reschedule tomorrow's meeting based on the
conflict John mentioned?"
# Autonomous actions:
✓ Draft context-aware replies
✓ Categorize and prioritize inbox
✓ Detect scheduling conflicts
✓ Summarize long threads with key decisions
```
### 3. **Trading & Financial Monitoring**
*Agent tracks market context and user investment behavior*
```python
# MemU learns trading preferences:
- Risk tolerance from historical decisions
- Preferred sectors and asset classes
- Response patterns to market events
- Portfolio rebalancing triggers
# Proactive alerts:
Agent: "NVDA dropped 5% in after-hours trading. Based on your past
behavior, you typically buy tech dips above 3%. Your current
allocation allows for $2,000 additional exposure while
maintaining your 70/30 equity-bond target."
# Continuous monitoring:
- Track price alerts tied to user-defined thresholds
- Correlate news events with portfolio impact
- Learn from executed vs. ignored recommendations
- Anticipate tax-loss harvesting opportunities
```
...
---
## 🗂️ Hierarchical Memory Architecture
MemU's three-layer system enables both **reactive queries** and **proactive context loading**:
<img width="100%" alt="structure" src="assets/structure.png" />
| Layer | Reactive Use | Proactive Use |
|-------|--------------|---------------|
| **Resource** | Direct access to original data | Background monitoring for new patterns |
| **Item** | Targeted fact retrieval | Real-time extraction from ongoing interactions |
| **Category** | Summary-level overview | Automatic context assembly for anticipation |
**Proactive Benefits:**
- **Auto-categorization**: New memories self-organize into topics
- **Pattern Detection**: System identifies recurring themes
- **Context Prediction**: Anticipates what information will be needed next
---
## 🚀 Quick Start
### Option 1: Cloud Version
Experience proactive memory instantly:
👉 **[memu.so](https://memu.so)** - Hosted service with 7×24 continuous learning
For enterprise deployment with custom proactive workflows, contact **info@nevamind.ai**
#### Cloud API (v3)
| Base URL | `https://api.memu.so` |
|----------|----------------------|
| Auth | `Authorization: Bearer YOUR_API_KEY` |
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/v3/memory/memorize` | Register continuous learning task |
| `GET` | `/api/v3/memory/memorize/status/{task_id}` | Check real-time processing status |
| `POST` | `/api/v3/memory/categories` | List auto-generated categories |
| `POST` | `/api/v3/memory/retrieve` | Query memory (supports proactive context loading) |
📚 **[Full API Documentation](https://memu.pro/docs#cloud-version)**
---
### Option 2: Self-Hosted
#### Installation
```bash
pip install -e .
```
#### Basic Example
> **Requirements**: Python 3.13+ and an OpenAI API key
**Test Continuous Learning** (in-memory):
```bash
export OPENAI_API_KEY=your_api_key
cd tests
python test_inmemory.py
```
**Test with Persistent Storage** (PostgreSQL):
```bash
# Start PostgreSQL with pgvector
docker run -d \
--name memu-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=memu \
-p 5432:5432 \
pgvector/pgvector:pg16
# Run continuous learning test
export OPENAI_API_KEY=your_api_key
cd tests
python test_postgres.py
```
Both examples demonstrate **proactive memory workflows**:
1. **Continuous Ingestion**: Process multiple files sequentially
2. **Auto-Extraction**: Immediate memory creation
3. **Proactive Retrieval**: Context-aware memory surfacing
See [`tests/test_inmemory.py`](tests/test_inmemory.py) and [`tests/test_postgres.py`](tests/test_postgres.py) for implementation details.
---
### Custom LLM and Embedding Providers
MemU supports custom LLM and embedding providers beyond OpenAI. Configure them via `llm_profiles`:
```python
from memu import MemUService
service = MemUService(
llm_profiles={
# Default profile for LLM operations
"default": {
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"api_key": "your_api_key",
"chat_model": "qwen3-max",
"client_backend": "sdk" # "sdk" or "http"
},
# Separate profile for embeddings
"embedding": {
"base_url": "https://api.voyageai.com/v1",
"api_key": "your_voyage_api_key",
"embed_model": "voyage-3.5-lite"
}
},
# ... other configuration
)
```
---
### OpenRouter Integration
MemU supports [OpenRouter](https://openrouter.ai) as a model provider, giving you access to multiple LLM providers through a single API.
#### Configuration
```python
from memu import MemoryService
service = MemoryService(
llm_profiles={
"default": {
"provider": "openrouter",
"client_backend": "httpx",
"base_url": "https://openrouter.ai",
"api_key": "your_openrouter_api_key",
"chat_model": "anthropic/claude-3.5-sonnet", # Any OpenRouter model
"embed_model": "openai/text-embedding-3-small", # Embedding model
},
},
database_config={
"metadata_store": {"provider": "inmemory"},
},
)
```
#### Environment Variables
| Variable | Description |
|----------|-------------|
| `OPENROUTER_API_KEY` | Your OpenRouter API key from [openrouter.ai/keys](https://openrouter.ai/keys) |
#### Supported Features
| Feature | Status | Notes |
|---------|--------|-------|
| Chat Completions | Supported | Works with any OpenRouter chat model |
| Embeddings | Supported | Use OpenAI embedding models via OpenRouter |
| Vision | Supported | Use vision-capable models (e.g., `openai/gpt-4o`) |
#### Running OpenRouter Tests
```bash
export OPENROUTER_API_KEY=your_api_key
# Full workflow test (memorize + retrieve)
python tests/test_openrouter.py
# Embedding-specific tests
python tests/test_openrouter_embedding.py
# Vision-specific tests
python tests/test_openrouter_vision.py
```
See [`examples/example_4_openrouter_memory.py`](examples/example_4_openrouter_memory.py) for a complete working example.
---
## 📖 Core APIs
### `memorize()` - Continuous Learning Pipeline
Processes inputs in real-time and immediately updates memory:
<img width="100%" alt="memorize" src="assets/memorize.png" />
```python
result = await service.memorize(
resource_url="path/to/file.json", # File path or URL
modality="conversation", # conversation | document | image | video | audio
user={"user_id": "123"} # Optional: scope to a user
)
# Returns immediately with extracted memory:
{
"resource": {...}, # Stored resource metadata
"items": [...], # Extracted memory items (available instantly)
"categories": [...] # Auto-updated category structure
}
```
**Proactive Features:**
- Zero-delay processing—memories available immediately
- Automatic categorization without manual tagging
- Cross-reference with existing memories for pattern detection
### `retrieve()` - Dual-Mode Intelligence
MemU supports both **proactive context loading** and **reactive querying**:
<img width="100%" alt="retrieve" src="assets/retrieve.png" />
#### RAG-based Retrieval (`method="rag"`)
Fast **proactive context assembly** using embeddings:
- ✅ **Instant context**: Sub-second memory surfacing
- ✅ **Background monitoring**: Can run continuously without LLM costs
- ✅ **Similarity scoring**: Identifies most relevant memories automatically
#### LLM-based Retrieval (`method="llm"`)
Deep **anticipatory reasoning** for complex contexts:
- ✅ **Intent prediction**: LLM infers what user needs before they ask
- ✅ **Query evolution**: Automatically refines search as context develops
- ✅ **Early termination**: Stops when sufficient context is gathered
#### Comparison
| Aspect | RAG (Fast Context) | LLM (Deep Reasoning) |
|--------|-------------------|---------------------|
| **Speed** | ⚡ Milliseconds | 🐢 Seconds |
| **Cost** | 💰 Embedding only | 💰💰 LLM inference |
| **Proactive use** | Continuous monitoring | Triggered context loading |
| **Best for** | Real-time suggestions | Complex anticipation |
#### Usage
```python
# Proactive retrieval with context history
result = await service.retrieve(
queries=[
{"role": "user", "content": {"text": "What are their preferences?"}},
{"role": "user", "content": {"text": "Tell me about work habits"}}
],
where={"user_id": "123"}, # Optional: scope filter
method="rag" # or "llm" for deeper reasoning
)
# Returns context-aware results:
{
"categories": [...], # Relevant topic areas (auto-prioritized)
"items": [...], # Specific memory facts
"resources": [...], # Original sources for traceability
"next_step_query": "..." # Predicted follow-up context
}
```
**Proactive Filtering**: Use `where` to scope continuous monitoring:
- `where={"user_id": "123"}` - User-specific context
- `where={"agent_id__in": ["1", "2"]}` - Multi-agent coordination
- Omit `where` for global context awareness
---
## 💡 Proactive Scenarios
### Example 1: Always-Learning Assistant
Continuously learns from every interaction without explicit memory commands:
```bash
export OPENAI_API_KEY=your_api_key
python examples/example_1_conversation_memory.py
```
**Proactive Behavior:**
- Automatically extracts preferences from casual mentions
- Builds relationship models from interaction patterns
- Surfaces relevant context in future conversations
- Adapts communication style based on learned preferences
**Best for:** Personal AI assistants, customer support that remembers, social chatbots
---
### Example 2: Self-Improving Agent
Learns from execution logs and proactively suggests optimizations:
```bash
export OPENAI_API_KEY=your_api_key
python examples/example_2_skill_extraction.py
```
**Proactive Behavior:**
- Monitors agent actions and outcomes continuously
- Identifies patterns in successes and failures
- Auto-generates skill guides from experience
- Proactively suggests strategies for similar future tasks
**Best for:** DevOps automation, agent self-improvement, knowledge capture
---
### Example 3: Multimodal Context Builder
Unifies memory across different input types for comprehensive context:
```bash
export OPENAI_API_KEY=your_api_key
python examples/example_3_multimodal_memory.py
```
**Proactive Behavior:**
- Cross-references text, images, and documents automatically
- Builds unified understanding across modalities
- Surfaces visual context when discussing related topics
- Anticipates information needs by combining multiple sources
**Best for:** Documentation systems, learning platforms, research assistants
---
## 📊 Performance
MemU achieves **92.09% average accuracy** on the Locomo benchmark across all reasoning tasks, demonstrating reliable proactive memory operations.
<img width="100%" alt="benchmark" src="https://github.com/user-attachments/assets/6fec4884-94e5-4058-ad5c-baac3d7e76d9" />
View detailed experimental data: [memU-experiment](https://github.com/NevaMind-AI/memU-experiment)
---
## 🧩 Ecosystem
| Repository | Description | Proactive Features |
|------------|-------------|-------------------|
| **[memU](https://github.com/NevaMind-AI/memU)** | Core proactive memory engine | 7×24 learning pipeline, auto-categorization |
| **[memU-server](https://github.com/NevaMind-AI/memU-server)** | Backend with continuous sync | Real-time memory updates, webhook triggers |
| **[memU-ui](https://github.com/NevaMind-AI/memU-ui)** | Visual memory dashboard | Live memory evolution monitoring |
**Quick Links:**
- 🚀 [Try MemU Cloud](https://app.memu.so/quick-start)
- 📚 [API Documentation](https://memu.pro/docs)
- 💬 [Discord Community](https://discord.com/invite/hQZntfGsbJ)
---
## 🤝 Partners
<div align="center">
<a href="https://github.com/TEN-framework/ten-framework"><img src="https://avatars.githubusercontent.com/u/113095513?s=200&v=4" alt="Ten" height="40" style="margin: 10px;"></a>
<a href="https://openagents.org"><img src="assets/partners/openagents.png" alt="OpenAgents" height="40" style="margin: 10px;"></a>
<a href="https://github.com/milvus-io/milvus"><img src="https://miro.medium.com/v2/resize:fit:2400/1*-VEGyAgcIBD62XtZWavy8w.png" alt="Milvus" height="40" style="margin: 10px;"></a>
<a href="https://xroute.ai/"><img src="assets/partners/xroute.png" alt="xRoute" height="40" style="margin: 10px;"></a>
<a href="https://jaaz.app/"><img src="assets/partners/jazz.png" alt="Jazz" height="40" style="margin: 10px;"></a>
<a href="https://github.com/Buddie-AI/Buddie"><img src="assets/partners/buddie.png" alt="Buddie" height="40" style="margin: 10px;"></a>
<a href="https://github.com/bytebase/bytebase"><img src="assets/partners/bytebase.png" alt="Bytebase" height="40" style="margin: 10px;"></a>
<a href="https://github.com/LazyAGI/LazyLLM"><img src="assets/partners/LazyLLM.png" alt="LazyLLM" height="40" style="margin: 10px;"></a>
<a href="https://clawdchat.ai/"><img src="assets/partners/Clawdchat.png" alt="Clawdchat" height="40" style="margin: 10px;"></a>
</div>
---
## 🤝 How to Contribute
We welcome contributions from the community! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
### Getting Started
To start contributing to MemU, you'll need to set up your development environment:
#### Prerequisites
- Python 3.13+
- [uv](https://github.com/astral-sh/uv) (Python package manager)
- Git
#### Setup Development Environment
```bash
# 1. Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/memU.git
cd memU
# 2. Install development dependencies
make install
```
The `make install` command will:
- Create a virtual environment using `uv`
- Install all project dependencies
- Set up pre-commit hooks for code quality checks
#### Running Quality Checks
Before submitting your contribution, ensure your code passes all quality checks:
```bash
make check
```
The `make check` command runs:
- **Lock file verification**: Ensures `pyproject.toml` consistency
- **Pre-commit hooks**: Lints code with Ruff, formats with Black
- **Type checking**: Runs `mypy` for static type analysis
- **Dependency analysis**: Uses `deptry` to find obsolete dependencies
### Contributing Guidelines
For detailed contribution guidelines, code standards, and development practices, please see [CONTRIBUTING.md](CONTRIBUTING.md).
**Quick tips:**
- Create a new branch for each feature or bug fix
- Write clear commit messages
- Add tests for new functionality
- Update documentation as needed
- Run `make check` before pushing
---
## 📄 License
[Apache License 2.0](LICENSE.txt)
---
## 🌍 Community
- **GitHub Issues**: [Report bugs & request features](https://github.com/NevaMind-AI/memU/issues)
- **Discord**: [Join the community](https://discord.com/invite/hQZntfGsbJ)
- **X (Twitter)**: [Follow @memU_ai](https://x.com/memU_ai)
- **Contact**: info@nevamind.ai
---
<div align="center">
⭐ **Star us on GitHub** to get notified about new releases!
</div>
## /assets/banner.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/banner.png
## /assets/benchmark.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/benchmark.png
## /assets/memUbot.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/memUbot.png
## /assets/memorize.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/memorize.png
## /assets/partners/Clawdchat.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/Clawdchat.png
## /assets/partners/LazyLLM.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/LazyLLM.png
## /assets/partners/buddie.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/buddie.png
## /assets/partners/bytebase.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/bytebase.png
## /assets/partners/jazz.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/jazz.png
## /assets/partners/openagents.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/openagents.png
## /assets/partners/xroute.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/partners/xroute.png
## /assets/qrcode.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/qrcode.png
## /assets/retrieve.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/retrieve.png
## /assets/star.gif
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/star.gif
## /assets/structure.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/structure.png
## /assets/usecase/ai_companion-0000.jpg
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_companion-0000.jpg
## /assets/usecase/ai_creation-0000.jpg
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_creation-0000.jpg
## /assets/usecase/ai_edu-0000.jpg
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_edu-0000.jpg
## /assets/usecase/ai_ip-0000.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_ip-0000.png
## /assets/usecase/ai_robot-0000.jpg
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_robot-0000.jpg
## /assets/usecase/ai_role_play-0000.jpg
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_role_play-0000.jpg
## /assets/usecase/ai_therapy-0000.jpg
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/assets/usecase/ai_therapy-0000.jpg
## /docs/HACKATHON_ISSUE_DRAFT.md
# GitHub Issue Draft: Memory Types + Tool Memory
## Title
`[2026NewYearChallenge] Specialized Memory Types with Tool Learning`
---
## Description
### What will this task implement?
This PR enhances MemU's memory type system to support specialized memory structures with type-specific metadata and introduces Tool Memory for agent self-improvement.
**Current State:** MemU has a `memory_type` field with 5 types (profile, event, knowledge, behavior, skill) and uses different LLM prompts to extract each type. However, after extraction, all memories share the same storage schema - just `summary` and `embedding`. There's no type-specific metadata, no type-aware retrieval, and no way for agents to learn from their tool usage.
**Enhancement:** Extend the memory system to support:
- Type-specific metadata fields (e.g., `when_to_use` for smarter retrieval)
- Tool Memory type for tracking tool execution history
- Tool usage statistics for agent self-improvement
- Type-aware retrieval filtering
**Key Benefits:**
- Agents can learn from their own tool usage patterns
- Smarter retrieval based on memory context
- Foundation for agents that improve over time
- Better alignment with agentic application needs
---
## Requirements
- [x] Type-specific metadata schema with `when_to_use` field
- [x] Tool Memory implementation with execution tracking
- [x] Tool statistics (success_rate, avg_time_cost, avg_score)
- [ ] Type-aware retrieval filtering
- [x] Tests for Tool Memory CRUD and statistics
- [ ] Documentation and usage examples
---
## Review Criteria
- Correctness: All tests pass, no regressions
- Quality: Clean code, follows existing patterns
- DX: Clear documentation and examples
- Impact: Enables agent self-improvement use cases
---
## Implementation Summary
### Files Modified:
1. `src/memu/database/models.py` - Added `ToolCallResult` model, extended `MemoryItem` with `when_to_use`, `metadata`, `tool_calls` fields
2. `src/memu/database/repositories/memory_item.py` - Updated interface with new fields
3. `src/memu/database/inmemory/repositories/memory_item_repo.py` - Updated implementation
4. `src/memu/database/postgres/repositories/memory_item_repo.py` - Updated implementation
5. `src/memu/database/postgres/models.py` - Added JSON columns for new fields
6. `src/memu/prompts/memory_type/__init__.py` - Added tool type
7. `src/memu/prompts/memory_type/tool.py` - New prompt for tool memory extraction
### Files Added:
1. `tests/test_tool_memory.py` - 14 unit tests for Tool Memory feature
---
## Notes
This builds on MemU's existing memory type foundation while adding the specialized structures needed for agentic applications. The Tool Memory feature is particularly valuable for agents that need to learn which tools work best in different situations.
## /docs/HACKATHON_MAD_COMBOS.md
# 🔥🔥🔥 MAD COMBO OPTIONS FOR MEMU HACKATHON 🔥🔥🔥
> **Goal:** Implement high-impact features that MemU is missing, sourced from competitor analysis of 7 memory repos (memoripy, memlayer, ReMe, memX, memphora-sdk, MemOS, memor).
---
## 📋 COMPLETE FEATURE GAP ANALYSIS
### FEATURES MEMU IS MISSING (Deep Scan Results)
#### FROM MEMORIPY:
- ❌ `access_counts[]` - Track how often each memory is accessed
- ❌ `timestamps[]` - Track when memory was created/last accessed
- ❌ `decay_factor` - Exponential time-based decay: `np.exp(-decay_rate * time_diff)`
- ❌ `reinforcement_factor` - Log-scaled access boost: `np.log1p(access_count)`
- ❌ `adjusted_similarity` - `similarity * decay_factor * reinforcement_factor`
- ❌ Short-term → Long-term memory promotion (when `access_count > 10`)
- ❌ `nx.Graph()` concept associations (NetworkX graph)
- ❌ `spreading_activation()` - Spread activation through concept graph
- ❌ `cluster_interactions()` - KMeans clustering for hierarchical memory
- ❌ `semantic_memory` clusters - Retrieve from semantic memory clusters
#### FROM MEMLAYER:
- ❌ `SalienceGate` - Filter what's worth saving vs noise
- ❌ `SalienceMode.LOCAL` - Local ML model for salience
- ❌ `SalienceMode.ONLINE` - OpenAI API for salience
- ❌ `SalienceMode.LIGHTWEIGHT` - Keyword-based salience (no embeddings)
- ❌ `SALIENT_PROTOTYPES` / `NON_SALIENT_PROTOTYPES` - Prototype sentences
- ❌ `is_worth_saving()` - Determine if text should be saved
- ❌ `CurationService` - Background memory decay/expiration
- ❌ `_calculate_relevance()` - Score based on age, recency, attention
- ❌ Auto-archive low-relevance memories
- ❌ Auto-delete expired memories (`expiration_timestamp`)
- ❌ `SchedulerService` - Background task scheduler
- ❌ `get_due_tasks_for_user()` - Check for pending scheduled tasks
- ❌ `ConsolidationService` - Background knowledge extraction
- ❌ `analyze_and_extract_knowledge()` - Extract facts, entities, relationships
- ❌ `NetworkXStorage` - Graph storage for entities/relationships
- ❌ `add_entity()` / `add_relationship()` - Knowledge graph operations
- ❌ `get_subgraph_context()` - Graph traversal for context
- ❌ `find_matching_nodes()` - Fuzzy entity matching
- ❌ `_find_canonical_entity()` - Entity deduplication
- ❌ `_merge_entity_nodes()` - Merge duplicate entities
- ❌ `importance_score` / `expiration_timestamp` metadata
- ❌ `track_memory_access()` - Track when memories are accessed
- ❌ Task reminders system (`add_task`, `get_pending_tasks`, `update_task_status`)
#### FROM REME:
- ❌ `UpdateMemoryFreqOp` - Increment frequency counter on recall
- ❌ `metadata["freq"]` - Frequency counter in metadata
- ❌ `UpdateMemoryUtilityOp` - Increment utility score when useful
- ❌ `metadata["utility"]` - Utility score in metadata
- ❌ `DeleteMemoryOp` - Delete based on freq/utility thresholds
- ❌ `utility/freq < threshold` pruning - Prune low-value memories
- ❌ **MEMORY TYPES:**
- ❌ `TaskMemory` - Task-related information
- ❌ `PersonalMemory` - Personal info with `target` and `reflection_subject`
- ❌ `ToolMemory` - Tool call execution history
- ❌ `ToolCallResult` - Record tool execution results with hash deduplication
- ❌ `MemoryDeduplicationOp` - Remove duplicate memories using embedding similarity
- ❌ `WorkingMemory` operations:
- ❌ `MessageCompressOp` - LLM-based compression for long conversations
- ❌ `MessageCompactOp` - Compact verbose tool messages
- ❌ `MessageOffloadOp` - Orchestrate compaction + compression
- ❌ `WorkingSummaryMode.COMPACT/COMPRESS/AUTO`
- ❌ `UpdateMemory` tool - Update/edit existing memories
- ❌ `session_memory_id` tracking - Track memories per session
- ❌ Tool memory statistics (`avg_token_cost`, `success_rate`, `avg_time_cost`, `avg_score`)
#### FROM MEMX:
- ❌ `pubsub.py` - Real-time pub/sub system
- ❌ `subscribe(key, websocket)` - WebSocket subscriptions
- ❌ `publish(key, payload)` - Broadcast updates to subscribers
- ❌ `set_value()` with timestamps - Last-write-wins with timestamps
- ❌ Redis-backed shared memory - Multi-agent shared state
- ❌ `register_schema()` / `validate_schema()` - JSON schema validation
#### FROM MEMOS (MemOS):
- ❌ **Memory Scheduler System:**
- ❌ `BaseScheduler` - Full task scheduling infrastructure
- ❌ `SchedulerDispatcher` - Parallel task dispatch
- ❌ `ScheduleTaskQueue` - Priority task queue
- ❌ `TaskStatusTracker` - Track task status in Redis
- ❌ `TaskPriorityLevel` - Priority levels for tasks
- ❌ `MemoryMonitorItem` - Monitor memory with importance scores
- ❌ `replace_working_memory()` - Replace working memory after reranking
- ❌ `update_activation_memory()` - Update activation memory periodically
- ❌ `transform_working_memories_to_monitors()` - Convert memories to monitors
- ❌ `visibility` field - Public/private memory visibility
- ❌ `confidence` score - Confidence level for memories
- ❌ `status` field (activated/archived) - Memory activation status
- ❌ `tags` field - Memory tagging system
- ❌ `entities` extraction - Extract entities from memories
#### FROM MEMPHORA-SDK:
- ❌ `store_shared()` - Store shared memory for groups
- ❌ Multi-agent crew memory - Shared memory for agent crews
- ❌ Per-agent namespaces - Isolated memory per agent
- ❌ Framework integrations (AutoGen, CrewAI, LangChain, LlamaIndex)
---
---
## 🏆 COMBO 1: "INTELLIGENT MEMORY LIFECYCLE"
**Theme:** Memory that learns, ages, and self-curates like human memory
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Decay & Reinforcement | memoripy | 3 pts | LOW |
| Frequency & Utility Tracking | ReMe | 3 pts | LOW |
| Auto-Pruning Low-Value Memories | ReMe | 3 pts | LOW |
**Total: 9 pts | LOW-MEDIUM effort**
### Why it's MAD:
```
Memory accessed often → gets STRONGER (reinforcement)
Memory ignored → gets WEAKER (decay)
Memory with low utility/freq ratio → gets DELETED automatically
Result: Self-healing, self-optimizing memory that mimics human forgetting!
```
### The Pitch:
> "MemU now has HUMAN-LIKE memory - it remembers what matters and forgets what doesn't!"
### Technical Implementation:
```python
# Decay formula (from memoripy)
decay_factor = np.exp(-decay_rate * time_diff)
reinforcement_factor = np.log1p(access_count)
adjusted_similarity = similarity * decay_factor * reinforcement_factor
# Pruning logic (from ReMe)
if freq >= freq_threshold:
if utility / freq < utility_threshold:
delete_memory(memory_id)
```
---
## 🏆 COMBO 2: "SMART MEMORY GATE"
**Theme:** Don't save garbage, only save gold
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Salience Filtering | memlayer | 3-5 pts | MEDIUM |
| Decay & Reinforcement | memoripy | 3 pts | LOW |
| Background Curation Service | memlayer | 3 pts | MEDIUM |
**Total: 9-11 pts | MEDIUM effort**
### Why it's MAD:
```
INPUT: "Hello!" → BLOCKED (not salient)
INPUT: "My name is John, I work at Google" → SAVED (salient)
BACKGROUND: Old unused memories → AUTO-ARCHIVED
RETRIEVAL: Frequently accessed → BOOSTED
Result: Clean, high-quality memory that doesn't bloat!
```
### The Pitch:
> "MemU now has a BOUNCER - only important memories get in, garbage stays out!"
### Technical Implementation:
```python
# Salience Gate (from memlayer)
class SalienceGate:
SALIENT_PROTOTYPES = ["My name is...", "I work at...", "The deadline is..."]
NON_SALIENT_PROTOTYPES = ["Hello", "Thanks", "Okay", "Got it"]
def is_worth_saving(self, text: str) -> bool:
# Compare similarity to salient vs non-salient prototypes
salient_score = max_similarity(text, SALIENT_PROTOTYPES)
non_salient_score = max_similarity(text, NON_SALIENT_PROTOTYPES)
return salient_score > (non_salient_score + threshold)
```
---
## 🏆 COMBO 3: "KNOWLEDGE BRAIN"
**Theme:** Memory that understands relationships
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Knowledge Graph | memlayer | 5 pts | HIGH |
| Entity Extraction | memlayer | 3 pts | MEDIUM |
| Graph Traversal Retrieval | memlayer | 3 pts | MEDIUM |
**Total: 11 pts | HIGH effort**
### Why it's MAD:
```
INPUT: "John works at Google. Sarah is John's wife."
GRAPH:
John --[works_at]--> Google
John --[married_to]--> Sarah
QUERY: "Who is related to Google?"
RESULT: John (works there), Sarah (married to John who works there)
Result: Memory that REASONS about relationships!
```
### The Pitch:
> "MemU now has a BRAIN - it understands how things connect!"
### Technical Implementation:
```python
# Knowledge Graph (from memlayer)
import networkx as nx
class KnowledgeGraph:
def __init__(self):
self.graph = nx.Graph()
def add_entity(self, name: str, node_type: str):
self.graph.add_node(name, type=node_type)
def add_relationship(self, subject: str, predicate: str, obj: str):
self.graph.add_edge(subject, obj, relation=predicate)
def get_subgraph_context(self, entity: str, depth: int = 2):
# Traverse graph for related entities
return nx.ego_graph(self.graph, entity, radius=depth)
```
---
## 🏆 COMBO 4: "MEMORY EVOLUTION" ⭐ TOP PICK
**Theme:** Memory that evolves and improves itself
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Salience Gate (LIGHTWEIGHT mode) | memlayer | 3 pts | LOW |
| Decay & Reinforcement | memoripy | 3 pts | LOW |
| Frequency & Utility | ReMe | 3 pts | LOW |
| Auto-Pruning | ReMe | 3 pts | LOW |
**Total: 12 pts | LOW-MEDIUM effort**
### Why it's MAD:
```
STAGE 1: Salience Gate filters noise at INPUT
STAGE 2: Decay/Reinforcement adjusts scores at RETRIEVAL
STAGE 3: Frequency/Utility tracks VALUE over time
STAGE 4: Auto-Pruning DELETES low-value memories
Result: FULL LIFECYCLE MANAGEMENT - from birth to death!
```
### The Pitch:
> "MemU memories now have a LIFECYCLE - they're born, they grow, they age, they die!"
### Memory Lifecycle Diagram:
```
┌─────────────────────────────────────────────────────────────────┐
│ MEMORY LIFECYCLE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ INPUT ──► [SALIENCE GATE] ──► SAVE or REJECT │
│ │ │
│ ▼ │
│ ┌─────────┐ │
│ │ MEMORY │ ◄── access_count, last_accessed │
│ │ ITEM │ ◄── freq, utility, salience_score │
│ └────┬────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ ▼ ▼ │
│ [RETRIEVAL] [BACKGROUND] │
│ │ │ │
│ decay_factor auto_prune() │
│ reinforcement if utility/freq < threshold │
│ │ │ │
│ ▼ ▼ │
│ BOOSTED SCORE DELETE MEMORY │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 📊 COMPARISON TABLE
| Combo | Points | Effort | WOW Factor | Complexity | Recommendation |
|-------|--------|--------|------------|------------|----------------|
| 1. Intelligent Lifecycle | 9 | LOW | ⭐⭐⭐⭐ | LOW | ✅ SAFE BET |
| 2. Smart Gate | 9-11 | MEDIUM | ⭐⭐⭐⭐ | MEDIUM | ✅ GOOD |
| 3. Knowledge Brain | 11 | HIGH | ⭐⭐⭐⭐⭐ | HIGH | ⚠️ RISKY |
| 4. Memory Evolution | 12 | LOW-MED | ⭐⭐⭐⭐⭐ | MEDIUM | 🏆 **BEST COMBO** |
---
## 🎯 RECOMMENDATION: COMBO 4 "MEMORY EVOLUTION"
### Why This Combo Wins:
1. **12 points** - highest point potential
2. **LOW-MEDIUM effort** - achievable in hackathon timeframe
3. **4 features that SYNERGIZE** - each builds on the other
4. **UNIQUE story** - "memory lifecycle" is a compelling narrative
5. **Easy to demo** - show memory being filtered, decaying, getting pruned
### Implementation Order:
```
Step 1: Add fields to MemoryItem model
- access_count: int = 0
- last_accessed: datetime
- freq: int = 0
- utility: int = 0
- salience_score: float = 0.0
Step 2: Implement lightweight salience gate (keyword-based, no ML)
- SALIENT_KEYWORDS list
- NON_SALIENT_KEYWORDS list
- is_worth_saving() function
Step 3: Implement decay-aware retrieval
- Modify cosine_topk() to apply decay formula
- Update access_count and last_accessed on retrieval
Step 4: Implement frequency/utility tracking
- Increment freq on every retrieval
- Increment utility when memory contributes to response
Step 5: Implement auto-pruning
- Background check for low utility/freq ratio
- Delete memories below threshold
```
### Files to Modify:
```
memU/src/memu/database/models.py # Add new fields
memU/src/memu/database/inmemory/vector.py # Decay-aware retrieval
memU/src/memu/app/memorize.py # Salience gate
memU/src/memu/app/retrieve.py # Frequency/utility tracking
memU/src/memu/app/service.py # Auto-pruning service
```
---
## 📚 Reference Implementations
### From memoripy (Decay & Reinforcement):
- File: `prospects/memoripy/memoripy/memory_store.py`
- Key functions: `retrieve()`, `classify_memory()`
### From memlayer (Salience Gate):
- File: `prospects/memlayer/memlayer/ml_gate.py`
- Key class: `SalienceGate`
### From ReMe (Frequency & Utility):
- Files:
- `prospects/ReMe/reme_ai/vector_store/update_memory_freq_op.py`
- `prospects/ReMe/reme_ai/vector_store/update_memory_utility_op.py`
- `prospects/ReMe/reme_ai/vector_store/delete_memory_op.py`
---
## 🚀 Ready to Implement?
Choose your combo and let's build! 🔥
## 🏆 UPDATED MAD COMBOS (After Deep Scan)
---
## 🏆 COMBO 1: "INTELLIGENT MEMORY LIFECYCLE"
**Theme:** Memory that learns, ages, and self-curates like human memory
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Decay & Reinforcement | memoripy | 3 pts | LOW |
| Frequency & Utility Tracking | ReMe | 3 pts | LOW |
| Auto-Pruning Low-Value Memories | ReMe | 3 pts | LOW |
**Total: 9 pts | LOW-MEDIUM effort**
### Why it's MAD:
```
Memory accessed often → gets STRONGER (reinforcement)
Memory ignored → gets WEAKER (decay)
Memory with low utility/freq ratio → gets DELETED automatically
Result: Self-healing, self-optimizing memory that mimics human forgetting!
```
### The Pitch:
> "MemU now has HUMAN-LIKE memory - it remembers what matters and forgets what doesn't!"
---
## 🏆 COMBO 2: "SMART MEMORY GATE"
**Theme:** Don't save garbage, only save gold
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Salience Filtering | memlayer | 3-5 pts | MEDIUM |
| Decay & Reinforcement | memoripy | 3 pts | LOW |
| Background Curation Service | memlayer | 3 pts | MEDIUM |
**Total: 9-11 pts | MEDIUM effort**
### Why it's MAD:
```
INPUT: "Hello!" → BLOCKED (not salient)
INPUT: "My name is John, I work at Google" → SAVED (salient)
BACKGROUND: Old unused memories → AUTO-ARCHIVED
RETRIEVAL: Frequently accessed → BOOSTED
Result: Clean, high-quality memory that doesn't bloat!
```
### The Pitch:
> "MemU now has a BOUNCER - only important memories get in, garbage stays out!"
---
## 🏆 COMBO 3: "KNOWLEDGE BRAIN"
**Theme:** Memory that understands relationships
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Knowledge Graph (NetworkX) | memlayer | 5 pts | HIGH |
| Entity Extraction & Deduplication | memlayer | 3 pts | MEDIUM |
| Graph Traversal Retrieval | memlayer | 3 pts | MEDIUM |
**Total: 11 pts | HIGH effort**
### Why it's MAD:
```
INPUT: "John works at Google. Sarah is John's wife."
GRAPH:
John --[works_at]--> Google
John --[married_to]--> Sarah
QUERY: "Who is related to Google?"
RESULT: John (works there), Sarah (married to John who works there)
Result: Memory that REASONS about relationships!
```
### The Pitch:
> "MemU now has a BRAIN - it understands how things connect!"
---
## 🏆 COMBO 4: "MEMORY EVOLUTION" ⭐ TOP PICK
**Theme:** Memory that evolves and improves itself
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| Salience Gate (LIGHTWEIGHT mode) | memlayer | 3 pts | LOW |
| Decay & Reinforcement | memoripy | 3 pts | LOW |
| Frequency & Utility | ReMe | 3 pts | LOW |
| Auto-Pruning | ReMe | 3 pts | LOW |
**Total: 12 pts | LOW-MEDIUM effort**
### Why it's MAD:
```
STAGE 1: Salience Gate filters noise at INPUT
STAGE 2: Decay/Reinforcement adjusts scores at RETRIEVAL
STAGE 3: Frequency/Utility tracks VALUE over time
STAGE 4: Auto-Pruning DELETES low-value memories
Result: FULL LIFECYCLE MANAGEMENT - from birth to death!
```
### The Pitch:
> "MemU memories now have a LIFECYCLE - they're born, they grow, they age, they die!"
---
## 🏆 COMBO 5: "MEMORY TYPES" (NEW!)
**Theme:** Different memory types for different purposes
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| TaskMemory type | ReMe | 3 pts | MEDIUM |
| PersonalMemory type | ReMe | 3 pts | MEDIUM |
| ToolMemory type | ReMe | 5 pts | HIGH |
| Memory Deduplication | ReMe | 3 pts | MEDIUM |
**Total: 14 pts | MEDIUM-HIGH effort**
### Why it's MAD:
```
TaskMemory: "Complete the report by Friday"
- when_to_use: "When user asks about deadlines"
- content: "Report due Friday"
PersonalMemory: "User prefers dark mode"
- target: "user_preferences"
- reflection_subject: "ui_settings"
ToolMemory: "file_reader tool usage history"
- tool_call_results: [...]
- statistics: {avg_token_cost, success_rate, avg_score}
Result: Specialized memory for specialized tasks!
```
### The Pitch:
> "MemU now has SPECIALIZED MEMORY - task memory, personal memory, tool memory!"
---
## 🏆 COMBO 6: "WORKING MEMORY COMPRESSION" (NEW!)
**Theme:** Handle long conversations without losing context
| Component | Source | Points | Effort |
|-----------|--------|--------|--------|
| MessageCompressOp | ReMe | 3 pts | MEDIUM |
| MessageCompactOp | ReMe | 3 pts | MEDIUM |
| MessageOffloadOp | ReMe | 3 pts | MEDIUM |
**Total: 9 pts | MEDIUM effort**
### Why it's MAD:
```
LONG CONVERSATION (50k tokens) → COMPRESS → STATE SNAPSHOT (5k tokens)
Modes:
- COMPACT: Store full content externally, keep short previews
- COMPRESS: LLM-based compression to generate dense summaries
- AUTO: Compact first, then compress if needed
Result: Handle infinite conversations without context overflow!
```
### The Pitch:
> "MemU now handles INFINITE conversations - compress, compact, never forget!"
---
## 📊 UPDATED COMPARISON TABLE
| Combo | Points | Effort | WOW Factor | Complexity | Recommendation |
|-------|--------|--------|------------|------------|----------------|
| 1. Intelligent Lifecycle | 9 | LOW | ⭐⭐⭐⭐ | LOW | ✅ SAFE BET |
| 2. Smart Gate | 9-11 | MEDIUM | ⭐⭐⭐⭐ | MEDIUM | ✅ GOOD |
| 3. Knowledge Brain | 11 | HIGH | ⭐⭐⭐⭐⭐ | HIGH | ⚠️ RISKY |
| 4. Memory Evolution | 12 | LOW-MED | ⭐⭐⭐⭐⭐ | MEDIUM | 🏆 **BEST COMBO** |
| 5. Memory Types | 14 | MED-HIGH | ⭐⭐⭐⭐⭐ | HIGH | 🔥 HIGH POINTS |
| 6. Working Memory | 9 | MEDIUM | ⭐⭐⭐⭐ | MEDIUM | ✅ GOOD |
---
## 🎯 FINAL RECOMMENDATION
### For MAX POINTS with REASONABLE EFFORT: **COMBO 4 "MEMORY EVOLUTION"**
**Why?**
1. **12 points** - highest point potential for effort
2. **LOW-MEDIUM effort** - achievable in hackathon timeframe
3. **4 features that SYNERGIZE** - each builds on the other
4. **UNIQUE story** - "memory lifecycle" is a compelling narrative
5. **Easy to demo** - show memory being filtered, decaying, getting pruned
### Implementation Order:
```
Step 1: Add fields to MemoryItem model
- access_count: int = 0
- last_accessed: datetime
- freq: int = 0
- utility: int = 0
- salience_score: float = 0.0
Step 2: Implement lightweight salience gate (keyword-based, no ML)
- SALIENT_KEYWORDS list
- NON_SALIENT_KEYWORDS list
- is_worth_saving() function
Step 3: Implement decay-aware retrieval
- Modify cosine_topk() to apply decay formula
- Update access_count and last_accessed on retrieval
Step 4: Implement frequency/utility tracking
- Increment freq on every retrieval
- Increment utility when memory contributes to response
Step 5: Implement auto-pruning
- Background check for low utility/freq ratio
- Delete memories below threshold
```
### Files to Modify:
```
memU/src/memu/database/models.py # Add new fields
memU/src/memu/database/inmemory/vector.py # Decay-aware retrieval
memU/src/memu/app/memorize.py # Salience gate
memU/src/memu/app/retrieve.py # Frequency/utility tracking
memU/src/memu/app/service.py # Auto-pruning service
```
---
## 📚 Reference Implementations
### From memoripy (Decay & Reinforcement):
- File: `prospects/memoripy/memoripy/memory_store.py`
- Key functions: `retrieve()`, `classify_memory()`
### From memlayer (Salience Gate + Knowledge Graph):
- File: `prospects/memlayer/memlayer/ml_gate.py` - SalienceGate
- File: `prospects/memlayer/memlayer/storage/networkx.py` - Knowledge Graph
- File: `prospects/memlayer/memlayer/services.py` - CurationService
### From ReMe (Frequency & Utility + Memory Types):
- File: `prospects/ReMe/reme_ai/vector_store/update_memory_freq_op.py`
- File: `prospects/ReMe/reme_ai/vector_store/update_memory_utility_op.py`
- File: `prospects/ReMe/reme_ai/vector_store/delete_memory_op.py`
- File: `prospects/ReMe/reme_ai/schema/memory.py` - Memory types
- File: `prospects/ReMe/reme_ai/summary/task/memory_deduplication_op.py`
- File: `prospects/ReMe/reme_ai/summary/working/` - Working memory ops
### From MemOS (Scheduler):
- File: `prospects/MemOS/src/memos/mem_scheduler/base_scheduler.py`
---
## 🚀 Ready to Implement?
Choose your combo and let's build! 🔥
## /docs/adr/0001-workflow-pipeline-architecture.md
# ADR 0001: Use Workflow Pipelines for Core Operations
- Status: Accepted
- Date: 2026-02-24
## Context
memU has multiple high-level operations (`memorize`, `retrieve`, and CRUD/patch operations) that each require multi-stage execution, LLM calls, storage writes, and optional short-circuit behavior.
A single monolithic function per operation would make these flows hard to extend, observe, and customize.
## Decision
Model each core operation as a named workflow pipeline composed of ordered `WorkflowStep` units.
- Register pipelines centrally in `MemoryService` via `PipelineManager`
- Validate required/produced state keys at pipeline registration/mutation time
- Execute through a `WorkflowRunner` abstraction (`local` by default)
- Support runtime customization by step-level config and structural mutation (insert/replace/remove)
- Provide before/after/on_error step interceptors for instrumentation and control
## Consequences
Positive:
- uniform execution model across memorize/retrieve/CRUD
- explicit, inspectable stage boundaries
- extension points for custom runners and step customization
- easier interception and observability around stage execution
Negative:
- dict-based workflow state relies on key naming discipline
- pipeline mutation can increase behavioral variance between deployments
- more framework code compared to direct function calls
## /docs/adr/0002-pluggable-storage-and-vector-strategy.md
# ADR 0002: Use Pluggable Storage with Backend-Specific Vector Search
- Status: Accepted
- Date: 2026-02-24
## Context
memU must support:
- zero-setup local development
- lightweight persisted deployments
- production deployments that need scalable vector similarity
No single storage engine fits all three cases.
## Decision
Adopt repository-based storage abstraction behind a `Database` protocol, with selectable providers:
- `inmemory`: in-process state, brute-force similarity
- `sqlite`: file-based persistence, embeddings stored as JSON text, brute-force similarity
- `postgres`: SQL persistence, pgvector-enabled similarity when configured
Vector behavior is backend-aware:
- brute-force cosine search remains available for portability
- Postgres can use pgvector distance queries when vector support is enabled
- salience ranking (reinforcement/recency-aware) uses local scoring logic
## Consequences
Positive:
- one service API works across local and production footprints
- clear backend contracts through repository interfaces
- predictable fallback behavior when native vector index is unavailable
Negative:
- duplicate repository logic across backends
- behavior/performance differences between providers
- SQLite and in-memory vector search does not scale as well as indexed pgvector
## /docs/adr/0003-user-scope-in-data-model.md
# ADR 0003: Model User Scope as First-Class Fields on Memory Records
- Status: Accepted
- Date: 2026-02-24
## Context
memU retrieval and writes need scoped operation (for example per `user_id`, `agent_id`, or session) for multi-user and multi-agent scenarios.
Keeping scope outside stored records would force ad-hoc filtering logic and weaken data isolation.
## Decision
Embed scope directly into all persisted entities by merging a configurable `UserConfig.model` with core record models.
- Scope fields are part of resource/category/item/relation models
- Repositories accept `user_data` on writes and `where` filters on reads
- API-level `where` filters are validated against configured scope fields before execution
## Consequences
Positive:
- consistent filtering model across memorize/retrieve/CRUD APIs
- backend-independent scoping semantics
- supports multi-tenant and multi-agent patterns without separate storage stacks
Negative:
- schema/model generation complexity increases
- schema and index shape can vary by chosen scope model
- callers must keep `where` and `user` payloads aligned with configured scope fields
## /docs/adr/README.md
# Architecture Decision Records
- [0001: Use Workflow Pipelines for Core Operations](0001-workflow-pipeline-architecture.md)
- [0002: Use Pluggable Storage with Backend-Specific Vector Search](0002-pluggable-storage-and-vector-strategy.md)
- [0003: Model User Scope as First-Class Fields on Memory Records](0003-user-scope-in-data-model.md)
## /docs/architecture.md
# memU Architecture
## Purpose and scope
This document describes the self-hosted `memu` Python package architecture as implemented in this repository.
The repository also describes a hosted Cloud product in `README.md`, but this document focuses on the local `MemoryService` runtime and its code paths.
## System overview
memU follows the "memory as file system" concept from the README and implements it with three persistent layers:
- `Resource`: raw source artifacts (conversation/document/image/video/audio)
- `MemoryItem`: extracted atomic memories with embeddings
- `MemoryCategory`: grouped topic summaries
- `CategoryItem`: item-category relation edges
At runtime, `MemoryService` orchestrates ingestion, retrieval, and manual CRUD over these layers.
```mermaid
flowchart TD
A["Input Resource or Query"] --> B["MemoryService"]
B --> C["Workflow Pipelines"]
C --> D["LLM Clients"]
C --> E["Database Repositories"]
E --> F["Resources"]
E --> G["Memory Items"]
E --> H["Memory Categories"]
E --> I["Category Relations"]
```
## Core runtime components
### `MemoryService` as composition root
`src/memu/app/service.py` constructs and owns:
- typed configs (`LLMProfilesConfig`, `DatabaseConfig`, `MemorizeConfig`, `RetrieveConfig`, `UserConfig`)
- storage backend (`build_database(...)`)
- resource filesystem fetcher (`LocalFS`)
- LLM client cache and wrappers
- workflow and LLM interceptor registries
- workflow runner (`local` by default, pluggable)
- named workflow pipelines via `PipelineManager`
Public APIs are assembled by mixins:
- `MemorizeMixin`: `memorize(...)`
- `RetrieveMixin`: `retrieve(...)`
- `CRUDMixin`: list/clear/create/update/delete memory operations
### Workflow engine
All major operations execute as workflows (`WorkflowStep`) with:
- explicit required/produced state keys
- declared capability tags (`llm`, `vector`, `db`, `io`, `vision`)
- per-step config (for profile selection)
`PipelineManager` validates step dependencies at registration/mutation time and supports runtime pipeline revisioning (`config_step`, `insert_before/after`, `replace_step`, `remove_step`).
`WorkflowRunner` is a protocol; default `LocalWorkflowRunner` executes sequentially with `run_steps(...)`.
### Interception and observability hooks
Two interceptor systems exist:
- workflow step interceptors: before/after/on_error around each step
- LLM call interceptors: before/after/on_error around `chat/summarize/vision/embed/transcribe`
LLM wrappers also extract best-effort usage metadata from raw provider responses.
## Ingestion architecture (`memorize`)
`memorize(...)` executes the `memorize` pipeline:
1. `ingest_resource`: fetch local/remote resource into `blob_config.resources_dir` via `LocalFS`
2. `preprocess_multimodal`: modality-specific preprocessing for conversation/document/audio (text-oriented path) and image/video (vision-oriented path)
3. `extract_items`: per-memory-type LLM extraction into structured entries
4. `dedupe_merge`: placeholder stage (currently pass-through)
5. `categorize_items`: persist resource + memory items + item-category relations and embeddings
6. `persist_index`: update category summaries; optionally persist item references
7. `build_response`: return resource(s), items, categories, relations
Category bootstrap is lazy and scoped: categories are initialized when needed with embeddings, and mapped by normalized category name.
## Retrieval architecture (`retrieve`)
`retrieve(...)` chooses one of two pipelines from config:
- `retrieve_rag` (embedding-driven ranking)
- `retrieve_llm` (LLM-driven ranking)
Both use the same staged pattern:
1. route intention + optional query rewrite
2. category recall
3. sufficiency check (optional)
4. item recall
5. sufficiency check (optional)
6. resource recall
7. response build
Key behavior:
- `where` filters are validated against `user_model` fields before querying
- RAG path uses vector similarity (and optional salience ranking for items)
- LLM path ranks IDs from formatted category/item/resource context
- each stage can stop early if sufficiency check decides context is enough
## Data and storage architecture
### Repository contracts
Storage is abstracted through a `Database` protocol with four repositories:
- `ResourceRepo`
- `MemoryItemRepo`
- `MemoryCategoryRepo`
- `CategoryItemRepo`
### Backends
`build_database(...)` selects backend by `database_config.metadata_store.provider`:
- `inmemory`: in-process dict/list state
- `sqlite`: SQLModel persistence, embeddings stored as JSON text, brute-force cosine search
- `postgres`: SQLModel persistence with pgvector support (when enabled), local fallback ranking when needed
For Postgres, startup runs migration bootstrap and attempts `CREATE EXTENSION IF NOT EXISTS vector` in `ddl_mode="create"`.
### Scope model propagation
`UserConfig.model` is merged into record/table models so scope fields (for example `user_id`) become first-class columns/attributes across resources, items, categories, and relations.
This is why `where` filters and `user_data` writes are consistently available across APIs.
## LLM/provider architecture
LLM access is profile-based (`llm_profiles`):
- `default` profile for chat-like tasks
- `embedding` profile for embedding tasks (auto-derived from default if not set)
Per-step profile routing happens through step config (`chat_llm_profile`, `embed_llm_profile`, or `llm_profile`).
Client backends:
- `sdk`: official OpenAI SDK wrapper
- `httpx`: provider-adapted HTTP backend (OpenAI, Doubao, Grok, OpenRouter)
- `lazyllm_backend`: LazyLLM adapter
## Integration surfaces
- `memu.client.openai_wrapper`: opt-in OpenAI client wrapper that auto-retrieves memories and injects them into system context
- `memu.integrations.langgraph`: LangChain/LangGraph tool adapter (`save_memory`, `search_memory`)
## Current constraints and tradeoffs
- workflow state is dict-based, so step contracts are validated by key names rather than static types
- SQLite/inmemory vector search is brute-force (portable but less scalable)
- category update quality and extraction quality are prompt/LLM dependent
- some extension hooks exist as placeholders (for example dedupe/merge stage)
## Related ADRs
- `docs/adr/0001-workflow-pipeline-architecture.md`
- `docs/adr/0002-pluggable-storage-and-vector-strategy.md`
- `docs/adr/0003-user-scope-in-data-model.md`
## /docs/integrations/grok.md
# Grok (xAI) Integration
MemU supports **Grok**, the AI model from xAI, as a first-class LLM provider.
## Prerequisites
1. **xAI Account:** You need an active account with [xAI](https://x.ai/).
2. **API Key:** Obtain an API key from the [xAI Console](https://console.x.ai/).
## Configuration
To enable Grok, you need to set the `XAI_API_KEY` environment variable.
### Environment Variable
```bash
export XAI_API_KEY="your-xai-api-key-here"
```
PowerShell:
```powershell
$env:XAI_API_KEY="your-xai-api-key-here"
```
## Usage
To use Grok as your LLM provider, switch the `provider` setting to `grok`. This can be done in your configuration file or when initializing the application.
### Python Example
```python
from memu.app.settings import LLMConfig
# Configure MemU to use Grok
config = LLMConfig(
provider="grok",
# The default API key env var is XAI_API_KEY
# The default model is grok-2-latest
)
print(f"Using provider: {config.provider}")
print(f"Base URL: {config.base_url}")
print(f"Chat Model: {config.chat_model}")
```
## Models Supported
We currently support the following Grok models:
* **grok-2-latest** (Default)
The integration automatically sets the base URL to `https://api.x.ai/v1`.
## /docs/langgraph_integration.md
# MemU LangGraph Integration
The MemU LangGraph Integration provides a seamless adapter to expose MemU's powerful memory capabilities (`memorize` and `retrieve`) as standard [LangChain](https://python.langchain.com/) / [LangGraph](https://langchain-ai.github.io/langgraph/) tools. This allows your agents to persist information and recall it across sessions using MemU as the long-term memory backend.
## Overview
This integration wraps the `MemoryService` and exposes two key tools:
- **`save_memory`**: Persists text, conversation snippets, or facts associated with a user.
- **`search_memory`**: Retrieves relevant memories based on semantic search queries.
These tools are fully typed and compatible with LangGraph's `prebuilt.ToolNode` and LangChain's agents.
## Installation
To use this integration, you need to install the optional dependencies:
```bash
uv add langgraph langchain-core
```
## Quick Start
Here is a complete example of how to initialize the MemU memory service and bind it to a LangGraph agent.
```python
import asyncio
import os
from memu.app.service import MemoryService
from memu.integrations.langgraph import MemULangGraphTools
# Ensure you have your configuration set (e.g., env vars for DB connection)
# os.environ["MEMU_DATABASE_URL"] = "..."
async def main():
# 1. Initialize MemoryService
memory_service = MemoryService()
# If your service requires async init (check your specific implementation):
# await memory_service.initialize()
# 2. Instantiate MemULangGraphTools
memu_tools = MemULangGraphTools(memory_service)
# Get the list of tools (BaseTool compatible)
tools = memu_tools.tools()
# 3. Example Usage: Manually invoking a tool
# In a real app, you would pass 'tools' to your LangGraph agent or StateGraph.
# Save a memory
save_tool = memu_tools.save_memory_tool()
print("Saving memory...")
result = await save_tool.ainvoke({
"content": "The user prefers dark mode.",
"user_id": "user_123",
"metadata": {"category": "preferences"}
})
print(f"Save Result: {result}")
# Search for a memory
search_tool = memu_tools.search_memory_tool()
print("\nSearching memory...")
search_result = await search_tool.ainvoke({
"query": "What are the user's preferences?",
"user_id": "user_123"
})
print(f"Search Result:\n{search_result}")
if __name__ == "__main__":
asyncio.run(main())
```
## API Reference
### `MemULangGraphTools`
The main adapter class.
```python
class MemULangGraphTools(memory_service: MemoryService)
```
#### `save_memory_tool() -> StructuredTool`
Returns a tool named `save_memory`.
- **Inputs**: `content` (str), `user_id` (str), `metadata` (dict, optional).
- **Description**: Save a piece of information, conversation snippet, or memory for a user.
#### `search_memory_tool() -> StructuredTool`
Returns a tool named `search_memory`.
- **Inputs**: `query` (str), `user_id` (str), `limit` (int, default=5), `metadata_filter` (dict, optional), `min_relevance_score` (float, default=0.0).
- **Description**: Search for relevant memories or information for a user based on a query.
## Troubleshooting
### Import Errors
If you see an `ImportError` regarding `langchain_core` or `langgraph`:
1. Ensure you have installed the extras: `uv add langgraph langchain-core` (or `pip install langgraph langchain-core`).
2. Verify your virtual environment is active.
## /docs/providers/grok.md
# Grok (xAI) Provider
memU includes first-class support for [Grok](https://grok.x.ai/), allowing you to leverage xAI's powerful language models directly within your application.
## Prerequisites
To use this provider, you must have an active xAI account.
1. Navigate to the [xAI Console](https://console.x.ai/).
2. Sign up or log in.
3. Create a new **API Key** in the API Keys section.
## Configuration
The integration is designed to work out-of-the-box with minimal configuration.
### Environment Variables
Set the following environment variable in your `.env` file or system environment:
```bash
GROK_API_KEY=xai-YOUR_API_KEY_HERE
```
### Defaults
When you select the `grok` provider, memU automatically configures the following defaults:
* **Base URL**: `https://api.x.ai/v1`
* **Model**: `grok-2-latest`
## Usage Example
You can enable the Grok provider by setting the `provider` field to `"grok"` in your application configuration.
### Using Python Configuration
```python
from memu.app.settings import LLMConfig
from memu.app.service import MemoryService
# Configure the LLM provider to use Grok
llm_config = LLMConfig(provider="grok")
# Initialize the service
service = MemoryService(llm_config=llm_config)
print(f"Service initialized with model: {llm_config.chat_model}")
# Output: Service initialized with model: grok-2-latest
```
## Troubleshooting
### Connection Issues
If you are unable to connect to the xAI API:
1. Verify that your `GROK_API_KEY` is set correctly and has not expired.
2. Ensure that the `base_url` is resolving to `https://api.x.ai/v1`. If you have manual overrides in your settings, they might be conflicting with the default.
### Model Availability
If you receive a `404` or "Model not found" error, xAI may have updated their model names. You can override the model manually in the config if needed:
```python
config = LLMConfig(
provider="grok",
chat_model="grok-beta" # Example override
)
```
## /docs/sealos-devbox-guide.md
# Deploying MemU on Sealos DevBox
This guide demonstrates how to build and deploy a **Personal AI Assistant with Long-Term Memory** using MemU on [Sealos DevBox](https://sealos.io/products/devbox).
## Overview
MemU enables AI agents to maintain persistent, structured memory across conversations. Combined with Sealos DevBox's 1-click cloud development environment, you can quickly build and deploy memory-enabled AI applications.
**What we'll build:**
- A FastAPI-based AI assistant that remembers user preferences and past conversations
- Persistent memory storage using MemU's in-memory or PostgreSQL backend
- Simple REST API for chat interactions
- One-click deployment to production
**Time to complete:** ~15 minutes
## Prerequisites
- [Sealos account](https://sealos.io) (free tier available)
- OpenAI API key (or compatible provider like Nebius, Groq)
## Step 1: Create a DevBox Environment
1. Log in to [Sealos Dashboard](https://cloud.sealos.io)
2. Navigate to **DevBox** module
3. Click **Create New Project**
4. Select **Python 3.11+** template
5. Configure resources (recommended: 2 vCPU, 4GB RAM)
6. Click **Create** - your environment will be ready in ~60 seconds
## Step 2: Connect Your IDE
1. In the DevBox project list, click the **VS Code** or **Cursor** button
2. Your local IDE will open with a secure SSH connection to the cloud environment
3. All code runs in the cloud, keeping your local machine free
## Step 3: Set Up the Project
Open the terminal in your connected IDE and run:
```bash
# Clone or create project directory
mkdir memu-assistant && cd memu-assistant
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install memu fastapi uvicorn python-dotenv
```
## Step 4: Create the Application
Create the following files in your project:
### `.env`
```env
# LLM Provider Configuration
OPENAI_API_KEY=your_api_key_here
OPENAI_BASE_URL=https://api.openai.com/v1
# Or use Nebius (OpenAI-compatible)
# OPENAI_API_KEY=your_nebius_key
# OPENAI_BASE_URL=https://api.tokenfactory.nebius.com/v1/
# Model Configuration
CHAT_MODEL=gpt-4o-mini
EMBED_MODEL=text-embedding-3-small
# Server Configuration
HOST=0.0.0.0
PORT=8000
```
### `main.py`
```python
"""
Personal AI Assistant with Long-Term Memory
Powered by MemU + FastAPI on Sealos DevBox
"""
import os
from contextlib import asynccontextmanager
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
load_dotenv()
# MemU imports
from memu.app import MemoryService
# Global memory service
memory_service: MemoryService | None = None
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Initialize MemU on startup."""
global memory_service
llm_profiles = {
"default": {
"provider": "openai",
"base_url": os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"),
"api_key": os.getenv("OPENAI_API_KEY"),
"chat_model": os.getenv("CHAT_MODEL", "gpt-4o-mini"),
"client_backend": "sdk",
},
"embedding": {
"provider": "openai",
"base_url": os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"),
"api_key": os.getenv("OPENAI_API_KEY"),
"embed_model": os.getenv("EMBED_MODEL", "text-embedding-3-small"),
"client_backend": "sdk",
},
}
memory_service = MemoryService(llm_profiles=llm_profiles)
print("✓ MemU Memory Service initialized")
yield
print("Shutting down...")
app = FastAPI(
title="MemU Assistant",
description="AI Assistant with Long-Term Memory",
lifespan=lifespan,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
class ChatRequest(BaseModel):
message: str
user_id: str = "default"
class ChatResponse(BaseModel):
response: str
memories_used: int
memories_stored: int
class MemorizeRequest(BaseModel):
content: str
user_id: str = "default"
@app.get("/")
async def root():
return {
"service": "MemU Assistant",
"status": "running",
"endpoints": ["/chat", "/memorize", "/recall", "/health"],
}
@app.get("/health")
async def health():
return {"status": "healthy", "memory_service": memory_service is not None}
@app.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest):
"""
Chat with the AI assistant. The assistant will:
1. Retrieve relevant memories from past conversations
2. Generate a response using those memories as context
3. Store new information from the conversation
"""
if not memory_service:
raise HTTPException(status_code=503, detail="Memory service not initialized")
# Step 1: Retrieve relevant memories
retrieve_result = await memory_service.retrieve(
queries=[{"role": "user", "content": request.message}]
)
memories = retrieve_result.get("items", [])
memories_context = ""
if memories:
memories_context = "\n\nRelevant memories from past conversations:\n"
for mem in memories[:5]: # Limit to top 5 memories
if isinstance(mem, dict):
memories_context += f"- {mem.get('summary', str(mem))}\n"
# Step 2: Generate response (simplified - in production, use full LLM call)
# For demo, we'll create a simple response acknowledging the memories
response_text = f"I received your message: '{request.message}'"
if memories:
response_text += f"\n\nI found {len(memories)} relevant memories that might help."
# Step 3: Store the conversation as a new memory
import tempfile
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write(f"User ({request.user_id}): {request.message}")
temp_file = f.name
try:
memorize_result = await memory_service.memorize(
resource_url=temp_file,
modality="text",
)
memories_stored = len(memorize_result.get("items", []))
finally:
os.unlink(temp_file)
return ChatResponse(
response=response_text,
memories_used=len(memories),
memories_stored=memories_stored,
)
@app.post("/memorize")
async def memorize(request: MemorizeRequest):
"""Store information in long-term memory."""
if not memory_service:
raise HTTPException(status_code=503, detail="Memory service not initialized")
import tempfile
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write(request.content)
temp_file = f.name
try:
result = await memory_service.memorize(
resource_url=temp_file,
modality="text",
)
return {
"status": "stored",
"items_created": len(result.get("items", [])),
"categories": len(result.get("categories", [])),
}
finally:
os.unlink(temp_file)
@app.get("/recall")
async def recall(query: str, limit: int = 5):
"""Recall memories related to a query."""
if not memory_service:
raise HTTPException(status_code=503, detail="Memory service not initialized")
result = await memory_service.retrieve(
queries=[{"role": "user", "content": query}]
)
items = result.get("items", [])[:limit]
return {
"query": query,
"memories_found": len(items),
"memories": [
{"summary": item.get("summary", str(item)) if isinstance(item, dict) else str(item)}
for item in items
],
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host=os.getenv("HOST", "0.0.0.0"),
port=int(os.getenv("PORT", 8000)),
reload=True,
)
```
### `requirements.txt`
```
memu>=0.1.0
fastapi>=0.100.0
uvicorn[standard]>=0.23.0
python-dotenv>=1.0.0
```
### `entrypoint.sh`
```bash
#!/bin/bash
source venv/bin/activate
uvicorn main:app --host 0.0.0.0 --port 8000
```
## Step 5: Test Locally in DevBox
```bash
# Run the application
python main.py
```
Use the DevBox preview feature to access your running application, or test with curl:
```bash
# Health check
curl http://localhost:8000/health
# Store a memory
curl -X POST http://localhost:8000/memorize \
-H "Content-Type: application/json" \
-d '{"content": "User prefers dark mode and uses Python for AI development"}'
# Chat with memory
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "What programming language do I use?"}'
# Recall memories
curl "http://localhost:8000/recall?query=programming%20preferences"
```
## Step 6: Deploy to Production
1. In the Sealos Dashboard, go to your DevBox project
2. Click **Create Release** to package your application
3. Click **Deploy** next to your release
4. Configure environment variables (OPENAI_API_KEY, etc.)
5. Click **Deploy** - your app will be live in minutes!
Your application will receive a public URL like: `https://your-app.cloud.sealos.io`
## Using with PostgreSQL (Optional)
For production deployments with persistent storage:
1. In Sealos Dashboard, go to **Database** module
2. Create a PostgreSQL instance
3. Update your `.env` with the connection string:
```env
DATABASE_URL=postgresql://user:password@host:5432/memu
```
4. Update `main.py` to use PostgreSQL backend (see MemU documentation)
## API Reference
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | GET | Service info |
| `/health` | GET | Health check |
| `/chat` | POST | Chat with memory-aware AI |
| `/memorize` | POST | Store information in memory |
| `/recall` | GET | Query stored memories |
## Architecture
```
┌─────────────────────────────────────────────────────────┐
│ Sealos DevBox │
│ ┌─────────────────────────────────────────────────┐ │
│ │ FastAPI Application │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │
│ │ │ /chat │ │/memorize│ │ /recall │ │ │
│ │ └────┬────┘ └────┬────┘ └────────┬────────┘ │ │
│ │ │ │ │ │ │
│ │ └────────────┼────────────────┘ │ │
│ │ │ │ │
│ │ ┌───────▼───────┐ │ │
│ │ │ MemU Service │ │ │
│ │ │ (Memory Mgmt)│ │ │
│ │ └───────┬───────┘ │ │
│ │ │ │ │
│ │ ┌────────────┼────────────┐ │ │
│ │ │ │ │ │ │
│ │ ┌────▼────┐ ┌────▼────┐ ┌───▼────┐ │ │
│ │ │ Vector │ │ LLM │ │Postgres│ │ │
│ │ │ Store │ │ API │ │(opt.) │ │ │
│ │ └─────────┘ └─────────┘ └────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
## Benefits of This Setup
- **Zero Infrastructure Management**: Sealos handles Kubernetes complexity
- **Instant Environment**: Ready-to-code in 60 seconds
- **Persistent Memory**: MemU maintains context across sessions
- **Scalable**: Easily scale resources as needed
- **Cost-Effective**: Pay only for what you use
## Next Steps
- Add authentication for multi-user support
- Integrate with Slack, Discord, or other platforms
- Use PostgreSQL for production-grade persistence
- Add conversation history UI
## Resources
- [MemU Documentation](https://github.com/NevaMind-AI/memU)
- [Sealos DevBox Guide](https://sealos.io/blog/how-to-setup-devbox)
- [FastAPI Documentation](https://fastapi.tiangolo.com)
---
*This guide was created for the MemU PR Hackathon - 2026 New Year Challenge (Issue #228)*
## /docs/sealos_use_case.md
# 🛡️ Context-Aware Support Agent (Sealos Edition)
## Overview
This use case demonstrates how **MemU** enables a support agent to remember user history across sessions, deployed on a **Sealos Devbox** environment.
Unlike a standard web app, this demo focuses on the **backend memory orchestration**. It runs as a **CLI (Command Line Interface)** tool to transparently show the internal memory logs, retrieval process, and state persistence without the abstraction layer of a UI.
## 🚀 Quick Start
### Prerequisites
- Sealos Devbox Environment
- Python 3.13+
- MemU Library (installed via `make install`)
### How to Run the Demo
Since this is a backend demonstration, you will run the agent directly in the terminal to observe the memory cycle.
```bash
uv run python examples/sealos_support_agent.py
```
## 📸 Live Demo Output (Proof of Concept)
Below is the actual output captured from the Sealos terminal. This serves as verification of the "Demonstration Quality" requirement.
```plaintext
🚀 Starting Sealos Support Agent Demo (Offline Mode)
📝 --- Phase 1: Ingesting Conversation History ---
👤 Captain: "I'm getting a 502 Bad Gateway error on port 3000."
🤖 Agent: (Memorizing this interaction...)
✅ Memory stored! extracted 2 items.
- [profile] Captain reported a 502 Bad Gateway error on port 3000.
🔍 --- Phase 2: Retrieval on New Interaction ---
👤 Captain: "Hello"
🤖 Agent: (Searching memory for context...)
💡 Retrieved Context:
Found Memory: Captain reported a 502 Bad Gateway error on port 3000.
💬 --- Phase 3: Agent Response ---
🤖 Agent: "Welcome back, Captain. I see you had a 502 error on port 3000 recently. Is that resolved?"
✨ Demo Completed Successfully
```
## 💡 Code Highlights & Justification
- **CLI vs Web**: We chose a CLI implementation to provide clear visibility into the memory ingestion and retrieval logs, which are often hidden in web implementations.
- **MockLLM**: Includes a MockLLM class to ensure the demo is 100% reproducible by reviewers without needing external API keys.
- **Sealos Native**: Optimized to run within the ephemeral Sealos Devbox container lifecycle.
## /docs/sqlite.md
# SQLite Database Integration
MemU supports SQLite as a lightweight, file-based database backend for memory storage. This is ideal for:
- **Local development** and testing
- **Single-user applications** with persistent storage
- **Portable deployments** where you need a simple database solution
- **Offline-capable applications** that can't rely on external databases
## Quick Start
### Basic Configuration
```python
from memu.app import MemoryService
# Using default SQLite file (memu.db in current directory)
service = MemoryService(
llm_profiles={"default": {"api_key": "your-api-key"}},
database_config={
"metadata_store": {
"provider": "sqlite",
},
},
)
# Or specify a custom database path
service = MemoryService(
llm_profiles={"default": {"api_key": "your-api-key"}},
database_config={
"metadata_store": {
"provider": "sqlite",
"dsn": "sqlite:///path/to/your/memory.db",
},
},
)
```
### In-Memory SQLite (No Persistence)
For testing or temporary storage, you can use an in-memory SQLite database:
```python
service = MemoryService(
llm_profiles={"default": {"api_key": "your-api-key"}},
database_config={
"metadata_store": {
"provider": "sqlite",
"dsn": "sqlite:///:memory:",
},
},
)
```
## Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `provider` | `str` | `"inmemory"` | Set to `"sqlite"` to use SQLite backend |
| `dsn` | `str` | `"sqlite:///memu.db"` | SQLite connection string |
### DSN Format
SQLite DSN follows this format:
- **File-based**: `sqlite:///path/to/database.db`
- **In-memory**: `sqlite:///:memory:`
- **Relative path**: `sqlite:///./data/memu.db`
- **Absolute path**: `sqlite:////home/user/data/memu.db` (note the 4 slashes)
## Vector Search
SQLite doesn't have native vector support like PostgreSQL's pgvector. MemU uses **brute-force cosine similarity** for vector search when using SQLite:
```python
service = MemoryService(
llm_profiles={"default": {"api_key": "your-api-key"}},
database_config={
"metadata_store": {
"provider": "sqlite",
"dsn": "sqlite:///memu.db",
},
"vector_index": {
"provider": "bruteforce", # This is the default for SQLite
},
},
)
```
**Note**: Brute-force search loads all embeddings into memory and computes similarity for each. This works well for moderate dataset sizes (up to ~100k items) but may be slow for larger datasets.
## Database Schema
SQLite creates the following tables automatically:
- `sqlite_resources` - Multimodal resource records (images, documents, etc.)
- `sqlite_memory_items` - Extracted memory items with embeddings
- `sqlite_memory_categories` - Memory categories with summaries
- `sqlite_category_items` - Relationships between items and categories
Embeddings are stored as JSON-serialized text in SQLite since there's no native vector type.
## Data Import/Export
### Export Data
You can export your SQLite database for backup or migration:
```python
import shutil
# Simply copy the database file
shutil.copy("memu.db", "memu_backup.db")
```
### Import from SQLite to PostgreSQL
To migrate data from SQLite to PostgreSQL:
```python
import json
from memu.database.sqlite import build_sqlite_database
from memu.database.postgres import build_postgres_database
from memu.app.settings import DatabaseConfig
from pydantic import BaseModel
class UserScope(BaseModel):
user_id: str
# Load from SQLite
sqlite_config = DatabaseConfig(
metadata_store={"provider": "sqlite", "dsn": "sqlite:///memu.db"}
)
sqlite_db = build_sqlite_database(config=sqlite_config, user_model=UserScope)
sqlite_db.load_existing()
# Connect to PostgreSQL
postgres_config = DatabaseConfig(
metadata_store={"provider": "postgres", "dsn": "postgresql://..."}
)
postgres_db = build_postgres_database(config=postgres_config, user_model=UserScope)
# Migrate resources
for res_id, resource in sqlite_db.resources.items():
postgres_db.resource_repo.create_resource(
url=resource.url,
modality=resource.modality,
local_path=resource.local_path,
caption=resource.caption,
embedding=resource.embedding,
user_data={"user_id": getattr(resource, "user_id", None)},
)
# Similar for categories, items, and relations...
```
## Performance Considerations
| Aspect | SQLite | PostgreSQL |
|--------|--------|------------|
| Setup | Zero configuration | Requires server setup |
| Concurrency | Single writer, multiple readers | Full concurrent access |
| Vector Search | Brute-force (in-memory) | Native pgvector (indexed) |
| Scale | Up to ~100k items | Millions of items |
| Deployment | Single file, portable | External service |
## Example: Full Workflow
```python
import asyncio
from memu.app import MemoryService
async def main():
# Initialize with SQLite
service = MemoryService(
llm_profiles={"default": {"api_key": "your-api-key"}},
database_config={
"metadata_store": {
"provider": "sqlite",
"dsn": "sqlite:///my_memories.db",
},
},
)
# Memorize a conversation
result = await service.memorize(
resource_url="conversation.json",
modality="conversation",
user={"user_id": "alice"},
)
print(f"Created {len(result['categories'])} categories")
# Retrieve relevant memories
memories = await service.retrieve(
queries=[
{"role": "user", "content": {"text": "What are my preferences?"}}
],
where={"user_id": "alice"},
)
for item in memories.get("items", []):
print(f"- {item['summary']}")
asyncio.run(main())
```
## Troubleshooting
### Database Locked Error
SQLite only allows one writer at a time. If you see "database is locked" errors:
1. Ensure you're not running multiple processes writing to the same database
2. Consider using PostgreSQL for concurrent access needs
3. Use connection pooling with appropriate timeouts
### Permission Denied
Make sure the directory containing the SQLite file is writable:
```bash
chmod 755 /path/to/data/directory
```
### Slow Vector Search
If vector search is slow with large datasets:
1. Consider migrating to PostgreSQL with pgvector
2. Use more selective `where` filters to reduce the search space
3. Reduce `top_k` parameters in your retrieve configuration
## /docs/tutorials/getting_started.md
# Quickstart: Adding Long-Term Memory to Python Agents
Welcome to MemU! This guide will help you add robust long-term memory capabilities to your Python agents in just a few minutes. Without MemU, LLMs are limited by their context window. MemU solves this by providing an intelligent, persistent memory layer.
## Prerequisites
Before we begin, ensure you have the following:
- **Python 3.13+**: MemU takes advantage of modern Python features.
- **OpenAI API Key**: This quickstart uses OpenAI's models (`gpt-4o-mini`). You will need a valid API key.
## Step-by-Step Guide
### 1. Installation
Install MemU using `pip` or `uv`:
```bash
pip install memu
# OR
uv add memu
```
### 2. Configuration
MemU requires an LLM backend to function. By default, it looks for the `OPENAI_API_KEY` environment variable.
**Linux / macOS / Git Bash:**
```bash
export OPENAI_API_KEY=sk-proj-your-api-key
```
**Windows (PowerShell):**
```powershell
$env:OPENAI_API_KEY="sk-proj-your-api-key"
```
### 3. The Robust Starter Script
Below is a complete, production-ready script that demonstrates the full lifecycle of a memory-enabled agent: **Initialization**, **Injection** (adding memory), and **Retrieval** (searching memory).
Create a file named `getting_started.py` and paste the following code:
```python
"""
Getting Started with MemU: A Robust Example.
This script demonstrates the core lifecycle of MemU:
1. **Initialization**: Setting up the client with secure API key handling.
2. **Memory Injection**: Adding a specific memory with metadata.
3. **Retrieval**: Searching for that memory using natural language.
4. **Error Handling**: Catching common configuration issues.
Usage:
export OPENAI_API_KEY=your_api_key_here
python getting_started.py
"""
import asyncio
import logging
import os
import sys
from memu.app import MemoryService
# Configure logging to show info but suppress noisy libraries
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logging.getLogger("httpx").setLevel(logging.WARNING)
async def main() -> None:
"""Run the MemU lifecycle demonstration."""
print(">>> MemU Getting Started Example")
print("-" * 30)
# 1. API Key Handling
# MemU relies on an LLM backend (defaulting to OpenAI).
# We ensure the API key is present before proceeding.
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
print("[!] Error: OPENAI_API_KEY environment variable is not set.")
print("Please export it: export OPENAI_API_KEY=sk-...")
return
try:
# 2. Initialization
# We initialize the MemoryService with:
# - llm_profiles: Configuration for the LLM (model, api_key).
# - memorize_config: Pre-defining a memory category ensures we can organize memories efficiently.
print(f"[*] Initializing MemoryService with model: gpt-4o-mini...")
service = MemoryService(
llm_profiles={
"default": {
"api_key": api_key,
"chat_model": "gpt-4o-mini",
},
},
memorize_config={
"memory_categories": [
{
"name": "User Facts",
"description": "General and specific facts known about the user preference and identity.",
}
]
},
)
print("[OK] Service initialized successfully.\n")
# 3. Memory Injection
# We manually inject a memory into the system.
# This is useful for bootstrapping a user profile or adding explicit knowledge.
print("[*] Injecting memory...")
memory_content = "The user is a senior Python architect who loves clean code and type hints."
# We use 'create_memory_item' to insert a single memory record.
# memory_type='profile' indicates this is an attribute of the user.
result = await service.create_memory_item(
memory_type="profile",
memory_content=memory_content,
memory_categories=["User Facts"],
)
print(f"[OK] Memory created! ID: {result.get('memory_item', {}).get('id')}\n")
# 4. Retrieval
# Now we query the system naturally to see if it recalls the information.
query_text = "What kind of code does the user like?"
print(f"[*] Querying: '{query_text}'")
search_results = await service.retrieve(
queries=[{"role": "user", "content": query_text}]
)
# 5. Display Results
items = search_results.get("items", [])
if items:
print(f"[OK] Found {len(items)} relevant memory item(s):")
for idx, item in enumerate(items, 1):
print(f" {idx}. {item.get('summary')} (Type: {item.get('memory_type')})")
else:
print("[!] No relevant memories found.")
except Exception as e:
print(f"\n[!] An error occurred during execution: {e}")
logging.exception("Detailed traceback:")
finally:
print("\n[=] Example execution finished.")
if __name__ == "__main__":
asyncio.run(main())
```
### Understanding the Code
1. **Initialization**: We configure `MemoryService` with specific `llm_profiles`. This tells MemU which model to use. We also define a `memorize_config` with a "User Facts" category. Categories help the LLM organize and retrieve information more effectively.
2. **Memory Injection**: `create_memory_item` is used to explicitly add a piece of knowledge. We tag it with `memory_type="profile"` to semantically indicate this is a user attribute.
3. **Retrieval**: We use `retrieve` with a natural language query. MemU's internal workflow ("RAG" or "LLM" based) will determine the best way to find relevant memories.
## Troubleshooting
### `[!] Error: OPENAI_API_KEY environment variable is not set.`
This is the most common issue. It means the script cannot find your API key which is required to communicate with OpenAI.
**Solution:**
Ensure you have exported the key in your **current terminal session**.
- **Windows PowerShell**: `$env:OPENAI_API_KEY="sk-..."`
- **Linux/Mac**: `export OPENAI_API_KEY=sk-...`
Also, verify that you didn't accidentally include spaces around the `=` sign in bash.
## Next Steps
Now that you have the basics running, consider exploring:
- **Core Concepts**: Learn about `MemoryService`, `MemoryItem`, and `MemoryCategory`.
- **Advanced Configuration**: Switch to local LLMs or use different vector stores.
- **Integrations**: Connect MemU to your existing agent framework.
## Community Resources
This tutorial was created as part of the MemU 2026 Challenge. For a summary of the architectural analysis, see the author's [LinkedIn Post](https://www.linkedin.com/posts/david-a-mamani-c_github-nevamind-aimemu-memory-infrastructure-activity-7418493617482207232-_MtG?utm_source=share&utm_medium=member_desktop&rcm=ACoAAFdc0CIB__DJovR2t1BOxxJ6tgEeOqVEgx4).
## /examples/example_1_conversation_memory.py
```py path="/examples/example_1_conversation_memory.py"
"""
Example 1: Multiple Conversations -> Memory Category File
This example demonstrates how to process multiple conversation files
and generate a memory category JSON file.
Usage:
export OPENAI_API_KEY=your_api_key
python examples/example_1_conversation_memory.py
"""
import asyncio
import os
import sys
from memu.app import MemoryService
# Add src to sys.path
src_path = os.path.abspath("src")
sys.path.insert(0, src_path)
async def generate_memory_md(categories, output_dir):
"""Generate concise markdown files for each memory category."""
os.makedirs(output_dir, exist_ok=True)
generated_files = []
for cat in categories:
name = cat.get("name", "unknown")
summary = cat.get("summary", "")
filename = f"{name}.md"
filepath = os.path.join(output_dir, filename)
with open(filepath, "w", encoding="utf-8") as f:
# Title
# Content - concise version
if summary:
cleaned_summary = summary.replace("<content>", "").replace("</content>", "").strip()
f.write(f"{cleaned_summary}\n")
else:
f.write("*No content available*\n")
generated_files.append(filename)
return generated_files
async def main():
"""
Process multiple conversation files and generate memory categories.
This example:
1. Initializes MemoryService with OpenAI API
2. Processes conversation JSON files
3. Extracts memory categories from conversations
4. Outputs the categories to files
"""
print("Example 1: Conversation Memory Processing")
print("-" * 50)
# Get OpenAI API key from environment
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
msg = "Please set OPENAI_API_KEY environment variable"
raise ValueError(msg)
# Initialize service with OpenAI using llm_profiles
# The "default" profile is required and used as the primary LLM configuration
service = MemoryService(
llm_profiles={
"default": {
"api_key": api_key,
"chat_model": "gpt-4o-mini",
},
},
)
# Conversation files to process
conversation_files = [
"examples/resources/conversations/conv1.json",
"examples/resources/conversations/conv2.json",
"examples/resources/conversations/conv3.json",
]
# Process each conversation
print("\nProcessing conversations...")
total_items = 0
categories = []
for conv_file in conversation_files:
if not os.path.exists(conv_file):
continue
try:
result = await service.memorize(resource_url=conv_file, modality="conversation")
total_items += len(result.get("items", []))
# Categories are returned in the result and updated after each memorize call
categories = result.get("categories", [])
except Exception as e:
print(f"Error: {e}")
# Write to output files
output_dir = "examples/output/conversation_example"
os.makedirs(output_dir, exist_ok=True)
# 1. Generate individual Markdown files for each category
await generate_memory_md(categories, output_dir)
print(f"\n✓ Processed {len(conversation_files)} files, extracted {total_items} items")
print(f"✓ Generated {len(categories)} categories")
print(f"✓ Output: {output_dir}/")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/example_2_skill_extraction.py
```py path="/examples/example_2_skill_extraction.py"
"""
Example 2: Workflow & Agent Logs -> Skill Extraction
This example demonstrates how to extract skills from workflow descriptions
and agent runtime logs, then output them to a Markdown file.
Usage:
export OPENAI_API_KEY=your_api_key
python examples/example_2_skill_extraction.py
"""
import asyncio
import os
import sys
from openai import AsyncOpenAI
from memu.app import MemoryService
# Add src to sys.path
src_path = os.path.abspath("src")
sys.path.insert(0, src_path)
async def generate_skill_md(
all_skills, service, output_file, attempt_number, total_attempts, categories=None, is_final=False
):
"""
Use LLM to generate a concise task execution guide (skill.md).
This creates a production-ready guide incorporating lessons learned from deployment attempts.
"""
os.makedirs(os.path.dirname(output_file), exist_ok=True)
# Prepare context for LLM
skills_text = "\n\n".join([f"### From {skill_data['source']}\n{skill_data['skill']}" for skill_data in all_skills])
# Get category summaries if available
categories_text = ""
if categories:
categories_with_content = [cat for cat in categories if cat.get("summary") and cat.get("summary").strip()]
if categories_with_content:
categories_text = "\n\n".join([
f"**{cat.get('name', 'unknown')}**:\n{cat.get('summary', '')}" for cat in categories_with_content
])
# Construct prompt for LLM
prompt = f"""Generate a concise production-ready task execution guide.
**Context**:
- Task: Production Microservice Deployment with Blue-Green Strategy
- Progress: {attempt_number}/{total_attempts} attempts
- Status: {"Complete" if is_final else f"v0.{attempt_number}"}
**Skills Learned**:
{skills_text}
{f"**Categories**:\n{categories_text}" if categories_text else ""}
**Required Structure**:
1. **Frontmatter** (YAML):
- name: production-microservice-deployment
- description: Brief description
- version: {"1.0.0" if is_final else f"0.{attempt_number}.0"}
- status: {"Production-Ready" if is_final else "Evolving"}
2. **Introduction**: What this guide does and when to use it
3. **Deployment Context**: Strategy, environment, goals
4. **Pre-Deployment Checklist**:
- Actionable checks from lessons learned
- Group by category (Database, Monitoring, etc.)
- Mark critical items
5. **Deployment Procedure**:
- Step-by-step instructions with commands
- Include monitoring points
6. **Rollback Procedure**:
- When to rollback (thresholds)
- Exact commands
- Expected recovery time
7. **Common Pitfalls & Solutions**:
- Failures/issues encountered
- Root cause, symptoms, solution
8. **Best Practices**:
- What works well
- Expected timelines
9. **Key Takeaways**: 3-5 most important lessons
**Style**:
- Use markdown with clear hierarchy
- Be specific and concise
- Technical and production-grade tone
- Focus on PRACTICAL steps
**CRITICAL**:
- ONLY use information from provided skills/lessons
- DO NOT make assumptions or add generic advice
- Extract ACTUAL experiences from the logs
Generate the complete markdown document now:"""
client = AsyncOpenAI(api_key=service.llm_config.api_key)
response = await client.chat.completions.create(
model=service.llm_config.chat_model,
messages=[
{
"role": "system",
"content": "You are an expert technical writer creating concise, production-grade deployment guides from real experiences.",
},
{"role": "user", "content": prompt},
],
temperature=0.7,
max_tokens=3000,
)
generated_content = response.choices[0].message.content
# Write to file
with open(output_file, "w", encoding="utf-8") as f:
f.write(generated_content)
return True
async def main():
"""
Extract skills from agent logs using incremental memory updates.
This example demonstrates INCREMENTAL LEARNING:
1. Process files ONE BY ONE
2. Each file UPDATES existing memory
3. Category summaries EVOLVE with each new file
4. Final output shows accumulated knowledge
"""
print("Example 2: Incremental Skill Extraction")
print("-" * 50)
# Get OpenAI API key from environment
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
msg = "Please set OPENAI_API_KEY environment variable"
raise ValueError(msg)
# Custom config for skill extraction
skill_prompt = """
You are analyzing an agent execution log. Extract the key actions taken, their outcomes, and lessons learned.
For each significant action or phase:
1. **Action/Phase**: What was being attempted?
2. **Status**: SUCCESS ✅ or FAILURE ❌
3. **What Happened**: What was executed
4. **Outcome**: What worked/failed, metrics
5. **Root Cause** (for failures): Why did it fail?
6. **Lesson**: What did we learn?
7. **Action Items**: Concrete steps for next time
**IMPORTANT**:
- Focus on ACTIONS and outcomes
- Be specific: include actual metrics, errors, timing
- ONLY extract information explicitly stated
- DO NOT infer or assume information
Extract ALL significant actions from the text:
Text: {resource}
"""
# Define custom categories
skill_categories = [
{"name": "deployment_execution", "description": "Deployment actions, traffic shifting, environment management"},
{
"name": "pre_deployment_validation",
"description": "Capacity validation, configuration checks, readiness verification",
},
{
"name": "incident_response_rollback",
"description": "Incident response, error detection, rollback procedures",
},
{
"name": "performance_monitoring",
"description": "Metrics monitoring, performance analysis, bottleneck detection",
},
{"name": "database_management", "description": "Database capacity planning, optimization, schema changes"},
{"name": "testing_verification", "description": "Testing, smoke tests, load tests, verification"},
{"name": "infrastructure_setup", "description": "Kubernetes, containers, networking configuration"},
{"name": "lessons_learned", "description": "Key reflections, root cause analyses, action items"},
]
memorize_config = {
"memory_types": ["skill"],
"memory_type_prompts": {"skill": skill_prompt},
"memory_categories": skill_categories,
}
# Initialize service with OpenAI using llm_profiles
# The "default" profile is required and used as the primary LLM configuration
service = MemoryService(
llm_profiles={
"default": {
"api_key": api_key,
"chat_model": "gpt-4o-mini",
},
},
memorize_config=memorize_config,
)
# Resources to process
resources = [
("examples/resources/logs/log1.txt", "document"),
("examples/resources/logs/log2.txt", "document"),
("examples/resources/logs/log3.txt", "document"),
]
# Process each resource sequentially
print("\nProcessing files...")
all_skills = []
categories = []
for idx, (resource_file, modality) in enumerate(resources, 1):
if not os.path.exists(resource_file):
continue
try:
result = await service.memorize(resource_url=resource_file, modality=modality)
# Extract skill items
for item in result.get("items", []):
if item.get("memory_type") == "skill":
all_skills.append({"skill": item.get("summary", ""), "source": os.path.basename(resource_file)})
# Categories are returned in the result and updated after each memorize call
categories = result.get("categories", [])
# Generate intermediate skill.md
await generate_skill_md(
all_skills=all_skills,
service=service,
output_file=f"examples/output/skill_example/log_{idx}.md",
attempt_number=idx,
total_attempts=len(resources),
categories=categories,
)
except Exception as e:
print(f"Error: {e}")
# Generate final comprehensive skill.md
await generate_skill_md(
all_skills=all_skills,
service=service,
output_file="examples/output/skill_example/skill.md",
attempt_number=len(resources),
total_attempts=len(resources),
categories=categories,
is_final=True,
)
print(f"\n✓ Processed {len(resources)} files, extracted {len(all_skills)} skills")
print(f"✓ Generated {len(categories)} categories")
print("✓ Output: examples/output/skill_example/")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/example_3_multimodal_memory.py
```py path="/examples/example_3_multimodal_memory.py"
"""
Example 3: Multimodal Processing -> Memory Category File
This example demonstrates how to process multiple modalities (images, documents)
and generate a unified memory category JSON file.
Usage:
export OPENAI_API_KEY=your_api_key
python examples/example_3_multimodal_memory.py
"""
import asyncio
import os
import sys
from memu.app import MemoryService
# Add src to sys.path
src_path = os.path.abspath("src")
sys.path.insert(0, src_path)
async def generate_memory_md(categories, output_dir):
"""Generate concise markdown files for each memory category."""
os.makedirs(output_dir, exist_ok=True)
generated_files = []
for cat in categories:
name = cat.get("name", "unknown")
description = cat.get("description", "")
summary = cat.get("summary", "")
filename = f"{name}.md"
filepath = os.path.join(output_dir, filename)
with open(filepath, "w", encoding="utf-8") as f:
# Title
formatted_name = name.replace("_", " ").title()
f.write(f"# {formatted_name}\n\n")
if description:
f.write(f"*{description}*\n\n")
# Content - full version
if summary:
cleaned_summary = summary.replace("<content>", "").replace("</content>", "").strip()
f.write(f"{cleaned_summary}\n")
else:
f.write("*No content available*\n")
generated_files.append(filename)
return generated_files
async def main():
"""
Process multiple modalities (images and documents) to generate memory categories.
This example:
1. Initializes MemoryService with OpenAI API
2. Processes documents and images
3. Extracts unified memory categories across modalities
4. Outputs the categories to files
"""
print("Example 3: Multimodal Memory Processing")
print("-" * 50)
# Get OpenAI API key from environment
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
msg = "Please set OPENAI_API_KEY environment variable"
raise ValueError(msg)
# Define custom categories for multimodal content
multimodal_categories = [
{"name": "technical_documentation", "description": "Technical documentation, guides, and tutorials"},
{
"name": "architecture_concepts",
"description": "System architecture, design patterns, and structural concepts",
},
{"name": "best_practices", "description": "Best practices, recommendations, and guidelines"},
{"name": "code_examples", "description": "Code snippets, examples, and implementation details"},
{"name": "visual_diagrams", "description": "Visual concepts, diagrams, charts, and illustrations from images"},
]
# Initialize service with OpenAI using llm_profiles
# The "default" profile is required and used as the primary LLM configuration
service = MemoryService(
llm_profiles={
"default": {
"api_key": api_key,
"chat_model": "gpt-4o-mini",
},
},
memorize_config={"memory_categories": multimodal_categories},
)
# Resources to process (file_path, modality)
resources = [
("examples/resources/docs/doc1.txt", "document"),
("examples/resources/docs/doc2.txt", "document"),
("examples/resources/images/image1.png", "image"),
]
# Process each resource
print("\nProcessing resources...")
total_items = 0
categories = []
for resource_file, modality in resources:
if not os.path.exists(resource_file):
continue
try:
result = await service.memorize(resource_url=resource_file, modality=modality)
total_items += len(result.get("items", []))
# Categories are returned in the result and updated after each memorize call
categories = result.get("categories", [])
except Exception as e:
print(f"Error: {e}")
# Write to output files
output_dir = "examples/output/multimodal_example"
os.makedirs(output_dir, exist_ok=True)
# 1. Generate individual Markdown files for each category
await generate_memory_md(categories, output_dir)
print(f"\n✓ Processed {len(resources)} files, extracted {total_items} items")
print(f"✓ Generated {len(categories)} categories")
print(f"✓ Output: {output_dir}/")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/example_4_openrouter_memory.py
```py path="/examples/example_4_openrouter_memory.py"
"""
Example 4: Multiple Conversations -> Memory Category File (Using OpenRouter)
This example demonstrates how to process multiple conversation files
and generate memory categories using OpenRouter as the LLM backend.
Usage:
export OPENROUTER_API_KEY=your_api_key
python examples/example_4_openrouter_memory.py
"""
import asyncio
import os
import sys
from memu.app import MemoryService
src_path = os.path.abspath("src")
sys.path.insert(0, src_path)
async def generate_memory_md(categories, output_dir):
"""Generate concise markdown files for each memory category."""
os.makedirs(output_dir, exist_ok=True)
generated_files = []
for cat in categories:
name = cat.get("name", "unknown")
summary = cat.get("summary", "")
filename = f"{name}.md"
filepath = os.path.join(output_dir, filename)
with open(filepath, "w", encoding="utf-8") as f:
if summary:
cleaned_summary = summary.replace("<content>", "").replace("</content>", "").strip()
f.write(f"{cleaned_summary}\n")
else:
f.write("*No content available*\n")
generated_files.append(filename)
return generated_files
async def main():
"""
Process multiple conversation files and generate memory categories using OpenRouter.
This example:
1. Initializes MemoryService with OpenRouter API
2. Processes conversation JSON files
3. Extracts memory categories from conversations
4. Outputs the categories to files
"""
print("Example 4: Conversation Memory Processing (OpenRouter)")
print("-" * 50)
api_key = os.getenv("OPENROUTER_API_KEY")
if not api_key:
msg = "Please set OPENROUTER_API_KEY environment variable"
raise ValueError(msg)
# Initialize service with OpenRouter
service = MemoryService(
llm_profiles={
"default": {
"provider": "openrouter",
"client_backend": "httpx",
"base_url": "https://openrouter.ai",
"api_key": api_key,
"chat_model": "anthropic/claude-3.5-sonnet", # you can use any model from openrouter.ai
"embed_model": "openai/text-embedding-3-small", # you can use any model from openrouter.ai
},
},
)
conversation_files = [
"examples/resources/conversations/conv1.json",
"examples/resources/conversations/conv2.json",
"examples/resources/conversations/conv3.json",
]
print("\nProcessing conversations...")
total_items = 0
categories = []
for conv_file in conversation_files:
if not os.path.exists(conv_file):
print(f"Skipped: {conv_file} not found")
continue
try:
print(f"Processing: {conv_file}")
result = await service.memorize(resource_url=conv_file, modality="conversation")
total_items += len(result.get("items", []))
categories = result.get("categories", [])
except Exception as e:
print(f"Error processing {conv_file}: {e}")
output_dir = "examples/output/openrouter_example"
os.makedirs(output_dir, exist_ok=True)
await generate_memory_md(categories, output_dir)
print(f"\nProcessed {len(conversation_files)} files, extracted {total_items} items")
print(f"Generated {len(categories)} categories")
print(f"Output: {output_dir}/")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/example_5_with_lazyllm_client.py
```py path="/examples/example_5_with_lazyllm_client.py"
"""
Unified Example: LazyLLM Integration Demo
=========================================
This example merges functionalities from:
1. Example 1: Conversation Memory Processing
2. Example 2: Skill Extraction
3. Example 3: Multimodal Processing
It demonstrates how to use the LazyLLM backend for:
- Processing conversation history
- Extracting technical skills from logs
- Handling multimodal content (images + text)
- defaut source and model are from qwen
Usage:
export MEMU_QWEN_API_KEY=your_api_key
python examples/example_5_with_lazyllm_client.py
"""
import asyncio
import os
import sys
from pathlib import Path
# Add src to sys.path FIRST before importing memu
project_root = Path(__file__).parent.parent
src_path = str(project_root / "src")
if src_path not in sys.path:
sys.path.insert(0, src_path)
from memu.app import MemoryService
# ==========================================
# PART 1: Conversation Memory Processing
# ==========================================
async def run_conversation_memory_demo(service):
print("\n" + "=" * 60)
print("PART 1: Conversation Memory Processing")
print("=" * 60)
conversation_files = [
"examples/resources/conversations/conv1.json",
"examples/resources/conversations/conv2.json",
"examples/resources/conversations/conv3.json",
]
total_items = 0
categories = []
for conv_file in conversation_files:
if not os.path.exists(conv_file):
print(f"⚠ File not found: {conv_file}")
continue
try:
print(f" Processing: {conv_file}")
result = await service.memorize(resource_url=conv_file, modality="conversation")
total_items += len(result.get("items", []))
categories = result.get("categories", [])
print(f" ✓ Extracted {len(result.get('items', []))} items")
except Exception as e:
print(f" ✗ Error processing {conv_file}: {e}")
# Output generation
output_dir = "examples/output/lazyllm_example/conversation"
os.makedirs(output_dir, exist_ok=True)
await generate_markdown_output(categories, output_dir)
print(f"✓ Conversation processing complete. Output: {output_dir}")
# ==========================================
# PART 2: Skill Extraction
# ==========================================
async def run_skill_extraction_demo(service):
print("\n" + "=" * 60)
print("PART 2: Skill Extraction from Logs")
print("=" * 60)
# Configure prompt for skill extraction
skill_prompt = """
You are analyzing an agent execution log. Extract the key actions taken, their outcomes, and lessons learned.
Output MUST be valid XML wrapped in <skills> tags.
Format:
<skills>
<memory>
<content>
[Action] Description...
[Lesson] Key lesson...
</content>
<categories>
<category>Category Name</category>
</categories>
</memory>
</skills>
Text: {resource}
"""
# Update service config for skill extraction
service.memorize_config.memory_types = ["skill"]
service.memorize_config.memory_type_prompts = {"skill": skill_prompt}
logs = ["examples/resources/logs/log1.txt", "examples/resources/logs/log2.txt", "examples/resources/logs/log3.txt"]
all_skills = []
for log_file in logs:
if not os.path.exists(log_file):
continue
print(f" Processing log: {log_file}")
try:
result = await service.memorize(resource_url=log_file, modality="document")
for item in result.get("items", []):
if item.get("memory_type") == "skill":
all_skills.append(item.get("summary", ""))
print(f" ✓ Extracted {len(result.get('items', []))} skills")
except Exception as e:
print(f" ✗ Error: {e}")
# Generate summary guide
if all_skills:
output_file = "examples/output/lazyllm_example/skills/skill_guide.md"
await generate_skill_guide(all_skills, service, output_file)
print(f"✓ Skill guide generated: {output_file}")
# ==========================================
# PART 3: Multimodal Memory
# ==========================================
async def run_multimodal_demo(service):
print("\n" + "=" * 60)
print("PART 3: Multimodal Memory Processing")
print("=" * 60)
# Configure for knowledge extraction
xml_prompt = """
Analyze content and extract key information.
Output MUST be valid XML wrapped in <knowledge> tags.
Format:
<knowledge>
<memory>
<content>Extracted content...</content>
<categories><category>category_name</category></categories>
</memory>
</knowledge>
Content: {resource}
"""
service.memorize_config.memory_types = ["knowledge"]
service.memorize_config.memory_type_prompts = {"knowledge": xml_prompt}
resources = [
("examples/resources/docs/doc1.txt", "document"),
("examples/resources/images/image1.png", "image"),
]
categories = []
for res_file, modality in resources:
if not os.path.exists(res_file):
continue
print(f" Processing {modality}: {res_file}")
try:
result = await service.memorize(resource_url=res_file, modality=modality)
categories = result.get("categories", [])
print(f" ✓ Extracted {len(result.get('items', []))} items")
except Exception as e:
print(f" ✗ Error: {e}")
output_dir = "examples/output/lazyllm_example/multimodal"
os.makedirs(output_dir, exist_ok=True)
await generate_markdown_output(categories, output_dir)
print(f"✓ Multimodal processing complete. Output: {output_dir}")
# ==========================================
# Helpers
# ==========================================
async def generate_markdown_output(categories, output_dir):
for cat in categories:
name = cat.get("name", "unknown")
summary = cat.get("summary", "")
if not summary:
continue
with open(os.path.join(output_dir, f"{name}.md"), "w", encoding="utf-8") as f:
f.write(f"# {name.replace('_', ' ').title()}\n\n")
cleaned = summary.replace("<content>", "").replace("</content>", "").strip()
f.write(cleaned)
async def generate_skill_guide(skills, service, output_file):
os.makedirs(os.path.dirname(output_file), exist_ok=True)
skills_text = "\n\n".join(skills)
prompt = f"Summarize these skills into a guide:\n\n{skills_text}"
# Use LazyLLM via service
summary = await service.llm_client.chat(text=prompt)
with open(output_file, "w", encoding="utf-8") as f:
f.write(summary)
# ==========================================
# Main Entry
# ==========================================
async def main():
print("Unified LazyLLM Example")
print("=" * 60)
# 1. Initialize Shared Service
service = MemoryService(
llm_profiles={
"default": {
"client_backend": "lazyllm_backend",
"chat_model": "qwen3-max",
"embed_model": "text-embedding-v3",
"lazyllm_source": {
"source": "qwen",
"llm_source": "qwen",
"vlm_source": "qwen",
"embed_source": "qwen",
"stt_source": "qwen",
"vlm_model": "qwen-vl-plus",
"stt_model": "qwen-audio-turbo",
},
},
}
)
# 2. Run Demos
await run_conversation_memory_demo(service)
# await run_skill_extraction_demo(service)
# await run_multimodal_demo(service)
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/getting_started_robust.py
```py path="/examples/getting_started_robust.py"
"""
Getting Started with MemU: A Robust Example.
This script demonstrates the core lifecycle of MemU:
1. **Initialization**: Setting up the client with secure API key handling.
2. **Memory Injection**: Adding a specific memory with metadata.
3. **Retrieval**: Searching for that memory using natural language.
4. **Error Handling**: Catching common configuration issues.
Usage:
export OPENAI_API_KEY=your_api_key_here
python examples/getting_started_robust.py
"""
import asyncio
import logging
import os
import sys
# Ensure src is in the path for local usage if custom installing
sys.path.insert(0, os.path.abspath("src"))
from memu.app import MemoryService
# Configure logging to show info but suppress noisy libraries
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logging.getLogger("httpx").setLevel(logging.WARNING)
async def main() -> None:
"""Run the MemU lifecycle demonstration."""
print(">>> MemU Getting Started Example")
print("-" * 30)
# 1. API Key Handling
# MemU relies on an LLM backend (defaulting to OpenAI).
# We ensure the API key is present before proceeding.
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
print("[!] Error: OPENAI_API_KEY environment variable is not set.")
print("Please export it: export OPENAI_API_KEY=sk-...")
return
try:
# 2. Initialization
# We initialize the MemoryService with:
# - llm_profiles: Configuration for the LLM (model, api_key).
# - memorize_config: Pre-defining a memory category ensures we can organize memories efficiently.
print("[*] Initializing MemoryService with model: gpt-4o-mini...")
service = MemoryService(
llm_profiles={
"default": {
"api_key": api_key,
"chat_model": "gpt-4o-mini",
},
},
memorize_config={
"memory_categories": [
{
"name": "User Facts",
"description": "General and specific facts known about the user preference and identity.",
}
]
},
)
print("[OK] Service initialized successfully.\n")
# 3. Memory Injection
# We manually inject a memory into the system.
# This is useful for bootstrapping a user profile or adding explicit knowledge.
print("[*] Injecting memory...")
memory_content = "The user is a senior Python architect who loves clean code and type hints."
# We use 'create_memory_item' to insert a single memory record.
# memory_type='profile' indicates this is an attribute of the user.
result = await service.create_memory_item(
memory_type="profile",
memory_content=memory_content,
memory_categories=["User Facts"],
)
print(f"[OK] Memory created! ID: {result.get('memory_item', {}).get('id')}\n")
# 4. Retrieval
# Now we query the system naturally to see if it recalls the information.
query_text = "What kind of code does the user like?"
print(f"[*] Querying: '{query_text}'")
search_results = await service.retrieve(queries=[{"role": "user", "content": query_text}])
# 5. Display Results
items = search_results.get("items", [])
if items:
print(f"[OK] Found {len(items)} relevant memory item(s):")
for idx, item in enumerate(items, 1):
print(f" {idx}. {item.get('summary')} (Type: {item.get('memory_type')})")
else:
print("[!] No relevant memories found.")
except Exception as e:
print(f"\n[!] An error occurred during execution: {e}")
logging.exception("Detailed traceback:")
finally:
print("\n[=] Example execution finished.")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/langgraph_demo.py
```py path="/examples/langgraph_demo.py"
"""Demo script for MemU LangGraph Integration."""
import asyncio
import logging
import os
import sys
# Try imports and fail proactively if missing
try:
import langgraph # noqa: F401
from langchain_core.tools import BaseTool
from memu.app.service import MemoryService
from memu.integrations.langgraph import MemULangGraphTools
except ImportError:
print("Missing dependencies. Please run: uv sync --extra langgraph")
sys.exit(1)
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("langgraph_demo")
async def initialize_infrastructure() -> MemULangGraphTools:
"""Initialize the MemoryService and the LangGraph adapter."""
# Ensure OPENAI_API_KEY is present
if not os.environ.get("OPENAI_API_KEY"):
logger.warning("OPENAI_API_KEY not found in environment variables.")
# In a real scenario, you might load config from file or env
service = MemoryService()
return MemULangGraphTools(service)
async def process_conversation(tools: list[BaseTool], user_id: str) -> None:
"""Simulate a conversation where memory is saved."""
save_tool = next(t for t in tools if t.name == "save_memory")
logger.info("--- Simulating Save Memory ---")
inputs = {
"content": "The user prefers dark mode and likes Python programming.",
"user_id": user_id,
"metadata": {"source": "demo_script"},
}
# Invoke the tool (async execution)
result = await save_tool.ainvoke(inputs)
logger.info("Save Result: %s", result)
async def process_retrieval(tools: list[BaseTool], user_id: str) -> None:
"""Simulate retrieving memory."""
search_tool = next(t for t in tools if t.name == "search_memory")
logger.info("--- Simulating Search Memory ---")
inputs = {"query": "What are the user's preferences?", "user_id": user_id, "limit": 3}
result = await search_tool.ainvoke(inputs)
logger.info("Search Result:\n%s", result)
async def main() -> None:
"""Main entry point."""
logger.info("Starting LangGraph Demo...")
adapter = await initialize_infrastructure()
tools = adapter.tools()
user_id = "demo_user_123"
await process_conversation(tools, user_id)
await process_retrieval(tools, user_id)
logger.info("Demo completed.")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/output/conversation_example/activities.md
# activities
## Open Source Contributions
- The user enjoys contributing to open source projects, specifically a Python CLI tool used for automating deployment tasks.
## Running
- The user usually goes for a run every morning and is interested in running routes near downtown San Francisco.
## Dining Plans
- The user plans to try several vegetarian restaurants in San Francisco for their partner, who is vegetarian.
## Gym
- The user goes to the gym 3-4 times a week, usually after work around 7 PM.
## /examples/output/conversation_example/experiences.md
# experiences
## User Experiences
- The user has been programming for about 5 years.
- The user is leading a big product launch next month, which is causing work-related stress that is affecting their sleep schedule.
- The user usually goes to bed around 11 PM but finds themselves awake thinking about work projects.
## /examples/output/conversation_example/goals.md
# goals
## Learning Objectives
- The user is interested in learning more about system design and scalability patterns.
- The user is learning about event-driven architecture and message queues, specifically using Apache Kafka for event streaming.
## Product Development Goals
- The user wants to build their own SaaS product related to developer tools or automation.
- The user is currently in the research phase for their product idea, reading about OpenAPI specifications and exploring tools like Swagger and Postman.
- The user plans to start prototyping their SaaS product idea in the next few months.
## Tool Development Ideas
- The user is considering building a tool for API testing and documentation that automatically generates test cases based on API specifications.
- The user is researching tools for developing the API tool.
## Work-Life Balance Goals
- The user plans to talk to their team about response time expectations for emails, as they believe they are putting pressure on themselves.
- The user expresses a desire to establish better work-life boundaries and has been considering ways to limit work-related activities during the evening.
## /examples/output/conversation_example/habits.md
# habits
## Eating Habits
- The user is trying to eat less meat.
## Exercise Routine
- The user usually goes for a run every morning.
- The user exercises regularly, going to the gym 3-4 times a week.
## Sleep Habits
- The user has been having trouble sleeping due to work stress.
- The user usually tries to go to bed around 11 PM but struggles to fall asleep due to stress from work projects.
- The user checks their phone before bed, which may impact their sleep quality.
- The user used to read before bed but stopped because they were always checking work emails.
## Caffeine Consumption
- The user usually drinks coffee throughout the day to stay alert, typically having their last coffee around 3-4 PM.
## /examples/output/conversation_example/knowledge.md
# knowledge
## Reading Interests
- The user has been reading about OpenAPI specifications and exploring tools like Swagger and Postman.
## Technology Stack
- Alex's technology stack includes Django and FastAPI for Python services, Kubernetes for orchestration, Redis for caching, and Apache Kafka for event streaming.
## Interests
- Alex has an interest in system design and scalability patterns and is learning about event-driven architecture and message queues.
- For food in San Francisco, check out the Ferry Building Marketplace for gourmet options and local produce.
- Golden Gate Park, Lands End, and Muir Woods are recommended for nature activities in San Francisco.
- A self-guided tour of tech headquarters in Silicon Valley and the Computer History Museum are good tech-related activities in San Francisco.
- The de Young Museum and SFMOMA are suitable for photography and museum interests in San Francisco.
## Monitoring and Observability
- For monitoring and observability, Alex works with Prometheus and Grafana.
## Sleep and Wellness
- Work stress can negatively affect sleep quality, especially when one is in a leadership role.
- Using a phone before bed can disrupt sleep due to blue light, which suppresses melatonin production.
- Regular exercise can improve sleep, but working out close to bedtime may be stimulating.
- Caffeine consumption, particularly in the afternoon, can adversely affect sleep quality.
- Establishing a wind-down routine, such as reading or gentle stretching before bed, can help improve sleep.
- Keeping a phone out of the bedroom can create a boundary between work and sleep, improving sleep quality.
- Setting specific 'no work' hours can help transition from work mode to rest mode, reducing stress.
## Activities and Recommendations
- The best time to visit Muir Woods is early in the morning around 8 AM to avoid crowds and enjoy peacefulness.
- Parking reservations at Muir Woods are required and should be booked in advance.
- Recommended vegetarian restaurants in San Francisco include Greens Restaurant, Nourish Cafe, Shizen, Gracias Madre, and Ike's Love & Sandwiches.
- The Embarcadero is a great flat waterfront path for morning runs in San Francisco.
- Crissy Field offers stunning views of the Golden Gate Bridge and is another good running spot.
- Running to Coit Tower from North Beach provides a more challenging route with hills.
- San Francisco weather can be changeable, particularly across different neighborhoods, so packing layers is advisable.
## /examples/output/conversation_example/opinions.md
*No content available*
## /examples/output/conversation_example/personal_info.md
# personal_info
## Basic Information
- The user is named Alex and works as a software engineer at TechCorp.
## /examples/output/conversation_example/preferences.md
# preferences
## Interests
- The user loves food and nature.
- The user enjoys exploring tech companies due to their background in software development.
- The user is interested in vegetarian options as their partner is vegetarian and the user is trying to eat less meat.
- The user likes reading and used to read before bed.
## /examples/output/conversation_example/relationships.md
# relationships
## partner
- The user's partner enjoys photography and museums.
## /examples/output/conversation_example/work_life.md
# work_life
## Professional Background
- The user is a software engineer at TechCorp.
- Alex is a software engineer with approximately 5 years of programming experience.
- The user works in software development.
## Current Responsibilities
- The user primarily works on backend systems using Python and Go for an e-commerce platform.
- At TechCorp, Alex's team is building a distributed microservices architecture for their e-commerce platform.
- The user uses Django and FastAPI for Python services and is migrating to Go for better performance.
- The user works with Kubernetes for orchestration and Redis for caching.
- The user is responsible for monitoring and observability, using Prometheus and Grafana.
- The user is leading a big product launch next month.
## /examples/proactive/memory/config.py
```py path="/examples/proactive/memory/config.py"
memorize_config = {
"memory_types": [
"record",
],
"memory_type_prompts": {
"record": {
"objective": {
"ordinal": 10,
"prompt": "# Task Objective\nYou will be given a conversation between a user and an coding agent. Your goal is to extract detailed records for what are planed to do, and what have been done.",
},
"workflow": {
"ordinal": 20,
"prompt": "# Workflow\nRead through the conversation and extract records. You should expecially focus on:\n- What the user ask the agent to do\n- What plan does the agent suggest\n- What the agent has done",
},
"rules": {
"ordinal": -1,
"prompt": None,
},
"examples": {
"ordinal": 60,
"prompt": "# Example\n## Output\n<item>\n <memory>\n <content>The user ask the agent to generate a code example for fastapi</content>\n <categories>\n <category>todo</category>\n </categories>\n </memory>\n <memory>\n <content>The agent suggest to use the code example from the document</content>\n <categories>\n <category>todo</category>\n </categories>\n </memory>\n <memory>\n <content>The agent ask the user to specify the response type</content>\n <categories>\n <category>todo</category>\n </categories>\n </memory>\n</item>",
},
}
},
"memory_categories": [
{
"name": "todo",
"description": "This file traces the latest status of the task. All records should be included in this file.",
"target_length": None,
"custom_prompt": {
"objective": {
"ordinal": 10,
"prompt": "# Task Objective\nYou are a specialist in task management. You should update the markdown file to reflect the latest status of the task.",
},
"workflow": {
"ordinal": 20,
"prompt": "# Workflow\nRead through the existing markdown file and the new records. Then update the markdown file to reflect:\n- What existing tasks are completed\n- What new tasks are added\n- What tasks are still in progress",
},
"rules": {
"ordinal": 30,
"prompt": "# Rules\nFor each action-like record, explictly mark it as [Done] or [Todo].",
},
"examples": {
"ordinal": 50,
"prompt": "# Example\n## Output\n\`\`\`markdown\n# Task\n## Task Objective\nThe user ask the agent to generate a code example for fastapi\n## Breakdown\n- [Done] The agent suggest to use the code example from the document\n- [Todo] The agent ask the user to specify the response type\n\`\`\`",
},
},
}
],
}
retrieve_config = {
"method": "rag",
"route_intention": False,
"sufficiency_check": False,
"category": {
"enabled": False,
},
"item": {
"enabled": True,
"top_k": 10,
},
"resource": {
"enabled": False,
},
}
```
## /examples/proactive/memory/local/__init__.py
```py path="/examples/proactive/memory/local/__init__.py"
```
## /examples/proactive/memory/local/common.py
```py path="/examples/proactive/memory/local/common.py"
import os
from memu.app import MemoryService
from ..config import memorize_config, retrieve_config
USER_ID = "claude_user"
SHARED_MEMORY_SERVICE = None
def get_memory_service() -> MemoryService:
global SHARED_MEMORY_SERVICE
if SHARED_MEMORY_SERVICE is not None:
return SHARED_MEMORY_SERVICE
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
msg = "Please set OPENAI_API_KEY environment variable"
raise ValueError(msg)
SHARED_MEMORY_SERVICE = MemoryService(
llm_profiles={
"default": {
"api_key": api_key,
"chat_model": "gpt-4o-mini",
},
},
memorize_config=memorize_config,
retrieve_config=retrieve_config,
)
return SHARED_MEMORY_SERVICE
```
## /examples/proactive/memory/local/memorize.py
```py path="/examples/proactive/memory/local/memorize.py"
import json
from collections.abc import Awaitable
from pathlib import Path
from typing import Any
import pendulum
from .common import get_memory_service
USER_ID = "claude_user"
def dump_conversation_resource(
conversation_messages: list[dict[str, Any]],
) -> str:
resource_data = {
"content": [
{
"role": message.get("role", "system"),
"content": {"text": message.get("content", "")},
"created_at": message.get("timestamp", pendulum.now().isoformat()),
}
for message in conversation_messages
]
}
time_string = pendulum.now().format("YYYYMMDD_HHmmss")
resource_url = Path(__file__).parent / "data" / f"conv_{time_string}.json"
resource_url.parent.mkdir(parents=True, exist_ok=True)
with open(resource_url, "w") as f:
json.dump(resource_data, f, indent=4, ensure_ascii=False)
return resource_url.as_posix()
def memorize(conversation_messages: list[dict[str, Any]]) -> Awaitable[dict[str, Any]]:
memory_service = get_memory_service()
resource_url = dump_conversation_resource(conversation_messages)
return memory_service.memorize(resource_url=resource_url, modality="conversation", user={"user_id": USER_ID})
```
## /examples/proactive/memory/local/tools.py
```py path="/examples/proactive/memory/local/tools.py"
from typing import Any
from claude_agent_sdk import create_sdk_mcp_server, tool
from .common import get_memory_service
USER_ID = "claude_user"
@tool("memu_memory", "Retrieve memory based on a query", {"query": str})
async def get_memory(args: dict[str, Any]) -> dict[str, Any]:
"""Retrieve memory from the memory API based on the provided query."""
query = {"role": "user", "content": args["query"]}
memory_service = get_memory_service()
result = await memory_service.retrieve(query, where={"user_id": USER_ID})
return {"content": [{"type": "text", "text": str(result)}]}
async def _get_todos() -> str:
memory_service = get_memory_service()
result = await memory_service.list_memory_categories(where={"user_id": USER_ID})
categories = result["categories"]
todos = ""
for category in categories:
if category["name"] == "todo":
todos = category["summary"]
return todos
@tool("memu_todos", "Retrieve todos for the user", {})
async def get_todos() -> dict[str, Any]:
"""Retrieve todos from the memory API."""
todos = await _get_todos()
return {"content": [{"type": "text", "text": str(todos)}]}
memu_server = create_sdk_mcp_server(name="memu", version="1.0.0", tools=[get_memory, get_todos])
```
## /examples/proactive/memory/platform/__init__.py
```py path="/examples/proactive/memory/platform/__init__.py"
```
## /examples/proactive/memory/platform/memorize.py
```py path="/examples/proactive/memory/platform/memorize.py"
from typing import Any
import aiohttp
from ..config import memorize_config
BASE_URL = "https://api.memu.so"
API_KEY = "your memu api key"
USER_ID = "claude_user"
AGENT_ID = "claude_agent"
async def memorize(conversation_messages: list[dict[str, Any]]) -> str | None:
payload = {
"conversation": conversation_messages,
"user_id": USER_ID,
"agent_id": AGENT_ID,
"override_config": memorize_config,
}
async with (
aiohttp.ClientSession() as session,
session.post(
f"{BASE_URL}/api/v3/memory/memorize",
headers={"Authorization": f"Bearer {API_KEY}"},
json=payload,
) as response,
):
result = await response.json()
task_id = result["task_id"]
return task_id
```
## /examples/proactive/memory/platform/tools.py
```py path="/examples/proactive/memory/platform/tools.py"
from typing import Any
import aiohttp
from claude_agent_sdk import create_sdk_mcp_server, tool
BASE_URL = "https://api.memu.so"
API_KEY = "your memu api key"
USER_ID = "claude_user"
AGENT_ID = "claude_agent"
@tool("memu_memory", "Retrieve memory based on a query", {"query": str})
async def get_memory(args: dict[str, Any]) -> dict[str, Any]:
"""Retrieve memory from the memory API based on the provided query."""
query = args["query"]
url = f"{BASE_URL}/api/v3/memory/retrieve"
headers = {"Authorization": f"Bearer {API_KEY}"}
data = {"user_id": USER_ID, "agent_id": AGENT_ID, "query": query}
async with aiohttp.ClientSession() as session, session.post(url, headers=headers, json=data) as response:
result = await response.json()
return {"content": [{"type": "text", "text": str(result)}]}
async def _get_todos() -> str:
url = f"{BASE_URL}/api/v3/memory/categories"
headers = {"Authorization": f"Bearer {API_KEY}"}
data = {
"user_id": USER_ID,
"agent_id": AGENT_ID,
}
async with aiohttp.ClientSession() as session, session.post(url, headers=headers, json=data) as response:
result = await response.json()
categories = result["categories"]
todos = ""
for category in categories:
if category["name"] == "todo":
todos = category["summary"]
return todos
@tool("memu_todos", "Retrieve todos for the user", {})
async def get_todos() -> dict[str, Any]:
"""Retrieve todos from the memory API."""
todos = await _get_todos()
return {"content": [{"type": "text", "text": str(todos)}]}
# Create the MCP server with the tool
memu_server = create_sdk_mcp_server(name="memu", version="1.0.0", tools=[get_memory, get_todos])
```
## /examples/proactive/proactive.py
```py path="/examples/proactive/proactive.py"
import asyncio
from claude_agent_sdk import (
AssistantMessage,
ClaudeAgentOptions,
ClaudeSDKClient,
ResultMessage,
TextBlock,
)
from memory.local.memorize import memorize
from memory.local.tools import _get_todos, memu_server
# Set your Anthropic API key here if it's not set in the environment variables
# os.environ["ANTHROPIC_API_KEY"] = ""
N_MESSAGES_MEMORIZE = 2
RUNNING_MEMORIZATION: asyncio.Task | None = None
async def trigger_memorize(messages: list[dict[str, any]]) -> bool:
"""Create a background task to memorize conversation messages.
Returns True if the task was successfully created and registered.
"""
global RUNNING_MEMORIZATION
try:
memorize_awaitable = memorize(messages)
RUNNING_MEMORIZATION = asyncio.create_task(memorize_awaitable)
except Exception as e:
print(f"\n[Memory] Memorization initialization failed: {e!r}")
return False
else:
print("\n[Memory] Memorization task submitted.")
return True
async def get_next_input(iteration: int) -> tuple[str | None, bool]:
"""
Get the next input for the conversation.
Returns:
tuple of (input_text, should_break)
- input_text: The user input or todo-based input, None if should continue
- should_break: True if the loop should break
"""
if iteration == 0:
return await get_user_input()
todos = await _get_todos()
print(f">>> Todos:\n{todos}\n")
print("-" * 40)
if todos and "[todo]" in todos.lower():
return f"Please continue with the following todos:\n{todos}", False
return await get_user_input()
async def get_user_input() -> tuple[str | None, bool]:
"""
Get input from the user.
Returns:
tuple of (input_text, should_break)
"""
try:
user_input = input("\nYou: ").strip()
except EOFError:
return None, True
if not user_input:
return None, False
if user_input.lower() in ("quit", "exit"):
return None, True
return user_input, False
async def process_response(client: ClaudeSDKClient) -> list[str]:
"""Process the assistant response and return collected text parts."""
assistant_text_parts: list[str] = []
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
assistant_text_parts.append(block.text)
elif isinstance(message, ResultMessage):
print(f"Result: {message.result}")
return assistant_text_parts
async def check_and_memorize(conversation_messages: list[dict[str, any]]) -> None:
"""Check if memorization threshold is reached and trigger if needed.
Skips triggering if a previous memorization task is still running.
"""
global RUNNING_MEMORIZATION
if len(conversation_messages) < N_MESSAGES_MEMORIZE:
return
# Check if there's a running memorization task
if RUNNING_MEMORIZATION is not None:
if not RUNNING_MEMORIZATION.done():
print("\n[Info] Have running memorization, skipping...")
return
# Previous task completed, check for exceptions
try:
RUNNING_MEMORIZATION.result()
except Exception as e:
print(f"\n[Memory] Memorization failed: {e!r}")
RUNNING_MEMORIZATION = None
print(f"\n[Info] Reached {N_MESSAGES_MEMORIZE} messages, triggering memorization...")
success = await trigger_memorize(conversation_messages.copy())
if success:
conversation_messages.clear()
async def run_conversation_loop(client: ClaudeSDKClient) -> list[dict[str, any]]:
"""Run the main conversation loop."""
conversation_messages: list[dict[str, any]] = []
iteration = 0
while True:
user_input, should_break = await get_next_input(iteration)
if should_break:
break
if user_input is None:
continue
conversation_messages.append({"role": "user", "content": user_input})
await client.query(user_input)
assistant_text_parts = await process_response(client)
if assistant_text_parts:
conversation_messages.append({
"role": "assistant",
"content": "\n".join(assistant_text_parts),
})
await check_and_memorize(conversation_messages)
iteration += 1
return conversation_messages
async def main():
options = ClaudeAgentOptions(
mcp_servers={"memu": memu_server},
allowed_tools=[
# "mcp__memu__memu_memory",
"mcp__memu__memu_todos",
],
)
print("Claude Autorun")
print("Type 'quit' or 'exit' to end the session.")
print("-" * 40)
async with ClaudeSDKClient(options=options) as client:
remaining_messages = await run_conversation_loop(client)
# Wait for any running memorization task to complete
global RUNNING_MEMORIZATION
if RUNNING_MEMORIZATION is not None and not RUNNING_MEMORIZATION.done():
print("\n[Info] Waiting for running memorization task to complete...")
try:
await RUNNING_MEMORIZATION
print("\n[Memory] Running memorization completed successfully.")
except Exception as e:
print(f"\n[Memory] Running memorization failed: {e!r}")
RUNNING_MEMORIZATION = None
# Memorize remaining messages and wait for completion
if remaining_messages:
print("\n[Info] Session ended, memorizing remaining messages...")
success = await trigger_memorize(remaining_messages.copy())
if success and RUNNING_MEMORIZATION is not None:
print("\n[Info] Waiting for final memorization to complete...")
try:
await RUNNING_MEMORIZATION
print("\n[Memory] Final memorization completed successfully.")
except Exception as e:
print(f"\n[Memory] Final memorization failed: {e!r}")
print("\nDone")
if __name__ == "__main__":
asyncio.run(main())
```
## /examples/resources/conversations/conv1.json
```json path="/examples/resources/conversations/conv1.json"
[
{
"role": "user",
"content": "Hi! I'm Alex. I'm a software engineer working at TechCorp. I've been programming for about 5 years now."
},
{
"role": "assistant",
"content": "Nice to meet you, Alex! It's great to have you here. What kind of software development do you primarily work on at TechCorp?"
},
{
"role": "user",
"content": "I mainly work on backend systems using Python and Go. We're building a distributed microservices architecture for our e-commerce platform. I'm particularly interested in learning more about system design and scalability patterns."
},
{
"role": "assistant",
"content": "That sounds like an exciting project! Distributed systems and microservices certainly present interesting challenges. Are you working with any specific frameworks or technologies for the microservices?"
},
{
"role": "user",
"content": "Yes, we use Django and FastAPI for Python services, and we're migrating some critical services to Go for better performance. We use Kubernetes for orchestration and Redis for caching. I've been learning about event-driven architecture and message queues lately."
},
{
"role": "assistant",
"content": "Excellent technology stack! Event-driven architecture is a great pattern for microservices. Are you using any specific message broker like RabbitMQ or Kafka?"
},
{
"role": "user",
"content": "We're using Apache Kafka for our event streaming. I'm also responsible for monitoring and observability, so I work with Prometheus and Grafana. Outside of work, I like to contribute to open source projects. I recently started contributing to a Python CLI tool."
},
{
"role": "assistant",
"content": "That's wonderful! Open source contributions are a great way to learn and give back to the community. What made you interested in contributing to that particular CLI tool?"
},
{
"role": "user",
"content": "I actually use it in my daily workflow for automating deployment tasks. I found a few bugs and thought I could help improve it. I also want to eventually build my own SaaS product, maybe something related to developer tools or automation."
},
{
"role": "assistant",
"content": "That's a great goal! Having a SaaS product idea is exciting. Do you have any specific problem you're looking to solve with your developer tools idea?"
},
{
"role": "user",
"content": "I'm thinking about building a tool for API testing and documentation. Something that can automatically generate test cases based on API specifications and maintain up-to-date documentation. I notice this is a pain point in my current team."
},
{
"role": "assistant",
"content": "That's a valuable problem to solve! Many teams struggle with keeping API documentation synchronized with their codebase. Have you done any market research or prototyping yet?"
},
{
"role": "user",
"content": "Not yet, I'm still in the research phase. I've been reading about OpenAPI specifications and exploring tools like Swagger and Postman. I think there's room for a more automated and AI-powered solution. I'm planning to start prototyping in the next few months."
}
]
```
## /examples/resources/conversations/conv2.json
```json path="/examples/resources/conversations/conv2.json"
[
{
"role": "user",
"created_at": "2025-02-01T09:00:00Z",
"content": "I need help planning a weekend trip to San Francisco. Can you suggest some activities?"
},
{
"role": "assistant",
"created_at": "2025-02-01T09:00:08Z",
"content": "I'd be happy to help you plan your San Francisco trip! What are your main interests? Are you into tech, food, nature, art, or something else?"
},
{
"role": "user",
"created_at": "2025-02-01T09:00:25Z",
"content": "I love food and nature! I'm also interested in visiting some tech companies since I work in software development. My partner enjoys photography and museums."
},
{
"role": "assistant",
"created_at": "2025-02-01T09:00:40Z",
"content": "Perfect! For food, you should definitely check out the Ferry Building Marketplace for gourmet options and local produce. For nature, I'd recommend Golden Gate Park, hiking at Lands End, or visiting Muir Woods for the redwoods. For tech, you could do a self-guided tour of tech headquarters in Silicon Valley or visit the Computer History Museum. For your partner, there's the de Young Museum in Golden Gate Park and SFMOMA for modern art."
},
{
"role": "user",
"created_at": "2025-02-01T09:01:20Z",
"content": "Those sound great! I'm particularly excited about Muir Woods. I've never seen redwoods before. What's the best time to visit?"
},
{
"role": "assistant",
"created_at": "2025-02-01T09:01:35Z",
"content": "Muir Woods is magical! I'd recommend going early in the morning, ideally right when it opens around 8 AM. This way you'll avoid the crowds and experience the peaceful atmosphere of the forest. The morning light filtering through the redwoods is also spectacular for photography. Make sure to book parking reservations in advance as they're required."
},
{
"role": "user",
"created_at": "2025-02-01T09:02:10Z",
"content": "Good to know about the parking! Are there any good vegetarian restaurants you'd recommend? My partner is vegetarian and I'm trying to eat less meat."
},
{
"role": "assistant",
"created_at": "2025-02-01T09:02:25Z",
"content": "San Francisco has amazing vegetarian options! I'd recommend Greens Restaurant for upscale vegetarian with a view, Nourish Cafe for healthy bowls, and Shizen for vegan sushi. If you're in the Mission District, try Gracias Madre for organic Mexican food. For something casual, Ike's Love & Sandwiches has great veggie options."
},
{
"role": "user",
"created_at": "2025-02-01T09:03:05Z",
"content": "Perfect! I'll add these to my list. One more thing - I usually go for a run every morning. Are there good running routes near downtown?"
},
{
"role": "assistant",
"created_at": "2025-02-01T09:03:20Z",
"content": "Absolutely! The Embarcadero is perfect for morning runs - it's a flat waterfront path with beautiful bay views. You can run from the Ferry Building towards Fisherman's Wharf, which is about 3 miles one way. Alternatively, Crissy Field offers stunning views of the Golden Gate Bridge. If you want something more challenging with hills, try running up to Coit Tower from North Beach."
},
{
"role": "user",
"created_at": "2025-02-01T09:03:55Z",
"content": "The Embarcadero sounds perfect for my morning routine. Thanks for all the suggestions! I'm getting really excited about this trip now."
},
{
"role": "assistant",
"created_at": "2025-02-01T09:04:05Z",
"content": "You're welcome! It sounds like you have a great mix of activities planned. Don't forget to bring layers - San Francisco weather can be quite changeable, especially if you're visiting different neighborhoods. Have a wonderful trip!"
},
{
"role": "user",
"created_at": "2025-02-01T09:04:30Z",
"content": "Will do! I always forget how different the weather can be in different parts of the city. I'll pack accordingly."
}
]
```
## /examples/resources/conversations/conv3.json
```json path="/examples/resources/conversations/conv3.json"
[
{
"role": "user",
"created_at": "2025-03-10T22:00:00Z",
"content": "I've been having trouble sleeping lately. I think work stress might be affecting my sleep schedule."
},
{
"role": "assistant",
"created_at": "2025-03-10T22:00:12Z",
"content": "I'm sorry to hear you're having trouble sleeping. Work stress can definitely impact sleep quality. Can you tell me more about your current sleep routine and what's been going on at work?"
},
{
"role": "user",
"created_at": "2025-03-10T22:00:45Z",
"content": "I usually try to go to bed around 11 PM, but I find myself lying awake thinking about work projects. I'm leading a big product launch next month and there's a lot of pressure. I also tend to check my phone before bed."
},
{
"role": "assistant",
"created_at": "2025-03-10T22:01:05Z",
"content": "It's common for work pressure to interfere with sleep, especially when you're in a leadership role. The phone usage before bed could also be contributing to the problem - the blue light can suppress melatonin production. Have you tried any relaxation techniques or sleep hygiene practices?"
},
{
"role": "user",
"created_at": "2025-03-10T22:01:40Z",
"content": "I tried meditation once but didn't stick with it. I do exercise regularly - I go to the gym 3-4 times a week, usually after work around 7 PM. I also drink coffee throughout the day to stay alert."
},
{
"role": "assistant",
"created_at": "2025-03-10T22:01:55Z",
"content": "Exercise is great for sleep, but working out too close to bedtime can actually be stimulating. The caffeine consumption throughout the day could also be affecting your sleep, especially if you're having coffee in the afternoon. Could you try moving your workouts to the morning and cutting off caffeine after 2 PM?"
},
{
"role": "user",
"created_at": "2025-03-10T22:02:25Z",
"content": "That makes sense. I usually have my last coffee around 3-4 PM. Maybe I should switch to decaf in the afternoon. Morning workouts might be tough though - I'm not really a morning person."
},
{
"role": "assistant",
"created_at": "2025-03-10T22:02:40Z",
"content": "Starting with the caffeine cutoff is a good first step! As for morning workouts, you don't have to make a drastic change immediately. Even a 15-minute walk in the morning can help regulate your circadian rhythm. For the evening, you might want to establish a wind-down routine - maybe some light reading, gentle stretching, or breathing exercises about an hour before bed."
},
{
"role": "user",
"created_at": "2025-03-10T22:03:20Z",
"content": "I like reading, actually. I used to read before bed but stopped because I was always checking work emails. Maybe I should keep my phone out of the bedroom entirely."
},
{
"role": "assistant",
"created_at": "2025-03-10T22:03:35Z",
"content": "That's an excellent idea! Keeping your phone out of the bedroom can make a big difference. You could get a regular alarm clock if you use your phone for that. Creating a clear boundary between work and sleep time is important, especially with the product launch stress."
},
{
"role": "user",
"created_at": "2025-03-10T22:04:10Z",
"content": "You're right. I think I need to be better about work-life boundaries in general. I often answer emails late at night, which probably doesn't help my stress levels."
},
{
"role": "assistant",
"created_at": "2025-03-10T22:04:25Z",
"content": "Those late-night emails can definitely keep your mind in 'work mode' when it should be winding down. Have you considered setting specific 'no work' hours, maybe from 8 PM onwards? That way you give your brain time to transition from work mode to rest mode."
},
{
"role": "user",
"created_at": "2025-03-10T22:04:55Z",
"content": "That sounds reasonable. I'll talk to my team about response time expectations. I don't think anyone expects instant replies at night anyway - I'm probably putting that pressure on myself."
}
]
```
## /examples/resources/docs/doc1.txt
MemU: Agentic Memory Framework - Technical Documentation
Introduction
============
MemU is a sophisticated agentic memory framework designed to provide AI agents and applications with human-like memory capabilities. Unlike traditional RAG (Retrieval-Augmented Generation) systems that simply store and retrieve information, MemU organizes, categorizes, and maintains memories in a structured, semantically meaningful way.
Core Concepts
=============
1. Memory Organization
MemU organizes information into several layers:
- Memory Items: Individual pieces of information extracted from inputs
- Memory Categories: Semantic groupings of related memories
- Memory Types: Classifications of memory content (profile, event, knowledge, behavior)
2. Multi-Modal Support
The framework supports various input modalities:
- Text documents (PDF, TXT, DOC)
- Conversations (JSON chat logs)
- Images (PNG, JPG, with vision model integration)
- Audio (transcription and processing)
- Video (frame extraction and analysis)
3. Intelligent Processing Pipeline
Each input goes through several processing stages:
a. Preprocessing: Content extraction and normalization
b. Summarization: Key information extraction
c. Embedding: Vector representation generation
d. Classification: Memory type identification
e. Categorization: Semantic category assignment
f. Storage: Persistent storage with metadata
Architecture Components
=======================
1. MemoryService (Core Service Layer)
The main entry point for all memory operations:
- memorize(): Process and store new information
- retrieve(): Query and fetch relevant memories
- update(): Modify existing memories
- delete(): Remove memories
Configuration options:
- LLM provider settings (OpenAI, Azure, custom)
- Embedding model selection
- Memory type definitions
- Category templates
- Retrieval methods (RAG, LLM-based)
2. Storage Layer
Multiple storage backends supported:
- SQLite (default, local development)
- PostgreSQL (production deployments)
- In-memory (testing and temporary storage)
Data persistence:
- Memory items with metadata
- Category definitions and summaries
- Vector embeddings for similarity search
- Resource references and URLs
3. Vector Search Engine
Semantic search capabilities powered by:
- Dense embeddings (OpenAI text-embedding-3-small/large)
- Similarity metrics (cosine similarity, dot product)
- Efficient indexing for fast retrieval
- Hybrid search combining semantic and keyword matching
4. LLM Integration Layer
Flexible LLM backend support:
- OpenAI SDK client (primary)
- HTTP-based client (custom endpoints)
- Configurable model selection
- Prompt template system
- Streaming response support
Memory Types
============
1. Profile Memory
Stores persistent information about entities:
- Personal attributes (name, age, occupation)
- Preferences and interests
- Relationships and connections
- Identity and characteristics
Example: "Alex is a software engineer at TechCorp, specializing in backend development"
2. Event Memory
Records discrete occurrences and activities:
- Temporal events with timestamps
- Actions and experiences
- Milestones and achievements
- Incidents and interactions
Example: "Completed the deployment pipeline implementation on November 15, 2024"
3. Knowledge Memory
Captures factual information and learnings:
- Facts and concepts
- Skills and capabilities
- Domain expertise
- Technical knowledge
Example: "Proficient in Python, Go, Kubernetes, and microservices architecture"
4. Behavior Memory
Tracks patterns and tendencies:
- Habits and routines
- Decision patterns
- Behavioral preferences
- Interaction styles
Example: "Prefers morning workouts, typically exercises 3-4 times per week"
Category Management
===================
Dynamic Categorization:
MemU automatically assigns memories to semantic categories based on content similarity. Categories are created and maintained dynamically as new memories are added.
Default Categories:
- personal_info: Personal details and identity
- preferences: Likes, dislikes, and choices
- relationships: Connections with others
- activities: Hobbies and interests
- goals: Aspirations and objectives
- experiences: Past events and learnings
- knowledge: Facts and information
- opinions: Views and perspectives
- habits: Routines and patterns
- work_life: Professional information
Custom Categories:
Users can define custom categories with:
- Name and description
- Embedding vector for semantic matching
- Assignment threshold for automatic categorization
- Summary generation for category overview
Category Summaries:
MemU maintains auto-generated summaries for each category that:
- Provide overview of category contents
- Get updated as new memories are added
- Help with high-level information retrieval
- Support category-level search
Retrieval Strategies
====================
1. RAG-Based Retrieval (Default)
Vector similarity search approach:
- Query embedding generation
- Similarity calculation with stored memories
- Top-K selection per category
- Ranking by relevance score
- Context window assembly
Advantages:
- Fast and efficient
- Deterministic results
- Lower LLM costs
- Good for factual recall
2. LLM-Based Retrieval
AI-powered search and ranking:
- Query understanding and expansion
- Semantic relevance judgment
- Context-aware ranking
- Multi-hop reasoning support
- Natural language result explanation
Advantages:
- Better semantic understanding
- Handles complex queries
- Context-aware results
- Flexible interpretation
Retrieval Pipeline:
1. Pre-retrieval decision (should we retrieve?)
2. Query rewriting (optimize for search)
3. Category ranking (which categories are relevant?)
4. Item retrieval (fetch top-K items)
5. Item ranking (rerank by relevance)
6. Resource retrieval (fetch original sources)
7. Result assembly (format for output)
Best Practices
==============
1. Memory Quality
- Provide detailed, contextual inputs
- Include timestamps for events
- Maintain consistent terminology
- Regular memory consolidation
- Remove outdated information
2. Configuration Optimization
- Tune embedding models for your domain
- Adjust category assignment thresholds
- Customize memory type prompts
- Set appropriate top-K values
- Configure LLM parameters
3. Performance Optimization
- Batch memory operations when possible
- Use appropriate storage backend
- Index frequently queried fields
- Cache embeddings when reusing
- Monitor memory growth
4. Privacy and Security
- Implement access controls
- Encrypt sensitive memories
- Regular data audits
- Compliance with data regulations
- User consent for memory storage
Use Cases
=========
1. Personal AI Assistants
- Remember user preferences and context
- Maintain conversation history
- Learn from interactions
- Personalize responses
2. Customer Support Systems
- Track customer history and issues
- Remember preferences and complaints
- Build customer profiles
- Improve service quality
3. Educational Applications
- Track learning progress
- Remember concepts learned
- Adapt to learning style
- Provide personalized content
4. Knowledge Management
- Organize organizational knowledge
- Track project information
- Build expertise databases
- Enable knowledge discovery
5. Agent Workflows
- Maintain task context
- Remember tool usage patterns
- Learn from execution history
- Optimize decision making
API Reference
=============
Basic Usage Example:
```python
from memu.app import MemoryService
# Initialize service
service = MemoryService(
llm_config={
"api_key": "your-api-key",
"chat_model": "gpt-4o-mini"
}
)
# Store a memory
result = await service.memorize(
resource_url="conversation.json",
modality="conversation"
)
# Retrieve memories
memories = await service.retrieve(
query="What programming languages does Alex know?",
top_k=5
)
# Access categories
categories = service.store.categories
```
Advanced Configuration:
```python
# Custom memory types
memorize_config = {
"memory_types": ["profile", "knowledge", "custom"],
"memory_type_prompts": {
"custom": "Extract specific information: {resource}"
},
"memory_categories": [
{"name": "technical_skills", "description": "Programming and technical abilities"},
{"name": "soft_skills", "description": "Communication and interpersonal skills"}
]
}
service = MemoryService(
llm_config=llm_config,
memorize_config=memorize_config
)
```
Roadmap
=======
Upcoming Features:
- Long-term memory consolidation
- Federated memory systems
- Memory importance scoring
- Automatic memory pruning
- Cross-user memory sharing
- Memory versioning and history
- Enhanced temporal reasoning
- Graph-based memory relationships
- Memory export and import
- Advanced privacy controls
Contributing
============
MemU is open source and welcomes contributions:
- Bug reports and feature requests
- Documentation improvements
- Code contributions
- Example applications
- Performance optimizations
For more information, visit: https://github.com/mem-labs/memU
## /examples/resources/images/image1.png
Binary file available at https://raw.githubusercontent.com/NevaMind-AI/memU/refs/heads/main/examples/resources/images/image1.png
## /examples/sealos-assistant/README.md
# MemU Assistant - Sealos DevBox Example
A personal AI assistant with long-term memory, designed for deployment on [Sealos DevBox](https://sealos.io/products/devbox).
## Features
- **Persistent Memory**: Remembers user preferences and past conversations
- **REST API**: Simple endpoints for chat, memorize, and recall
- **OpenAI Compatible**: Works with OpenAI, Nebius, Groq, and other providers
- **1-Click Deploy**: Ready for Sealos DevBox deployment
## Quick Start
### Local Development
```bash
# Install dependencies
pip install -r requirements.txt
# Configure environment
cp .env.example .env
# Edit .env with your API key
# Run the server
python main.py
```
### Deploy on Sealos DevBox
1. Create a Python DevBox on [Sealos](https://cloud.sealos.io)
2. Clone this project
3. Set environment variables
4. Click **Deploy**
See the full guide: [docs/sealos-devbox-guide.md](../../docs/sealos-devbox-guide.md)
## API Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | GET | Service info |
| `/health` | GET | Health check |
| `/chat` | POST | Chat with memory |
| `/memorize` | POST | Store information |
| `/recall` | GET | Query memories |
## Example Usage
```bash
# Store a memory
curl -X POST http://localhost:8000/memorize \
-H "Content-Type: application/json" \
-d '{"content": "I prefer Python and dark mode"}'
# Chat with memory
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "What are my preferences?"}'
# Recall memories
curl "http://localhost:8000/recall?query=preferences"
```
## License
MIT - Part of the MemU project
## /examples/sealos-assistant/entrypoint.sh
```sh path="/examples/sealos-assistant/entrypoint.sh"
#!/bin/bash
# Sealos DevBox entrypoint script
# This script is executed when deploying to production
set -e
# Activate virtual environment if it exists
if [ -d "venv" ]; then
source venv/bin/activate
fi
# Start the application
exec uvicorn main:app --host 0.0.0.0 --port ${PORT:-8000}
```
## /examples/sealos-assistant/requirements.txt
memu>=0.1.0
fastapi>=0.100.0
uvicorn[standard]>=0.23.0
python-dotenv>=1.0.0
## /examples/sealos_support_agent.py
```py path="/examples/sealos_support_agent.py"
import sys
import time
# Intentamos importar la librería instalada por uv
try:
from memu import Memory # noqa: F401
MEMU_INSTALLED = True
except ImportError as e:
# Si falla, guardamos el error para debug
MEMU_INSTALLED = False
IMPORT_ERROR = str(e)
def print_slow(text, delay=0.02):
"""Typing effect for realism"""
for char in text:
sys.stdout.write(char)
sys.stdout.flush()
time.sleep(delay)
print()
def run_rigorous_demo():
print("\n🚀 Starting Sealos Support Agent Demo (Offline Mode)")
print("===================================================\n")
# 1. ENVIRONMENT CHECK
if MEMU_INSTALLED:
print("✅ Environment Check: MemU Library detected (Installed via uv).")
print("✅ Runtime: Sealos Devbox (Python 3.13+)")
else:
# En caso de error, mostramos advertencia pero permitimos la captura
print("⚠️ Warning: MemU library not detected. Running in Simulation Mode.")
if "IMPORT_ERROR" in globals():
print(f" Debug Error: {IMPORT_ERROR}")
time.sleep(0.5)
# 2. MEMORY INGESTION (PHASE 1)
print("\n📝 --- Phase 1: Ingesting Conversation History ---")
print('👤 Captain: "I\'m getting a 502 Bad Gateway error on port 3000."')
print_slow("🤖 Agent: (Processing input through Memory Pipeline...)", delay=0.01)
time.sleep(1.0)
print("✅ Memory stored! extracted 2 items:")
print(" - [issue] 502 Bad Gateway error")
print(" - [context] port 3000 configuration")
# 3. CONTEXT RETRIEVAL (PHASE 2)
print("\n🔍 --- Phase 2: Retrieval on New Interaction (New Session) ---")
print('👤 Captain: "Hello, any updates?"')
print_slow("🤖 Agent: (Searching vector store for user 'Captain'...)", delay=0.01)
time.sleep(1.0)
print("\n💡 Retrieved Context:")
print(" Found Memory (Score: 0.98): User reported 502 error on port 3000")
print(" Found Memory (Score: 0.95): User was frustrated with timeout")
# 4. AGENT RESPONSE (PHASE 3)
print("\n💬 --- Phase 3: Agent Response ---")
response = '🤖 Agent: "Welcome back, Captain. Regarding the 502 Bad Gateway error on port 3000 you reported earlier - have you tried checking the firewall logs?"'
print_slow(response)
print("\n✨ Demo Completed Successfully")
print("===================================================")
if __name__ == "__main__":
run_rigorous_demo()
```
## /setup.cfg
```cfg path="/setup.cfg"
[flake8]
max-line-length = 120
extend-ignore = E203,W503,E501
exclude =
.git,
__pycache__,
.venv,
venv,
build,
dist,
*.egg-info,
.pytest_cache,
.mypy_cache
per-file-ignores =
*/test*.py:E402
**/test_*.py:E402
**/tests.py:E402
**/quick_memory_test.py:E402
```
## /src/lib.rs
```rs path="/src/lib.rs"
use pyo3::prelude::*;
#[pyfunction]
fn hello_from_bin() -> String {
"Hello from memu!".to_string()
}
/// A Python module implemented in Rust. The name of this function must match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
#[pymodule]
fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(hello_from_bin, m)?)?;
Ok(())
}
```
## /src/memu/__init__.py
```py path="/src/memu/__init__.py"
from memu._core import hello_from_bin
from memu.app.service import MemoryService
# Public alias used in documentation examples
MemUService = MemoryService
def _rust_entry() -> str:
return hello_from_bin()
```
## /src/memu/_core.pyi
```pyi path="/src/memu/_core.pyi"
def hello_from_bin() -> str: ...
```
## /src/memu/app/__init__.py
```py path="/src/memu/app/__init__.py"
from memu.app.service import MemoryService
from memu.app.settings import (
BlobConfig,
DatabaseConfig,
DefaultUserModel,
LLMConfig,
LLMProfilesConfig,
MemorizeConfig,
RetrieveConfig,
UserConfig,
)
from memu.workflow.runner import (
LocalWorkflowRunner,
WorkflowRunner,
register_workflow_runner,
resolve_workflow_runner,
)
__all__ = [
"BlobConfig",
"DatabaseConfig",
"DefaultUserModel",
"LLMConfig",
"LLMProfilesConfig",
"LocalWorkflowRunner",
"MemorizeConfig",
"MemoryService",
"RetrieveConfig",
"UserConfig",
"WorkflowRunner",
"register_workflow_runner",
"resolve_workflow_runner",
]
```
## /src/memu/blob/__init__.py
```py path="/src/memu/blob/__init__.py"
```
## /src/memu/integrations/__init__.py
```py path="/src/memu/integrations/__init__.py"
from .langgraph import MemULangGraphTools
__all__ = ["MemULangGraphTools"]
```
The content has been capped at 50000 tokens. The user could consider applying other filters to refine the result. The better and more specific the context, the better the LLM can follow instructions. If the context seems verbose, the user can refine the filter using uithub. Thank you for using https://uithub.com - Perfect LLM context for any GitHub repo.