@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.
Files changed (70) hide show
  1. package/README.md +233 -40
  2. package/assets/hooks-handlers/codex-session-end.sh +4 -69
  3. package/assets/hooks-handlers/cursor-session-start.sh +19 -1
  4. package/assets/hooks-handlers/lib/capture-cleanup-cli.js +1473 -0
  5. package/assets/hooks-handlers/lib/capture-notices.js +438 -0
  6. package/assets/hooks-handlers/lib/capture-state.js +2173 -0
  7. package/assets/hooks-handlers/lib/capture-status-cli.js +86 -0
  8. package/assets/hooks-handlers/lib/capture.js +2782 -403
  9. package/assets/hooks-handlers/lib/checkpoint-timer.js +485 -81
  10. package/assets/hooks-handlers/lib/journal-bridge.js +218 -0
  11. package/assets/hooks-handlers/lib/kiro-handler.js +760 -0
  12. package/assets/hooks-handlers/lib/opencode-handler.js +620 -0
  13. package/assets/hooks-handlers/lib/opencode-normalizer.js +145 -0
  14. package/assets/hooks-handlers/lib/terminal-handoff.js +427 -0
  15. package/assets/hooks-handlers/session-end.sh +3 -34
  16. package/assets/opencode-plugin/meko.js +213 -0
  17. package/assets/scripts/meko-statusline.sh +123 -16
  18. package/assets/skills/meko-mcp-tools/SKILL.md +116 -126
  19. package/assets/skills/meko-mcp-tools/references/_sections.md +3 -3
  20. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +25 -18
  21. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +99 -24
  22. package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +1 -1
  23. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +53 -6
  24. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +25 -79
  25. package/assets/skills/meko-mcp-tools/references/tools-overview.md +37 -26
  26. package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +14 -8
  27. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +66 -1
  28. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +7 -40
  29. package/assets/skills/meko-mcp-tools-desktop/SKILL.md +56 -20
  30. package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +1 -1
  31. package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +1 -1
  32. package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +15 -8
  33. package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +99 -36
  34. package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +22 -5
  35. package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +18 -14
  36. package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +39 -28
  37. package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +14 -8
  38. package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +67 -1
  39. package/assets/skills/meko-select-datapack-desktop/SKILL.md +4 -4
  40. package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +8 -8
  41. package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +7 -5
  42. package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +4 -4
  43. package/bin/create-meko-setup.mjs +113 -12
  44. package/lib/capture-cleanup.mjs +63 -0
  45. package/lib/capture-status.mjs +67 -0
  46. package/lib/clients/aliases.mjs +5 -0
  47. package/lib/clients/claude-code.mjs +1 -0
  48. package/lib/clients/claude-desktop.mjs +120 -5
  49. package/lib/clients/codex.mjs +85 -37
  50. package/lib/clients/common.mjs +7 -0
  51. package/lib/clients/index.mjs +4 -0
  52. package/lib/clients/kiro.mjs +705 -0
  53. package/lib/clients/opencode.mjs +532 -0
  54. package/lib/config.mjs +158 -1
  55. package/lib/installer.mjs +18 -1
  56. package/lib/migrate/adapters/claude-code.mjs +11 -2
  57. package/lib/migrate/adapters/codex.mjs +497 -0
  58. package/lib/migrate/adapters/memory-md.mjs +27 -8
  59. package/lib/migrate/adapters/opencode.mjs +148 -0
  60. package/lib/migrate/claude-parser.mjs +153 -9
  61. package/lib/migrate/id.mjs +217 -10
  62. package/lib/migrate/mcp-client.mjs +25 -1
  63. package/lib/migrate/opencode-normalizer.mjs +132 -0
  64. package/lib/migrate/orchestrator.mjs +299 -56
  65. package/lib/migrate/progress.mjs +239 -5
  66. package/lib/migrate/registry.mjs +72 -0
  67. package/lib/migrate.mjs +100 -10
  68. package/lib/prompt.mjs +16 -1
  69. package/package.json +4 -4
  70. package/scripts/bundle-assets.mjs +4 -0
@@ -42,7 +42,7 @@ Empirically verified 2026-07-23 on Cloud prod: memories written under two distin
42
42
 
43
43
  ### Personal conversation reads — `conversation_get`, `conversation_list`
44
44
 
45
- - `conversation_get` is agent-owned: pass the exact `agent_id` that created the conversation.
45
+ - `conversation_get`, `conversation_add_message`, `conversation_update`, and `conversation_delete` are agent-owned: pass the exact `agent_id` that created the conversation, or the call returns `agent_id_mismatch`.
46
46
  - `conversation_list` is not agent-filtered and returns the datapack's conversations for this user across agents.
47
47
 
48
48
  ### Team-shared reads — `knowledgebase_search`
@@ -83,18 +83,25 @@ knowledgebase_search(agent_id=anything, query=...)
83
83
 
84
84
  If the user asks "what do you know about X?":
85
85
 
