@yugabytedb/meko-mcp 1.2.0 → 2.1.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 (57) hide show
  1. package/README.md +59 -25
  2. package/assets/hooks-handlers/before-submit-prompt.sh +2 -2
  3. package/assets/hooks-handlers/codex-session-end.sh +78 -0
  4. package/assets/hooks-handlers/lib/capture.js +366 -152
  5. package/assets/hooks-handlers/lib/checkpoint-timer.js +67 -13
  6. package/assets/hooks-handlers/session-end.sh +10 -0
  7. package/assets/hooks-handlers/session-start.sh +14 -3
  8. package/assets/hooks-handlers/test_checkpoint_timer.sh +162 -0
  9. package/assets/scripts/meko-statusline.sh +119 -0
  10. package/assets/scripts/package-desktop-skill.sh +64 -30
  11. package/assets/skills/meko-mcp-tools/SKILL.md +84 -86
  12. package/assets/skills/meko-mcp-tools/references/_sections.md +2 -4
  13. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +29 -25
  14. package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +5 -7
  15. package/assets/skills/meko-mcp-tools/references/tools-conversation-reasoning.md +50 -0
  16. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +126 -184
  17. package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +31 -37
  18. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +10 -26
  19. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +26 -30
  20. package/assets/skills/meko-mcp-tools/references/tools-overview.md +60 -66
  21. package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +28 -93
  22. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +5 -99
  23. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +9 -8
  24. package/assets/skills/meko-mcp-tools-desktop/SKILL.md +138 -138
  25. package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +46 -16
  26. package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +2 -2
  27. package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +28 -24
  28. package/assets/skills/meko-mcp-tools-desktop/references/tools-conversation-reasoning.md +50 -0
  29. package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +120 -174
  30. package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +16 -22
  31. package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +28 -34
  32. package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +60 -66
  33. package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +28 -93
  34. package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +4 -98
  35. package/assets/skills/meko-select-datapack-desktop/SKILL.md +208 -0
  36. package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +121 -0
  37. package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +41 -0
  38. package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +66 -0
  39. package/bin/create-meko-setup.mjs +74 -6
  40. package/lib/clients/claude-code.mjs +137 -6
  41. package/lib/clients/claude-desktop.mjs +51 -12
  42. package/lib/clients/codex.mjs +329 -13
  43. package/lib/clients/common.mjs +43 -1
  44. package/lib/clients/cursor.mjs +82 -21
  45. package/lib/config.mjs +26 -0
  46. package/lib/detect.mjs +7 -2
  47. package/lib/installer.mjs +24 -0
  48. package/lib/mcp-transport.mjs +5 -0
  49. package/lib/prompt.mjs +1 -1
  50. package/lib/url-selection.mjs +55 -0
  51. package/lib/validate.mjs +0 -1
  52. package/package.json +1 -1
  53. package/scripts/bundle-assets.mjs +8 -0
  54. package/assets/skills/meko-mcp-tools/references/tools-db-query-patterns.md +0 -38
  55. package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +0 -75
  56. package/assets/skills/meko-mcp-tools/references/tools-write-guardrails.md +0 -30
  57. package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +0 -75
@@ -1,23 +1,26 @@
1
1
  ---
2
2
  name: meko-mcp-tools
3
- description: Behavioral guide for AI agents using Meko MCP tools. Triggers when calling MCP tools, storing memories, persisting knowledge, managing datapacks, or working with YugabyteDB databases through Meko.
3
+ description: Behavioral guide for AI agents using Meko MCP tools. Triggers when calling MCP tools, storing memories, persisting knowledge, managing datapacks, or searching shared knowledge bases through Meko.
4
4
  license: MIT
5
5
  metadata:
6
6
  author: Meko
7
- version: "2.3.0"
8
- tags: mcp, yugabytedb, tools, datapack, memory, conversation, rag, meko
7
+ version: "3.0.2"
8
+ tags: mcp, tools, datapack, memory, conversation, rag, meko
9
9
  ---
10
10
 
11
11
  # Meko MCP Tools — Agent Behavioral Guide
12
12
 
13
- Meko is agent-native data infrastructure that enables continuous learning from context windows through collective memory and shared knowledge. This skill teaches you how to use Meko's 26 MCP tools — and more importantly, **when to use them proactively** without waiting to be asked.
13
+ Meko is agent-native data infrastructure that enables continuous learning from context windows through collective memory and shared knowledge. This skill teaches you how to use Meko's 23 MCP tools.
14
+
15
+
16
+ **Read this first.** On Claude Code, conversation capture is automatic (SessionStart / PreCompact / SessionEnd hooks) and the Meko server extracts durable memories from the captured turns on its own. Facts the user states in conversation are saved for you — you do **not** proactively call `memory_add` for them. Your active jobs are: **recall** what's already known (`memory_search`, `knowledgebase_search`), and the **few** save cases automatic extraction cannot reach. Details below.
14
17
 
15
18
  ## What Meko enables
16
19
 
17
20
  Meko turns your volatile context window into persistent, shareable knowledge:
18
21
 
19
- - **Personal memory** — Store who the user is, their preferences, role, and working style. Private to you (scoped per-user and per-agent). Survives across sessions.
20
- - **Team-shared knowledge** — When the user promotes important memories from the Cloud UI's Learnings tab (or uploads documents via **Add Knowledge**), the content becomes visible to every member of the datapack. Queryable via `knowledgebase_search`.
22
+ - **Personal memory** — Store who the user is, their preferences, role, and working style. Private to you (scoped per-user; readable across all of your agents). Survives across sessions.
23
+ - **Team-shared knowledge** — Important memories can be promoted with `memory_promote` (after explicit confirmation) or from the Cloud UI's Learnings tab. Uploaded documents arrive through **Add Knowledge**. The resulting content is visible to every datapack member and queryable via `knowledgebase_search`.
21
24
  - **Conversation history** — Preserve full dialog exchanges with reasoning traces for audit, replay, and learning transfer.
22
25
  - **Decision traces** — Capture how and why decisions were made, enabling debugging and continuous improvement.
23
26
 
@@ -27,7 +30,7 @@ Meko turns your volatile context window into persistent, shareable knowledge:
27
30
  - You need to decide what to store, where, and how (personal memory vs. team-shared knowledge)
28
31
  - You want to search the team's shared knowledge base (`knowledgebase_search`)
29
32
  - You are managing datapacks
30
- - You want to understand scope/permission requirements, `agent_id` conventions, or `datapack_id` routing
33
+ - You want to understand `agent_id` conventions, or `datapack_id` routing
31
34
 
32
35
  ## `agent_id` — multi-agent identity
33
36
 
@@ -44,25 +47,26 @@ agent_id = "claude_code:meko-mcp-server" # this session's project bucket
44
47
  agent_id = "meko_agent" # cross-project facts
