@yugabytedb/meko-mcp 2.0.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.
- package/README.md +31 -6
- package/assets/hooks-handlers/codex-session-end.sh +78 -0
- package/assets/hooks-handlers/lib/capture.js +163 -14
- package/assets/hooks-handlers/lib/checkpoint-timer.js +44 -2
- package/assets/hooks-handlers/session-end.sh +10 -0
- package/assets/hooks-handlers/session-start.sh +8 -1
- package/assets/hooks-handlers/test_checkpoint_timer.sh +162 -0
- package/assets/scripts/package-desktop-skill.sh +32 -1
- package/assets/skills/meko-mcp-tools/SKILL.md +47 -41
- package/assets/skills/meko-mcp-tools/references/_sections.md +2 -4
- package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +29 -25
- package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +5 -7
- package/assets/skills/meko-mcp-tools/references/tools-conversation-reasoning.md +50 -0
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +63 -46
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +6 -6
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +4 -4
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +17 -22
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +40 -39
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +1 -2
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +4 -18
- package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +9 -8
- package/assets/skills/meko-mcp-tools-desktop/SKILL.md +49 -42
- package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +6 -6
- package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +2 -2
- package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +28 -24
- package/assets/skills/meko-mcp-tools-desktop/references/tools-conversation-reasoning.md +50 -0
- package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +61 -36
- package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +4 -4
- package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +16 -19
- package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +40 -39
- package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +1 -2
- package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +3 -17
- package/assets/skills/meko-select-datapack-desktop/SKILL.md +31 -21
- package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +8 -8
- package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +41 -0
- package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +1 -1
- package/bin/create-meko-setup.mjs +45 -6
- package/lib/clients/claude-code.mjs +8 -4
- package/lib/clients/claude-desktop.mjs +14 -0
- package/lib/clients/codex.mjs +23 -8
- package/lib/clients/common.mjs +2 -0
- package/lib/clients/cursor.mjs +7 -2
- package/lib/detect.mjs +7 -2
- package/lib/prompt.mjs +1 -1
- package/lib/url-selection.mjs +55 -0
- package/package.json +1 -1
- package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +0 -71
- package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +0 -71
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# test_checkpoint_timer.sh — Regression tests for issue #159:
|
|
4
|
+
# - Defect 1: the checkpoint timer must spawn even when the transcript file
|
|
5
|
+
# does not exist yet at SessionStart time (spawn race).
|
|
6
|
+
# - Defect 3: the timer must self-exit (max-age / idle backstop) and
|
|
7
|
+
# session-end.sh must kill it by transcript path when the pid file is gone,
|
|
8
|
+
# so orphaned daemons cannot tick forever.
|
|
9
|
+
#
|
|
10
|
+
# These tests do NOT require a live Meko MCP server: the timer's self-guard and
|
|
11
|
+
# self-exit paths run before any capture.js checkpoint would reach MCP, and we
|
|
12
|
+
# assert on process liveness / pid-file presence only.
|
|
13
|
+
#
|
|
14
|
+
# Usage: ./test_checkpoint_timer.sh
|
|
15
|
+
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
19
|
+
TIMER_JS="$SCRIPT_DIR/lib/checkpoint-timer.js"
|
|
20
|
+
SESSION_START="$SCRIPT_DIR/session-start.sh"
|
|
21
|
+
SESSION_END="$SCRIPT_DIR/session-end.sh"
|
|
22
|
+
|
|
23
|
+
WM_DIR="$(mktemp -d -t meko-timer-test-XXXXXX)"
|
|
24
|
+
TX_ROOT="$(mktemp -d -t meko-timer-tx-XXXXXX)"
|
|
25
|
+
# Exercise session-end matching when the absolute transcript path contains
|
|
26
|
+
# characters that have special meaning in a regular expression.
|
|
27
|
+
TX_DIR="$TX_ROOT/path with [regex] chars"
|
|
28
|
+
mkdir -p "$TX_DIR"
|
|
29
|
+
SESSION_ID="timer-test-$$"
|
|
30
|
+
TRANSCRIPT_PATH="$TX_DIR/${SESSION_ID}.jsonl"
|
|
31
|
+
PID_FILE="$WM_DIR/${SESSION_ID}.timer.pid"
|
|
32
|
+
|
|
33
|
+
PASS=0
|
|
34
|
+
FAIL=0
|
|
35
|
+
SPAWNED_PIDS=()
|
|
36
|
+
|
|
37
|
+
cleanup() {
|
|
38
|
+
for p in "${SPAWNED_PIDS[@]:-}"; do kill "$p" 2>/dev/null || true; done
|
|
39
|
+
rm -rf "$WM_DIR" "$TX_ROOT"
|
|
40
|
+
}
|
|
41
|
+
trap cleanup EXIT
|
|
42
|
+
|
|
43
|
+
log() { printf " %-55s" "$1"; }
|
|
44
|
+
pass() { printf "\033[32mPASS\033[0m %s\n" "${1:-}"; PASS=$((PASS + 1)); }
|
|
45
|
+
fail() { printf "\033[31mFAIL\033[0m %s\n" "${1:-}"; FAIL=$((FAIL + 1)); }
|
|
46
|
+
|
|
47
|
+
# Poll up to N deciseconds for a process to die. Returns 0 if it died.
|
|
48
|
+
wait_gone() {
|
|
49
|
+
local pid="$1" tries="${2:-50}"
|
|
50
|
+
while [ "$tries" -gt 0 ]; do
|
|
51
|
+
kill -0 "$pid" 2>/dev/null || return 0
|
|
52
|
+
sleep 0.1
|
|
53
|
+
tries=$((tries - 1))
|
|
54
|
+
done
|
|
55
|
+
return 1
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export MEKO_WATERMARK_DIR="$WM_DIR"
|
|
59
|
+
|
|
60
|
+
echo "============================================================"
|
|
61
|
+
echo "Test: checkpoint-timer regression (issue #159)"
|
|
62
|
+
echo "============================================================"
|
|
63
|
+
echo " Watermark dir: $WM_DIR"
|
|
64
|
+
echo " Transcript: $TRANSCRIPT_PATH"
|
|
65
|
+
echo ""
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Defect 1 — timer spawns even though transcript does not exist yet.
|
|
69
|
+
# session-start.sh backgrounds the timer; capture.js session-start will fail to
|
|
70
|
+
# reach MCP but must not block the spawn. The timer must remain alive after its
|
|
71
|
+
# first tick while transcript creation is still within the startup grace period.
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
echo "--- Defect 1: spawn race (transcript absent at SessionStart) ---"
|
|
74
|
+
log "Transcript absent before hook"
|
|
75
|
+
[ ! -f "$TRANSCRIPT_PATH" ] && pass || fail "transcript unexpectedly exists"
|
|
76
|
+
|
|
77
|
+
# Spawn the timer directly the way the fixed session-start.sh does. A one-second
|
|
78
|
+
# interval guarantees the missing-transcript branch runs before the assertion.
|
|
79
|
+
MEKO_CHECKPOINT_INTERVAL=1 MEKO_TIMER_MAX_AGE=999 MEKO_TIMER_IDLE_EXIT=999 \
|
|
80
|
+
MEKO_TIMER_STARTUP_GRACE=10 \
|
|
81
|
+
nohup node "$TIMER_JS" "$TRANSCRIPT_PATH" </dev/null >/dev/null 2>&1 &
|
|
82
|
+
TIMER_PID=$!
|
|
83
|
+
SPAWNED_PIDS+=("$TIMER_PID")
|
|
84
|
+
sleep 1.5
|
|
85
|
+
|
|
86
|
+
log "Timer survives first tick with missing transcript"
|
|
87
|
+
if kill -0 "$TIMER_PID" 2>/dev/null; then pass "pid $TIMER_PID"; else fail "timer did not stay up"; fi
|
|
88
|
+
|
|
89
|
+
log "Timer wrote its pid file"
|
|
90
|
+
[ -f "$PID_FILE" ] && pass || fail "no pid file at $PID_FILE"
|
|
91
|
+
|
|
92
|
+
kill "$TIMER_PID" 2>/dev/null || true
|
|
93
|
+
wait_gone "$TIMER_PID" || true
|
|
94
|
+
rm -f "$PID_FILE"
|
|
95
|
+
|
|
96
|
+
# ---------------------------------------------------------------------------
|
|
97
|
+
# Defect 3a — max-age self-exit. Transcript exists and is fresh, but max-age is
|
|
98
|
+
# tiny, so the first tick must self-exit and remove its pid file.
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
echo ""
|
|
101
|
+
echo "--- Defect 3a: max-age self-exit backstop ---"
|
|
102
|
+
printf '{"type":"user","uuid":"u1","message":{"content":"hi"}}\n' > "$TRANSCRIPT_PATH"
|
|
103
|
+
|
|
104
|
+
MEKO_CHECKPOINT_INTERVAL=1 MEKO_TIMER_MAX_AGE=1 MEKO_TIMER_IDLE_EXIT=999 \
|
|
105
|
+
nohup node "$TIMER_JS" "$TRANSCRIPT_PATH" </dev/null >/dev/null 2>&1 &
|
|
106
|
+
TIMER_PID=$!
|
|
107
|
+
SPAWNED_PIDS+=("$TIMER_PID")
|
|
108
|
+
|
|
109
|
+
log "Timer self-exits after max-age"
|
|
110
|
+
if wait_gone "$TIMER_PID" 60; then pass; else fail "still running after max-age"; fi
|
|
111
|
+
|
|
112
|
+
log "Pid file removed on self-exit"
|
|
113
|
+
[ ! -f "$PID_FILE" ] && pass || fail "stale pid file remains"
|
|
114
|
+
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
# Defect 3b — idle self-exit. Make the transcript look old (mtime in the past)
|
|
117
|
+
# so the idle backstop trips on the first tick.
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
echo ""
|
|
120
|
+
echo "--- Defect 3b: idle self-exit backstop ---"
|
|
121
|
+
printf '{"type":"user","uuid":"u1","message":{"content":"hi"}}\n' > "$TRANSCRIPT_PATH"
|
|
122
|
+
touch -t 202001010000 "$TRANSCRIPT_PATH" # far in the past
|
|
123
|
+
|
|
124
|
+
MEKO_CHECKPOINT_INTERVAL=1 MEKO_TIMER_MAX_AGE=999 MEKO_TIMER_IDLE_EXIT=1 \
|
|
125
|
+
nohup node "$TIMER_JS" "$TRANSCRIPT_PATH" </dev/null >/dev/null 2>&1 &
|
|
126
|
+
TIMER_PID=$!
|
|
127
|
+
SPAWNED_PIDS+=("$TIMER_PID")
|
|
128
|
+
|
|
129
|
+
log "Timer self-exits on idle transcript"
|
|
130
|
+
if wait_gone "$TIMER_PID" 60; then pass; else fail "still running with idle transcript"; fi
|
|
131
|
+
|
|
132
|
+
# ---------------------------------------------------------------------------
|
|
133
|
+
# Defect 3c — session-end.sh kills by transcript path when the pid file is gone.
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
echo ""
|
|
136
|
+
echo "--- Defect 3c: session-end path-based kill (no pid file) ---"
|
|
137
|
+
printf '{"type":"user","uuid":"u1","message":{"content":"hi"}}\n' > "$TRANSCRIPT_PATH"
|
|
138
|
+
|
|
139
|
+
# Long-lived timer; then delete its pid file to simulate the orphan condition.
|
|
140
|
+
MEKO_CHECKPOINT_INTERVAL=999 MEKO_TIMER_MAX_AGE=999 MEKO_TIMER_IDLE_EXIT=999 \
|
|
141
|
+
nohup node "$TIMER_JS" "$TRANSCRIPT_PATH" </dev/null >/dev/null 2>&1 &
|
|
142
|
+
TIMER_PID=$!
|
|
143
|
+
SPAWNED_PIDS+=("$TIMER_PID")
|
|
144
|
+
sleep 0.5
|
|
145
|
+
rm -f "$PID_FILE" # pid file vanished out of band -> classic orphan setup
|
|
146
|
+
|
|
147
|
+
log "Orphan timer running with no pid file"
|
|
148
|
+
if kill -0 "$TIMER_PID" 2>/dev/null && [ ! -f "$PID_FILE" ]; then pass "pid $TIMER_PID"; else fail "precondition not met"; fi
|
|
149
|
+
|
|
150
|
+
# session-end.sh must find it by transcript path and kill it.
|
|
151
|
+
printf '{"transcript_path":"%s"}' "$TRANSCRIPT_PATH" | bash "$SESSION_END" >/dev/null 2>&1 || true
|
|
152
|
+
|
|
153
|
+
log "session-end.sh killed the orphan by transcript path"
|
|
154
|
+
if wait_gone "$TIMER_PID" 30; then pass; else fail "orphan survived session-end"; fi
|
|
155
|
+
|
|
156
|
+
# ---------------------------------------------------------------------------
|
|
157
|
+
echo ""
|
|
158
|
+
echo "============================================================"
|
|
159
|
+
TOTAL=$((PASS + FAIL))
|
|
160
|
+
echo " Total: $TOTAL | Passed: $PASS | Failed: $FAIL"
|
|
161
|
+
echo "============================================================"
|
|
162
|
+
[ "$FAIL" -gt 0 ] && { echo " RESULT: FAILED"; exit 1; } || { echo " RESULT: ALL PASSED"; exit 0; }
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
8
8
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
|
-
SKILLS_ROOT="$SCRIPT_DIR/../skills"
|
|
9
|
+
SKILLS_ROOT="${MEKO_DESKTOP_SKILLS_ROOT:-$SCRIPT_DIR/../skills}"
|
|
10
10
|
SKILL_NAMES=("meko-mcp-tools-desktop" "meko-select-datapack-desktop")
|
|
11
|
+
XML_TAG_PATTERN='</?[[:alpha:]_:][[:alnum:]_.:-]*([[:blank:]][^<>]*)?[[:blank:]]*/?>'
|
|
11
12
|
|
|
12
13
|
for SKILL_NAME in "${SKILL_NAMES[@]}"; do
|
|
13
14
|
if [ ! -d "$SKILLS_ROOT/$SKILL_NAME" ]; then
|
|
@@ -19,6 +20,36 @@ for SKILL_NAME in "${SKILL_NAMES[@]}"; do
|
|
|
19
20
|
echo "Error: SKILL.md not found in $SKILLS_ROOT/$SKILL_NAME/" >&2
|
|
20
21
|
exit 1
|
|
21
22
|
fi
|
|
23
|
+
|
|
24
|
+
if ! grep -q '^description:[[:space:]]*' "$SKILLS_ROOT/$SKILL_NAME/SKILL.md"; then
|
|
25
|
+
echo "Error: SKILL.md description is missing: $SKILL_NAME" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
DESCRIPTION="$(awk '
|
|
30
|
+
/^description:[[:space:]]*/ {
|
|
31
|
+
in_description = 1
|
|
32
|
+
value = $0
|
|
33
|
+
sub(/^description:[[:space:]]*/, "", value)
|
|
34
|
+
if (value !~ /^[>|][+-]?$/) printf "%s ", value
|
|
35
|
+
next
|
|
36
|
+
}
|
|
37
|
+
in_description && /^[^[:space:]]/ { exit }
|
|
38
|
+
in_description {
|
|
39
|
+
sub(/^[[:space:]]+/, "")
|
|
40
|
+
printf "%s ", $0
|
|
41
|
+
}
|
|
42
|
+
' "$SKILLS_ROOT/$SKILL_NAME/SKILL.md")"
|
|
43
|
+
|
|
44
|
+
if [[ -z "${DESCRIPTION//[[:space:]]/}" ]]; then
|
|
45
|
+
echo "Error: SKILL.md description is empty: $SKILL_NAME" >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
if printf '%s\n' "$DESCRIPTION" | grep -Eq "$XML_TAG_PATTERN"; then
|
|
50
|
+
echo "Error: SKILL.md description cannot contain XML-like tags: $SKILL_NAME" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
22
53
|
done
|
|
23
54
|
|
|
24
55
|
for SKILL_NAME in "${SKILL_NAMES[@]}"; do
|
|
@@ -4,13 +4,14 @@ description: Behavioral guide for AI agents using Meko MCP tools. Triggers when
|
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: Meko
|
|
7
|
-
version: "3.0.
|
|
7
|
+
version: "3.0.2"
|
|
8
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
|
|
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
|
+
|
|
14
15
|
|
|
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.
|
|
16
17
|
|
|
@@ -18,8 +19,8 @@ Meko is agent-native data infrastructure that enables continuous learning from c
|
|
|
18
19
|
|
|
19
20
|
Meko turns your volatile context window into persistent, shareable knowledge:
|
|
20
21
|
|
|
21
|
-
- **Personal memory** — Store who the user is, their preferences, role, and working style. Private to you (scoped per-user
|
|
22
|
-
- **Team-shared knowledge** —
|
|
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`.
|
|
23
24
|
- **Conversation history** — Preserve full dialog exchanges with reasoning traces for audit, replay, and learning transfer.
|
|
24
25
|
- **Decision traces** — Capture how and why decisions were made, enabling debugging and continuous improvement.
|
|
25
26
|
|
|
@@ -29,7 +30,7 @@ Meko turns your volatile context window into persistent, shareable knowledge:
|
|
|
29
30
|
- You need to decide what to store, where, and how (personal memory vs. team-shared knowledge)
|
|
30
31
|
- You want to search the team's shared knowledge base (`knowledgebase_search`)
|
|
31
32
|
- You are managing datapacks
|
|
32
|
-
- You want to understand
|
|
33
|
+
- You want to understand `agent_id` conventions, or `datapack_id` routing
|
|
33
34
|
|
|
34
35
|
## `agent_id` — multi-agent identity
|
|
35
36
|
|
|
@@ -46,10 +47,12 @@ agent_id = "claude_code:meko-mcp-server" # this session's project bucket
|
|
|
46
47
|
agent_id = "meko_agent" # cross-project facts
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
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
|
|
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.
|
|
50
51
|
|
|
51
52
|
**Read scoping varies by tool:**
|
|
52
|
-
- `memory_search` / `memory_get_all`
|
|
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).
|
|
53
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.
|
|
54
57
|
|
|
55
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.
|
|
@@ -131,8 +134,9 @@ So your Meko reflexes are:
|
|
|
131
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`. |
|
|
132
135
|
| User explicitly says "remember this" / "save this to memory" | `memory_add` (verbatim). This is the clearest explicit-save case. |
|
|
133
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. |
|
|
134
|
-
| User asks "what do you know about X?" |
|
|
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). |
|
|
135
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. |
|
|
136
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. |
|
|
137
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
|
|
|
@@ -161,7 +165,7 @@ All three are handled automatically. **Do NOT set up CronCreate for conversation
|
|
|
161
165
|
The SessionStart hook has already done the setup for you:
|
|
162
166
|
|
|
163
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`.
|
|
164
|
-
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
|
|
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.
|
|
165
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.
|
|
166
170
|
|
|
167
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`.
|
|
@@ -171,11 +175,11 @@ If `additionalContext` is absent or empty (hook failed, MCP unavailable), ask th
|
|
|
171
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:
|
|
172
176
|
|
|
173
177
|
```
|
|
174
|
-
memory_search(
|
|
178
|
+
memory_search(query="destructive <action type> preferences feedback",
|
|
175
179
|
agent_id=<your agent_id>, conversation_id=<session_conversation_id>)
|
|
176
180
|
```
|
|
177
181
|
|
|
178
|
-
|
|
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.
|
|
179
183
|
|
|
180
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.
|
|
181
185
|
|
|
@@ -196,46 +200,53 @@ In the examples below, `<your-agent-id>` means the value the SessionStart hook i
|
|
|
196
200
|
|
|
197
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:
|
|
198
202
|
```
|
|
199
|
-
memory_add(
|
|
203
|
+
memory_add(
|
|
200
204
|
text="Remember: deploy scripts must be run from the repo root, never a subdir",
|
|
201
205
|
agent_id="<your-agent-id>",
|
|
202
206
|
conversation_id="<session_conversation_id>")
|
|
203
207
|
```
|
|
204
|
-
Required parameters: `
|
|
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.
|
|
205
209
|
|
|
206
210
|
### memory_search — correct call pattern
|
|
207
211
|
```
|
|
208
|
-
memory_search(
|
|
212
|
+
memory_search(
|
|
209
213
|
query="user role",
|
|
210
214
|
agent_id="<your-agent-id>",
|
|
211
215
|
conversation_id="<session_conversation_id>")
|
|
212
216
|
```
|
|
213
|
-
Required parameters: `
|
|
214
|
-
|
|
215
|
-
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:
|
|
216
|
-
```
|
|
217
|
-
memory_search(scope="read", query="user role",
|
|
218
|
-
agent_id="meko_agent", conversation_id="<session_conversation_id>")
|
|
219
|
-
```
|
|
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.
|
|
220
218
|
|
|
221
|
-
|
|
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.
|
|
222
220
|
|
|
223
221
|
### knowledgebase_search — correct call pattern
|
|
224
222
|
```
|
|
225
|
-
knowledgebase_search(
|
|
223
|
+
knowledgebase_search(
|
|
226
224
|
query="...",
|
|
227
225
|
agent_id="<anything — ignored>",
|
|
228
226
|
conversation_id="<session_conversation_id>",
|
|
229
227
|
datapack_id="<datapack UUID>",
|
|
230
228
|
limit=10)
|
|
231
229
|
```
|
|
232
|
-
Required parameters: `
|
|
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.
|
|
233
245
|
|
|
234
246
|
### Critical parameter rules
|
|
235
247
|
|
|
236
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`.
|
|
237
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.
|
|
238
|
-
- **scope**: Only `"read"`, `"write"`, or `"admin"`. Nothing else. Use the minimum the code actually requires (the per-tool cookbook shows it).
|
|
239
250
|
- **When in doubt about optional parameters, omit them.** The server has sensible defaults.
|
|
240
251
|
|
|
241
252
|
### Verify after writing
|
|
@@ -254,7 +265,6 @@ On the first Meko tool call in a fresh session (no prior Meko tool call since pr
|
|
|
254
265
|
|
|
255
266
|
**Canary memory shape.** This is the spec; keep the fields stable so support can grep for them.
|
|
256
267
|
|
|
257
|
-
- `scope`: `"write"`
|
|
258
268
|
- `agent_id`: the session's `agent_id` (from `additionalContext`); not a constant
|
|
259
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.
|
|
260
270
|
- `text`: `"Meko connection test: <client> @ <installer-version> — <ISO timestamp>. Safe to delete."`
|
|
@@ -268,31 +278,27 @@ On the first Meko tool call in a fresh session (no prior Meko tool call since pr
|
|
|
268
278
|
|
|
269
279
|
## Key concepts
|
|
270
280
|
|
|
271
|
-
1. **
|
|
272
|
-
2. **
|
|
273
|
-
3. **
|
|
274
|
-
4. **
|
|
275
|
-
5. **
|
|
276
|
-
6. **
|
|
277
|
-
7. **
|
|
278
|
-
8. **
|
|
279
|
-
9. **
|
|
280
|
-
10. **
|
|
281
|
-
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.
|
|
282
291
|
|
|
283
292
|
## Reference sections
|
|
284
293
|
|
|
285
294
|
| File | What it covers |
|
|
286
295
|
|------|---------------|
|
|
287
|
-
| `tools-overview.md` | Complete catalog of all
|
|
296
|
+
| `tools-overview.md` | Complete catalog of all 23 tools with decision tree |
|
|
288
297
|
| `tools-cookbook.md` | Per-tool examples with correct parameters, responses, and error cases |
|
|
289
298
|
| `tools-memory-vs-conversation.md` | When to use memory tools vs conversation tools |
|
|
290
299
|
| `tools-datapack-workflow.md` | Datapack lifecycle and datapack_id routing |
|
|
291
300
|
| `tools-rag-workflow.md` | End-to-end RAG pipeline flow |
|
|
292
|
-
| `tools-write-guardrails.md` | Blocked SQL patterns and configurable limits |
|
|
293
|
-
| `tools-scope-permissions.md` | read/write/admin permission hierarchy |
|
|
294
301
|
| `tools-agent-id-conventions.md` | Naming rules and constraints for agent_id |
|
|
295
302
|
| `tools-conversation-dedup.md` | Seed-based trace deduplication |
|
|
296
|
-
| `tools-db-query-patterns.md` | Read-only vs write query execution patterns |
|
|
297
303
|
| `tools-troubleshooting.md` | Error recovery, retry strategies, stuck pipeline diagnosis |
|
|
298
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
|
|
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
|
|
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;
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
66
|
+
mem0_collection ── personal memories, tagged (datapack, user, agent)
|
|
61
67
|
│
|
|
62
|
-
│
|
|
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
|
|
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?"
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
93
|
+
## Optional sub-scoping
|
|
90
94
|
|
|
91
|
-
Optional parameters narrow
|
|
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;
|
|
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.
|
|
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.
|