86
- 1. **`memory_search(agent_id="claude_desktop", query="X")`** — returns all of this user's personal memories across every agent. `agent_id` attributes the trace.
87
- 2. **`knowledgebase_search(agent_id="<anything>", datapack_id="<datapack>", query="X")`** — returns team-shared knowledge. Useful when the answer may have been promoted by the user or a teammate.
86
+ call **`context_search(agent_id="claude_desktop", conversation_id="<id>", datapack_id="<datapack>", query="X")`**. It returns separate buckets:
88
87
 
89
- Always tell the user which surface you searched: personal memory or team-shared knowledge.
88
+ - memory: all of this user's personal memories across every agent;
89
+ - knowledge base: team-shared knowledge, including anything the user or a teammate promoted;
90
+ - conversation: matching past turns from any user or agent on the datapack.
91
+
92
+ Always tell the user which surface each finding came from. Confirm an empty memory or KB bucket with `memory_search` or `knowledgebase_search` before saying nothing is there.
90
93
 
91
94
  ## Optional sub-scoping
92
95
 
93
96
  Optional parameters can narrow a call further:
94
- - `user_id` — explicitly scope writes/reads to a specific end-user if your agent serves multiple (rare in Claude Desktop; more common in API products)
95
- - `run_id` — per-execution run
96
-
97
- Available on `memory_add`, `memory_search`, `memory_get_all`, `memory_delete_all`, `conversation_create`, `conversation_list`.
97
+ - `run_id` — **read/delete filter only**, and it filters on the row's
98
+ `meko_conversation_id`, so the value to pass is a *conversation id*, not a
99
+ free-form run label. On `memory_add` it is Langfuse trace metadata only and is
100
+ never persisted on the row: writing with `run_id=X` then reading with
101
+ `memory_search(run_id=X)` returns nothing, silently. Scope writes with
102
+ `conversation_id` instead (MEKO-473).
103
+
104
+ Accepted by `memory_add`, `memory_search`, `memory_get_all`, `memory_delete_all`, and `conversation_create`. `memory_get_all` ignores it. No tool takes a `user_id` argument; the server resolves it from your credentials.
98
105
 
99
106
  ## Things I checked and found in-data on real Cloud datapacks
100
107
 
@@ -6,6 +6,47 @@ 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="claude_desktop",
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
52
  **Critical:** Pass your session's `agent_id` on every memory call. For Claude Desktop that's `claude_desktop` for normal attribution, or `meko_agent` when writing genuinely cross-project facts. Writes retain that attribution, while personal memory reads span all of this user's agents.
@@ -16,6 +57,7 @@ Every tool example below shows the correct parameters, expected response, and co
16
57
 
17
58
  ```
18
59
  memory_add(agent_id="claude_desktop",
60
+ conversation_id="<id from conversation_create>",
19
61
  text="Remember: deploy scripts must be run from the repo root, never a subdir.")
20
62
  ```
21
63
 