45
48
  ```
46
49
 
47
- The SessionStart hook injects the project-bucket value into the first-turn `additionalContext`. Use that value verbatim for project-scoped Meko MCP calls in this session; do not re-derive it. Use `meko_agent` explicitly when you want a write or read to span projects.
50
+ The SessionStart hook injects the project-bucket value into the first-turn `additionalContext`. Use that value verbatim for project-scoped Meko MCP calls in this session; do not re-derive it. Use `meko_agent` explicitly when you want a write to land in the cross-project bucket.
48
51
 
49
52
  **Read scoping varies by tool:**
50
- - `memory_search` / `memory_get_all` / `conversation_list` / `conversation_get` — scoped to `(datapack_id, user_id, agent_id)`. Each agent_id is its own bucket; pass the exact value you want to read from. Empty/whitespace gets rewritten to `meko_agent` server-side, so it returns common-bucket rows only — **not** a cross-agent fan-out.
53
+ - `memory_search` / `memory_get_all` — scoped to `(datapack_id, user_id)`. **`agent_id` does not filter memory reads:** one call returns all of your memories for this user across every `agent_id` (the tool passes `meko_agent_id=None` to mem0, so `agent_id` scopes the Langfuse trace, not the result set). No need to fan out per agent_id or read the `meko_agent` bucket separately — a single search already includes it.
54
+ - `conversation_get` — agent-owned: pass the exact `agent_id` that created the conversation; any other value returns `agent_id_mismatch`.
55
+ - `conversation_list` — returns the datapack's conversations for your user regardless of `agent_id` (the argument is trace-attribution only, like memory reads).
51
56
  - `knowledgebase_search` — scoped to `(datapack_id)` only. `agent_id` on the request is **ignored**; you see the team's shared knowledge regardless of what you pass. Includes uploaded documents and memories that the user promoted via the UI's "Promote to Knowledge" flow.
52
57
 
53
58
  See `tools-agent-id-conventions.md` for the full model, including how promotion works and how to phrase broad-query responses to the user.
54
59
 
55
60
  Some pre-existing rows in real datapacks use the older `agent_id="agent"` constant or other ad-hoc shapes (`claude_code`, `cursor:<slug>`). They remain readable — query them with `agent_id="agent"` explicitly. New writes should follow the schema above.
56
61
 
57
- ## Critical: Use Meko tools, not local storage
62
+ ## Critical: Use Meko, not local storage
58
63
 
59
- **When Meko MCP tools are available, ALWAYS use them instead of local/built-in storage mechanisms.** Do not write to local memory files, markdown notes, or any file-based memory system. Meko's memory is persistent across all agents, sessions, and team members — local files are not.
64
+ **Meko is the memory store — never write memories to local files, markdown notes, or any file-based memory system.** Meko's memory is persistent across all agents, sessions, and team members; local files are not. On Claude Code, memory reaches Meko two ways, and neither is a local file:
60
65
 
61
- - User shares personal info → call `memory_add` on the MCP server, NOT write to a local file
62
- - User asks what you know → call `memory_search` on the MCP server, NOT read local files
63
- - Conversation worth preserving → call `conversation_create`, NOT save to a local log
66
+ - **Automatic capture + extraction** (the dominant path) — the hooks capture this session's turns and the server extracts memories from them. Facts the user states are stored without any tool call from you.
67
+ - **Explicit `memory_add`** (the narrow path) — only for the cases extraction can't reach (see "When to call memory_add" below).
64
68
 
65
- If a Meko tool call fails, you may fall back to local storage and tell the user — but Meko is always the first choice.
69
+ To recall, call `memory_search` on the MCP server, NOT read local files. If a Meko read/write call fails, you may fall back to local storage and tell the user — but Meko is always the first choice.
66
70
 
67
71
  ## When spawning subagents
68
72
 
@@ -112,49 +116,39 @@ If the inherited block is **absent**, the subagent MUST NOT guess — see the se
112
116
 
113
117
  Subagents cannot auto-discover the parent's watermark today: Claude Code does not expose a `CLAUDE_PARENT_SESSION_ID` env var or any equivalent marker file to subagent processes (see the spike note in `skills/hooks-handlers/lib/capture.js`). Prompt injection is the only enforcement mechanism.
114
118
 
115
- ## Core principle: Be Meko's persistent brain
119
+ ## Core principle: capture is automatic — recall, don't re-store
116
120
 
117
- **Do not wait for the user to say "save this to memory."** Proactively store context that would be valuable in future sessions. Think of Meko as your long-term memory that persists across conversations.
121
+ Meko is your long-term memory, but on Claude Code you do **not** build it by hand. The hooks capture every turn of this session and the server extracts durable memories from them automatically. **A fact the user states in conversation — name, role, preferences, org conventions, corrections, casual asides — is already saved. Calling `memory_add` for it just duplicates what extraction stored.** (Verified empirically: the server extracts conversationally-stated facts verbatim, including multi-fact turns and precise multi-clause facts.)
118
122
 
119
- ### Proactive behavior rules
123
+ So your Meko reflexes are:
120
124
 
121
- | Signal in conversation | What to do | Tool to use |
122
- |---|---|---|
123
- | User shares personal info ("I'm Amiram", "I'm a VP of Product") | Store as personal memory immediately | `memory_add` |
124
- | User states a preference ("I prefer dark mode", "always use Python") | Store as personal preference | `memory_add` |
125
- | User shares org convention ("we write in Go", "our standard is X") | Store as organizational memory | `memory_add` |
126
- | User teaches domain knowledge ("Meko traces are decision traces") | Store as memory; consider suggesting they promote it to Shared Knowledge from the Learnings tab | `memory_add` |
127
- | User corrects your behavior ("don't do X, do Y instead") | Store the correction as a learning | `memory_add` |
128
- | User asks "what do you know about X?" | Three-call sweep: your project's memories, then the cross-project common bucket, then team-shared knowledge | `memory_search(agent_id=<yours>)` → `memory_search(agent_id="meko_agent")` → `knowledgebase_search` |
129
- | User asks "what do we (as a team) know about X?" or about uploaded documents | Query the team's Shared Knowledge directly | `knowledgebase_search` (returns uploaded docs + promoted memories) |
130
- | Session produced a valuable multi-turn exchange | Preserve the full conversation | `conversation_create` + `conversation_add_message` |
131
- | Significant learnings accumulated during session | Offer to persist key takeaways; remind the user they can promote important ones to Shared Knowledge from the Cloud UI | Summarize and propose `memory_add` calls |
132
- | User provides structured/tabular data (CSV, data dictionary) | Not natively supported via MCP on Cloud today — `db_run_write_query` returns `{"error": "not_available"}`. Store the key facts as memories or point the user at the UI's knowledge-base upload for file form | `memory_add` for facts, UI "Add Knowledge" for files |
133
- | User wants to add documents to the team's knowledge base | Point them at the Cloud UI flow — Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). The MCP ingestion tools are not available on Cloud. | UI only |
125
+ 1. **Recall first.** When the user asks what's known, or before you act on something they may have an opinion about, search — don't assume.
126
+ 2. **Save only what capture can't reach** (the three narrow cases below).
127
+ 3. **Never** re-store a fact the user just said. **Never** write memories to local files.
134
128
 
135
- ### Information classification
129
+ ### When the user shares information
136
130
 
137
- When the user shares information, classify it before storing:
131
+ | Signal in conversation | What to do |
132
+ |---|---|
133
+ | User states a fact about themselves, their team, tools, or preferences | **Nothing — automatic capture + extraction stores it.** Just answer. |
134
+ | User corrects your behavior or negates a prior fact ("actually, we use Nomad now") | The new fact is captured automatically, but extraction is **additive** — it does not remove the old one. If a stale, contradicted memory must not survive, `memory_search` for it and `memory_update` / `memory_delete_by_id`. |
135
+ | User explicitly says "remember this" / "save this to memory" | `memory_add` (verbatim). This is the clearest explicit-save case. |
136
+ | A durable fact appears only in YOUR output or a tool result, never in the user's words | `memory_add`. Extraction reads only the **user** turn, so facts you derive or a tool surfaces are never captured otherwise. |
137
+ | User asks "what do you know about X?" | Two surfaces: `memory_search` (one call — all your personal memories for this user, every agent) then `knowledgebase_search` (team-shared knowledge). |
138
+ | User asks "what do we (as a team) know about X?" or about uploaded documents | `knowledgebase_search` (returns uploaded docs + promoted memories). |
139
+ | User asks to share specific private memories with the team | Follow the `memory_promote` confirmation workflow below. Never promote based on a fuzzy search result or implied consent. |
140
+ | User provides structured/tabular data (CSV, data dictionary) | Not natively supported via MCP. Point the user at the UI's Add Knowledge upload; do not `memory_add` row-by-row. |
141
+ | User wants to add documents to the team's knowledge base | Point them at the Cloud UI flow — Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). MCP ingestion tools are not available on Cloud. |
138
142
 
139
- ```
140
- User says something → Classify:
141
- ├── About themselves (name, role, preferences)
142
- │ → memory_add — personal profile
143
- ├── About how their team/org works (conventions, standards, policies)
144
- │ → memory_add — personal memory; the user can promote it to Shared
145
- │ Knowledge from the UI's Learnings tab so teammates see it too
146
- ├── Domain knowledge (facts, definitions, specs, research)
147
- │ → memory_add for quick recall; for bulk documents, the user uploads
148
- │ files via the UI's Datapack → Actions → Add Knowledge flow
149
- ├── A correction or learning ("don't do X", "always do Y")
150
- │ → memory_add — behavioral feedback
151
- ├── Full conversation worth preserving (multi-turn, reasoning traces)
152
- │ → conversation_create + conversation_add_message — verbatim
153
- └── Structured/tabular data (CSV rows, schemas, data dictionaries)
154
- → Not MCP-supported on Cloud today (db_run_write_query returns
155
- {"error": "not_available"}). Extract key facts to memory_add
156
- or tell the user this isn't a Cloud feature yet.
157
- ```
143
+ ### When to call memory_add (the whole list)
144
+
145
+ Automatic capture handles the rest, so explicit `memory_add` is reserved for exactly three cases:
146
+
147
+ 1. **Explicit request** — the user says "remember this" / "save this."
148
+ 2. **Output-only / tool-derived fact** — a durable fact that lives only in the assistant's output or a tool result, never in a user turn (extraction only sees the user turn).
149
+ 3. **Overwriting correction** — a prior fact was negated and the stale memory must not survive (extraction is additive; pair `memory_add`/`memory_update` with a `memory_delete_by_id` of the old one).
150
+
151
+ When you do call it, store the fact verbatim in the user's own words; do not summarize.
158
152
 
159
153
  ## Automatic conversation capture
160
154
 
@@ -171,7 +165,7 @@ All three are handled automatically. **Do NOT set up CronCreate for conversation
171
165
  The SessionStart hook has already done the setup for you:
172
166
 
173
167
  1. **Created a Meko conversation** — `conversation_id` is injected into `additionalContext` on the first turn. Use that value for all subsequent MCP tool calls that accept `conversation_id`.
174
- 2. **Echoed the session's `agent_id`** — also injected into `additionalContext`. Use the injected value verbatim for project-scoped Meko tool calls. It's a per-session value derived from the cwd (shape: `claude_code:<repo-basename>`), not a constant. For genuinely cross-project facts, write/read with `agent_id="meko_agent"` (the common bucket) instead.
168
+ 2. **Echoed the session's `agent_id`** — also injected into `additionalContext`. Use the injected value verbatim for project-scoped Meko tool calls. It's a per-session value derived from the cwd (shape: `claude_code:<repo-basename>`), not a constant. For genuinely cross-project facts, write with `agent_id="meko_agent"` (the common bucket) instead.
175
169
  3. **Preloaded recent memories** — `additionalContext` may include a `### Memories from prior sessions` block. Inspect it before acting so you don't re-ask questions the user has already answered.
