mem0-cli 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,188 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ **/node_modules/
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended not to include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+ pyenv/
131
+
132
+ # Spyder project settings
133
+ .spyderproject
134
+ .spyproject
135
+
136
+ # Rope project settings
137
+ .ropeproject
138
+
139
+ # mkdocs documentation
140
+ /site
141
+
142
+ # mypy
143
+ .mypy_cache/
144
+ .dmypy.json
145
+ dmypy.json
146
+
147
+ # Pyre type checker
148
+ .pyre/
149
+
150
+ # pytype static type analyzer
151
+ .pytype/
152
+
153
+ # Cython debug symbols
154
+ cython_debug/
155
+
156
+ # PyCharm
157
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
158
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
159
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
160
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
161
+ #.idea/
162
+
163
+ .ideas.md
164
+ .todos.md
165
+
166
+ # Database
167
+ db
168
+ test-db
169
+ !embedchain/embedchain/core/db/
170
+
171
+ .vscode
172
+ .idea/
173
+
174
+ .DS_Store
175
+
176
+ notebooks/*.yaml
177
+ .ipynb_checkpoints/
178
+
179
+ !configs/*.yaml
180
+
181
+ # cache db
182
+ *.db
183
+
184
+ # local directories for testing
185
+ eval/
186
+ qdrant_storage/
187
+ .crossnote
188
+ testing.ipynb
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mem0-cli
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: The official CLI for mem0 — the memory layer for AI agents
5
5
  Author-email: "mem0.ai" <founders@mem0.ai>
6
6
  License-Expression: Apache-2.0
@@ -32,10 +32,20 @@ The official command-line interface for [mem0](https://mem0.ai) — the memory l
32
32
 
33
33
  ## Installation
34
34
 
35
+ ### Using pipx (recommended)
36
+
37
+ ```bash
38
+ pipx install mem0-cli
39
+ ```
40
+
41
+ ### Using pip
42
+
35
43
  ```bash
36
44
  pip install mem0-cli
37
45
  ```
38
46
 
47
+ > **Note:** On macOS with Homebrew Python, `pip install` outside a virtual environment will fail with an `externally-managed-environment` error ([PEP 668](https://peps.python.org/pep-0668/)). Use `pipx` instead, or install inside a virtual environment.
48
+
39
49
  ## Quick Start
40
50
 
41
51
  ```bash
@@ -52,6 +62,13 @@ mem0 search "What are Alice's preferences?" --user-id alice
52
62
  mem0 list --user-id alice
53
63
  ```
54
64
 
65
+ ## Releasing
66
+
67
+ 1. Update `version` in `pyproject.toml`
68
+ 2. Create a GitHub Release with tag `cli-v<version>` (e.g. `cli-v0.2.0`)
69
+
70
+ For a pre-release, use a beta version like `0.2.0b1` and check the **pre-release** checkbox.
71
+
55
72
  ## License
56
73
 
57
74
  Apache-2.0
@@ -0,0 +1,46 @@
1
+ # mem0 CLI
2
+
3
+ The official command-line interface for [mem0](https://mem0.ai) — the memory layer for AI agents.
4
+
5
+ ## Installation
6
+
7
+ ### Using pipx (recommended)
8
+
9
+ ```bash
10
+ pipx install mem0-cli
11
+ ```
12
+
13
+ ### Using pip
14
+
15
+ ```bash
16
+ pip install mem0-cli
17
+ ```
18
+
19
+ > **Note:** On macOS with Homebrew Python, `pip install` outside a virtual environment will fail with an `externally-managed-environment` error ([PEP 668](https://peps.python.org/pep-0668/)). Use `pipx` instead, or install inside a virtual environment.
20
+
21
+ ## Quick Start
22
+
23
+ ```bash
24
+ # Set up your configuration
25
+ mem0 init
26
+
27
+ # Add a memory
28
+ mem0 add "I prefer dark mode and use vim keybindings" --user-id alice
29
+
30
+ # Search memories
31
+ mem0 search "What are Alice's preferences?" --user-id alice
32
+
33
+ # List all memories
34
+ mem0 list --user-id alice
35
+ ```
36
+
37
+ ## Releasing
38
+
39
+ 1. Update `version` in `pyproject.toml`
40
+ 2. Create a GitHub Release with tag `cli-v<version>` (e.g. `cli-v0.2.0`)
41
+
42
+ For a pre-release, use a beta version like `0.2.0b1` and check the **pre-release** checkbox.
43
+
44
+ ## License
45
+
46
+ Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "mem0-cli"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "The official CLI for mem0 — the memory layer for AI agents"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -3,6 +3,8 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import json as _json
6
+ import os
7
+ import stat as _stat_mod
6
8
  import sys
7
9
  from pathlib import Path
8
10
 
@@ -43,7 +45,14 @@ entity_app = typer.Typer(
43
45
  no_args_is_help=True,
44
46
  rich_markup_mode="rich",
45
47
  )
46
- # entity_app registered after Memory commands to control panel ordering
48
+
49
+ event_app = typer.Typer(
50
+ name="event",
51
+ help="Inspect background processing events.",
52
+ no_args_is_help=True,
53
+ rich_markup_mode="rich",
54
+ )
55
+ # entity_app and event_app registered after Memory commands to control panel ordering
47
56
 
48
57
 
49
58
  # ── Helpers ───────────────────────────────────────────────────────────────
@@ -114,9 +123,22 @@ def _resolve_ids(
114
123
  }
115
124
 
116
125
 
126
+ def _stdin_is_piped() -> bool:
127
+ """Return True only when stdin is an actual pipe or file redirect — not a bare open fd."""
128
+ from mem0_cli.state import is_agent_mode
129
+
130
+ if is_agent_mode():
131
+ return False
132
+ try:
133
+ mode = os.fstat(sys.stdin.fileno()).st_mode
134
+ return _stat_mod.S_ISFIFO(mode) or _stat_mod.S_ISREG(mode)
135
+ except Exception:
136
+ return False
137
+
138
+
117
139
  def _read_stdin() -> str | None:
118
- """Read from stdin if it is piped (not a TTY)."""
119
- if not sys.stdin.isatty():
140
+ """Read from stdin if it is an actual pipe or file redirect (not a TTY, not agent mode)."""
141
+ if _stdin_is_piped():
120
142
  return sys.stdin.read().strip() or None
121
143
  return None
122
144
 
@@ -128,7 +150,18 @@ def _read_stdin() -> str | None:
128
150
  def main_callback(
129
151
  ctx: typer.Context,
130
152
  version: bool = typer.Option(False, "--version", help="Show version and exit."),
153
+ json_agent: bool = typer.Option(
154
+ False,
155
+ "--json",
156
+ "--agent",
157
+ help="Output as JSON for agent/programmatic use.",
158
+ is_eager=False,
159
+ ),
131
160
  ) -> None:
161
+ if json_agent:
162
+ from mem0_cli.state import set_agent_mode
163
+
164
+ set_agent_mode(True)
132
165
  if version:
133
166
  from mem0_cli.commands.utils import cmd_version
134
167
 
@@ -253,8 +286,12 @@ def search(
253
286
  help="Specific fields to return (comma-separated).",
254
287
  rich_help_panel="Search",
255
288
  ),
256
- graph: bool = typer.Option(False, "--graph", help="Enable graph in search.", rich_help_panel="Search"),
257
- no_graph: bool = typer.Option(False, "--no-graph", help="Disable graph in search.", rich_help_panel="Search"),
289
+ graph: bool = typer.Option(
290
+ False, "--graph", help="Enable graph in search.", rich_help_panel="Search"
291
+ ),
292
+ no_graph: bool = typer.Option(
293
+ False, "--no-graph", help="Disable graph in search.", rich_help_panel="Search"
294
+ ),
258
295
  output: str = typer.Option(
259
296
  "text", "--output", "-o", help="Output: text, json, table.", rich_help_panel="Output"
260
297
  ),
@@ -269,7 +306,7 @@ def search(
269
306
  None, "--base-url", help="Override API base URL.", rich_help_panel="Connection"
270
307
  ),
271
308
  ) -> None:
272
- """Search memories by semantic query.
309
+ """Query your memory store — semantic, keyword, or hybrid retrieval.
273
310
 
274
311
  Examples:
275
312
  mem0 search "preferences" --user-id alice
@@ -281,8 +318,8 @@ def search(
281
318
  # STEP 7: stdin fallback for query
282
319
  if query is None:
283
320
  query = _read_stdin()
284
- if query is None:
285
- print_error(err_console, "No query provided. Pass a query argument or pipe via stdin.")
321
+ if not query or not query.strip():
322
+ print_error(err_console, "Search query cannot be empty.")
286
323
  raise typer.Exit(1)
287
324
 
288
325
  backend, config = _get_backend_and_config(api_key, base_url)
@@ -372,8 +409,12 @@ def list_cmd(
372
409
  before: str | None = typer.Option(
373
410
  None, "--before", help="Created before (YYYY-MM-DD).", rich_help_panel="Filters"
374
411
  ),
375
- graph: bool = typer.Option(False, "--graph", help="Enable graph in listing.", rich_help_panel="Filters"),
376
- no_graph: bool = typer.Option(False, "--no-graph", help="Disable graph in listing.", rich_help_panel="Filters"),
412
+ graph: bool = typer.Option(
413
+ False, "--graph", help="Enable graph in listing.", rich_help_panel="Filters"
414
+ ),
415
+ no_graph: bool = typer.Option(
416
+ False, "--no-graph", help="Disable graph in listing.", rich_help_panel="Filters"
417
+ ),
377
418
  output: str = typer.Option(
378
419
  "table", "--output", "-o", help="Output: text, json, table.", rich_help_panel="Output"
379
420
  ),
@@ -463,11 +504,19 @@ def update(
463
504
 
464
505
  @app.command(rich_help_panel="Memory")
465
506
  def delete(
466
- memory_id: str | None = typer.Argument(None, help="Memory ID to delete (omit when using --all or --entity)."),
507
+ memory_id: str | None = typer.Argument(
508
+ None, help="Memory ID to delete (omit when using --all or --entity)."
509
+ ),
467
510
  all_: bool = typer.Option(False, "--all", help="Delete all memories matching scope filters."),
468
- entity: bool = typer.Option(False, "--entity", help="Delete the entity itself and all its memories (cascade)."),
469
- project: bool = typer.Option(False, "--project", help="With --all: delete ALL memories project-wide."),
470
- dry_run: bool = typer.Option(False, "--dry-run", help="Show what would be deleted without deleting."),
511
+ entity: bool = typer.Option(
512
+ False, "--entity", help="Delete the entity itself and all its memories (cascade)."
513
+ ),
514
+ project: bool = typer.Option(
515
+ False, "--project", help="With --all: delete ALL memories project-wide."
516
+ ),
517
+ dry_run: bool = typer.Option(
518
+ False, "--dry-run", help="Show what would be deleted without deleting."
519
+ ),
471
520
  force: bool = typer.Option(False, "--force", help="Skip confirmation."),
472
521
  user_id: str | None = typer.Option(
473
522
  None, "--user-id", "-u", help="Scope to user.", rich_help_panel="Scope"
@@ -641,14 +690,12 @@ def entity_delete(
641
690
  agent_id: str | None = typer.Option(
642
691
  None, "--agent-id", help="Agent ID.", rich_help_panel="Scope"
643
692
  ),
644
- app_id: str | None = typer.Option(
645
- None, "--app-id", help="App ID.", rich_help_panel="Scope"
646
- ),
647
- run_id: str | None = typer.Option(
648
- None, "--run-id", help="Run ID.", rich_help_panel="Scope"
649
- ),
693
+ app_id: str | None = typer.Option(None, "--app-id", help="App ID.", rich_help_panel="Scope"),
694
+ run_id: str | None = typer.Option(None, "--run-id", help="Run ID.", rich_help_panel="Scope"),
650
695
  force: bool = typer.Option(False, "--force", help="Skip confirmation."),
651
- dry_run: bool = typer.Option(False, "--dry-run", help="Show what would be deleted without deleting."),
696
+ dry_run: bool = typer.Option(
697
+ False, "--dry-run", help="Show what would be deleted without deleting."
698
+ ),
652
699
  output: str = typer.Option(
653
700
  "text", "--output", "-o", help="Output: text, json, quiet.", rich_help_panel="Output"
654
701
  ),
@@ -688,23 +735,98 @@ def entity_delete(
688
735
  app.add_typer(entity_app, name="entity", rich_help_panel="Management")
689
736
 
690
737
 
738
+ # ── Event subcommands ─────────────────────────────────────────────────────
739
+
740
+
741
+ @event_app.command("list")
742
+ def event_list(
743
+ output: str = typer.Option(
744
+ "table", "--output", "-o", help="Output: table, json.", rich_help_panel="Output"
745
+ ),
746
+ api_key: str | None = typer.Option(
747
+ None,
748
+ "--api-key",
749
+ help="Override API key.",
750
+ envvar="MEM0_API_KEY",
751
+ rich_help_panel="Connection",
752
+ ),
753
+ base_url: str | None = typer.Option(
754
+ None, "--base-url", help="Override API base URL.", rich_help_panel="Connection"
755
+ ),
756
+ ) -> None:
757
+ """List recent background processing events.
758
+
759
+ Examples:
760
+ mem0 event list
761
+ mem0 event list -o json
762
+ """
763
+ from mem0_cli.commands.events_cmd import cmd_event_list
764
+
765
+ backend = _get_backend(api_key, base_url)
766
+ cmd_event_list(backend, output=output)
767
+
768
+
769
+ @event_app.command("status")
770
+ def event_status(
771
+ event_id: str = typer.Argument(..., help="Event ID to inspect."),
772
+ output: str = typer.Option(
773
+ "text", "--output", "-o", help="Output: text, json.", rich_help_panel="Output"
774
+ ),
775
+ api_key: str | None = typer.Option(
776
+ None,
777
+ "--api-key",
778
+ help="Override API key.",
779
+ envvar="MEM0_API_KEY",
780
+ rich_help_panel="Connection",
781
+ ),
782
+ base_url: str | None = typer.Option(
783
+ None, "--base-url", help="Override API base URL.", rich_help_panel="Connection"
784
+ ),
785
+ ) -> None:
786
+ """Check the status of a specific background event.
787
+
788
+ Examples:
789
+ mem0 event status <event-id>
790
+ mem0 event status <event-id> -o json
791
+ """
792
+ from mem0_cli.commands.events_cmd import cmd_event_status
793
+
794
+ backend = _get_backend(api_key, base_url)
795
+ cmd_event_status(backend, event_id, output=output)
796
+
797
+
798
+ # ── Event subgroup ──
799
+ app.add_typer(event_app, name="event", rich_help_panel="Management")
800
+
801
+
691
802
  # ── Management commands ───────────────────────────────────────────────────
692
803
 
693
804
 
694
805
  @app.command(rich_help_panel="Management")
695
806
  def init(
696
807
  api_key: str | None = typer.Option(None, "--api-key", help="API key (skip prompt)."),
697
- user_id: str | None = typer.Option(None, "--user-id", "-u", help="Default user ID (skip prompt)."),
808
+ user_id: str | None = typer.Option(
809
+ None, "--user-id", "-u", help="Default user ID (skip prompt)."
810
+ ),
811
+ email: str | None = typer.Option(None, "--email", help="Login via email verification code."),
812
+ code: str | None = typer.Option(
813
+ None, "--code", help="Verification code (use with --email for non-interactive login)."
814
+ ),
815
+ force: bool = typer.Option(
816
+ False, "--force", help="Overwrite existing config without confirmation."
817
+ ),
698
818
  ) -> None:
699
819
  """Interactive setup wizard for mem0 CLI.
700
820
 
701
821
  Examples:
702
822
  mem0 init
703
823
  mem0 init --api-key m0-xxx --user-id alice
824
+ mem0 init --email alice@company.com
825
+ mem0 init --email alice@company.com --code 482901
704
826
  """
705
827
  from mem0_cli.commands.init_cmd import run_init
706
828
 
707
- run_init(api_key=api_key, user_id=user_id)
829
+ run_init(api_key=api_key, user_id=user_id, email=email, code=code, force=force)
708
830
 
709
831
 
710
832
  # (entity_app registered at module level, below sub-group definitions)
@@ -743,7 +865,6 @@ def status(
743
865
  )
744
866
 
745
867
 
746
-
747
868
  @app.command("import", rich_help_panel="Management")
748
869
  def import_cmd(
749
870
  file_path: str = typer.Argument(..., help="JSON file to import."),
@@ -810,7 +931,7 @@ def _build_help_json() -> dict:
810
931
  },
811
932
  },
812
933
  "search": {
813
- "description": "Search memories by semantic query.",
934
+ "description": "Query your memory store — semantic, keyword, or hybrid retrieval.",
814
935
  "usage": "mem0 search <query> [OPTIONS]",
815
936
  "arguments": {"query": {"description": "Search query.", "required": False}},
816
937
  "options": {
@@ -914,6 +1035,24 @@ def _build_help_json() -> dict:
914
1035
  "value": {"description": "Value to set.", "required": True},
915
1036
  },
916
1037
  },
1038
+ "event": {
1039
+ "description": "Inspect background processing events.",
1040
+ "subcommands": {
1041
+ "list": {
1042
+ "description": "List recent background processing events.",
1043
+ "usage": "mem0 event list [OPTIONS]",
1044
+ "options": {"--output, -o": "Output format: table, json."},
1045
+ },
1046
+ "status": {
1047
+ "description": "Check the status of a specific background event.",
1048
+ "usage": "mem0 event status <event_id> [OPTIONS]",
1049
+ "arguments": {
1050
+ "event_id": {"description": "Event ID to inspect.", "required": True}
1051
+ },
1052
+ "options": {"--output, -o": "Output format: text, json."},
1053
+ },
1054
+ },
1055
+ },
917
1056
  "entity": {
918
1057
  "description": "Manage entities.",
919
1058
  "subcommands": {
@@ -965,6 +1104,7 @@ def _build_help_json() -> dict:
965
1104
  "global_options": {
966
1105
  "--api-key": "Override API key (env: MEM0_API_KEY).",
967
1106
  "--base-url": "Override API base URL.",
1107
+ "--json / --agent": "Output as JSON for agent/programmatic use.",
968
1108
  "--help": "Show help for a command.",
969
1109
  "--version": "Show version and exit.",
970
1110
  },
@@ -994,7 +1134,7 @@ def help(
994
1134
  console.print("Usage: mem0 <command> [OPTIONS]\n")
995
1135
  console.print("[bold]Commands:[/]")
996
1136
  console.print(" add Add a memory from text, messages, file, or stdin")
997
- console.print(" search Search memories by semantic query")
1137
+ console.print(" search Query your memory store (semantic, keyword, hybrid)")
998
1138
  console.print(" get Get a specific memory by ID")
999
1139
  console.print(" list List memories with optional filters")
1000
1140
  console.print(" update Update a memory's text or metadata")
@@ -1002,6 +1142,7 @@ def help(
1002
1142
  console.print(" import Import memories from a JSON file")
1003
1143
  console.print(" config Manage configuration (show, get, set)")
1004
1144
  console.print(" entity Manage entities (list, delete)")
1145
+ console.print(" event Inspect background events (list, status)")
1005
1146
  console.print(" init Interactive setup wizard")
1006
1147
  console.print(" status Check connectivity and authentication")
1007
1148
  console.print()
@@ -1018,4 +1159,14 @@ app.add_typer(config_app, name="config", rich_help_panel="Management")
1018
1159
 
1019
1160
 
1020
1161
  def main() -> None:
1162
+ import sys
1163
+
1164
+ # Allow --json/--agent anywhere in the command line (not just before subcommand).
1165
+ _json_flags = {"--json", "--agent"}
1166
+ if any(a in _json_flags for a in sys.argv[1:]):
1167
+ from mem0_cli.state import set_agent_mode
1168
+
1169
+ set_agent_mode(True)
1170
+ sys.argv = [sys.argv[0]] + [a for a in sys.argv[1:] if a not in _json_flags]
1171
+
1021
1172
  app()
@@ -104,6 +104,11 @@ class Backend(ABC):
104
104
  @abstractmethod
105
105
  def entities(self, entity_type: str) -> list[dict]: ...
106
106
 
107
+ @abstractmethod
108
+ def list_events(self) -> list[dict]: ...
109
+
110
+ @abstractmethod
111
+ def get_event(self, event_id: str) -> dict: ...
107
112
 
108
113
 
109
114
  def get_backend(config: Mem0Config) -> Backend: