@yugabytedb/meko-mcp 2.1.0 → 2.3.0
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.
- package/README.md +233 -40
- package/assets/hooks-handlers/codex-session-end.sh +4 -69
- package/assets/hooks-handlers/cursor-session-start.sh +19 -1
- package/assets/hooks-handlers/lib/capture-cleanup-cli.js +1473 -0
- package/assets/hooks-handlers/lib/capture-notices.js +438 -0
- package/assets/hooks-handlers/lib/capture-state.js +2173 -0
- package/assets/hooks-handlers/lib/capture-status-cli.js +86 -0
- package/assets/hooks-handlers/lib/capture.js +2782 -403
- package/assets/hooks-handlers/lib/checkpoint-timer.js +485 -81
- package/assets/hooks-handlers/lib/journal-bridge.js +218 -0
- package/assets/hooks-handlers/lib/kiro-handler.js +760 -0
- package/assets/hooks-handlers/lib/opencode-handler.js +620 -0
- package/assets/hooks-handlers/lib/opencode-normalizer.js +145 -0
- package/assets/hooks-handlers/lib/terminal-handoff.js +427 -0
- package/assets/hooks-handlers/session-end.sh +3 -34
- package/assets/opencode-plugin/meko.js +213 -0
- package/assets/scripts/meko-statusline.sh +123 -16
- package/assets/skills/meko-mcp-tools/SKILL.md +116 -126
- package/assets/skills/meko-mcp-tools/references/_sections.md +3 -3
- package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +25 -18
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +99 -24
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +1 -1
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +53 -6
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +25 -79
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +37 -26
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +14 -8
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +66 -1
- package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +7 -40
- package/assets/skills/meko-mcp-tools-desktop/SKILL.md +56 -20
- package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +1 -1
- package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +1 -1
- package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +15 -8
- package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +99 -36
- package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +22 -5
- package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +18 -14
- package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +39 -28
- package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +14 -8
- package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +67 -1
- package/assets/skills/meko-select-datapack-desktop/SKILL.md +4 -4
- package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +8 -8
- package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +7 -5
- package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +4 -4
- package/bin/create-meko-setup.mjs +113 -12
- package/lib/capture-cleanup.mjs +63 -0
- package/lib/capture-status.mjs +67 -0
- package/lib/clients/aliases.mjs +5 -0
- package/lib/clients/claude-code.mjs +1 -0
- package/lib/clients/claude-desktop.mjs +120 -5
- package/lib/clients/codex.mjs +85 -37
- package/lib/clients/common.mjs +7 -0
- package/lib/clients/index.mjs +4 -0
- package/lib/clients/kiro.mjs +705 -0
- package/lib/clients/opencode.mjs +532 -0
- package/lib/config.mjs +158 -1
- package/lib/installer.mjs +18 -1
- package/lib/migrate/adapters/claude-code.mjs +11 -2
- package/lib/migrate/adapters/codex.mjs +497 -0
- package/lib/migrate/adapters/memory-md.mjs +27 -8
- package/lib/migrate/adapters/opencode.mjs +148 -0
- package/lib/migrate/claude-parser.mjs +153 -9
- package/lib/migrate/id.mjs +217 -10
- package/lib/migrate/mcp-client.mjs +25 -1
- package/lib/migrate/opencode-normalizer.mjs +132 -0
- package/lib/migrate/orchestrator.mjs +299 -56
- package/lib/migrate/progress.mjs +239 -5
- package/lib/migrate/registry.mjs +72 -0
- package/lib/migrate.mjs +100 -10
- package/lib/prompt.mjs +16 -1
- package/package.json +4 -4
- package/scripts/bundle-assets.mjs +4 -0
|
@@ -6,9 +6,50 @@ Every tool example below shows the correct parameters, expected response, and co
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## Retrieval
|
|
10
|
+
|
|
11
|
+
### context_search
|
|
12
|
+
|
|
13
|
+
Default first call for open-ended recall ("what do you know about X?"). One call queries memory, the knowledge base, and the conversation-history cache in parallel.
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
context_search(
|
|
17
|
+
query="auth migration decisions",
|
|
18
|
+
agent_id="<your agent_id>",
|
|
19
|
+
conversation_id="<session conversation id>",
|
|
20
|
+
datapack_id="<datapack UUID>")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Required: `query`, `conversation_id`. `datapack_id` is optional (default datapack if omitted); pass the pinned id when you have one.
|
|
24
|
+
|
|
25
|
+
Response:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
{
|
|
29
|
+
"results": {
|
|
30
|
+
"memory": [{"id": "...", "memory": "...", "score": 0.51, ...}],
|
|
31
|
+
"knowledge_base": [{"id": "...", "chunk_text": "...", "document_id": "...", "distance": 0.31, "match_type": "hybrid", ...}],
|
|
32
|
+
"conversation": {"hits": [...], "thread": [...]}
|
|
33
|
+
},
|
|
34
|
+
"token_savings": {"total_tokens": 49000, "memory": {"tokens_sent": 600, "tokens_saved": 48400}, "tokens_saved": 48400}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- A bucket is `null` only when that source wasn't queried: `force_source` excluded it, or the server couldn't build a query vector for it.
|
|
39
|
+
- An empty bucket is ambiguous: either that source found nothing relevant, or it failed. `context_search` turns a failed source into an empty list and records the error only in the trace. Before you tell the user nothing is stored about X, confirm with `memory_search` or `knowledgebase_search`, which return errors.
|
|
40
|
+
- The conversation bucket is datapack-wide. It returns embedded turns from every user and agent on the datapack, and each hit carries its author's `user_id`. Don't present a hit as this user's own history.
|
|
41
|
+
- `limit` bounds the memory and KB buckets only; the conversation bucket returns up to 10 hits plus a thread of whole turns.
|
|
42
|
+
- The memory bucket has no similarity floor on the default path. The KB bucket drops chunks above an absolute distance cutoff, so it can be empty even when `knowledgebase_search` would return a weak best match.
|
|
43
|
+
- `force_source="memory" | "knowledge_base" | "conversation"` queries only that source. `force_source="memory"` reapplies the `memory_search` similarity floor.
|
|
44
|
+
- `token_savings` is an estimate for reporting. Don't base decisions on it.
|
|
45
|
+
|
|
46
|
+
**Errors:** `conversation_id_required`, `invalid_force_source`, `datapack_access_denied`, and `free_tier_limit_reached` (Free tier: 1,000 lifetime calls). Treat any error as a failed search (SKILL.md operating contract 1).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
9
50
|
## Memory Tools
|
|
10
51
|
|
|
11
|
-
**Critical:** Pass your session's `agent_id` on every memory *write* (
|
|
52
|
+
**Critical:** Pass your session's `agent_id` on every memory *write* (from the SessionStart `additionalContext`) — it is stored on the row as attribution. It does **not** filter reads: one `memory_search` / `memory_get_all` returns all of your memories across every `agent_id`. For cross-project facts, write with `agent_id="meko_agent"`.
|
|
12
53
|
|
|
13
54
|
### memory_add
|
|
14
55
|
|
|
@@ -22,12 +63,13 @@ memory_add(agent_id="<your-agent-id>",
|
|
|
22
63
|
|
|
23
64
|
**Response:**
|
|
24
65
|
```json
|
|
25
|
-
{"results": [{"id": "mem-uuid-123", "memory": "
|
|
66
|
+
{"results": [{"id": "mem-uuid-123", "memory": "Deploy scripts must be run from the repo root, never a subdir."}]}
|
|
26
67
|
```
|
|
27
68
|
|
|
28
69
|
**What NOT to store via memory_add:**
|
|
29
70
|
- Full conversations (use `conversation_create` + `conversation_add_message`)
|
|
30
71
|
- Large documents (use the UI's Datapack → Actions → Add Knowledge upload flow)
|
|
72
|
+
- Multi-topic dumps (transcripts, mixed logs + decisions) — store **one coherent fact per memory**, with the identifiers a later search will use
|
|
31
73
|
|
|
32
74
|
**Common errors:**
|
|
33
75
|
- `syntax error at or near "-"` — legacy error from the pre-multi-tenancy schema when `agent_id` became part of a PostgreSQL identifier. No longer applies on Cloud (agent_id is a TEXT column value, any string is accepted). If you hit it on a deployment that still uses the old schema, use underscores instead of hyphens.
|
|
@@ -43,23 +85,29 @@ memory_add(agent_id="<your-agent-id>",
|
|
|
43
85
|
memory_search(query="What programming language does the team use?", agent_id="agent", conversation_id="<uuid>")
|
|
44
86
|
```
|
|
45
87
|
|
|
46
|
-
**Cross-conversation discovery.** `memory_search` returns hits across every stored conversation for the `(datapack_id, user_id)` pair, across all agents (
|
|
88
|
+
**Cross-conversation discovery.** `memory_search` returns hits across every stored conversation for the `(datapack_id, user_id)` pair, across all agents (`agent_id` scopes the call's trace, not the results). When a hit references an interesting conversation, follow up with `conversation_list` to browse the associated threads and `conversation_get` to read a specific one — the memory hit's `meko_conversation_id` field is the id to fetch. For a deliberately cross-conversation search leave `run_id` off; to scope a search to a single conversation instead, pass `run_id=<conversation_id>` (it filters on `meko_conversation_id` — see `tools-known-limitations.md`).
|
|
89
|
+
|
|
90
|
+
**Relevance floor.** `memory_search` drops results whose raw cosine similarity is below the server's `memory_search_min_score` setting (default `0.2`, tunable at runtime). A query can return fewer results than `limit`, or an empty list, when nothing clears the bar. That means no sufficiently relevant memory, not a broken call.
|
|
47
91
|
|
|
48
92
|
**Response:**
|
|
49
93
|
```json
|
|
50
|
-
{"results": [{"id": "mem-uuid-123", "memory": "Team uses Python for backend", "score": 0.89}]}
|
|
94
|
+
{"results": [{"id": "mem-uuid-123", "memory": "Team uses Python for backend", "score": 0.89, "raw_similarity_score": 0.72}]}
|
|
51
95
|
```
|
|
52
96
|
|
|
97
|
+
`score` is the fused hybrid rank (semantic + keyword + entity boost) used to order results; `raw_similarity_score` is the unfused cosine value. A similarity threshold like `MEMORY_SEARCH_MIN_SCORE` gates on `raw_similarity_score` when it is not null, and falls back to `score` when the raw field is absent or null.
|
|
98
|
+
|
|
53
99
|
**With limit:**
|
|
54
100
|
```
|
|
55
101
|
memory_search(query="user preferences", agent_id="agent", conversation_id="<uuid>", limit=5)
|
|
56
102
|
```
|
|
57
103
|
|
|
104
|
+
**Evidence cap (SKILL.md operating contract 3): reason over at most ~10 results, no matter how many were retrieved or requested.** If asked to "use everything," still select the ~10 most relevant and say that you did.
|
|
105
|
+
|
|
58
106
|
---
|
|
59
107
|
|
|
60
108
|
### memory_get_all
|
|
61
109
|
|
|
62
|
-
**When to use:**
|
|
110
|
+
**When to use:** See the most recent memories (about 20 rows) across every `agent_id`, plus the true `total`. It is not a complete listing and takes no paging arguments (SKILL.md operating contract 2). Use `memory_search` or `memory_get_by_id` for anything older or specific.
|
|
63
111
|
|
|
64
112
|
```
|
|
65
113
|
memory_get_all(agent_id="agent", conversation_id="<uuid>")
|
|
@@ -91,11 +139,13 @@ memory_update(memory_id="mem-uuid-123", text="Updated: Team uses Go for all new
|
|
|
91
139
|
memory_delete_by_id(memory_id="mem-uuid-123", agent_id="agent", conversation_id="<uuid>")
|
|
92
140
|
```
|
|
93
141
|
|
|
142
|
+
`memory_update` and `memory_delete_by_id` return `memory_is_promoted` for a promoted memory, and `not_found` for an id that is missing or belongs to another account.
|
|
143
|
+
|
|
94
144
|
---
|
|
95
145
|
|
|
96
146
|
### memory_delete_all
|
|
97
147
|
|
|
98
|
-
**Destructive.** Deletes all memories
|
|
148
|
+
**Destructive.** Deletes all memories in the passed `agent_id`'s bucket in the datapack. It does not touch other agents' rows, even though `memory_search` shows them; omitting `agent_id` deletes only the `meko_agent` bucket. Pass `run_id=<conversation_id>` to limit it to one conversation. For removing a single memory, prefer `memory_delete_by_id`.
|
|
99
149
|
|
|
100
150
|
```
|
|
101
151
|
memory_delete_all(agent_id="agent", conversation_id="<uuid>")
|
|
@@ -117,9 +167,7 @@ memory_promote(memory_ids=["mem-uuid-123", "mem-uuid-456"],
|
|
|
117
167
|
{"inserted_ids": ["mem-uuid-123"], "updated_ids": ["mem-uuid-456"], "not_found_ids": []}
|
|
118
168
|
```
|
|
119
169
|
|
|
120
|
-
Get exact UUIDs from the `id` field of `memory_search` / `memory_get_all` results
|
|
121
|
-
|
|
122
|
-
On 403, authentication, or permission failure, report the error and stop — do not escalate scope, change datapacks, or alter identity. After a successful call, `knowledgebase_search` may verify shared visibility, but it is not a rollback mechanism.
|
|
170
|
+
Get exact UUIDs from the `id` field of `memory_search` / `memory_get_all` results (never any other identifier), and follow the confirmation checklist in SKILL.md before calling. On 403 or any auth failure, report and stop — never escalate scope, change datapacks, or alter identity.
|
|
123
171
|
|
|
124
172
|
---
|
|
125
173
|
|
|
@@ -131,9 +179,12 @@ On 403, authentication, or permission failure, report the error and stop — do
|
|
|
131
179
|
|
|
132
180
|
```
|
|
133
181
|
conversation_create(agent_id="agent",
|
|
134
|
-
title="Debugging the auth middleware"
|
|
182
|
+
title="Debugging the auth middleware",
|
|
183
|
+
datapack_id="<uuid from datapack_list>")
|
|
135
184
|
```
|
|
136
185
|
|
|
186
|
+
`datapack_id` is required whenever no server-side default resolves for the caller. Omitting it in that state returns `{"error": "datapack_id_required"}` and persists nothing; the same contract applies to `conversation_add_message`, `conversation_get`, `conversation_update`, and `conversation_delete`.
|
|
187
|
+
|
|
137
188
|
**Response:**
|
|
138
189
|
```json
|
|
139
190
|
{"id": "conv-uuid-123", "title": "Debugging the auth middleware"}
|
|
@@ -145,8 +196,6 @@ conversation_create(agent_id="agent",
|
|
|
145
196
|
|
|
146
197
|
**When to use:** Add a user/assistant exchange to an existing conversation. **All fields must be verbatim** — never summarize or rephrase.
|
|
147
198
|
|
|
148
|
-
Leave `index_for_search` at its default (`False`). Conversation-cache embedding is currently a WorkbenchLM-only feature — the inference gateway opts in on its own turns; agent-harness conversations should not opt in.
|
|
149
|
-
|
|
150
199
|
```
|
|
151
200
|
conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
|
|
152
201
|
input="Why is the auth middleware returning 401?",
|
|
@@ -206,7 +255,7 @@ conversation_delete(conversation_id="conv-uuid-123", agent_id="agent")
|
|
|
206
255
|
|
|
207
256
|
## Knowledge Base Tools
|
|
208
257
|
|
|
209
|
-
**KB ingestion is a UI-only activity.** Users upload files via the datapack's Actions → **Add Knowledge** dialog (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). `knowledgebase_search
|
|
258
|
+
**KB ingestion is a UI-only activity.** Users upload files via the datapack's Actions → **Add Knowledge** dialog (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). MCP exposes two KB tools: `knowledgebase_search`, and `knowledgebase_delete_document` for removing a single uploaded file.
|
|
210
259
|
|
|
211
260
|
See `tools-rag-workflow.md` for the decision table.
|
|
212
261
|
|
|
@@ -225,7 +274,7 @@ knowledgebase_search(
|
|
|
225
274
|
|
|
226
275
|
Unlike memory tools, `datapack_id` has no default — you must pass it explicitly.
|
|
227
276
|
|
|
228
|
-
**Response (empty KB
|
|
277
|
+
**Response (empty KB):**
|
|
229
278
|
```json
|
|
230
279
|
{"results": [], "count": 0}
|
|
231
280
|
```
|
|
@@ -234,6 +283,17 @@ Populated KBs return results with chunk content and similarity scores. An empty/
|
|
|
234
283
|
|
|
235
284
|
---
|
|
236
285
|
|
|
286
|
+
### knowledgebase_delete_document
|
|
287
|
+
|
|
288
|
+
Permanently deletes ONE knowledge-base file — its chunks and metadata in one transaction, plus a best-effort delete of the stored file. Irreversible: confirm with the user before calling, and take `document_id` from `knowledgebase_search` hits — hits carry `document_id` but NOT a filename, so confirm by echoing the id and the matched chunk text (the documents list API / Meko UI is the authoritative name source). Never guess an id; non-UUID values are rejected.
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
knowledgebase_delete_document(document_id="<uuid from a search hit>",
|
|
292
|
+
conversation_id="<session conversation id>")
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Returns `{"document_id", "chunks_deleted", "s3_deleted"}` — if `s3_deleted` is `false`, say so: the index entries are gone but the stored file may remain. Errors include a numeric `status`: `403` means the user is not the datapack owner, a maintainer, or the file's uploader — report it, don't retry; `409` (`DOCUMENT_PROCESSING`) means the file is still being indexed — wait for indexing to finish, then retry.
|
|
296
|
+
|
|
237
297
|
## Artifact Tools
|
|
238
298
|
|
|
239
299
|
### artifact_put
|
|
@@ -267,6 +327,7 @@ Save the `content_hash` — it's the retrieval key for `artifact_get`.
|
|
|
267
327
|
**Common errors:**
|
|
268
328
|
- `invalid_base64` — `content_base64` is not valid base64; decode the file before passing it.
|
|
269
329
|
- `artifact_too_large` — file exceeds 5 MiB (default). Set `MEKO_MAX_ARTIFACT_UPLOAD_BYTES` to raise the limit.
|
|
330
|
+
- `PAT_RATE_LIMITED` — burst uploads throttle; the error carries **no `content_hash`**, which mimics silent write loss. Pace bulk uploads, back off ~60s. The `content_hash` is the plain SHA-256 of the bytes — compute it locally and verify important artifacts with an `artifact_get` read-back.
|
|
270
331
|
|
|
271
332
|
---
|
|
272
333
|
|
|
@@ -320,22 +381,36 @@ For large files use the `local_path` value to read the file with normal file too
|
|
|
320
381
|
### datapack_create / datapack_list / datapack_describe
|
|
321
382
|
|
|
322
383
|
```
|
|
323
|
-
datapack_create(name="analytics_prod")
|
|
324
|
-
datapack_list() # returns datapack_id for each datapack
|
|
325
|
-
datapack_describe(datapack_id="<uuid>", include_status=True)
|
|
384
|
+
datapack_create(name="analytics_prod", conversation_id="<conversation id>")
|
|
385
|
+
datapack_list(conversation_id="<session conversation id>") # returns datapack_id for each datapack
|
|
386
|
+
datapack_describe(datapack_id="<uuid>", include_status=True, conversation_id="<conversation id>")
|
|
326
387
|
```
|
|
327
388
|
|
|
389
|
+
`datapack_describe` returns these counts:
|
|
390
|
+
|
|
391
|
+
| Field | Meaning |
|
|
392
|
+
|---|---|
|
|
393
|
+
| `memory_count` | All memories stored in the datapack |
|
|
394
|
+
| `collective_memory_count` | Memories promoted to shared knowledge |
|
|
395
|
+
| `learnings_count` | Memories awaiting a promotion decision |
|
|
396
|
+
| `knowledge_base_file_count` | Uploaded KB documents; `null` if the status endpoint is unreachable |
|
|
397
|
+
| `knowledge_chunk_count` | KB chunks across all documents (for debugging retrieval) |
|
|
398
|
+
| `shared_knowledge_count` | `collective_memory_count + knowledge_base_file_count`; `null` when the file count is `null` |
|
|
399
|
+
|
|
400
|
+
`knowledge_count` is a deprecated alias of `knowledge_chunk_count`. `datapack_list` doesn't compute counts; call `datapack_describe` for them.
|
|
401
|
+
|
|
328
402
|
### datapack_update / datapack_delete
|
|
329
403
|
|
|
330
|
-
`datapack_update` renames
|
|
404
|
+
`datapack_update` renames a datapack, edits its description, and/or opts it in/out of conversation-search embedding. `name`, `description`, and `conversation_search_opt_out` are all optional; pass at least one. If none are provided the tool returns `nothing_to_update` without hitting the API.
|
|
331
405
|
|
|
332
|
-
The server refuses to rename the caller's `meko_default_datapack` — a rename call against that datapack returns `"meko_default_datapack cannot be renamed"`. Description edits on the default datapack are still allowed. Passing `description=""` does NOT clear an existing description; clearing is not supported via MCP.
|
|
406
|
+
The server refuses to rename the caller's `meko_default_datapack` — a rename call against that datapack returns `"meko_default_datapack cannot be renamed"`. Description edits on the default datapack are still allowed. Passing `description=""` does NOT clear an existing description; clearing is not supported via MCP. Conversation-search embedding is on by default; `conversation_search_opt_out=True` stops future turns from being indexed (already-cached turns are unaffected) and is restricted to the datapack's owner or a maintainer. This is best-effort, not a hard guarantee — a transient database error on the live embed path's opt-out check fails open, so a turn can occasionally still get embedded for an opted-out datapack.
|
|
333
407
|
|
|
334
408
|
```
|
|
335
|
-
datapack_update(datapack_id="<uuid>", name="renamed-datapack")
|
|
336
|
-
datapack_update(datapack_id="<uuid>", description="new description")
|
|
337
|
-
datapack_update(datapack_id="<uuid>", name="x", description="y")
|
|
338
|
-
|
|
409
|
+
datapack_update(datapack_id="<uuid>", name="renamed-datapack", conversation_id="<conversation id>")
|
|
410
|
+
datapack_update(datapack_id="<uuid>", description="new description", conversation_id="<conversation id>")
|
|
411
|
+
datapack_update(datapack_id="<uuid>", name="x", description="y", conversation_id="<conversation id>")
|
|
412
|
+
datapack_update(datapack_id="<uuid>", conversation_search_opt_out=True, conversation_id="<conversation id>")
|
|
413
|
+
datapack_delete(datapack_id="<uuid>", conversation_id="<conversation id>") # Irreversible!
|
|
339
414
|
```
|
|
340
415
|
|
|
341
416
|
### Agent and knowledge-base management (NOT MCP — control-plane only)
|
|
@@ -345,4 +420,4 @@ Agent and KB lifecycle does not ship as MCP tools. If the user asks to create/li
|
|
|
345
420
|
- REST: `POST/GET/DELETE /datapacks/:datapack_id/agents` (agents), `POST/GET/DELETE /datapacks/:datapack_id/knowledge-bases` (KB sources).
|
|
346
421
|
- Or the Meko Cloud UI at `cloud.mekodata.ai` → Datapacks → agents / knowledge-bases.
|
|
347
422
|
|
|
348
|
-
KB ingestion specifically lives in the UI today: Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5 MB each, 10/batch). Agents querying a populated index use `knowledgebase_search` — see `tools-rag-workflow.md`.
|
|
423
|
+
KB ingestion specifically lives in the UI today: Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5 MB each, 10/batch). Agents querying a populated index use `knowledgebase_search`, and can remove a single uploaded file with `knowledgebase_delete_document` — see `tools-rag-workflow.md`.
|
|
@@ -50,7 +50,7 @@ Delete child resources first (agents and KB sources via the control plane), then
|
|
|
50
50
|
```
|
|
51
51
|
# Control-plane (REST or UI): DELETE /datapacks/:datapack_id/knowledge-bases
|
|
52
52
|
# Control-plane (REST or UI): DELETE /datapacks/:datapack_id/agents/sales_agent
|
|
53
|
-
datapack_delete(datapack_id="dp-uuid-123") # MCP-exposed, destructive, irreversible
|
|
53
|
+
datapack_delete(datapack_id="dp-uuid-123", conversation_id="<conversation id>") # MCP-exposed, destructive, irreversible
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
## Common mistake: forgetting datapack_id on memory tools
|
|
@@ -2,7 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
These are current limitations of the Meko MCP tools. Know them upfront to avoid wasted tool calls.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Lifetime request quotas by tier
|
|
6
|
+
|
|
7
|
+
`memory_search`, `knowledgebase_search`, and `memory_add` are quota-gated **per user, lifetime** — not per minute or per day. Default caps by plan:
|
|
8
|
+
|
|
9
|
+
| Tier | memory_search | knowledgebase_search | memory_add |
|
|
10
|
+
|---|---:|---:|---:|
|
|
11
|
+
| Free | 1,000 | 1,000 | 10,000 |
|
|
12
|
+
| Standard | 5,000 | 5,000 | 30,000 |
|
|
13
|
+
| Pro / Enterprise | uncapped | uncapped | uncapped |
|
|
14
|
+
|
|
15
|
+
The Free tier also caps `context_search` and `conversation_add_message` at 1,000 calls each. Embedding turns into the conversation-search cache has its own cap (2,000 turns on Free, 10,000 on Pro). When that cap is reached, `conversation_add_message` still stores the turn and reports `conversation_search_skipped: "quota_exceeded"`; the turn just won't appear in `context_search`'s conversation bucket.
|
|
16
|
+
|
|
17
|
+
A quota error can arrive with HTTP 403. It is not an authentication failure; don't reconfigure credentials because of it.
|
|
18
|
+
|
|
19
|
+
When the cap is reached the tool returns an error object with code `free_tier_limit_reached` (on every tier; the `tier` field names the capped tier) and **no `results` key**.
|
|
20
|
+
|
|
21
|
+
- **Do not retry** — the cap is lifetime.
|
|
22
|
+
- **Budget searches**: polling, verify read-backs, and per-item sweeps all draw from one pool.
|
|
23
|
+
- **Never report this error as "no results"** — it is a failed search; see `tools-troubleshooting.md`.
|
|
24
|
+
|
|
25
|
+
## memory_get_all returns a fixed recent window — it has NO pagination
|
|
26
|
+
|
|
27
|
+
One call returns roughly the **20 most recent rows**; the response's `total` reports the true count. Scoping arguments do not narrow the window, and paging parameters are rejected — there is no way to reach older rows through this tool. A second call with `promoted=true` returns the recent window of promoted rows, not the remaining personal rows; neither call alone nor the two together is a complete listing. Follow SKILL.md operating contract 2: state the gap when `total` exceeds rows returned, never claim a complete enumeration, and use `memory_search` or `memory_get_by_id` for anything specific.
|
|
28
|
+
|
|
29
|
+
## run_id is a read/delete filter on the conversation id, not a write key
|
|
30
|
+
|
|
31
|
+
`memory_search(run_id=<conversation_id>)` and `memory_delete_all(run_id=<conversation_id>)` filter on the row's `meko_conversation_id`, so passing a conversation id there correctly scopes the call to that one conversation — a supported, reliable way to read a single conversation's memories (read/write/delete scoping was made consistent in MEKO-473/MEKO-474, #271). The one gotcha is on the write side: `memory_add`'s own `run_id` is Langfuse trace metadata only and is **not** persisted as the row's conversation id, so a row written with `memory_add(run_id=X)` is not findable via `memory_search(run_id=X)`. Scope writes with `conversation_id`, then filter the matching read by that same id.
|
|
32
|
+
|
|
33
|
+
`memory_get_all` accepts `run_id` but ignores it, and `conversation_list` has no `run_id`.
|
|
34
|
+
|
|
35
|
+
## memory_delete_all is agent-scoped; memory reads are not
|
|
36
|
+
|
|
37
|
+
`memory_search` and `memory_get_all` return every agent's rows for the user. `memory_delete_all` deletes only rows in the `agent_id` you pass, and an omitted `agent_id` means the `meko_agent` bucket. A `memory_search(run_id=X)` preview can therefore list rows that `memory_delete_all(run_id=X)` leaves in place. To clear rows written by several agents, delete them by id with `memory_delete_by_id`, or call `memory_delete_all` once per `agent_id` shown in the preview.
|
|
38
|
+
|
|
39
|
+
## Promoted memories are read-only through MCP
|
|
40
|
+
|
|
41
|
+
`memory_update` and `memory_delete_by_id` return `memory_is_promoted` for a memory that has been promoted to shared knowledge. Edit or remove promoted content in the Cloud UI Learnings tab.
|
|
42
|
+
|
|
43
|
+
## No MCP tools for index / source / pipeline lifecycle
|
|
6
44
|
|
|
7
45
|
There are no MCP tools to:
|
|
8
46
|
- Delete a vector index
|
|
@@ -10,7 +48,7 @@ There are no MCP tools to:
|
|
|
10
48
|
- Clear stuck work queue entries
|
|
11
49
|
- Reset a failed pipeline
|
|
12
50
|
|
|
13
|
-
KB
|
|
51
|
+
The one exception is a single uploaded **file**: `knowledgebase_delete_document` removes that file's chunks and metadata. KB-**source** deletion (the registered source, not one file) happens via the Meko control plane (REST: `DELETE /datapacks/:datapack_id/knowledge-bases`, or the UI): it unregisters the source from the Meko API but does **not** touch the actual `dist_rag` index, source records, or vector data in the datapack's database.
|
|
14
52
|
|
|
15
53
|
**Workaround:** For stuck or failed indexes, create a new index with a different name. Stale indexes remain in the database until manually cleaned up by an admin.
|
|
16
54
|
|
|
@@ -25,7 +63,7 @@ To **query** a built index, use `knowledgebase_search` — it returns both uploa
|
|
|
25
63
|
`memory_add` passes text through Mem0's fact extraction pipeline. This works well for:
|
|
26
64
|
- Facts: "Alice works at Acme Corp"
|
|
27
65
|
- Preferences: "User prefers dark mode"
|
|
28
|
-
- Entity relationships: "
|
|
66
|
+
- Entity relationships: "Alice reports to Bob"
|
|
29
67
|
|
|
30
68
|
It works **poorly** for:
|
|
31
69
|
- CSV rows or tabular data — columns and rows get dropped
|
|
@@ -46,8 +84,17 @@ It works **poorly** for:
|
|
|
46
84
|
|
|
47
85
|
Never ingest CSV row-by-row into memory — each row becomes a fragmented fact with lost context.
|
|
48
86
|
|
|
49
|
-
##
|
|
87
|
+
## Conversation search covers embedded turns only
|
|
88
|
+
|
|
89
|
+
`context_search` searches past conversation turns by meaning in its `conversation` bucket. Only turns embedded into the conversation-search cache are searchable. Turns are embedded by default, except when:
|
|
90
|
+
|
|
91
|
+
- the datapack opted out with `datapack_update(datapack_id=..., conversation_search_opt_out=True, conversation_id=...)`;
|
|
92
|
+
- the account hit the embedding quota (`conversation_search_skipped: "quota_exceeded"`); or
|
|
93
|
+
- the turn was too short to carry content (the server skips trivial turns); or
|
|
94
|
+
- the turn was stored before conversation search was enabled.
|
|
95
|
+
|
|
96
|
+
To find a conversation by other attributes, browse with `conversation_list` and inspect candidates with `conversation_get`.
|
|
50
97
|
|
|
51
|
-
|
|
98
|
+
## Very long conversations can't be read back
|
|
52
99
|
|
|
53
|
-
|
|
100
|
+
When a conversation's trace grows too large for Langfuse, `conversation_get` and `conversation_update` return `{"error": "not_found", "detail": "Conversation <id> not found"}` or time out for that conversation, even though `conversation_add_message` and `conversation_delete` still work. Servers without the MEKO-714 fix instead return `not_found` from `conversation_add_message` on these conversations. If read-back or a write fails with `not_found` on a long conversation that you know exists, report the failure as a server-side limit on that conversation. Don't recreate the conversation under the same id or replay its messages; that makes the trace larger.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- A **preference**: "Customer budget is $50k"
|
|
9
9
|
- An **entity relationship**: "Alice works at Acme Corp"
|
|
10
10
|
|
|
11
|
-
Memory is backed by pgvector
|
|
11
|
+
Memory is backed by pgvector. Search is hybrid: semantic similarity, keyword matching, and a boost for memories that mention the entities named in your query (people, projects, tools). It retrieves relevant facts by meaning, not by conversation order.
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
memory_add(agent_id="support_bot",
|
|
@@ -26,22 +26,26 @@ memory_search(query="What plan does Alice have?", agent_id="support_bot")
|
|
|
26
26
|
Conversations are backed by Langfuse sessions and traces. They preserve full structure: who said what, in what order, with what reasoning.
|
|
27
27
|
|
|
28
28
|
```
|
|
29
|
-
conversation_create(agent_id="support_bot", title="Pricing discussion"
|
|
29
|
+
conversation_create(agent_id="support_bot", title="Pricing discussion",
|
|
30
|
+
datapack_id="<uuid from datapack_list>")
|
|
30
31
|
-- Returns: {"id": "conv-uuid-here"}
|
|
31
32
|
|
|
32
33
|
conversation_add_message(conversation_id="conv-uuid-here", agent_id="support_bot",
|
|
34
|
+
datapack_id="<uuid from datapack_list>",
|
|
33
35
|
input="What are your pricing tiers?",
|
|
34
36
|
output="We offer Starter ($10/mo), Pro ($50/mo), and Enterprise (custom).",
|
|
35
37
|
reasoning="Retrieved pricing page data. No special discounts apply.")
|
|
36
38
|
```
|
|
37
39
|
|
|
40
|
+
`datapack_id` is required for both calls whenever no server-side default resolves for the caller. Omitting it in that state returns `{"error": "datapack_id_required"}` and persists nothing.
|
|
41
|
+
|
|
38
42
|
## Decision Matrix
|
|
39
43
|
|
|
40
44
|
| Signal | Tool |
|
|
41
45
|
|--------|------|
|
|
42
46
|
| "remember that...", "note that...", "keep in mind..." | `memory_add` |
|
|
43
47
|
| "store this conversation", "save this chat" | `conversation_create` + `conversation_add_message` |
|
|
44
|
-
| "what do you know about X?", "recall..." | `
|
|
48
|
+
| "what do you know about X?", "recall..." | `context_search` |
|
|
45
49
|
| "show me our past conversation about..." | `conversation_list` + `conversation_get` |
|
|
46
50
|
| "the user prefers...", "their budget is..." | `memory_add` |
|
|
47
51
|
| "save my query and your response" | `conversation_add_message` |
|
|
@@ -71,7 +75,7 @@ Agents on Cloud Meko have two distinct read surfaces. Pick the right one for the
|
|
|
71
75
|
|
|
72
76
|
| Read path | What it returns | How to call |
|
|
73
77
|
|---|---|---|
|
|
74
|
-
| Your personal memories | Everything you and any of your agents wrote for this user — filtered by `(datapack_id, user_id)`, **not** by `agent_id
|
|
78
|
+
| Your personal memories | Everything you and any of your agents wrote for this user — filtered by `(datapack_id, user_id)`, **not** by `agent_id`; one call covers every bucket | `memory_search(agent_id="<your agent_id>", query="...", ...)` |
|
|
75
79
|
| Team's shared knowledge | Promoted memories + uploaded documents, visible to every member of the datapack | `knowledgebase_search(agent_id="<anything>", datapack_id="<datapack UUID>", query="...")` — `agent_id` is ignored |
|
|
76
80
|
|
|
77
81
|
`agent_id` does not filter memory reads, so a single `memory_search` already spans all of your agents; there is no per-agent fan-out to do.
|
|
@@ -80,7 +84,7 @@ Agents on Cloud Meko have two distinct read surfaces. Pick the right one for the
|
|
|
80
84
|
|
|
81
85
|
- **Personal memories** — written by `memory_add`. The `agent_id` records the writer but does not restrict reads; memories are scoped **per-user**, so any of that user's agents can read them via MCP, and no other user can.
|
|
82
86
|
- **Team-shared Shared Knowledge** — arrives two ways:
|
|
83
|
-
1. An agent calls `memory_promote` for exact, user-confirmed memory UUIDs, or the user promotes them from the Cloud UI's Learnings tab. Promotion moves the memories
|
|
87
|
+
1. An agent calls `memory_promote` for exact, user-confirmed memory UUIDs, or the user promotes them from the Cloud UI's Learnings tab. Promotion moves the memories into shared knowledge, strips `user_id`, preserves originating `agent_id` as provenance, and evicts the private mem0 records.
|
|
84
88
|
2. The user uploads a file via Datapack → Actions → **Add Knowledge** in the Cloud UI. PDF/TXT/MD/JSON/MP4 up to 5MB each.
|
|
85
89
|
|
|
86
90
|
Both show up in `knowledgebase_search`, tagged `metadata_filters.source: "memory"` vs other values so the agent can distinguish provenance in responses.
|
|
@@ -89,18 +93,7 @@ Agents on Cloud Meko have two distinct read surfaces. Pick the right one for the
|
|
|
89
93
|
|
|
90
94
|
### When the user asks "what do you know about X?"
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
memory_search(agent_id="<your-agent-id>", query="X", conversation_id=..., ...) # all your personal memories, every agent
|
|
96
|
-
knowledgebase_search(agent_id="<anything>", datapack_id="<uuid>", query="X", conversation_id=..., ...)
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
The single `memory_search` already returns everything you and any other agent wrote for this user (`agent_id` doesn't filter memory reads) — no per-agent fan-out. When you answer, be explicit about scope so the user knows why something is or isn't there:
|
|
100
|
-
|
|
101
|
-
- "I found this in your personal memories (something you or another of your agents saved earlier)…"
|
|
102
|
-
- "I found this in your team's Shared Knowledge — someone (you or a teammate) promoted it earlier…"
|
|
103
|
-
- "I couldn't find anything in your personal memories. You might want to check the Cloud UI's Memory Summary tab."
|
|
96
|
+
Call `context_search`. One call returns your personal memories (every agent, no per-agent fan-out), team-shared knowledge, and matching past-conversation turns from anyone on the datapack. If the memory or KB bucket is empty, confirm with `memory_search` or `knowledgebase_search` before saying nothing is there, because `context_search` returns an empty list for a failed source. When you answer, name which surface each finding came from, so the user knows why something is or isn't there.
|
|
104
97
|
|
|
105
98
|
## Memory limitations for structured data
|
|
106
99
|
|
|
@@ -114,72 +107,28 @@ There is no MCP-side "just put it in a database table" option — raw SQL access
|
|
|
114
107
|
|
|
115
108
|
## Memory Storage: automatic, not proactive
|
|
116
109
|
|
|
117
|
-
On Claude Code, do **not** proactively `memory_add` facts the user states
|
|
118
|
-
|
|
119
|
-
Explicit `memory_add` is reserved for the three cases automatic extraction cannot reach:
|
|
120
|
-
|
|
121
|
-
- **Explicit request** → the user says "remember this" / "save this."
|
|
122
|
-
- **Output-only / tool-derived fact** → a durable fact that lives only in your output or a tool result, never in a user turn. Extraction reads only the user turn, so it never sees these.
|
|
123
|
-
- **Overwriting correction** → a prior fact was negated and the stale memory must not survive. Extraction is additive (it adds the new fact but leaves the old one live), so `memory_search` for the stale memory and `memory_update` / `memory_delete_by_id` it.
|
|
124
|
-
|
|
125
|
-
Use `memory_search` at the start of sessions to recall what you already know before asking the user to repeat themselves.
|
|
126
|
-
|
|
127
|
-
## Using Both Together
|
|
128
|
-
|
|
129
|
-
Capture stores the full conversation (preserves structure) and extraction derives searchable memories from it — both happen automatically. Add an explicit `memory_add` only for the three cases above.
|
|
110
|
+
On Claude Code, do **not** proactively `memory_add` facts the user states — capture + server-side extraction stores them automatically. Explicit `memory_add` is reserved for the three cases extraction cannot reach (explicit "remember this"; output-only/tool-derived facts; overwriting a negated fact) — the canonical list and rules live in SKILL.md. Use `memory_search` at session start to recall what you already know.
|
|
130
111
|
|
|
131
112
|
## Key Retrieval Difference
|
|
132
113
|
|
|
133
|
-
- `memory_search`: **semantic similarity** across all memories
|
|
134
|
-
- `conversation_get`: **ordered
|
|
114
|
+
- `memory_search`: **semantic similarity** across all memories — relevant facts regardless of when stored.
|
|
115
|
+
- `conversation_get`: **ordered message turns** for one conversation. No semantic search; requires `conversation_id`.
|
|
135
116
|
|
|
136
117
|
## Automatic Conversation Capture
|
|
137
118
|
|
|
138
|
-
The
|
|
139
|
-
|
|
140
|
-
1. **Periodic checkpoint (~10 min)** — Agent-driven via CronCreate, uses `conversation_add_message` MCP tool directly
|
|
141
|
-
2. **PreCompact hook** — Shell script that fires before Claude Code's auto-compaction, captures via MCP JSON-RPC
|
|
142
|
-
3. **SessionEnd hook** — Shell script that fires at session termination, captures final exchanges
|
|
143
|
-
|
|
144
|
-
### What gets captured
|
|
145
|
-
|
|
146
|
-
The full transcript including:
|
|
147
|
-
- **User prompts** — verbatim text (the `input` field)
|
|
148
|
-
- **Assistant responses** — all text blocks (the `output` field)
|
|
149
|
-
- **Tool calls** — tool name + input parameters (the `reasoning` field)
|
|
150
|
-
- **Tool results** — output from tool executions (appended to `reasoning`)
|
|
151
|
-
|
|
152
|
-
This is more than just text — tool calls and results are critical context for session replay, cross-agent sharing, and compaction.
|
|
119
|
+
The plugin captures conversations via three mechanisms — a periodic checkpoint (~10 min), a PreCompact hook, and a SessionEnd hook — storing the full transcript verbatim (user prompts as `input`, assistant text as `output`, tool calls and results as `reasoning`). Skill bodies, background-task notifications, and subagent reports that Claude Code writes into the transcript go to `reasoning` of the turn they belong to, never to `input`. A typed `/skill args` is captured with that command as its `input`.
|
|
153
120
|
|
|
154
|
-
|
|
121
|
+
Each message's seed is `<conversation_id>:<user_message_uuid>`; all three mechanisms derive the same deterministic trace ID from it, so overlapping captures are idempotent. A shared watermark file tracks what has been saved.
|
|
155
122
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
### When to manually store conversations
|
|
159
|
-
|
|
160
|
-
Automatic capture handles the raw exchange. You should still manually use `conversation_create` + `conversation_add_message` when:
|
|
161
|
-
- The user explicitly asks to "save this conversation"
|
|
162
|
-
- You want to add curated `reasoning` traces beyond raw tool calls
|
|
163
|
-
- You want to store a selected subset of the conversation with a descriptive title
|
|
164
|
-
|
|
165
|
-
### Watermark coordination
|
|
166
|
-
|
|
167
|
-
A shared watermark file at `~/.claude/meko-capture/<session-id>.watermark.json` tracks what has been saved. Both hooks and the agent's periodic checkpoint use this to avoid reprocessing already-captured exchanges.
|
|
123
|
+
Manually use `conversation_create` + `conversation_add_message` only when the user explicitly asks to save a conversation, or you want curated `reasoning` traces or a titled subset.
|
|
168
124
|
|
|
169
125
|
## Observability: conversation_id IS the Langfuse trace ID
|
|
170
126
|
|
|
171
|
-
This is the feature agents tend to miss.
|
|
127
|
+
This is the feature agents tend to miss.
|
|
172
128
|
|
|
173
|
-
- `conversation_create` returns a `conversation_id
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
- Child spans reveal internals. Observed structure:
|
|
177
|
-
- `memory_add`: `Memory Add (Meko MCP)` → `Create a new memory in Mem0` → `Bulk Payload Update (yugabytedb / vector)` → `Execute Query (yugabytedb / vector)`
|
|
178
|
-
- `memory_search`: `Memory Search (Meko MCP)` → `Search for memories based on a query in Mem0` (Retriever)
|
|
179
|
-
- `conversation_add_message`: `Conversation Add Message (Meko MCP)` → `Conversation Message Added` span → `Reasoning` generation (the `reasoning` field is stored as a Langfuse *generation*-typed span, not a plain text field)
|
|
180
|
-
- `knowledgebase_search`: `Knowledgebase Search (Meko MCP)` → multiple `Execute Query (yugabytedb)` child spans
|
|
181
|
-
- Trace tags include `agent:<agent_id>` and the Meko org UUID. Both are searchable/filterable in Langfuse.
|
|
182
|
-
- Each datapack has its own Langfuse project — traces for a tool call land in the project for whichever `datapack_id` was on the call (or the default datapack if omitted).
|
|
129
|
+
- `conversation_create` returns a `conversation_id`; that ID **is** the Langfuse trace_id — not a separate trace, the same identifier.
|
|
130
|
+
- Every MCP tool call made with that `conversation_id` becomes a span under the trace, named after the tool (e.g. `Memory Search (Meko MCP)`), with child spans exposing the storage steps.
|
|
131
|
+
- Trace tags include `agent:<agent_id>` and are filterable. Each datapack has its own Langfuse project — traces land in the project of whichever `datapack_id` was on the call.
|
|
183
132
|
|
|
184
133
|
### Finding a trace in the UI
|
|
185
134
|
|
|
@@ -190,14 +139,14 @@ Two navigation paths, both verified in the Meko UI:
|
|
|
190
139
|
|
|
191
140
|
The Conversations-tab row preview shows the first user turn verbatim, plus the agent_id tag, message count, and started-at timestamp. If you want a conversation to be recognizable in the UI, call `conversation_add_message` with a clean first-turn `input` early in the session.
|
|
192
141
|
|
|
193
|
-
###
|
|
142
|
+
### Typical latencies
|
|
194
143
|
|
|
195
144
|
From real traces, not the docstring happy path:
|
|
196
145
|
|
|
197
146
|
| Tool | Latency per call |
|
|
198
147
|
|---|---|
|
|
199
|
-
| `memory_add` |
|
|
200
|
-
| `memory_search` |
|
|
148
|
+
| `memory_add` | ~10-30 seconds (calls an LLM for extraction, then writes to the vector store; scales with payload size) |
|
|
149
|
+
| `memory_search` | ~2-6 seconds (small, focused memories; whole-document stores read ~4x slower — chunk on write) |
|
|
201
150
|
| `knowledgebase_search` | 0.6 seconds (empty index; will grow with index size) |
|
|
202
151
|
| `conversation_add_message` | 0.11 seconds (fire-and-forget; queued to Langfuse) |
|
|
203
152
|
|
|
@@ -205,9 +154,6 @@ From real traces, not the docstring happy path:
|
|
|
205
154
|
|
|
206
155
|
### Proactive diagnostic pattern
|
|
207
156
|
|
|
208
|
-
If a user reports "my memory_add didn't seem to save", open the Observe hub
|
|
209
|
-
|
|
210
|
-
- A `Memory Add (Meko MCP)` span with `Create a new memory in Mem0` child → the call reached Mem0. The fact extractor may have returned `"results": []` (common on short or non-fact-shaped text; not a bug, but lossy).
|
|
211
|
-
- No span at all → the call never reached the server. Likely a transport / auth / `conversation_id` mismatch issue.
|
|
157
|
+
If a user reports "my memory_add didn't seem to save", open the Observe hub, filter on their `conversation_id`, and check the span tree: a memory-add span present means the call arrived (the extractor may still have returned `"results": []` on non-fact-shaped text); no span means the call never reached the server (transport / auth / `conversation_id` mismatch).
|
|
212
158
|
|
|
213
|
-
The mem0 extractor is lossy — it extracts atomic facts and
|
|
159
|
+
The mem0 extractor is lossy — it extracts atomic facts and may drop prose that doesn't look fact-shaped to it; a `memory_add` can return `"results": []` on non-fact-shaped text. When preserving authoritative text matters, store it via `conversation_add_message` (verbatim in `input`/`output`/`reasoning`) — the conversation path preserves text without LLM re-extraction.
|