176
170
 
177
171
  If `additionalContext` is absent or empty (hook failed, MCP unavailable), ask the user for their `agent_id` — do not invent one. See `tools-agent-id-conventions.md`.
@@ -181,11 +175,11 @@ If `additionalContext` is absent or empty (hook failed, MCP unavailable), ask th
181
175
  Before any action that deletes, overwrites, or restructures user content — `Write` overwriting an existing file, large `Edit` deletions, `rm` / `rm -rf`, `git reset --hard`, destructive SQL (`DROP`, `TRUNCATE`, `DELETE` without `WHERE`) — run a `memory_search` for relevant feedback:
182
176
 
183
177
  ```
184
- memory_search(scope="read", query="destructive <action type> preferences feedback",
178
+ memory_search(query="destructive <action type> preferences feedback",
185
179
  agent_id=<your agent_id>, conversation_id=<session_conversation_id>)
186
180
  ```
187
181
 
188
- Also consider a second call with `agent_id="meko_agent"` to surface common-bucket feedback — preferences the user (or any other agent) wrote under the cross-project bucket. And a `knowledgebase_search` for team-wide guidance if the action is one the team has promoted policy on.
182
+ A single `memory_search` already covers everything you and other agents wrote for this user — `agent_id` doesn't filter memory reads. Also consider a `knowledgebase_search` for team-wide guidance if the action is one the team has promoted policy on.
189
183
 