@@ -24,12 +66,6 @@ memory_add(agent_id="claude_desktop",
24
66
  {"results": [{"id": "mem-uuid-123", "memory": "User Amiram is VP of Product at YugabyteDB. Prefers concise responses."}]}
25
67
  ```
26
68
 
27
- **With user scoping:**
28
- ```
29
- memory_add(agent_id="agent", user_id="amiram",
30
- text="Prefers Python for backend, Go for infrastructure.")
31
- ```
32
-
33
69
  **What NOT to store via memory_add:**
34
70
  - Full conversations (use `conversation_create` + `conversation_add_message`)
35
71
  - Large documents (use the UI's Datapack → Actions → Add Knowledge upload flow)
@@ -46,33 +82,32 @@ memory_add(agent_id="agent", user_id="amiram",
46
82
 
47
83
  **Cross-conversation discovery.** `memory_search` returns hits across every stored conversation for the `(datapack_id, user_id)` pair, across all agents (the tool intentionally passes `meko_agent_id=None` to mem0, so the `agent_id` argument scopes the trace but does not filter 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. Pass `run_id` on the search itself to narrow to a single conversation up front.
48
84
 
85
+ **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.
86
+
49
87
  ```
50
- memory_search(query="What programming language does the team use?", agent_id="agent")
88
+ memory_search(query="What programming language does the team use?", agent_id="claude_desktop", conversation_id="<id>")
51
89
  ```
52
90
 
53
91
  **Response:**
54
92
  ```json
55
- {"results": [{"id": "mem-uuid-123", "memory": "Team uses Python for backend", "score": 0.89}]}
93
+ {"results": [{"id": "mem-uuid-123", "memory": "Team uses Python for backend", "score": 0.89, "raw_similarity_score": 0.72}]}
56
94
  ```
57
95
 
96
+ `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.
97
+
58
98
  **With limit:**
59
99
  ```
60
- memory_search(query="user preferences", agent_id="agent", limit=5)
100
+ memory_search(query="user preferences", agent_id="claude_desktop", conversation_id="<id>", limit=5)
61
101
  ```
62
102
 
63
103
  ---
64
104
 
65
105
  ### memory_get_all
66
106
 
67
- **When to use:** List everything stored for an agent. Useful at session start to load context.
107
+ **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.
68
108
 
69
109
  ```
70
- memory_get_all(agent_id="agent")
71
- ```
72
-
73
- **With user scoping:**
74
- ```
75
- memory_get_all(agent_id="agent", user_id="amiram")
110
+ memory_get_all(agent_id="claude_desktop", conversation_id="<id>")
76
111
  ```
77
112
 
78
113
  ---
@@ -80,7 +115,7 @@ memory_get_all(agent_id="agent", user_id="amiram")
80
115
  ### memory_get_by_id
81
116
 
82
117
  ```
83
- memory_get_by_id(memory_id="mem-uuid-123", agent_id="agent")
118
+ memory_get_by_id(memory_id="mem-uuid-123", agent_id="claude_desktop", conversation_id="<id>")
84
119
  ```
85
120
 
86
121
  ---
@@ -90,7 +125,7 @@ memory_get_by_id(memory_id="mem-uuid-123", agent_id="agent")
90
125
  **When to use:** Overwrite a specific memory's text. Requires the memory UUID.
91
126
 
92
127
  ```
93
- memory_update(memory_id="mem-uuid-123", text="Updated: Team uses Go for all new services", agent_id="agent")
128
+ memory_update(memory_id="mem-uuid-123", text="Updated: Team uses Go for all new services", agent_id="claude_desktop", conversation_id="<id>")
94
129
  ```
95
130
 
96
131
  ---
@@ -98,17 +133,19 @@ memory_update(memory_id="mem-uuid-123", text="Updated: Team uses Go for all new
98
133
  ### memory_delete_by_id
99
134
 
100
135
  ```
101
- memory_delete_by_id(memory_id="mem-uuid-123", agent_id="agent")
136
+ memory_delete_by_id(memory_id="mem-uuid-123", agent_id="claude_desktop", conversation_id="<id>")
102
137
  ```
103
138
 
139
+ `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.
140
+
104
141
  ---
105
142
 
106
143
  ### memory_delete_all
107
144
 
108
- **Destructive.** Deletes all memories for the agent. For removing a single memory, prefer `memory_delete_by_id` — `memory_delete_all` wipes the entire agent scope in the datapack.
145
+ **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`.
109
146
 
110
147
  ```
111
- memory_delete_all(agent_id="agent")
148
+ memory_delete_all(agent_id="claude_desktop", conversation_id="<id>")
112
149
  ```
113
150
 
114
151
  ---
@@ -127,7 +164,7 @@ memory_promote(memory_ids=["mem-uuid-123", "mem-uuid-456"],
127
164
  {"inserted_ids": ["mem-uuid-123"], "updated_ids": ["mem-uuid-456"], "not_found_ids": []}
128
165
  ```
129
166
 
130
- Get exact UUIDs from the `id` field of `memory_search` / `memory_get_all` results; never use graph relation IDs. Before the call, show the user each exact memory and UUID, explain that promotion is team-visible, one-way, and evicts the private records, then obtain explicit confirmation for those candidates. Pass the active `conversation_id` and intended `agent_id` / `datapack_id`; on legacy schemas that expose `scope`, use `write`, not `admin`.
167
+ Get exact UUIDs from the `id` field of `memory_search` / `memory_get_all` results; never pass any other identifier. Before the call, show the user each exact memory and UUID, explain that promotion is team-visible, one-way, and evicts the private records, then obtain explicit confirmation for those candidates. Pass the active `conversation_id` and intended `agent_id` / `datapack_id`; on legacy schemas that expose `scope`, use `write`, not `admin`.
131
168
 
132
169
  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.
133
170
 
@@ -140,10 +177,13 @@ On 403, authentication, or permission failure, report the error and stop — do
140
177
  **When to use:** Start storing a multi-turn exchange. Do this when the session contains valuable dialog worth preserving.
141
178
 
142
179
  ```
143
- conversation_create(agent_id="agent", user_id="amiram",
144
- title="Debugging the auth middleware")
180
+ conversation_create(agent_id="claude_desktop",
181
+ title="Debugging the auth middleware",
182
+ datapack_id="<uuid from datapack_list>")
145
183
  ```
146
184
 
185
+ `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`.
186
+
147
187
  **Response:**
148
188
  ```json
149
189
  {"id": "conv-uuid-123", "title": "Debugging the auth middleware"}
@@ -155,8 +195,6 @@ conversation_create(agent_id="agent", user_id="amiram",
155
195
 
156
196
  **When to use:** Add a user/assistant exchange to an existing conversation. **All fields must be verbatim** — never summarize or rephrase.
157
197
 
158
- 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.
159
-
160
198
  ```
161
199
  conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
162
200
  input="Why is the auth middleware returning 401?",
@@ -216,7 +254,7 @@ conversation_delete(conversation_id="conv-uuid-123", agent_id="agent")
216
254
 
217
255
  ## Knowledge Base Tools
218
256
 
219
- **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` is the one KB tool exposed via MCP.
257
+ **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.
220
258
 
221
259
  See `tools-rag-workflow.md` for the decision table.
222
260
 
@@ -244,6 +282,17 @@ Populated KBs return results with chunk content and similarity scores. An empty/
244
282
 
245
283
  ---
246
284
 
285
+ ### knowledgebase_delete_document
286
+
287
+ 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.
288
+
289
+ ```
290
+ knowledgebase_delete_document(document_id="<uuid from a search hit>",
291
+ conversation_id="<session conversation id>")
292
+ ```
293
+
294
+ 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.
295
+
247
296
  ## Artifact Tools
248
297
 
249
298
  ### artifact_put
@@ -326,20 +375,34 @@ For large files use `local_path` to read the file. S3 URLs are never exposed.
326
375
  ### datapack_create / datapack_list / datapack_describe
327
376
 
328
377
  ```
329
- datapack_create(name="analytics_prod")
330
- datapack_list() # returns datapack_id for each datapack
331
- datapack_describe(datapack_id="<uuid>", include_status=True)
378
+ datapack_create(name="analytics_prod", conversation_id="<conversation id>")
379
+ datapack_list(conversation_id="<this conversation's id>") # returns datapack_id for each datapack
380
+ datapack_describe(datapack_id="<uuid>", include_status=True, conversation_id="<conversation id>")
332
381
  ```
333
382
 
383
+ `datapack_describe` returns these counts:
384
+
385
+ | Field | Meaning |
386
+ |---|---|
387
+ | `memory_count` | All memories stored in the datapack |
388
+ | `collective_memory_count` | Memories promoted to shared knowledge |
389
+ | `learnings_count` | Memories awaiting a promotion decision |
390
+ | `knowledge_base_file_count` | Uploaded KB documents; `null` if the status endpoint is unreachable |
391
+ | `knowledge_chunk_count` | KB chunks across all documents (for debugging retrieval) |
392
+ | `shared_knowledge_count` | `collective_memory_count + knowledge_base_file_count`; `null` when the file count is `null` |
393
+
394
+ `knowledge_count` is a deprecated alias of `knowledge_chunk_count`. `datapack_list` doesn't compute counts; call `datapack_describe` for them.
395
+
334
396
  ### datapack_update / datapack_delete
335
397
 
336
- `datapack_update` renames or edits a datapack's description. At least one of `name` / `description` must be provided (or the tool returns `nothing_to_update`). The server refuses to rename `meko_default_datapack` — the error is `"meko_default_datapack cannot be renamed"`. Passing `description=""` does NOT clear an existing description.
398
+ `datapack_update` renames a datapack, edits its description, and/or opts it in/out of conversation-search embedding. At least one of `name` / `description` / `conversation_search_opt_out` must be provided (or the tool returns `nothing_to_update`). The server refuses to rename `meko_default_datapack` — the error is `"meko_default_datapack cannot be renamed"`. Passing `description=""` does NOT clear an existing description. `conversation_search_opt_out=True` stops future turns from being indexed 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.
337
399
 
338
400
  ```
339
- datapack_update(datapack_id="<uuid>", name="renamed-datapack")
340
- datapack_update(datapack_id="<uuid>", description="new description")
341
- datapack_update(datapack_id="<uuid>", name="x", description="y")
342
- datapack_delete(datapack_id="<uuid>") # Irreversible!
401
+ datapack_update(datapack_id="<uuid>", name="renamed-datapack", conversation_id="<conversation id>")
402
+ datapack_update(datapack_id="<uuid>", description="new description", conversation_id="<conversation id>")
403
+ datapack_update(datapack_id="<uuid>", name="x", description="y", conversation_id="<conversation id>")
404
+ datapack_update(datapack_id="<uuid>", conversation_search_opt_out=True, conversation_id="<conversation id>")
405
+ datapack_delete(datapack_id="<uuid>", conversation_id="<conversation id>") # Irreversible!
343
406
  ```
344
407
 
345
408
  ### Agent and knowledge-base management (NOT MCP — control-plane only)
@@ -349,4 +412,4 @@ Agent and KB lifecycle does not ship as MCP tools. If the user asks to create/li
349
412
  - REST: `POST/GET/DELETE /datapacks/:datapack_id/agents` (agents), `POST/GET/DELETE /datapacks/:datapack_id/knowledge-bases` (KB sources).
350
413
  - Or the Meko Cloud UI at `cloud.mekodata.ai` → Datapacks → agents / knowledge-bases.
351
414
 
352
- 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`.
415
+ 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`.
@@ -2,7 +2,7 @@
2
2
 
3
3
  These are current limitations of the Meko MCP tools. Know them upfront to avoid wasted tool calls.
4
4
 
5
- ## No delete tools for RAG artifacts
5
+ ## No MCP tools for index / source / pipeline lifecycle
6
6
 
7
7
  There are no MCP tools to:
8
8
  - Delete a vector index
@@ -10,7 +10,7 @@ There are no MCP tools to:
10
10
  - Clear stuck work queue entries
11
11
  - Reset a failed pipeline
12
12
 
13
- KB-source deletion happens via the Meko control plane (REST: `DELETE /datapacks/:datapack_id/knowledge-bases`, or the UI), which removes the registration from the Meko API — but does **not** touch the actual `dist_rag` index, source records, or vector data in the datapack's database.
13
+ 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
14
 
15
15
  **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
16
 
@@ -56,8 +56,25 @@ The skill description is tuned to its 1024-char ceiling; broadening it further d
56
56
  2. **Server-side guidance** — the `agent_id` tool docstrings and the server's connect-time instructions name `claude_desktop` as this client's bucket, so even a skill-less tool-search call avoids the wrong-bucket (`claude_code`) write.
57
57
  3. Nothing is lost when the *user* explicitly recalls or saves — only passive capture of in-passing facts is best-effort.
58
58
 
59
- ## No semantic search over conversation content
59
+ ## memory_delete_all is agent-scoped; memory reads are not
60
60
 
61
- Semantic (meaning-based) search across stored conversation content is not part of the public tool surface today. To find a past conversation, browse with `conversation_list` (by datapack) and inspect candidates with `conversation_get`.
61
+ `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.
62
62
 
63
- For finding past knowledge by meaning, `memory_search` remains the most reliable path — which is why storing key facts via `memory_add` alongside conversations is important.
63
+ ## Promoted memories are read-only through MCP
64
+
65
+ `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.
66
+
67
+ ## Conversation search covers embedded turns only
68
+
69
+ `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:
70
+
71
+ - the datapack opted out with `datapack_update(datapack_id=..., conversation_search_opt_out=True, conversation_id=...)`;
72
+ - the account hit the embedding quota (`conversation_search_skipped: "quota_exceeded"`); or
73
+ - the turn was too short to carry content (the server skips trivial turns); or
74
+ - the turn was stored before conversation search was enabled.
75
+
76
+ To find a conversation by other attributes, browse with `conversation_list` and inspect candidates with `conversation_get`.
77
+
78
+ ## Very long conversations can't be read back
79
+
80
+ 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,13 +8,13 @@
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 (semantic search) and Apache AGE (entity-relationship graph). It retrieves relevant facts by meaning, not by conversation order.
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
- memory_add(agent_id="support_bot",
15
- text="Customer Alice (alice@acme.com) prefers email, has Pro plan.", user_id="alice_123")
14
+ memory_add(agent_id="claude_desktop", conversation_id="<id>",
15
+ text="Customer Alice (alice@acme.com) prefers email, has Pro plan.")
16
16
 
17
- memory_search(query="What plan does Alice have?", agent_id="support_bot")
17
+ memory_search(query="What plan does Alice have?", agent_id="claude_desktop", conversation_id="<id>")
18
18
  ```
19
19
 
20
20
  ## Use `conversation_create` + `conversation_add_message` when storing:
@@ -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", user_id="alice_123", title="Pricing discussion")
29
+ conversation_create(agent_id="claude_desktop", title="Pricing discussion",
30
+ datapack_id="<uuid from datapack_list>")
30
31
  -- Returns: {"id": "conv-uuid-here"}
31
32
 
32
- conversation_add_message(conversation_id="conv-uuid-here", agent_id="support_bot",
33
+ conversation_add_message(conversation_id="conv-uuid-here", agent_id="claude_desktop",
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..." | `memory_search` |
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` |
@@ -80,7 +84,7 @@ One `memory_search` already spans this user's memories across all agents; no per
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 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 and graph context into shared knowledge, strips `user_id`, preserves originating `agent_id` as provenance, and evicts the private mem0 records.
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,14 +93,13 @@ One `memory_search` already spans this user's memories across all agents; no per
89
93
 
90
94
  ### When the user asks "what do you know about X?"
91
95
 
92
- A full sweep is two calls (budget for it — each is 2-6 seconds):
96
+ Call `context_search`:
93
97
 
94
98
  ```
95
- memory_search(agent_id="claude_desktop", query="X", conversation_id=..., ...)
96
- knowledgebase_search(agent_id="<anything>", datapack_id="<uuid>", query="X", conversation_id=..., ...)
99
+ context_search(agent_id="claude_desktop", query="X", conversation_id=..., datapack_id="<uuid>")
97
100
  ```
98
101
 
99
- The single `memory_search` includes everything this user and their other agents wrote in the datapack.
102
+ Its memory bucket includes everything this user and their other agents wrote in the datapack. The KB bucket holds team-shared knowledge, and the conversation bucket holds matching past 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.
100
103
 
101
104
  When you answer, be explicit about scope so the user knows why something is or isn't there:
102
105
 
@@ -146,6 +149,7 @@ The full transcript including:
146
149
  - **Assistant responses** — all text blocks (the `output` field)
147
150
  - **Tool calls** — tool name + input parameters (the `reasoning` field)
148
151
  - **Tool results** — output from tool executions (appended to `reasoning`)
152
+ - **Injected context** — skill bodies, background-task notifications, and subagent reports that the client writes into the transcript (appended to `reasoning` of the turn they belong to, never used as `input`)
149
153
 
150
154
  This is more than just text — tool calls and results are critical context for session replay, cross-agent sharing, and compaction.
151
155
 
@@ -194,7 +198,7 @@ From real traces, not the docstring happy path:
194
198
 
195
199
  | Tool | Latency per call |
196
200
  |---|---|
197
- | `memory_add` | 12-21 seconds (calls OpenAI for extraction, then writes to vector + graph) |
201
+ | `memory_add` | 12-21 seconds (calls OpenAI for extraction, then writes to the vector store) |
198
202
  | `memory_search` | 1.8-5.9 seconds |
199
203
  | `knowledgebase_search` | 0.6 seconds (empty index; will grow with index size) |
200
204
  | `conversation_add_message` | 0.11 seconds (fire-and-forget; queued to Langfuse) |
@@ -208,4 +212,4 @@ If a user reports "my memory_add didn't seem to save", open the Observe hub for
208
212
  - 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).
209
213
  - No span at all → the call never reached the server. Likely a transport / auth / `conversation_id` mismatch issue.
210
214
 
211
- The mem0 extractor is lossy — it extracts atomic facts and graph triples, and may drop prose that doesn't look fact-shaped to it. Observed 2026-05-07: 2 of 5 `memory_add` calls returned `"results": []` and only the graph side landed. 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.
215
+ The mem0 extractor is lossy — it extracts atomic facts and may drop prose that doesn't look fact-shaped to it. Observed 2026-05-07 (on the graph-era server): 2 of 5 `memory_add` calls returned `"results": []`. 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.
@@ -1,21 +1,23 @@
1
1
  # Complete Tool Catalog and Decision Tree
2
2
 
3
- **23 tools on Cloud Meko** (verified against `https://mcp.mekodata.ai/mcp`). Grouped: Memory (8), Conversation (6), Knowledge Base (1), Datapack (5), Artifacts (2), Observability (1).
3
+ **25 Meko data tools covered by this skill.** These are the tools available in production, grouped as: Retrieval (1), Memory (8), Conversation (6), Knowledge Base (2), Datapack (5), Artifacts (2), Observability (1). Combined Meko + AMP endpoints may expose additional infrastructure tools; those are outside this skill's scope.
4
4
 
5
5
  ## Quick health check before using tools
6
6
 
7
7
  Before starting a session, verify that the Meko MCP tools are working:
8
8
 
9
- 1. `memory_search(query="test", agent_id="<your-session-agent-id>", conversation_id="<session-conversation-id>")` — Confirms memory subsystem is up. Use the `agent_id` and `conversation_id` from the SessionStart `additionalContext`. May fail with "connection already closed" — see `tools-troubleshooting.md`.
10
- 2. `datapack_list()` — Confirms Meko API connectivity. Returns the datapacks your token has access to.
9
+ 1. `memory_search(query="test", agent_id="claude_desktop", conversation_id="<id from conversation_create>")` — Confirms memory subsystem is up. May fail with "connection already closed" — see `tools-troubleshooting.md`.
10
+ 2. `datapack_list(conversation_id="<this conversation's id>")` — Confirms Meko API connectivity. Returns the datapacks your token has access to.
11
11
 
12
12
  ## Decision tree: which tool do I need?
13
13
 
14
14
  ```
15
15
  User wants to...
16
- ├── Search a knowledge base? ---------------> knowledgebase_search (read)
16
+ ├── Ask "what do you know about X?" --------> context_search (read; memory + KB + past conversations in one call)
17
+ ├── Search personal context? ---------------> memory_search (read)
18
+ ├── Search shared datapack knowledge? ------> knowledgebase_search (read)
17
19
  ├── Add documents to a knowledge base? -----> point user at Meko UI: Datapack → Actions → Add Knowledge
18
- │ (no MCP tool — Cloud uses UI ingestion only)
20
+ ├── Delete ONE knowledge-base file? --------> knowledgebase_delete_document (destructive — confirm with the user first)
19
21
  ├── Store or recall information?
20
22
  │ ├── Store a fact/preference/entity? -----------> memory_add (write)
21
23
  │ ├── Store a full conversation (multi-turn)? ---> conversation_create + conversation_add_message (write)
@@ -29,47 +31,56 @@ User wants to...
29
31
  └── CRUD datapack? --------------------> datapack_create/list/describe/update/delete
30
32
  ```
31
33
 
32
- Agent / knowledge-base lifecycle is managed **outside** the MCP surface — typically in the Meko control-plane UI — and is not exposed as tools here.
34
+ Agent lifecycle and KB **ingestion / index lifecycle** (adding sources, uploads, re-indexing) are managed outside the MCP surface — typically in the Meko control-plane UI. Deleting a single KB file IS exposed here (`knowledgebase_delete_document`).
33
35
 
34
- ## Knowledge Base Tools (1)
36
+ ## Retrieval Tools (1)
35
37
 
36
38
  | Tool | Purpose |
37
39
  |------|---------|
38
- | `knowledgebase_search(query, agent_id, conversation_id, datapack_id, limit=10)` | Semantic search across KB chunks. `datapack_id` is REQUIRED (no default). |
40
+ | `context_search(query, conversation_id, agent_id=None, datapack_id=None, limit=10, force_source="auto")` | Default first call for open-ended recall. Queries memory, the knowledge base, and the conversation-history cache in parallel and returns each source in its own bucket: `{"results": {"memory": [...], "knowledge_base": [...], "conversation": {"hits": [...], "thread": [...]}}, "token_savings": {...}}`. 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. 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. `force_source` is `"auto"` (all three), `"memory"`, `"knowledge_base"`, or `"conversation"`; any other value returns `invalid_force_source`. `limit` bounds the memory and KB buckets only; the conversation bucket returns up to 10 hits plus a thread of whole turns. 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
+
42
+ ## Knowledge Base Tools (2)
43
+
44
+ | Tool | Purpose |
45
+ |------|---------|
46
+ | `knowledgebase_search(query, conversation_id, datapack_id, agent_id=None, limit=10)` | Hybrid (semantic + keyword) search across KB chunks and promoted memories. `datapack_id` is REQUIRED (no default). Each hit has `id`, `chunk_text`, `document_id`, `metadata_filters`, `distance`, and `match_type` (`semantic`, `keyword`, or `hybrid`). |
47
+ | `knowledgebase_delete_document(document_id, conversation_id, datapack_id="")` | Permanently delete ONE KB file (chunks + metadata; stored-file delete is best-effort — check `s3_deleted`). Irreversible: confirm with the user first. `document_id` comes from `knowledgebase_search` hits (no filename in hits — echo the id + chunk text). Owner/maintainer/uploader only (status 403 otherwise); status 409 while still indexing — wait and retry. |
39
48
 
40
49
  ## Memory Tools (8)
41
50
 
42
51
  | Tool | Purpose |
43
52
  |------|---------|
44
- | `memory_add(text, agent_id, conversation_id, user_id=None, app_id=None, run_id=None, metadata=None, messages=None, datapack_id=None)` | Store fact/preference/entity as long-term memory |
45
- | `memory_search(query, agent_id, conversation_id="", user_id=None, limit=10, datapack_id=None)` | Semantic search across memories + graph relations. `conversation_id` optional (omit or pass `""` for cross-conversation discovery). |
46
- | `memory_get_by_id(memory_id, agent_id, conversation_id, datapack_id=None)` | Direct pgvector row lookup by UUID. Preferred over `memory_search` for exact-id verification. |
47
- | `memory_get_all(agent_id, conversation_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | List all memories for agent |
48
- | `memory_update(memory_id, text, agent_id, conversation_id, datapack_id=None)` | Overwrite memory text |
49
- | `memory_delete_by_id(memory_id, agent_id, conversation_id, datapack_id=None)` | Delete a single memory |
50
- | `memory_delete_all(agent_id, conversation_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | Delete all memories for agent (destructive) |
51
- | `memory_promote(conversation_id, memory_ids, agent_id=None, datapack_id=None)` | Promote private memories into the datapack's shared knowledge base (moves them + graph context out of mem0, then evicts from mem0 — one-way). Owners/maintainers only; viewers/contributors get 403.
53
+ | `memory_add(text, conversation_id, agent_id=None, run_id=None, metadata=None, messages=None, datapack_id=None)` | Store fact/preference/entity as long-term memory |
54
+ | `memory_search(query, conversation_id, agent_id=None, limit=10, datapack_id=None, run_id=None)` | Hybrid search across memories (semantic + keyword + entity boost). Drops rows below a server-configured similarity floor (default 0.2), so a weak query can return an empty list. `conversation_id` is required but only nests the trace. It must be a 32-hex id: `""` currently fails (MEKO-707), so pass a freshly generated one if you have no conversation yet. `run_id` filters to one conversation's memories. |
55
+ | `memory_get_by_id(memory_id, conversation_id, agent_id=None, datapack_id=None)` | Direct pgvector row lookup by UUID. Preferred over `memory_search` for exact-id verification. Returns `not_found` for a missing id and for an id that belongs to another account. |
56
+ | `memory_get_all(conversation_id, agent_id=None, run_id=None, datapack_id=None, promoted=False)` | Recent window (about 20 rows) of the user's memories across every agent, plus the true `total`. Not a complete listing. `promoted=True` returns the recent window of promoted memories instead. `run_id` is ignored. |
57
+ | `memory_update(memory_id, text, conversation_id, agent_id=None, datapack_id=None)` | Overwrite memory text. Returns `memory_is_promoted` for a promoted memory (edit those in the Cloud UI Learnings tab). |
58
+ | `memory_delete_by_id(memory_id, conversation_id, agent_id=None, datapack_id=None)` | Delete a single memory. Returns `memory_is_promoted` for a promoted memory. |
59
+ | `memory_delete_all(conversation_id, agent_id=None, run_id=None, datapack_id=None)` | Delete all memories in the **passed `agent_id`'s bucket** (destructive). Unlike reads, this is agent-scoped: omitting `agent_id` deletes only the `meko_agent` bucket. `run_id` narrows it to one conversation; a malformed value returns `invalid_run_id`. |
60
+ | `memory_promote(conversation_id, memory_ids, agent_id=None, datapack_id=None)` | Promote private memories into the datapack's shared knowledge base (moves them out of mem0, then evicts from mem0 — one-way). Owners/maintainers only; viewers/contributors get 403. |
52
61
 
53
62
  ## Conversation Tools (6)
54
63
 
55
64
  | Tool | Purpose |
56
65
  |------|---------|
57
- | `conversation_create(agent_id, user_id=None, app_id=None, run_id=None, title=None, metadata=None, session_id="")` | Create conversation container (Langfuse session) |
58
- | `conversation_add_message(conversation_id, agent_id, input, output=None, reasoning=None, metadata=None, seed=None, trace_id="")` | Add a message turn (Langfuse trace) |
59
- | `conversation_get(conversation_id, agent_id, include_messages=False, limit=100, offset=0)` | Retrieve conversation, optionally with messages |
60
- | `conversation_list(agent_id=None, limit=20, offset=0, conversation_id="", datapack_id=None)` | List conversations for agent within a datapack. `datapack_id` (UUID) is optional — defaults to the pinned/tenant datapack; use `datapack_list` to look it up. `conversation_id` optional (omit for browse). |
61
- | `conversation_update(conversation_id, agent_id, title=None, metadata=None)` | Update title or metadata |
62
- | `conversation_delete(conversation_id, agent_id)` | Delete entire conversation (destructive) |
66
+ | `conversation_create(agent_id=None, run_id=None, title=None, metadata=None, session_id="", datapack_id=None)` | Create conversation container (Langfuse session) |
67
+ | `conversation_add_message(conversation_id, input, output, agent_id=None, reasoning=None, metadata=None, seed=None, datapack_id=None, plan=None)` | Add a message turn (Langfuse trace). `output` is required. The response may include `extracted_memories` and, when the turn wasn't embedded for conversation search, `conversation_search_skipped` (`quota_exceeded` or `datapack_opted_out`). |
68
+ | `conversation_get(conversation_id, agent_id=None, include_messages=False, limit=100, offset=0, datapack_id=None)` | Retrieve conversation, optionally with messages |
69
+ | `conversation_list(agent_id=None, limit=20, offset=0, conversation_id="", datapack_id=None)` | List the user's conversations within a datapack (`agent_id` does not filter — trace attribution only). `datapack_id` (UUID) is optional — defaults to the pinned/tenant datapack; use `datapack_list` to look it up. `conversation_id` optional (omit for browse). |
70
+ | `conversation_update(conversation_id, agent_id=None, title=None, metadata=None, datapack_id=None)` | Update title or metadata |
71
+ | `conversation_delete(conversation_id, agent_id=None, datapack_id=None)` | Delete entire conversation (destructive) |
63
72
 
64
73
  ## Datapack Management Tools (5)
65
74
 
66
75
  | Tool | Purpose |
67
76
  |------|---------|
68
- | `datapack_create(name)` | Create new datapack |
69
- | `datapack_list()` | List all datapacks |
70
- | `datapack_describe(datapack_id, include_status=False)` | Describe datapack by UUID |
71
- | `datapack_update(datapack_id, name=None, description=None)` | Rename a datapack and/or update its description. Pass at least one of `name` / `description`. |
72
- | `datapack_delete(datapack_id)` | Delete datapack by UUID (irreversible) |
77
+ | `datapack_create(name, conversation_id)` | Create new datapack |
78
+ | `datapack_list(conversation_id, datapack_id=None)` | List all datapacks. `conversation_id` is required for trace nesting; omit `datapack_id` to use the endpoint default. |
79
+ | `datapack_describe(conversation_id, datapack_id="", include_status=False)` | Describe a datapack by UUID (default datapack if omitted). Returns `memory_count`, `collective_memory_count` (promoted), `learnings_count` (awaiting a promotion decision), `knowledge_base_file_count`, `knowledge_chunk_count`, and `shared_knowledge_count`. `knowledge_base_file_count` and `shared_knowledge_count` are `null` when the status endpoint is unreachable; `knowledge_count` is a deprecated alias of `knowledge_chunk_count`. |
80
+ | `datapack_update(datapack_id, conversation_id, name=None, description=None, conversation_search_opt_out=None)` | Rename a datapack, update its description, and/or opt out of (or back into) conversation-search caching. Pass at least one field. Opt-out is owner/maintainer only. |
81
+ | `datapack_delete(datapack_id, conversation_id)` | Delete datapack by UUID (irreversible) |
82
+
83
+ All five datapack tools reject an empty `conversation_id` with `conversation_id_required`.
73
84
 
74
85
  ## Artifact Tools (2)
75
86
 
@@ -103,4 +114,4 @@ For knowledge-base content on Cloud, the canonical path is **UI upload**: Datapa
103
114
 
104
115
  ## Common Parameter Patterns
105
116
 
106
- Memory and KB tools accept optional `datapack_id` to target a specific datapack. Memory and conversation tools require `agent_id` for namespace isolation (see `tools-agent-id-conventions.md`).
117
+ Memory and KB tools accept optional `datapack_id` to target a specific datapack. A `datapack_id` your account can't access returns `datapack_access_denied`. `agent_id` attributes writes. Conversations are agent-owned: `conversation_get`, `conversation_add_message`, `conversation_update`, and `conversation_delete` return `agent_id_mismatch` for any value other than the creating agent's. `agent_id` does **not** filter memory reads (`memory_search`/`memory_get_all`) or `conversation_list`, which return all your agents' rows for the user. `memory_delete_all` is the exception on the memory side: it deletes only the passed `agent_id`'s bucket. See `tools-agent-id-conventions.md`.