190
184
  If a relevant feedback memory exists (e.g., "always ask before deleting content"), confirm with the user before proceeding. If the search is empty, proceed, but treat the action as irreversible and prefer a dry-run / preview when one is available.
191
185
 
@@ -203,47 +197,56 @@ If a relevant feedback memory exists (e.g., "always ask before deleting content"
203
197
  In the examples below, `<your-agent-id>` means the value the SessionStart hook injected into `additionalContext` — for Claude Code, something like `claude_code:meko-mcp-server`. Not the literal string `"<your-agent-id>"`.
204
198
 
205
199
  ### memory_add — correct call pattern
200
+
201
+ Only for the three narrow cases in "When to call memory_add" above — not for facts the user stated in conversation (those are captured automatically). The example below is an explicit "remember this" save:
206
202
  ```
207
- memory_add(scope="write",
208
- text="User is VP of Product at YugabyteDB",
203
+ memory_add(
204
+ text="Remember: deploy scripts must be run from the repo root, never a subdir",
209
205
  agent_id="<your-agent-id>",
210
206
  conversation_id="<session_conversation_id>")
211
207
  ```
212
- Required parameters: `scope`, `text`, `conversation_id`. On **writes**, `conversation_id` must be a real UUID (from `conversation_create` or the SessionStart hook) — writes attached to a nil/empty conversation are orphaned in Langfuse traces. NEVER pass `"current"` or other non-UUID values. `agent_id` is technically optional — empty/missing routes the write into the `meko_agent` common bucket — but for project-scoped facts pass the SessionStart-injected value verbatim.
208
+ Required parameters: `text`, `conversation_id`. On **writes**, `conversation_id` must be a real UUID (from `conversation_create` or the SessionStart hook) — writes attached to a nil/empty conversation are orphaned in Langfuse traces. NEVER pass `"current"` or other non-UUID values. `agent_id` is technically optional — empty/missing routes the write into the `meko_agent` common bucket — but for project-scoped facts pass the SessionStart-injected value verbatim.
213
209
 
214
210
  ### memory_search — correct call pattern
215
211
  ```
216
- memory_search(scope="read",
212
+ memory_search(
217
213
  query="user role",
218
214
  agent_id="<your-agent-id>",
219
215
  conversation_id="<session_conversation_id>")
220
216
  ```
221
- Required parameters: `scope`, `query`, `agent_id`, `conversation_id`. On **`memory_search`** specifically, `conversation_id` is used only for Langfuse trace nesting — it does NOT filter results. Pass the session's UUID so the search span appears under the active conversation in Observe; passing `""` is accepted and means "don't nest under any trace." For conversation-scoped filtering use the separate `run_id` parameter.
217
+ Required parameters: `query`, `agent_id`, `conversation_id`. On **`memory_search`** specifically, `conversation_id` is used only for Langfuse trace nesting — it does NOT filter results. Pass the session's UUID so the search span appears under the active conversation in Observe; passing `""` is accepted and means "don't nest under any trace." For conversation-scoped filtering use the separate `run_id` parameter.
222
218
 
223
- For cross-project common-bucket search (facts written under `agent_id="meko_agent"`, including everything you wrote with empty/missing agent_id), pass it explicitly:
224
- ```
225
- memory_search(scope="read", query="user role",
226
- agent_id="meko_agent", conversation_id="<session_conversation_id>")
227
- ```
228
-
229
- Empty string also resolves to `meko_agent` server-side, but be explicit so it's obvious from the call you mean the common bucket. To search results across multiple specific projects (e.g. also see what was written from `claude_code:other-repo`), call `memory_search` once per agent_id — there's no single-call fan-out.
219
+ `agent_id` does not filter what `memory_search` returns — a single call already surfaces everything you and every other agent wrote for this user in the datapack, including the `meko_agent` common bucket and any other project's rows. There's no need to repeat the search per agent_id. Use `run_id` if you want to narrow to a single conversation/run.
230
220
 
231
221
  ### knowledgebase_search — correct call pattern
232
222
  ```
233
- knowledgebase_search(scope="read",
223
+ knowledgebase_search(
234
224
  query="...",
235
225
  agent_id="<anything — ignored>",
236
226
  conversation_id="<session_conversation_id>",
237
227
  datapack_id="<datapack UUID>",
238
228
  limit=10)
239
229
  ```
240
- Required parameters: `scope`, `query`, `agent_id`, `conversation_id`, `datapack_id`. `datapack_id` has no default here. `agent_id` is ignored for filtering — results are the team's shared knowledge on the datapack regardless of what you pass.
230
+ Required parameters: `query`, `agent_id`, `conversation_id`, `datapack_id`. `datapack_id` has no default here. `agent_id` is ignored for filtering — results are the team's shared knowledge on the datapack regardless of what you pass.
231
+
232
+ ### memory_promote — explicit confirmation required
233
+
234
+ `memory_promote` is destructive and non-idempotent: it makes selected content visible to the datapack, moves the memories and graph context into shared knowledge, and evicts the private mem0 records. There is no MCP rollback.
235
+
236
+ 1. Use `memory_search` or `memory_get_all` to obtain exact memory UUIDs. Never pass relation or graph-edge IDs.
237
+ 2. Present each exact candidate memory and its UUID to the user.
238
+ 3. State that promotion is one-way, team-visible, and removes the private records.
239
+ 4. Obtain explicit confirmation for those exact candidates before calling `memory_promote`.
240
+ 5. Call it with the active `conversation_id`, exact `memory_ids`, intended `agent_id`, and intended `datapack_id`. If a legacy deployment exposes `scope`, use the minimum `write` scope; do not escalate to `admin`.
241
+ 6. Only datapack owners and maintainers may promote. If a viewer/contributor receives 403, or any authentication/permission error occurs, report it and stop. Do not retry with a broader scope, another datapack, or altered identity.
242
+ 7. After success, optionally verify visibility with `knowledgebase_search`. Do not claim rollback is possible.
243
+
244
+ The Cloud UI's Learnings tab remains an alternative user-driven path.
241
245
 
242
246
  ### Critical parameter rules
243
247
 
244
248
  - **agent_id**: Per-session value, injected via `additionalContext` by the SessionStart hook. Shape: `<client>:<repo-basename>`. Pass verbatim on project-scoped writes and reads. Pass `"meko_agent"` for the cross-project common bucket (or empty/omit — server rewrites empty to `meko_agent`). Ignored on `knowledgebase_search`. See `tools-agent-id-conventions.md`.
245
249
  - **conversation_id**: Behavior varies by tool. On write tools (`memory_add`, `conversation_add_message`) pass a real UUID from `conversation_create` or the SessionStart hook — a nil/empty value orphans the Langfuse trace. On `memory_search` it's used only for trace nesting (not for filtering), and empty-string is accepted; on `memory_get_all` and most read tools, still pass the session UUID when you have one. Never pass `"current"` or other non-UUID junk — only a real UUID or an intentionally empty string where the tool allows it.
246
- - **scope**: Only `"read"`, `"write"`, or `"admin"`. Nothing else. Use the minimum the code actually requires (the per-tool cookbook shows it).
247
250
  - **When in doubt about optional parameters, omit them.** The server has sensible defaults.
248
251
 
249
252
  ### Verify after writing
@@ -262,7 +265,6 @@ On the first Meko tool call in a fresh session (no prior Meko tool call since pr
262
265
 
263
266
  **Canary memory shape.** This is the spec; keep the fields stable so support can grep for them.
264
267
 
265
- - `scope`: `"write"`
266
268
  - `agent_id`: the session's `agent_id` (from `additionalContext`); not a constant
267
269
  - `conversation_id`: the session's `conversation_id` (from `additionalContext`). If the hook failed and you truly have no conversation_id, call `conversation_create` first and use the returned id — do not use a nil UUID, it orphans the canary trace.
268
270
  - `text`: `"Meko connection test: <client> @ <installer-version> — <ISO timestamp>. Safe to delete."`
@@ -276,31 +278,27 @@ On the first Meko tool call in a fresh session (no prior Meko tool call since pr
276
278
 
277
279
  ## Key concepts
278
280
 
279
- 1. **26 tools in 5 groups**: Memory (8), Conversation (6), Knowledge Base (4), Datapack (5), Database (3). On Cloud Meko today, all DB tools and the three KB ingestion tools return `{"error": "not_available"}` — only `knowledgebase_search` works in the KB group. See `tools-overview.md` for the full availability map.
280
- 2. **Scope hierarchy**: `read < write < admin` — every tool validates scope at entry. Only three valid values: `"read"`, `"write"`, `"admin"`. Using anything else (e.g., `"all"`) will fail. Tool docstrings sometimes say `"Pass 'admin'"` but the code only requires `"read"` or `"write"` — use the minimum the code actually enforces.
281
- 3. **datapack_id routing**: DB, RAG, and memory tools accept optional `datapack_id` (default datapack if omitted). `knowledgebase_search` is the exception: `datapack_id` is **required** there.
282
- 4. **agent_id is multi-agent**: Each client+project uses its own `agent_id` (shape `<client>:<repo-basename>`). Writes are scoped to `(datapack_id, user_id, agent_id)`. Personal reads (`memory_search`, `memory_get_all`) filter strictly on this tuple. Empty/missing `agent_id` lands in the `meko_agent` common bucket — use it explicitly for cross-project facts. `knowledgebase_search` ignores `agent_id` entirely and returns the team-shared knowledge on the datapack. See `tools-agent-id-conventions.md`.
283
- 5. **Personal memory vs. team-shared knowledge**: Un-promoted memories (`mem0_collection`) are scoped per-user and per-agent — only you see them. The user can promote important memories to Shared Knowledge via the Cloud UI's Learnings tab, which makes them visible to every team member on the datapack (user_id filter stripped). `knowledgebase_search` is the MCP read path for both Shared Knowledge and uploaded documents. See `tools-memory-vs-conversation.md`.
284
- 6. **conversation_id IS the Langfuse trace ID**: every MCP tool call inside a conversation becomes a span under that trace. Observable in the Meko UI's Observe hub (`/observe-hub?project=<langfuse_pid>&session=<conversation_id>`) or directly from a datapack's Conversations tab via the **Open in Observe** button. See `tools-memory-vs-conversation.md`.
285
- 7. **Adding documents or growing a knowledge base is UI-only on Cloud today**: users upload files via Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each). The MCP ingestion tools are not available on Cloud. See `tools-rag-workflow.md`.
286
- 8. **Conversation dedup**: `conversation_add_message` supports seed-based deterministic trace IDs to prevent duplicates.
287
- 9. **Memory latencies are not cheap**: observed on prod 2026-05-07 — `memory_add` 12-21s/call (calls OpenAI), `memory_search` 2-6s/call. Budget accordingly.
288
- 10. **Known limitations**: see `tools-known-limitations.md` before attempting write operations on tools that appear in the catalog but aren't available on Cloud.
289
- 11. **Error recovery**: Connection errors are common with memory tools — see `tools-troubleshooting.md` for retry strategies and fallbacks.
281
+ 1. **23 tools in 6 groups**: Memory (8 — including `memory_promote`), Conversation (6), Knowledge Base (1 — `knowledgebase_search`), Datapack (5), Artifacts (2 — `artifact_put`, `artifact_get`), Observability (1 — `track_token_usage`). KB ingestion is UI-only (Datapack → Actions → Add Knowledge); raw SQL is not exposed. See `tools-overview.md`.
282
+ 2. **datapack_id routing**: DB, RAG, and memory tools accept optional `datapack_id` (default datapack if omitted). `knowledgebase_search` is the exception: `datapack_id` is **required** there.
283
+ 3. **agent_id is multi-agent**: Each client+project uses its own `agent_id` (shape `<client>:<repo-basename>`). Writes are attributed to `(datapack_id, user_id, agent_id)`. Personal **memory** reads (`memory_search`, `memory_get_all`) are NOT filtered by `agent_id` — one call returns all of your memories for this user across every agent, scoped to `(datapack_id, user_id)`. Empty/missing `agent_id` on a write lands in the `meko_agent` common bucket. `knowledgebase_search` ignores `agent_id` entirely and returns the team-shared knowledge on the datapack. See `tools-agent-id-conventions.md`.
284
+ 4. **Personal memory vs. team-shared knowledge**: Un-promoted memories (`mem0_collection`) are scoped per-user — readable across all of your agents, but no other user can see them. With explicit confirmation, `memory_promote` moves exact memories into Shared Knowledge; the Cloud UI's Learnings tab is an alternative. Promoted content is visible to every datapack member (user_id filter stripped). `knowledgebase_search` is the MCP read path for both Shared Knowledge and uploaded documents. See `tools-memory-vs-conversation.md`.
285
+ 5. **conversation_id IS the Langfuse trace ID**: every MCP tool call inside a conversation becomes a span under that trace. Observable in the Meko UI's Observe hub (`/observe-hub?project=<langfuse_pid>&session=<conversation_id>`) or directly from a datapack's Conversations tab via the **Open in Observe** button. See `tools-memory-vs-conversation.md`.
286
+ 6. **Adding documents or growing a knowledge base is UI-only on Cloud today**: users upload files via Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each). The MCP ingestion tools are not available on Cloud. See `tools-rag-workflow.md`.
287
+ 7. **Conversation dedup**: `conversation_add_message` supports seed-based deterministic trace IDs to prevent duplicates.
288
+ 8. **Memory latencies are not cheap**: observed on prod 2026-05-07 — `memory_add` 12-21s/call (calls OpenAI), `memory_search` 2-6s/call. Budget accordingly.
289
+ 9. **Known limitations**: see `tools-known-limitations.md` before attempting write operations on tools that appear in the catalog but aren't available on Cloud.
290
+ 10. **Error recovery**: Connection errors are common with memory tools — see `tools-troubleshooting.md` for retry strategies and fallbacks.
290
291
 
291
292
  ## Reference sections
292
293
 
293
294
  | File | What it covers |
294
295
  |------|---------------|
295
- | `tools-overview.md` | Complete catalog of all 26 tools with decision tree + cloud Free-Tier gating map |
296
+ | `tools-overview.md` | Complete catalog of all 23 tools with decision tree |
296
297
  | `tools-cookbook.md` | Per-tool examples with correct parameters, responses, and error cases |
297
298
  | `tools-memory-vs-conversation.md` | When to use memory tools vs conversation tools |
298
299
  | `tools-datapack-workflow.md` | Datapack lifecycle and datapack_id routing |
299
300
  | `tools-rag-workflow.md` | End-to-end RAG pipeline flow |
300
- | `tools-write-guardrails.md` | Blocked SQL patterns and configurable limits |
301
- | `tools-scope-permissions.md` | read/write/admin permission hierarchy |
302
301
  | `tools-agent-id-conventions.md` | Naming rules and constraints for agent_id |
303
302
  | `tools-conversation-dedup.md` | Seed-based trace deduplication |
304
- | `tools-db-query-patterns.md` | Read-only vs write query execution patterns |
305
303
  | `tools-troubleshooting.md` | Error recovery, retry strategies, stuck pipeline diagnosis |
306
304
  | `tools-known-limitations.md` | Broken tools, missing capabilities, permission gaps |
@@ -6,17 +6,15 @@ description: Maps reference files to their topics for the meko-mcp-tools skill
6
6
  # Reference Sections
7
7
 
8
8
  ## Tool Selection & Catalog
9
- - [tools-overview.md](tools-overview.md) — Complete catalog of all 26 tools with a decision tree and cloud Free-Tier gating map
9
+ - [tools-overview.md](tools-overview.md) — Complete catalog of all 23 tools with a decision tree
10
10
 
11
11
  ## Tool-Specific Guidance
12
12
  - [tools-memory-vs-conversation.md](tools-memory-vs-conversation.md) — Decision framework: memory_add vs conversation_create/conversation_add_message
13
+ - [tools-conversation-reasoning.md](tools-conversation-reasoning.md) — Authoring the `reasoning` and `plan` fields on `conversation_add_message`, with worked examples
13
14
  - [tools-datapack-workflow.md](tools-datapack-workflow.md) — Datapack lifecycle, datapack_id routing, and multi-database patterns
14
15
  - [tools-rag-workflow.md](tools-rag-workflow.md) — End-to-end RAG pipeline: source registration, index creation, status polling
15
- - [tools-db-query-patterns.md](tools-db-query-patterns.md) — Read-only vs write query execution patterns and SQL conventions
16
16
 
17
17
  ## Safety & Permissions
18
- - [tools-write-guardrails.md](tools-write-guardrails.md) — Blocked SQL operations, bulk insert limits, WHERE clause enforcement
19
- - [tools-scope-permissions.md](tools-scope-permissions.md) — read/write/admin permission hierarchy and per-tool requirements
20
18
 
21
19
  ## Conventions & Deduplication
22
20
  - [tools-agent-id-conventions.md](tools-agent-id-conventions.md) — agent_id naming rules, hyphen prohibition, and namespace isolation
@@ -1,12 +1,12 @@
1
1
  # agent_id — multi-agent identity on Cloud Meko
2
2
 
3
- `agent_id` identifies **which agent wrote a memory or created a conversation**. It is not a constant. Pick a value that represents the specific agent + project you're acting for, use it consistently for writes within this session, and use it to scope your own reads.
3
+ `agent_id` identifies **which agent wrote a memory or created a conversation**. It is not a constant. Pick a value that represents the specific agent + project you're acting for and use it consistently for writes and trace attribution within this session.
4
4
 
5
- The Cloud UI (`cloud.mekodata.ai`) renders `agent_id` as a badge on every memory and conversation row — so the value you pick is user-visible. Multiple different agents with different `agent_id` values can write into the same datapack; each one's personal view is scoped to itself, and the UI shows the full cross-agent picture.
5
+ The Cloud UI (`cloud.mekodata.ai`) renders `agent_id` as a badge on every memory and conversation row — so the value you pick is user-visible. Multiple different agents with different `agent_id` values can write into the same datapack; the badge records who wrote each row, and both the UI and a `memory_search` show the full cross-agent picture for the user.
6
6
 
7
7
  ## The three buckets
8
8
 
9
- Memories segregate strictly by `agent_id`. Pick the right bucket up front:
9
+ Each memory is written under an `agent_id` (stored on the row, shown as the UI badge). It labels *who wrote* the row — it does not restrict who can later read it (`memory_search` spans all your agents for the user). Still, pick the right value up front so attribution is meaningful:
10
10
 
11
11
  | Pattern | When to use | Example |
12
12
  |---|---|---|
@@ -16,13 +16,15 @@ Memories segregate strictly by `agent_id`. Pick the right bucket up front:
16
16
 
17
17
  **Discover the value at session start.** The SessionStart hook injects the chosen `agent_id` into the first-turn `additionalContext` based on the cwd's repo basename. Use that value verbatim — do not re-derive it. If the block is absent, fall back to `<client>:<basename(cwd)>` or ask the user.
18
18
 
19
- For genuinely cross-project facts ("the user's name is Amiram", "the user prefers dark mode") write with `agent_id="meko_agent"` so future agents in different projects can read them.
19
+ For genuinely cross-project facts ("the user's name is Amiram", "the user prefers dark mode") write with `agent_id="meko_agent"` so their attribution clearly identifies the common cross-project bucket.
20
+
21
+ **Pick a value that matches the running client — don't invent another client's shape.** A Claude Desktop session that writes with `agent_id="claude_code"` (or `claude_code:something`) creates rows the UI will attribute to Claude Code — a misleading badge for both clients. Use the pattern from the table that matches the client you're actually running under.
20
22
 
21
23
  ## Valid characters
22
24
 
23
25
  The server stores `agent_id` as a row-level column value — it never becomes a PostgreSQL identifier on Cloud. Any printable string works: colons, hyphens, dots, underscores, spaces. Stay within what's readable in the UI badge.
24
26
 
25
- Pre-existing data in real datapacks includes a mix of legacy shapes — `agent`, `claude-code`, `claude_code`, `cursor:<slug>`, `claude-code:-Users-...`. None of them cause errors. To query those rows, pass the literal legacy value as `agent_id` (e.g. `agent_id="agent"` for rows from before the rewrite). New writes should follow the table above.
27
+ Pre-existing data in real datapacks includes a mix of legacy shapes — `agent`, `claude-code`, `claude_code`, `cursor:<slug>`, `claude-code:-Users-...`. None of them cause errors or prevent memory recall. New writes should follow the table above.
26
28
 
27
29
  ## How agent_id filters reads and writes
28
30
 
@@ -31,15 +33,19 @@ Pre-existing data in real datapacks includes a mix of legacy shapes — `agent`,
31
33
  - The row stores `(meko_datapack_id, meko_user_id, meko_agent_id)` — the user_id comes from your cognito account; the datapack_id defaults or is explicit; the agent_id is what you pass.
32
34
  - If you pass an empty or whitespace-only `agent_id`, the server stores `meko_agent`. That's the common bucket — fine for cross-project facts; not what you want for project-scoped writes.
33
35
 
34
- ### Personal reads — `memory_search`, `memory_get_all`, `conversation_list`, `conversation_get`
36
+ ### Personal memory reads — `memory_search`, `memory_get_all`
37
+
38
+ Filter tuple: `(datapack_id, user_id)`. `agent_id` is **not** applied on memory reads.
35
39
 
36
- Filter tuple: `(datapack_id, user_id, agent_id)`.
40
+ - `user_id` is **always enforced**: you can only see memories you wrote (or that other team members shared with you via promotion — see below). One user cannot read another team member's un-promoted memories directly from MCP.
41
+ - `agent_id` does **not** filter results. A single `memory_search` returns your memories for this user across *every* `agent_id`: a memory written under `agent_id="cursor:foo"` IS returned by a search passing `agent_id="claude_code:meko-mcp-server"` — or empty, or any value. The tool passes `meko_agent_id=None` to mem0, so `agent_id` scopes only the Langfuse trace, not the result set. There is nothing to "fan out"; one call already sees all of your agents' memories (including the `meko_agent` common bucket).
37
42
 
38
- - `user_id` is **always enforced**: you can only see memories and conversations you wrote (or that other team members shared with you via promotion — see below). One user cannot read another team member's un-promoted memories directly from MCP.
39
- - `agent_id` is **strictly matched**: a search with `agent_id="claude_code:meko-mcp-server"` returns only rows whose stored value is exactly that. A memory written by `agent_id="cursor:foo"` is invisible to it.
40
- - An empty `agent_id` is rewritten to `meko_agent` server-side, so a "broad" read with empty string returns only common-bucket rows — **not** a cross-agent fan-out. To search across multiple agent_ids, call once per known value.
43
+ Empirically verified 2026-07-23 on Cloud prod: memories written under two distinct `agent_id`s were both returned by a `memory_search` passing a third, never-written `agent_id` (and by one passing empty string).
41
44
 
42
- Empirically verified 2026-05-19 on Cloud prod (free-tier multitenant mode, segregation via row-level filter).
45
+ ### Personal conversation reads — `conversation_get`, `conversation_list`
46
+
47
+ - `conversation_get` — agent-owned. Filter tuple `(datapack_id, user_id, agent_id)`: pass the exact `agent_id` that created the conversation; a wrong value returns `agent_id_mismatch`.
48
+ - `conversation_list` — **not** agent-filtered. It lists by `(datapack_id, user_id)` only; `agent_id` on the call is trace-attribution only (like memory reads), so one call returns the datapack's conversations for your user regardless of which agent created them.
43
49
 
44
50
  ### Team-shared reads — `knowledgebase_search`
45
51
 
@@ -57,9 +63,10 @@ The originating `agent_id` is preserved in each result's `metadata_filters.agent
57
63
  memory_add(agent_id=X, text=...)
58
64
  │
59
65
  ▼
60
- mem0_collection ── personal memories, scoped (datapack, user, agent)
66
+ mem0_collection ── personal memories, tagged (datapack, user, agent)
61
67
  │
62
- │ UI "Promote to Knowledge" (Learnings tab)
68
+ │ memory_promote (exact UUIDs + explicit confirmation)
69
+ │ or UI "Promote to Knowledge" (Learnings tab)
63
70
  │ ─────────────────────────────────────────
64
71
  │ Strips user_id, keeps agent_id as metadata,
65
72
  │ copies into team-shared table
@@ -72,23 +79,20 @@ knowledgebase_search(agent_id=anything, query=...)
72
79
 
73
80
  - **Personal memories** are what you get from `memory_search` / `memory_get_all`. Private to you.
74
81
  - **Shared Knowledge** is what you get from `knowledgebase_search`. Visible to every user and every agent on the datapack.
75
- - **Promotion is UI-only.** There is no MCP tool for promoting a memory to Shared Knowledge — the user triggers it from the datapack's Learnings tab in the Cloud UI.
82
+ - **Promotion has MCP and UI paths.** `memory_promote` moves exact, user-confirmed memories into Shared Knowledge and evicts the private records; the Learnings tab is the user-driven alternative. Only datapack owners and maintainers may use the MCP path.
76
83
 
77
84
  ## When to use what — broad-query guidance
78
85
 
79
- If the user asks "what do you know about X?" and you want to maximize recall:
80
-
81
- 1. **First call**: `memory_search(agent_id="<your agent_id>", query="X")` — returns your own project's memories. Most relevant if the context is "what have you and I done in this repo."
82
- 2. **Second call**: `memory_search(agent_id="meko_agent", query="X")` — returns the common cross-project bucket (user identity, global preferences). Anything you wrote with `agent_id="meko_agent"` from any agent or project, plus rows the server stored under that name when called with empty `agent_id`.
83
- 3. **Third call**: `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
+ If the user asks "what do you know about X?":
84
87
 
85
- For a true cross-agent fan-out (e.g. you also want to see what was written from `claude_code:other-repo` or `cursor:foo`), call `memory_search` once per known agent_id — the empty-string shortcut does not bypass the filter; the server rewrites empty to `meko_agent`.
88
+ 1. **`memory_search(agent_id="<your agent_id>", query="X")`** — returns all of your personal memories for this user, across every `agent_id` (your project bucket, the `meko_agent` common bucket, and any other project's rows). One call is the whole personal surface — `agent_id` doesn't filter memory reads, so there's nothing to fan out.
89
+ 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
90
 
87
- Always tell the user what scope you searched, so they understand why the answer is or isn't there. Example wording: "I found this in your project memories" vs. "I found this in your common cross-project bucket" vs. "I found this in your team's shared knowledge."
91
+ Always tell the user what scope you searched, so they understand why the answer is or isn't there. Example wording: "I found this in your personal memories" vs. "I found this in your team's shared knowledge."
88
92
 
89
- ## Sub-scoping within an agent
93
+ ## Optional sub-scoping
90
94
 
91
- Optional parameters narrow further within the same `agent_id`:
95
+ Optional parameters can narrow a call further:
92
96
  - `user_id` — explicitly scope writes/reads to a specific end-user if your agent serves multiple (rare in Claude Code; more common in API products)
93
97
  - `run_id` — per-execution run
94
98
 
@@ -96,6 +100,6 @@ Available on `memory_add`, `memory_search`, `memory_get_all`, `memory_delete_all
96
100
 
97
101
  ## Things I checked and found in-data on real Cloud datapacks
98
102
 
99
- - `agent_id="agent"` appears on many legacy rows — it was the previous canonical constant. New writes should use the schema in the table above; query legacy rows with `agent_id="agent"` explicitly.
100
- - Memory Summary UI (`/datapacks/<name>/memory-summary`) is agent-id-agnostic — shows every row in the datapack, renders the stored `agent_id` as a badge. The filtering is MCP-side only.
103
+ - `agent_id="agent"` appears on many legacy rows — it was the previous canonical constant. New writes should use the schema in the table above; memory reads still return the legacy rows.
104
+ - Memory Summary UI (`/datapacks/<name>/memory-summary`) is agent-id-agnostic — shows every row in the datapack, renders the stored `agent_id` as a badge. `memory_search` and `conversation_list` are likewise agent-agnostic (they return all your agents' rows for the user); only `conversation_get` enforces `agent_id` (agent ownership).
101
105
  - Subagents spawned via the `Agent` tool in Claude Code do not automatically inherit the parent's `agent_id`. The parent must inject it into the spawn prompt. See the SKILL.md "When spawning subagents" section.
@@ -4,13 +4,13 @@
4
4
 
5
5
  When MCP clients have built-in Langfuse hooks (Cursor, Claude Code), both the client hook and the MCP server may write a trace for the same message → duplicate traces, doubled message counts, corrupted conversation retrieval.
6
6
 
7
- **WRONG:** Neither `seed` nor `trace_id` provided → both sides generate random IDs → two traces per message.
7
+ **WRONG:** No `seed` provided → both sides generate random trace IDs → two traces per message.
8
8
 
9
9
  ## Solution: Use seed for deterministic trace IDs
10
10
 
11
11
  ```
12
12
  conversation_add_message(
13
- scope="write", conversation_id="conv-uuid", agent_id="my_agent",
13
+ conversation_id="conv-uuid", agent_id="my_agent",
14
14
  input="What is our Q3 revenue?",
15
15
  output="Q3 revenue was $4.2M, up 15% from Q2.",
16
16
  seed="conv-uuid:my_agent:What is our Q3 revenue?"
@@ -19,11 +19,10 @@ conversation_add_message(
19
19
 
20
20
  Both sides hash the same seed string to produce the same trace ID. Langfuse treats the second write as an upsert → exactly one trace.
21
21
 
22
- ## Priority Rules
22
+ ## Trace ID Rules
23
23
 
24
- 1. **`trace_id`** — if provided, used directly (highest precedence)
25
- 2. **`seed`** — if provided, hashed to produce deterministic trace ID
26
- 3. **Neither** — random trace ID generated
24
+ 1. **`seed`** — if provided, hashed to produce a deterministic trace ID
25
+ 2. **Not provided** — a random trace ID is generated
27
26
 
28
27
  ## Choosing a Good Seed
29
28
 
@@ -41,7 +40,6 @@ seed = f"{conversation_id}:{agent_id}:{message_index}"
41
40
  |----------|-----|
42
41
  | Client hook + MCP server both write to Langfuse | `seed` |
43
42
  | Only the MCP server writes (no client hook) | Neither (random is fine) |
44
- | Migrating from another system with existing IDs | `trace_id` |
45
43
  | Replaying messages idempotently | `seed` |
46
44
 
47
45
  ## session_id on conversation_create
@@ -0,0 +1,50 @@
1
+ # Authoring `reasoning` and `plan` on `conversation_add_message`
2
+
3
+ `conversation_add_message` accepts two optional fields — `reasoning` and `plan` — that capture *why* the assistant replied the way it did and *what* concrete steps it took. They are stored side-by-side on the per-turn `Reasoning` observation in Langfuse, independently, so consumers can read or render either one on its own.
4
+
5
+ Provide them on the large majority of substantive turns. Skip both only for genuinely trivial acknowledgements (a one-word reply, a pure restatement). Do not fabricate deliberation — but in practice, almost every substantive reply has at least a one-line *why* and a one-step plan.
6
+
7
+ ## `reasoning`
8
+
9
+ A short paragraph (1–3 sentences) of the **why**. Plain English. Explain which trade-off you weighed, which user fact tipped the decision, why this answer beat the alternatives. Inline markdown (`**bold**`, `*italics*`, `` `code` ``) is fine.
10
+
11
+ Do NOT include a `**Plan:**` heading inside `reasoning` — put steps in the `plan` field instead.
12
+
13
+ ## `plan`
14
+
15
+ A list of 2 to 4 concrete actions taken for this turn. Each entry is a single imperative sentence, like a checklist item. Pass a list of strings.
16
+
17
+ Do NOT pre-number entries. Do NOT include a `**Plan:**` heading inside the strings — `plan` is stored as a structured array on the observation's `metadata.plan`, independent of `reasoning`.
18
+
19
+ ## Two examples
20
+
21
+ ### Example A — database recommendation
22
+
23
+ ```
24
+ reasoning:
25
+ "The user cares about low latency and predictable cost.
26
+ Option A wins on latency but costs more per month; option
27
+ B is cheaper but adds 30 ms p99. Latency was their top
28
+ priority, so I picked Option A."
29
+
30
+ plan: [
31
+ "Recommend Option A and call out the latency advantage.",
32
+ "Show the monthly cost delta in clear numbers.",
33
+ "Flag the cost difference so the user can decide if it fits."
34
+ ]
35
+ ```
36
+
37
+ ### Example B — book pick for a long flight
38
+
39
+ ```
40
+ reasoning:
41
+ "The user wants a non-fiction book for a six-hour flight
42
+ and does not enjoy business memoirs. *Sapiens* fits the
43
+ time slot, is non-fiction, and is not a memoir."
44
+
45
+ plan: [
46
+ "Recommend *Sapiens* as the main pick.",
47
+ "Offer *Bad Blood* as a non-memoir backup.",
48
+ "Skip founder memoirs per the user's stated dislike."
49
+ ]
50
+ ```