1use serde_json::json;
4
5use super::protocol::{ToolAnnotations, ToolDefinition};
6
7pub struct ToolDef {
9 pub name: &'static str,
10 pub description: &'static str,
11 pub schema: &'static str,
12 pub annotations: ToolAnnotations,
13}
14
15pub const TOOL_DEFINITIONS: &[ToolDef] = &[
17 ToolDef {
19 name: "memory_create",
20 description: "Store a new memory. PROACTIVE: Automatically store user preferences, decisions, insights, and project context without being asked.",
21 schema: r#"{
22 "type": "object",
23 "properties": {
24 "content": {"type": "string", "description": "The content to remember"},
25 "memory_type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential", "episodic", "procedural", "summary", "checkpoint", "image", "audio", "video"], "default": "note", "description": "Memory type (preferred field; alias: type)"},
26 "type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential", "episodic", "procedural", "summary", "checkpoint", "image", "audio", "video"], "default": "note", "description": "Deprecated alias for memory_type"},
27 "tags": {"type": "array", "items": {"type": "string"}, "description": "Tags for categorization"},
28 "metadata": {"type": "object", "description": "Additional metadata as key-value pairs"},
29 "importance": {"type": "number", "minimum": 0, "maximum": 1, "description": "Importance score (0-1)"},
30 "workspace": {"type": "string", "description": "Workspace to store the memory in (default: 'default')"},
31 "tier": {"type": "string", "enum": ["permanent", "daily"], "default": "permanent", "description": "Memory tier: permanent (never expires) or daily (auto-expires)"},
32 "defer_embedding": {"type": "boolean", "default": false, "description": "Defer embedding to background queue"},
33 "ttl_seconds": {"type": "integer", "description": "Time-to-live in seconds. Memory will auto-expire after this duration. Omit for permanent storage. Setting this implies tier='daily'."},
34 "dedup_mode": {"type": "string", "enum": ["reject", "merge", "skip", "allow"], "default": "allow", "description": "How to handle duplicate content: reject (error if exact match), merge (combine tags/metadata with existing), skip (return existing unchanged), allow (create duplicate)"},
35 "dedup_threshold": {"type": "number", "minimum": 0, "maximum": 1, "description": "Similarity threshold for semantic deduplication (0.0-1.0). When set with dedup_mode != 'allow', memories with cosine similarity >= threshold are treated as duplicates. Requires embeddings. If not set, only exact content hash matching is used."},
36 "event_time": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp for episodic memories (when the event occurred)"},
37 "event_duration_seconds": {"type": "integer", "description": "Duration of the event in seconds (for episodic memories)"},
38 "trigger_pattern": {"type": "string", "description": "Pattern that triggers this procedure (for procedural memories)"},
39 "summary_of_id": {"type": "integer", "description": "ID of the memory this summarizes (for summary memories)"},
40 "media_url": {"type": "string", "description": "URL or local path to the primary media asset (for Image/Audio/Video memory types). Format: local:///path, https://..., or s3://..."}
41 },
42 "required": ["content"]
43 }"#,
44 annotations: ToolAnnotations::mutating(),
45 },
46 ToolDef {
47 name: "context_seed",
48 description: "Injects initial context (premises, persona assumptions, or structured facts) about an entity to avoid cold start. Seeded memories are tagged as origin:seed and status:unverified, and should be treated as revisable assumptions.",
49 schema: r#"{
50 "type": "object",
51 "properties": {
52 "entity_context": {
53 "type": "string",
54 "maxLength": 200,
55 "description": "Name or ID of the entity (e.g., 'Client: Roberto', 'Account: ACME', 'Project: Alpha')"
56 },
57 "workspace": {"type": "string", "description": "Workspace to store the memories in (default: 'default')"},
58 "base_tags": {
59 "type": "array",
60 "items": {"type": "string"},
61 "description": "Tags applied to all facts (e.g., ['vip', 'prospect'])"
62 },
63 "ttl_seconds": {
64 "type": "integer",
65 "description": "Override TTL for all facts in seconds (0 = disable TTL). If omitted, TTL is derived from confidence."
66 },
67 "disable_ttl": {
68 "type": "boolean",
69 "default": false,
70 "description": "Disable TTL and keep seeded memories permanent regardless of confidence."
71 },
72 "facts": {
73 "type": "array",
74 "minItems": 1,
75 "items": {
76 "type": "object",
77 "properties": {
78 "content": {"type": "string", "minLength": 1},
79 "category": {
80 "type": "string",
81 "enum": ["fact", "behavior_instruction", "interest", "persona", "preference"],
82 "description": "Structured category for filtering and ranking"
83 },
84 "confidence": {
85 "type": "number",
86 "minimum": 0.0,
87 "maximum": 1.0,
88 "description": "0.0 to 1.0 (defaults to 0.7 for seeds). TTL derived by confidence if ttl_seconds not provided."
89 }
90 },
91 "required": ["content"]
92 }
93 }
94 },
95 "required": ["facts"]
96 }"#,
97 annotations: ToolAnnotations::mutating(),
98 },
99 ToolDef {
100 name: "memory_seed",
101 description: "Deprecated alias for context_seed. Use context_seed instead.",
102 schema: r#"{
103 "type": "object",
104 "properties": {
105 "entity_context": {
106 "type": "string",
107 "maxLength": 200,
108 "description": "Name or ID of the entity (e.g., 'Client: Roberto', 'Account: ACME', 'Project: Alpha')"
109 },
110 "workspace": {"type": "string", "description": "Workspace to store the memories in (default: 'default')"},
111 "base_tags": {
112 "type": "array",
113 "items": {"type": "string"},
114 "description": "Tags applied to all facts (e.g., ['vip', 'prospect'])"
115 },
116 "ttl_seconds": {
117 "type": "integer",
118 "description": "Override TTL for all facts in seconds (0 = disable TTL). If omitted, TTL is derived from confidence."
119 },
120 "disable_ttl": {
121 "type": "boolean",
122 "default": false,
123 "description": "Disable TTL and keep seeded memories permanent regardless of confidence."
124 },
125 "facts": {
126 "type": "array",
127 "minItems": 1,
128 "items": {
129 "type": "object",
130 "properties": {
131 "content": {"type": "string", "minLength": 1},
132 "category": {
133 "type": "string",
134 "enum": ["fact", "behavior_instruction", "interest", "persona", "preference"],
135 "description": "Structured category for filtering and ranking"
136 },
137 "confidence": {
138 "type": "number",
139 "minimum": 0.0,
140 "maximum": 1.0,
141 "description": "0.0 to 1.0 (defaults to 0.7 for seeds). TTL derived by confidence if ttl_seconds not provided."
142 }
143 },
144 "required": ["content"]
145 }
146 }
147 },
148 "required": ["facts"]
149 }"#,
150 annotations: ToolAnnotations::mutating(),
151 },
152 ToolDef {
153 name: "memory_get",
154 description: "Retrieve a memory by its ID",
155 schema: r#"{
156 "type": "object",
157 "properties": {
158 "id": {"type": "integer", "description": "Memory ID"},
159 "strip_private": {"type": "boolean", "description": "When true, removes all <private>...</private> tagged sections from the content before returning (default: false)"}
160 },
161 "required": ["id"]
162 }"#,
163 annotations: ToolAnnotations::read_only(),
164 },
165 ToolDef {
166 name: "memory_update",
167 description: "Update an existing memory",
168 schema: r#"{
169 "type": "object",
170 "properties": {
171 "id": {"type": "integer", "description": "Memory ID"},
172 "content": {"type": "string", "description": "New content"},
173 "memory_type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential", "episodic", "procedural", "summary", "checkpoint", "image", "audio", "video"], "description": "Memory type (preferred field; alias: type)"},
174 "type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential", "episodic", "procedural", "summary", "checkpoint", "image", "audio", "video"], "description": "Deprecated alias for memory_type"},
175 "tags": {"type": "array", "items": {"type": "string"}},
176 "metadata": {"type": "object"},
177 "importance": {"type": "number", "minimum": 0, "maximum": 1},
178 "ttl_seconds": {"type": "integer", "description": "Time-to-live in seconds (0 = remove expiration, positive = set new expiration)"},
179 "event_time": {"type": ["string", "null"], "format": "date-time", "description": "ISO8601 timestamp for episodic memories (null to clear)"},
180 "trigger_pattern": {"type": ["string", "null"], "description": "Pattern that triggers this procedure (null to clear)"}
181 },
182 "required": ["id"]
183 }"#,
184 annotations: ToolAnnotations::mutating(),
185 },
186 ToolDef {
187 name: "memory_delete",
188 description: "Delete a memory (soft delete)",
189 schema: r#"{
190 "type": "object",
191 "properties": {
192 "id": {"type": "integer", "description": "Memory ID"}
193 },
194 "required": ["id"]
195 }"#,
196 annotations: ToolAnnotations::destructive(),
197 },
198 ToolDef {
199 name: "memory_list",
200 description: "List memories with filtering and pagination. Supports workspace isolation, tier filtering, and advanced filter syntax with AND/OR and comparison operators.",
201 schema: r#"{
202 "type": "object",
203 "properties": {
204 "limit": {"type": "integer", "default": 20},
205 "offset": {"type": "integer", "default": 0},
206 "tags": {"type": "array", "items": {"type": "string"}},
207 "memory_type": {"type": "string", "description": "Filter by memory type (preferred field; alias: type)"},
208 "type": {"type": "string", "description": "Deprecated alias for memory_type"},
209 "workspace": {"type": "string", "description": "Filter by single workspace"},
210 "workspaces": {"type": "array", "items": {"type": "string"}, "description": "Filter by multiple workspaces"},
211 "tier": {"type": "string", "enum": ["permanent", "daily"], "description": "Filter by memory tier"},
212 "sort_by": {"type": "string", "enum": ["created_at", "updated_at", "last_accessed_at", "importance", "access_count"]},
213 "sort_order": {"type": "string", "enum": ["asc", "desc"], "default": "desc"},
214 "filter": {
215 "type": "object",
216 "description": "Advanced filter with AND/OR logic and comparison operators. Supports workspace, tier, and metadata fields. Example: {\"AND\": [{\"metadata.project\": {\"eq\": \"engram\"}}, {\"importance\": {\"gte\": 0.5}}]}. Supported operators: eq, neq, gt, gte, lt, lte, contains, not_contains, exists. Fields: content, memory_type, importance, tags, workspace, tier, created_at, updated_at, metadata.*"
217 },
218 "metadata_filter": {
219 "type": "object",
220 "description": "Legacy simple key-value filter (deprecated, use 'filter' instead)"
221 }
222 }
223 }"#,
224 annotations: ToolAnnotations::read_only(),
225 },
226 ToolDef {
228 name: "memory_search",
229 description: "Search memories using hybrid search (keyword + semantic). Automatically selects optimal strategy with optional reranking. Supports workspace isolation, tier filtering, and advanced filters.",
230 schema: r#"{
231 "type": "object",
232 "properties": {
233 "query": {"type": "string", "description": "Search query"},
234 "limit": {"type": "integer", "default": 10},
235 "min_score": {"type": "number", "default": 0.1},
236 "tags": {"type": "array", "items": {"type": "string"}},
237 "memory_type": {"type": "string", "description": "Filter by memory type (preferred field; alias: type)"},
238 "type": {"type": "string", "description": "Deprecated alias for memory_type"},
239 "workspace": {"type": "string", "description": "Filter by single workspace"},
240 "workspaces": {"type": "array", "items": {"type": "string"}, "description": "Filter by multiple workspaces"},
241 "tier": {"type": "string", "enum": ["permanent", "daily"], "description": "Filter by memory tier"},
242 "include_transcripts": {"type": "boolean", "default": false, "description": "Include transcript chunk memories (excluded by default)"},
243 "strategy": {"type": "string", "enum": ["auto", "keyword", "keyword_only", "semantic", "semantic_only", "hybrid"], "description": "Force specific strategy (auto selects based on query; keyword/semantic are aliases for keyword_only/semantic_only)"},
244 "explain": {"type": "boolean", "default": false, "description": "Include match explanations"},
245 "rerank": {"type": "boolean", "default": true, "description": "Apply reranking to improve result quality"},
246 "rerank_strategy": {"type": "string", "enum": ["none", "heuristic", "multi_signal"], "default": "heuristic", "description": "Reranking strategy to use"},
247 "filter": {
248 "type": "object",
249 "description": "Advanced filter with AND/OR logic. Supports workspace, tier, and metadata fields. Example: {\"AND\": [{\"workspace\": {\"eq\": \"my-project\"}}, {\"importance\": {\"gte\": 0.5}}]}"
250 }
251 },
252 "required": ["query"]
253 }"#,
254 annotations: ToolAnnotations::read_only(),
255 },
256 ToolDef {
257 name: "memory_search_suggest",
258 description: "Get search suggestions and typo corrections",
259 schema: r#"{
260 "type": "object",
261 "properties": {
262 "query": {"type": "string"}
263 },
264 "required": ["query"]
265 }"#,
266 annotations: ToolAnnotations::read_only(),
267 },
268 ToolDef {
270 name: "memory_link",
271 description: "Create a cross-reference between two memories",
272 schema: r#"{
273 "type": "object",
274 "properties": {
275 "from_id": {"type": "integer"},
276 "to_id": {"type": "integer"},
277 "edge_type": {"type": "string", "enum": ["related_to", "supersedes", "contradicts", "implements", "extends", "references", "depends_on", "blocks", "follows_up"], "default": "related_to"},
278 "strength": {"type": "number", "minimum": 0, "maximum": 1, "description": "Relationship strength"},
279 "source_context": {"type": "string", "description": "Why this link exists"},
280 "pinned": {"type": "boolean", "default": false, "description": "Exempt from confidence decay"}
281 },
282 "required": ["from_id", "to_id"]
283 }"#,
284 annotations: ToolAnnotations::mutating(),
285 },
286 ToolDef {
287 name: "memory_unlink",
288 description: "Remove a cross-reference",
289 schema: r#"{
290 "type": "object",
291 "properties": {
292 "from_id": {"type": "integer"},
293 "to_id": {"type": "integer"},
294 "edge_type": {"type": "string", "default": "related_to"}
295 },
296 "required": ["from_id", "to_id"]
297 }"#,
298 annotations: ToolAnnotations::mutating(),
299 },
300 ToolDef {
301 name: "memory_related",
302 description: "Get memories related to a given memory (depth>1 or include_entities returns traversal result)",
303 schema: r#"{
304 "type": "object",
305 "properties": {
306 "id": {"type": "integer", "description": "Starting memory ID"},
307 "depth": {"type": "integer", "default": 1, "description": "Traversal depth (1 = direct relations only)"},
308 "include_entities": {"type": "boolean", "default": false, "description": "Include connections through shared entities"},
309 "edge_type": {"type": "string", "description": "Filter by edge type"},
310 "include_decayed": {"type": "boolean", "default": false}
311 },
312 "required": ["id"]
313 }"#,
314 annotations: ToolAnnotations::read_only(),
315 },
316 ToolDef {
318 name: "memory_create_todo",
319 description: "Create a TODO memory with priority",
320 schema: r#"{
321 "type": "object",
322 "properties": {
323 "content": {"type": "string"},
324 "priority": {"type": "string", "enum": ["low", "medium", "high", "critical"], "default": "medium"},
325 "due_date": {"type": "string", "format": "date"},
326 "tags": {"type": "array", "items": {"type": "string"}}
327 },
328 "required": ["content"]
329 }"#,
330 annotations: ToolAnnotations::mutating(),
331 },
332 ToolDef {
333 name: "memory_create_issue",
334 description: "Create an ISSUE memory for tracking problems",
335 schema: r#"{
336 "type": "object",
337 "properties": {
338 "title": {"type": "string"},
339 "description": {"type": "string"},
340 "severity": {"type": "string", "enum": ["low", "medium", "high", "critical"], "default": "medium"},
341 "tags": {"type": "array", "items": {"type": "string"}}
342 },
343 "required": ["title"]
344 }"#,
345 annotations: ToolAnnotations::mutating(),
346 },
347 ToolDef {
349 name: "memory_versions",
350 description: "Get version history for a memory",
351 schema: r#"{
352 "type": "object",
353 "properties": {
354 "id": {"type": "integer"}
355 },
356 "required": ["id"]
357 }"#,
358 annotations: ToolAnnotations::read_only(),
359 },
360 ToolDef {
361 name: "memory_get_version",
362 description: "Get a specific version of a memory",
363 schema: r#"{
364 "type": "object",
365 "properties": {
366 "id": {"type": "integer"},
367 "version": {"type": "integer"}
368 },
369 "required": ["id", "version"]
370 }"#,
371 annotations: ToolAnnotations::read_only(),
372 },
373 ToolDef {
374 name: "memory_revert",
375 description: "Revert a memory to a previous version",
376 schema: r#"{
377 "type": "object",
378 "properties": {
379 "id": {"type": "integer"},
380 "version": {"type": "integer"}
381 },
382 "required": ["id", "version"]
383 }"#,
384 annotations: ToolAnnotations::mutating(),
385 },
386 ToolDef {
388 name: "memory_embedding_status",
389 description: "Check embedding computation status",
390 schema: r#"{
391 "type": "object",
392 "properties": {
393 "id": {"type": "integer"}
394 },
395 "required": ["id"]
396 }"#,
397 annotations: ToolAnnotations::read_only(),
398 },
399 ToolDef {
401 name: "memory_set_expiration",
402 description: "Set or update the expiration time for a memory",
403 schema: r#"{
404 "type": "object",
405 "properties": {
406 "id": {"type": "integer", "description": "Memory ID"},
407 "ttl_seconds": {"type": "integer", "description": "Time-to-live in seconds from now. Use 0 to remove expiration (make permanent)."}
408 },
409 "required": ["id", "ttl_seconds"]
410 }"#,
411 annotations: ToolAnnotations::mutating(),
412 },
413 ToolDef {
414 name: "memory_cleanup_expired",
415 description: "Delete all expired memories. Typically called by a background job, but can be invoked manually.",
416 schema: r#"{
417 "type": "object",
418 "properties": {}
419 }"#,
420 annotations: ToolAnnotations::destructive(),
421 },
422 ToolDef {
424 name: "memory_sync_status",
425 description: "Get cloud sync status",
426 schema: r#"{"type": "object", "properties": {}}"#,
427 annotations: ToolAnnotations::read_only(),
428 },
429 ToolDef {
430 name: "memory_sync_media",
431 description: "Sync local media assets (images, audio, video) to cloud S3/R2 storage. Uploads files from media_assets table that have not yet been synced. Returns a report of synced files. Requires both multimodal and cloud features.",
432 schema: r#"{
433 "type": "object",
434 "properties": {
435 "dry_run": {"type": "boolean", "default": false, "description": "If true, report what would be synced without actually uploading"}
436 }
437 }"#,
438 annotations: ToolAnnotations::mutating(),
439 },
440 ToolDef {
441 name: "memory_search_by_image",
442 description: "Search memories using an image as the query. Uses multimodal embeddings (CLIP-style) or falls back to describing the image via vision model and searching by description. Returns semantically similar memories — text or media — ranked by relevance.",
443 schema: r#"{
444 "type": "object",
445 "properties": {
446 "image_path": {"type": "string", "description": "Path to the local image file to use as the search query"},
447 "limit": {"type": "integer", "default": 10, "description": "Maximum number of results to return"},
448 "min_score": {"type": "number", "minimum": 0, "maximum": 1, "description": "Minimum similarity score (0.0-1.0)"},
449 "workspace": {"type": "string", "description": "Restrict search to a specific workspace"},
450 "strategy": {"type": "string", "enum": ["clip", "description", "auto"], "default": "auto", "description": "Embedding strategy: clip (requires CLIP embedder), description (vision model + text embedding), auto (use CLIP if available, else description)"}
451 },
452 "required": ["image_path"]
453 }"#,
454 annotations: ToolAnnotations::read_only(),
455 },
456 ToolDef {
458 name: "memory_stats",
459 description: "Get storage statistics",
460 schema: r#"{"type": "object", "properties": {}}"#,
461 annotations: ToolAnnotations::read_only(),
462 },
463 ToolDef {
464 name: "memory_aggregate",
465 description: "Aggregate memories by field",
466 schema: r#"{
467 "type": "object",
468 "properties": {
469 "group_by": {"type": "string", "enum": ["type", "tags", "month"]},
470 "metrics": {"type": "array", "items": {"type": "string", "enum": ["count", "avg_importance"]}}
471 },
472 "required": ["group_by"]
473 }"#,
474 annotations: ToolAnnotations::read_only(),
475 },
476 ToolDef {
478 name: "memory_export_graph",
479 description: "Export knowledge graph visualization",
480 schema: r#"{
481 "type": "object",
482 "properties": {
483 "format": {"type": "string", "enum": ["html", "json"], "default": "html"},
484 "max_nodes": {"type": "integer", "default": 500},
485 "focus_id": {"type": "integer", "description": "Center graph on this memory"}
486 }
487 }"#,
488 annotations: ToolAnnotations::read_only(),
489 },
490 ToolDef {
492 name: "memory_quality_report",
493 description: "Get quality report for memories",
494 schema: r#"{
495 "type": "object",
496 "properties": {
497 "limit": {"type": "integer", "default": 20},
498 "min_quality": {"type": "number", "minimum": 0, "maximum": 1}
499 }
500 }"#,
501 annotations: ToolAnnotations::read_only(),
502 },
503 ToolDef {
505 name: "memory_clusters",
506 description: "Find clusters of related memories",
507 schema: r#"{
508 "type": "object",
509 "properties": {
510 "min_similarity": {"type": "number", "default": 0.7},
511 "min_cluster_size": {"type": "integer", "default": 2}
512 }
513 }"#,
514 annotations: ToolAnnotations::read_only(),
515 },
516 ToolDef {
517 name: "memory_find_duplicates",
518 description: "Find potential duplicate memories",
519 schema: r#"{
520 "type": "object",
521 "properties": {
522 "threshold": {"type": "number", "default": 0.9}
523 }
524 }"#,
525 annotations: ToolAnnotations::read_only(),
526 },
527 ToolDef {
528 name: "memory_find_semantic_duplicates",
529 description: "Find semantically similar memories using embedding cosine similarity (LLM-powered dedup). Goes beyond hash/n-gram to detect paraphrased content.",
530 schema: r#"{
531 "type": "object",
532 "properties": {
533 "threshold": {"type": "number", "default": 0.92, "description": "Cosine similarity threshold (0.92 = very similar)"},
534 "workspace": {"type": "string", "description": "Filter by workspace (optional)"},
535 "limit": {"type": "integer", "default": 50, "description": "Maximum duplicate pairs to return"}
536 }
537 }"#,
538 annotations: ToolAnnotations::read_only(),
539 },
540 ToolDef {
541 name: "memory_merge",
542 description: "Merge duplicate memories",
543 schema: r#"{
544 "type": "object",
545 "properties": {
546 "ids": {"type": "array", "items": {"type": "integer"}, "minItems": 2},
547 "keep_id": {"type": "integer", "description": "ID to keep (others will be merged into it)"}
548 },
549 "required": ["ids"]
550 }"#,
551 annotations: ToolAnnotations::mutating(),
552 },
553 ToolDef {
555 name: "memory_scan_project",
556 description: "Scan current directory for AI instruction files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) and ingest them as memories. Creates parent memory for each file and child memories for sections.",
557 schema: r#"{
558 "type": "object",
559 "properties": {
560 "path": {"type": "string", "description": "Directory to scan (defaults to current working directory)"},
561 "scan_parents": {"type": "boolean", "default": false, "description": "Also scan parent directories (security: disabled by default)"},
562 "extract_sections": {"type": "boolean", "default": true, "description": "Create separate memories for each section"}
563 }
564 }"#,
565 annotations: ToolAnnotations::mutating(),
566 },
567 ToolDef {
568 name: "memory_get_project_context",
569 description: "Get all project context memories for the current working directory. Returns instruction files and their sections.",
570 schema: r#"{
571 "type": "object",
572 "properties": {
573 "path": {"type": "string", "description": "Project path (defaults to current working directory)"},
574 "include_sections": {"type": "boolean", "default": true, "description": "Include section memories"},
575 "file_types": {"type": "array", "items": {"type": "string"}, "description": "Filter by file type (claude-md, cursorrules, etc.)"}
576 }
577 }"#,
578 annotations: ToolAnnotations::read_only(),
579 },
580 ToolDef {
581 name: "memory_list_instruction_files",
582 description: "List AI instruction files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) in a directory without ingesting them. Returns file paths, types, and sizes for discovery purposes.",
583 schema: r#"{
584 "type": "object",
585 "properties": {
586 "path": {"type": "string", "description": "Directory to scan (defaults to current working directory)"},
587 "scan_parents": {"type": "boolean", "default": false, "description": "Also scan parent directories for instruction files"}
588 }
589 }"#,
590 annotations: ToolAnnotations::read_only(),
591 },
592 ToolDef {
594 name: "memory_extract_entities",
595 description: "Extract named entities (people, organizations, projects, concepts) from a memory and store them",
596 schema: r#"{
597 "type": "object",
598 "properties": {
599 "id": {"type": "integer", "description": "Memory ID to extract entities from"}
600 },
601 "required": ["id"]
602 }"#,
603 annotations: ToolAnnotations::idempotent(),
604 },
605 ToolDef {
606 name: "memory_get_entities",
607 description: "Get all entities linked to a memory",
608 schema: r#"{
609 "type": "object",
610 "properties": {
611 "id": {"type": "integer", "description": "Memory ID"}
612 },
613 "required": ["id"]
614 }"#,
615 annotations: ToolAnnotations::read_only(),
616 },
617 ToolDef {
618 name: "memory_search_entities",
619 description: "Search for entities by name prefix",
620 schema: r#"{
621 "type": "object",
622 "properties": {
623 "query": {"type": "string", "description": "Search query (prefix match)"},
624 "entity_type": {"type": "string", "description": "Filter by entity type (person, organization, project, concept, etc.)"},
625 "limit": {"type": "integer", "default": 20}
626 },
627 "required": ["query"]
628 }"#,
629 annotations: ToolAnnotations::read_only(),
630 },
631 ToolDef {
632 name: "memory_entity_stats",
633 description: "Get statistics about extracted entities",
634 schema: r#"{
635 "type": "object",
636 "properties": {}
637 }"#,
638 annotations: ToolAnnotations::read_only(),
639 },
640 ToolDef {
642 name: "memory_traverse",
643 description: "Traverse the knowledge graph from a starting memory with full control over traversal options",
644 schema: r#"{
645 "type": "object",
646 "properties": {
647 "id": {"type": "integer", "description": "Starting memory ID"},
648 "depth": {"type": "integer", "default": 2, "description": "Maximum traversal depth"},
649 "direction": {"type": "string", "enum": ["outgoing", "incoming", "both"], "default": "both"},
650 "edge_types": {"type": "array", "items": {"type": "string"}, "description": "Filter by edge types (related_to, depends_on, etc.)"},
651 "min_score": {"type": "number", "default": 0, "description": "Minimum edge score threshold"},
652 "min_confidence": {"type": "number", "default": 0, "description": "Minimum confidence threshold"},
653 "limit_per_hop": {"type": "integer", "default": 50, "description": "Max results per hop"},
654 "include_entities": {"type": "boolean", "default": true, "description": "Include entity-based connections"}
655 },
656 "required": ["id"]
657 }"#,
658 annotations: ToolAnnotations::read_only(),
659 },
660 ToolDef {
661 name: "memory_find_path",
662 description: "Find the shortest path between two memories in the knowledge graph",
663 schema: r#"{
664 "type": "object",
665 "properties": {
666 "from_id": {"type": "integer", "description": "Starting memory ID"},
667 "to_id": {"type": "integer", "description": "Target memory ID"},
668 "max_depth": {"type": "integer", "default": 5, "description": "Maximum path length to search"}
669 },
670 "required": ["from_id", "to_id"]
671 }"#,
672 annotations: ToolAnnotations::read_only(),
673 },
674 ToolDef {
676 name: "memory_ingest_document",
677 description: "Ingest a document (PDF or Markdown) into memory. Extracts text, splits into chunks with overlap, and creates memories with deduplication.",
678 schema: r#"{
679 "type": "object",
680 "properties": {
681 "path": {"type": "string", "description": "Local file path to the document"},
682 "format": {"type": "string", "enum": ["auto", "md", "pdf"], "default": "auto", "description": "Document format (auto-detect from extension if not specified)"},
683 "chunk_size": {"type": "integer", "default": 1200, "description": "Maximum characters per chunk"},
684 "overlap": {"type": "integer", "default": 200, "description": "Overlap between chunks in characters"},
685 "max_file_size": {"type": "integer", "default": 10485760, "description": "Maximum file size in bytes (default 10MB)"},
686 "tags": {"type": "array", "items": {"type": "string"}, "description": "Additional tags to add to all chunks"}
687 },
688 "required": ["path"]
689 }"#,
690 annotations: ToolAnnotations::mutating(),
691 },
692 ToolDef {
694 name: "workspace_list",
695 description: "List all workspaces with their statistics (memory count, tier breakdown, etc.)",
696 schema: r#"{
697 "type": "object",
698 "properties": {}
699 }"#,
700 annotations: ToolAnnotations::read_only(),
701 },
702 ToolDef {
703 name: "workspace_stats",
704 description: "Get detailed statistics for a specific workspace",
705 schema: r#"{
706 "type": "object",
707 "properties": {
708 "workspace": {"type": "string", "description": "Workspace name"}
709 },
710 "required": ["workspace"]
711 }"#,
712 annotations: ToolAnnotations::read_only(),
713 },
714 ToolDef {
715 name: "workspace_move",
716 description: "Move a memory to a different workspace",
717 schema: r#"{
718 "type": "object",
719 "properties": {
720 "id": {"type": "integer", "description": "Memory ID to move"},
721 "workspace": {"type": "string", "description": "Target workspace name"}
722 },
723 "required": ["id", "workspace"]
724 }"#,
725 annotations: ToolAnnotations::mutating(),
726 },
727 ToolDef {
728 name: "workspace_delete",
729 description: "Delete a workspace. Can either move all memories to 'default' workspace or hard delete them.",
730 schema: r#"{
731 "type": "object",
732 "properties": {
733 "workspace": {"type": "string", "description": "Workspace to delete"},
734 "move_to_default": {"type": "boolean", "default": true, "description": "If true, moves memories to 'default' workspace. If false, deletes all memories in the workspace."}
735 },
736 "required": ["workspace"]
737 }"#,
738 annotations: ToolAnnotations::destructive(),
739 },
740 ToolDef {
742 name: "memory_create_daily",
743 description: "Create a daily (ephemeral) memory that auto-expires after the specified TTL. Useful for session context and scratch notes.",
744 schema: r#"{
745 "type": "object",
746 "properties": {
747 "content": {"type": "string", "description": "The content to remember"},
748 "type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential"], "default": "note"},
749 "tags": {"type": "array", "items": {"type": "string"}, "description": "Tags for categorization"},
750 "metadata": {"type": "object", "description": "Additional metadata as key-value pairs"},
751 "importance": {"type": "number", "minimum": 0, "maximum": 1, "description": "Importance score (0-1)"},
752 "ttl_seconds": {"type": "integer", "default": 86400, "description": "Time-to-live in seconds (default: 24 hours)"},
753 "workspace": {"type": "string", "description": "Workspace to store the memory in (default: 'default')"}
754 },
755 "required": ["content"]
756 }"#,
757 annotations: ToolAnnotations::mutating(),
758 },
759 ToolDef {
760 name: "memory_promote_to_permanent",
761 description: "Promote a daily memory to permanent tier. Clears the expiration and makes the memory permanent.",
762 schema: r#"{
763 "type": "object",
764 "properties": {
765 "id": {"type": "integer", "description": "Memory ID to promote"}
766 },
767 "required": ["id"]
768 }"#,
769 annotations: ToolAnnotations::mutating(),
770 },
771 ToolDef {
773 name: "embedding_cache_stats",
774 description: "Get statistics about the embedding cache (hits, misses, entries, bytes used, hit rate)",
775 schema: r#"{
776 "type": "object",
777 "properties": {}
778 }"#,
779 annotations: ToolAnnotations::read_only(),
780 },
781 ToolDef {
782 name: "embedding_cache_clear",
783 description: "Clear all entries from the embedding cache",
784 schema: r#"{
785 "type": "object",
786 "properties": {}
787 }"#,
788 annotations: ToolAnnotations::destructive(),
789 },
790 ToolDef {
792 name: "session_index",
793 description: "Index a conversation into searchable memory chunks. Uses dual-limiter chunking (messages + characters) with overlap.",
794 schema: r#"{
795 "type": "object",
796 "properties": {
797 "session_id": {"type": "string", "description": "Unique session identifier"},
798 "messages": {
799 "type": "array",
800 "description": "Array of conversation messages",
801 "items": {
802 "type": "object",
803 "properties": {
804 "role": {"type": "string", "description": "Message role (user, assistant, system)"},
805 "content": {"type": "string", "description": "Message content"},
806 "timestamp": {"type": "string", "description": "ISO 8601 timestamp"},
807 "id": {"type": "string", "description": "Optional message ID"}
808 },
809 "required": ["role", "content"]
810 }
811 },
812 "title": {"type": "string", "description": "Optional session title"},
813 "workspace": {"type": "string", "description": "Workspace to store chunks in (default: 'default')"},
814 "agent_id": {"type": "string", "description": "Optional agent identifier"},
815 "max_messages": {"type": "integer", "default": 10, "description": "Max messages per chunk"},
816 "max_chars": {"type": "integer", "default": 8000, "description": "Max characters per chunk"},
817 "overlap": {"type": "integer", "default": 2, "description": "Overlap messages between chunks"},
818 "ttl_days": {"type": "integer", "default": 7, "description": "TTL for transcript chunks in days"}
819 },
820 "required": ["session_id", "messages"]
821 }"#,
822 annotations: ToolAnnotations::mutating(),
823 },
824 ToolDef {
825 name: "session_index_delta",
826 description: "Incrementally index new messages to an existing session. More efficient than full reindex.",
827 schema: r#"{
828 "type": "object",
829 "properties": {
830 "session_id": {"type": "string", "description": "Session to update"},
831 "messages": {
832 "type": "array",
833 "description": "New messages to add",
834 "items": {
835 "type": "object",
836 "properties": {
837 "role": {"type": "string"},
838 "content": {"type": "string"},
839 "timestamp": {"type": "string"},
840 "id": {"type": "string"}
841 },
842 "required": ["role", "content"]
843 }
844 }
845 },
846 "required": ["session_id", "messages"]
847 }"#,
848 annotations: ToolAnnotations::mutating(),
849 },
850 ToolDef {
851 name: "session_get",
852 description: "Get information about an indexed session",
853 schema: r#"{
854 "type": "object",
855 "properties": {
856 "session_id": {"type": "string", "description": "Session ID to retrieve"}
857 },
858 "required": ["session_id"]
859 }"#,
860 annotations: ToolAnnotations::read_only(),
861 },
862 ToolDef {
863 name: "session_list",
864 description: "List indexed sessions with optional workspace filter",
865 schema: r#"{
866 "type": "object",
867 "properties": {
868 "workspace": {"type": "string", "description": "Filter by workspace"},
869 "limit": {"type": "integer", "default": 20, "description": "Maximum sessions to return"}
870 }
871 }"#,
872 annotations: ToolAnnotations::read_only(),
873 },
874 ToolDef {
875 name: "session_delete",
876 description: "Delete a session and all its indexed chunks",
877 schema: r#"{
878 "type": "object",
879 "properties": {
880 "session_id": {"type": "string", "description": "Session to delete"}
881 },
882 "required": ["session_id"]
883 }"#,
884 annotations: ToolAnnotations::destructive(),
885 },
886 ToolDef {
888 name: "identity_create",
889 description: "Create a new identity with canonical ID, display name, and optional aliases",
890 schema: r#"{
891 "type": "object",
892 "properties": {
893 "canonical_id": {"type": "string", "description": "Unique canonical identifier (e.g., 'user:ronaldo', 'org:acme')"},
894 "display_name": {"type": "string", "description": "Human-readable display name"},
895 "entity_type": {"type": "string", "enum": ["person", "organization", "project", "tool", "concept", "other"], "default": "person"},
896 "description": {"type": "string", "description": "Optional description"},
897 "aliases": {"type": "array", "items": {"type": "string"}, "description": "Initial aliases for this identity"},
898 "metadata": {"type": "object", "description": "Additional metadata"}
899 },
900 "required": ["canonical_id", "display_name"]
901 }"#,
902 annotations: ToolAnnotations::mutating(),
903 },
904 ToolDef {
905 name: "identity_get",
906 description: "Get an identity by its canonical ID",
907 schema: r#"{
908 "type": "object",
909 "properties": {
910 "canonical_id": {"type": "string", "description": "Canonical identifier"}
911 },
912 "required": ["canonical_id"]
913 }"#,
914 annotations: ToolAnnotations::read_only(),
915 },
916 ToolDef {
917 name: "identity_update",
918 description: "Update an identity's display name, description, or type",
919 schema: r#"{
920 "type": "object",
921 "properties": {
922 "canonical_id": {"type": "string", "description": "Canonical identifier"},
923 "display_name": {"type": "string", "description": "New display name"},
924 "description": {"type": "string", "description": "New description"},
925 "entity_type": {"type": "string", "enum": ["person", "organization", "project", "tool", "concept", "other"]}
926 },
927 "required": ["canonical_id"]
928 }"#,
929 annotations: ToolAnnotations::mutating(),
930 },
931 ToolDef {
932 name: "identity_delete",
933 description: "Delete an identity and all its aliases",
934 schema: r#"{
935 "type": "object",
936 "properties": {
937 "canonical_id": {"type": "string", "description": "Canonical identifier to delete"}
938 },
939 "required": ["canonical_id"]
940 }"#,
941 annotations: ToolAnnotations::destructive(),
942 },
943 ToolDef {
944 name: "identity_add_alias",
945 description: "Add an alias to an identity. Aliases are normalized (lowercase, trimmed). Conflicts with existing aliases are rejected.",
946 schema: r#"{
947 "type": "object",
948 "properties": {
949 "canonical_id": {"type": "string", "description": "Canonical identifier"},
950 "alias": {"type": "string", "description": "Alias to add"},
951 "source": {"type": "string", "description": "Optional source of the alias (e.g., 'manual', 'extracted')"}
952 },
953 "required": ["canonical_id", "alias"]
954 }"#,
955 annotations: ToolAnnotations::mutating(),
956 },
957 ToolDef {
958 name: "identity_remove_alias",
959 description: "Remove an alias from any identity",
960 schema: r#"{
961 "type": "object",
962 "properties": {
963 "alias": {"type": "string", "description": "Alias to remove"}
964 },
965 "required": ["alias"]
966 }"#,
967 annotations: ToolAnnotations::mutating(),
968 },
969 ToolDef {
970 name: "identity_resolve",
971 description: "Resolve an alias to its canonical identity. Returns the identity if found, null otherwise.",
972 schema: r#"{
973 "type": "object",
974 "properties": {
975 "alias": {"type": "string", "description": "Alias to resolve"}
976 },
977 "required": ["alias"]
978 }"#,
979 annotations: ToolAnnotations::read_only(),
980 },
981 ToolDef {
982 name: "identity_list",
983 description: "List all identities with optional type filter",
984 schema: r#"{
985 "type": "object",
986 "properties": {
987 "entity_type": {"type": "string", "enum": ["person", "organization", "project", "tool", "concept", "other"]},
988 "limit": {"type": "integer", "default": 50}
989 }
990 }"#,
991 annotations: ToolAnnotations::read_only(),
992 },
993 ToolDef {
994 name: "identity_search",
995 description: "Search identities by alias or display name",
996 schema: r#"{
997 "type": "object",
998 "properties": {
999 "query": {"type": "string", "description": "Search query"},
1000 "limit": {"type": "integer", "default": 20}
1001 },
1002 "required": ["query"]
1003 }"#,
1004 annotations: ToolAnnotations::read_only(),
1005 },
1006 ToolDef {
1007 name: "identity_link",
1008 description: "Link an identity to a memory (mark that the identity is mentioned in the memory)",
1009 schema: r#"{
1010 "type": "object",
1011 "properties": {
1012 "memory_id": {"type": "integer", "description": "Memory ID"},
1013 "canonical_id": {"type": "string", "description": "Identity canonical ID"},
1014 "mention_text": {"type": "string", "description": "The text that mentions this identity"}
1015 },
1016 "required": ["memory_id", "canonical_id"]
1017 }"#,
1018 annotations: ToolAnnotations::mutating(),
1019 },
1020 ToolDef {
1021 name: "identity_unlink",
1022 description: "Remove the link between an identity and a memory",
1023 schema: r#"{
1024 "type": "object",
1025 "properties": {
1026 "memory_id": {"type": "integer", "description": "Memory ID"},
1027 "canonical_id": {"type": "string", "description": "Identity canonical ID"}
1028 },
1029 "required": ["memory_id", "canonical_id"]
1030 }"#,
1031 annotations: ToolAnnotations::mutating(),
1032 },
1033 ToolDef {
1034 name: "memory_get_identities",
1035 description: "Get all identities (persons, organizations, projects, etc.) linked to a memory. Returns identity details including display name, type, aliases, and mention information.",
1036 schema: r#"{
1037 "type": "object",
1038 "properties": {
1039 "id": {"type": "integer", "description": "Memory ID"}
1040 },
1041 "required": ["id"]
1042 }"#,
1043 annotations: ToolAnnotations::read_only(),
1044 },
1045 ToolDef {
1047 name: "memory_soft_trim",
1048 description: "Intelligently trim memory content while preserving context. Keeps the beginning (head) and end (tail) of content with an ellipsis in the middle. Useful for displaying long content in limited space while keeping important context from both ends.",
1049 schema: r#"{
1050 "type": "object",
1051 "properties": {
1052 "id": {"type": "integer", "description": "Memory ID to trim"},
1053 "max_chars": {"type": "integer", "default": 500, "description": "Maximum characters for trimmed output"},
1054 "head_percent": {"type": "integer", "default": 60, "description": "Percentage of space for the head (0-100)"},
1055 "tail_percent": {"type": "integer", "default": 30, "description": "Percentage of space for the tail (0-100)"},
1056 "ellipsis": {"type": "string", "default": "\n...\n", "description": "Text to insert between head and tail"},
1057 "preserve_words": {"type": "boolean", "default": true, "description": "Avoid breaking in the middle of words"}
1058 },
1059 "required": ["id"]
1060 }"#,
1061 annotations: ToolAnnotations::read_only(),
1062 },
1063 ToolDef {
1064 name: "memory_list_compact",
1065 description: "List memories with compact preview instead of full content. More efficient for browsing/listing UIs. Returns only essential fields and a truncated content preview with metadata about original content length.",
1066 schema: r#"{
1067 "type": "object",
1068 "properties": {
1069 "limit": {"type": "integer", "default": 20, "description": "Maximum memories to return"},
1070 "offset": {"type": "integer", "default": 0, "description": "Pagination offset"},
1071 "tags": {"type": "array", "items": {"type": "string"}, "description": "Filter by tags"},
1072 "memory_type": {"type": "string", "description": "Filter by memory type (preferred field; alias: type)"},
1073 "type": {"type": "string", "description": "Deprecated alias for memory_type"},
1074 "workspace": {"type": "string", "description": "Filter by workspace"},
1075 "tier": {"type": "string", "enum": ["permanent", "daily"], "description": "Filter by tier"},
1076 "sort_by": {"type": "string", "enum": ["created_at", "updated_at", "last_accessed_at", "importance", "access_count"], "default": "created_at"},
1077 "sort_order": {"type": "string", "enum": ["asc", "desc"], "default": "desc"},
1078 "preview_chars": {"type": "integer", "default": 100, "description": "Maximum characters for content preview"}
1079 }
1080 }"#,
1081 annotations: ToolAnnotations::read_only(),
1082 },
1083 ToolDef {
1084 name: "memory_content_stats",
1085 description: "Get content statistics for a memory (character count, word count, line count, sentence count, paragraph count)",
1086 schema: r#"{
1087 "type": "object",
1088 "properties": {
1089 "id": {"type": "integer", "description": "Memory ID"}
1090 },
1091 "required": ["id"]
1092 }"#,
1093 annotations: ToolAnnotations::read_only(),
1094 },
1095 ToolDef {
1097 name: "memory_create_batch",
1098 description: "Create multiple memories in a single operation. More efficient than individual creates for bulk imports.",
1099 schema: r#"{
1100 "type": "object",
1101 "properties": {
1102 "memories": {
1103 "type": "array",
1104 "items": {
1105 "type": "object",
1106 "properties": {
1107 "content": {"type": "string"},
1108 "type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential"]},
1109 "tags": {"type": "array", "items": {"type": "string"}},
1110 "metadata": {"type": "object"},
1111 "importance": {"type": "number", "minimum": 0, "maximum": 1},
1112 "workspace": {"type": "string"}
1113 },
1114 "required": ["content"]
1115 },
1116 "description": "Array of memories to create"
1117 }
1118 },
1119 "required": ["memories"]
1120 }"#,
1121 annotations: ToolAnnotations::mutating(),
1122 },
1123 ToolDef {
1124 name: "memory_delete_batch",
1125 description: "Delete multiple memories in a single operation.",
1126 schema: r#"{
1127 "type": "object",
1128 "properties": {
1129 "ids": {
1130 "type": "array",
1131 "items": {"type": "integer"},
1132 "description": "Array of memory IDs to delete"
1133 }
1134 },
1135 "required": ["ids"]
1136 }"#,
1137 annotations: ToolAnnotations::destructive(),
1138 },
1139 ToolDef {
1141 name: "memory_tags",
1142 description: "List all tags with usage counts and most recent usage timestamps.",
1143 schema: r#"{
1144 "type": "object",
1145 "properties": {}
1146 }"#,
1147 annotations: ToolAnnotations::read_only(),
1148 },
1149 ToolDef {
1150 name: "memory_tag_hierarchy",
1151 description: "Get tags organized in a hierarchical tree structure. Tags with slashes are treated as paths (e.g., 'project/engram/core').",
1152 schema: r#"{
1153 "type": "object",
1154 "properties": {}
1155 }"#,
1156 annotations: ToolAnnotations::read_only(),
1157 },
1158 ToolDef {
1159 name: "memory_validate_tags",
1160 description: "Validate tag consistency across memories. Reports orphaned tags, unused tags, and suggested normalizations.",
1161 schema: r#"{
1162 "type": "object",
1163 "properties": {}
1164 }"#,
1165 annotations: ToolAnnotations::read_only(),
1166 },
1167 ToolDef {
1169 name: "memory_export",
1170 description: "Export all memories to a JSON-serializable format for backup or migration.",
1171 schema: r#"{
1172 "type": "object",
1173 "properties": {
1174 "workspace": {"type": "string", "description": "Optional: export only from specific workspace"},
1175 "include_embeddings": {"type": "boolean", "default": false, "description": "Include embedding vectors in export (larger file size)"}
1176 }
1177 }"#,
1178 annotations: ToolAnnotations::read_only(),
1179 },
1180 ToolDef {
1181 name: "memory_import",
1182 description: "Import memories from a previously exported JSON format.",
1183 schema: r#"{
1184 "type": "object",
1185 "properties": {
1186 "data": {"type": "object", "description": "The exported data object"},
1187 "skip_duplicates": {"type": "boolean", "default": true, "description": "Skip memories with matching content hash"}
1188 },
1189 "required": ["data"]
1190 }"#,
1191 annotations: ToolAnnotations::mutating(),
1192 },
1193 ToolDef {
1195 name: "memory_rebuild_embeddings",
1196 description: "Rebuild embeddings for all memories that are missing them. Useful after model changes or data recovery.",
1197 schema: r#"{
1198 "type": "object",
1199 "properties": {}
1200 }"#,
1201 annotations: ToolAnnotations::idempotent(),
1202 },
1203 ToolDef {
1204 name: "memory_rebuild_crossrefs",
1205 description: "Rebuild cross-reference links between memories. Re-analyzes all memories to find and create links.",
1206 schema: r#"{
1207 "type": "object",
1208 "properties": {}
1209 }"#,
1210 annotations: ToolAnnotations::idempotent(),
1211 },
1212 ToolDef {
1214 name: "memory_create_section",
1215 description: "Create a section memory for organizing content hierarchically. Sections can have parent sections for nested organization.",
1216 schema: r#"{
1217 "type": "object",
1218 "properties": {
1219 "title": {"type": "string", "description": "Section title"},
1220 "content": {"type": "string", "description": "Section description or content"},
1221 "parent_id": {"type": "integer", "description": "Optional parent section ID for nesting"},
1222 "level": {"type": "integer", "default": 1, "description": "Heading level (1-6)"},
1223 "workspace": {"type": "string", "description": "Workspace for the section"}
1224 },
1225 "required": ["title"]
1226 }"#,
1227 annotations: ToolAnnotations::mutating(),
1228 },
1229 ToolDef {
1230 name: "memory_checkpoint",
1231 description: "Create a checkpoint memory marking a significant point in a session. Useful for session resumption and context restoration.",
1232 schema: r#"{
1233 "type": "object",
1234 "properties": {
1235 "session_id": {"type": "string", "description": "Session identifier"},
1236 "summary": {"type": "string", "description": "Summary of session state at checkpoint"},
1237 "context": {"type": "object", "description": "Additional context data to preserve"},
1238 "workspace": {"type": "string", "description": "Workspace for the checkpoint"}
1239 },
1240 "required": ["session_id", "summary"]
1241 }"#,
1242 annotations: ToolAnnotations::mutating(),
1243 },
1244 ToolDef {
1246 name: "memory_create_episodic",
1247 description: "Create an episodic memory representing an event with temporal context. Use for tracking when things happened and their duration.",
1248 schema: r#"{
1249 "type": "object",
1250 "properties": {
1251 "content": {"type": "string", "description": "Description of the event"},
1252 "event_time": {"type": "string", "format": "date-time", "description": "ISO8601 timestamp when the event occurred"},
1253 "event_duration_seconds": {"type": "integer", "description": "Duration of the event in seconds"},
1254 "tags": {"type": "array", "items": {"type": "string"}, "description": "Tags for categorization"},
1255 "metadata": {"type": "object", "description": "Additional metadata"},
1256 "importance": {"type": "number", "minimum": 0, "maximum": 1, "description": "Importance score (0-1)"},
1257 "workspace": {"type": "string", "description": "Workspace (default: 'default')"}
1258 },
1259 "required": ["content", "event_time"]
1260 }"#,
1261 annotations: ToolAnnotations::mutating(),
1262 },
1263 ToolDef {
1264 name: "memory_create_procedural",
1265 description: "Create a procedural memory representing a learned pattern or workflow. Tracks success/failure to measure effectiveness.",
1266 schema: r#"{
1267 "type": "object",
1268 "properties": {
1269 "content": {"type": "string", "description": "Description of the procedure/workflow"},
1270 "trigger_pattern": {"type": "string", "description": "Pattern that triggers this procedure (e.g., 'When user asks about auth')"},
1271 "tags": {"type": "array", "items": {"type": "string"}, "description": "Tags for categorization"},
1272 "metadata": {"type": "object", "description": "Additional metadata"},
1273 "importance": {"type": "number", "minimum": 0, "maximum": 1, "description": "Importance score (0-1)"},
1274 "workspace": {"type": "string", "description": "Workspace (default: 'default')"}
1275 },
1276 "required": ["content", "trigger_pattern"]
1277 }"#,
1278 annotations: ToolAnnotations::mutating(),
1279 },
1280 ToolDef {
1281 name: "memory_get_timeline",
1282 description: "Query episodic memories by time range. Returns events ordered by event_time.",
1283 schema: r#"{
1284 "type": "object",
1285 "properties": {
1286 "start_time": {"type": "string", "format": "date-time", "description": "Start of time range (ISO8601)"},
1287 "end_time": {"type": "string", "format": "date-time", "description": "End of time range (ISO8601)"},
1288 "workspace": {"type": "string", "description": "Filter by workspace"},
1289 "tags": {"type": "array", "items": {"type": "string"}, "description": "Filter by tags"},
1290 "limit": {"type": "integer", "default": 50, "description": "Maximum results to return"}
1291 }
1292 }"#,
1293 annotations: ToolAnnotations::read_only(),
1294 },
1295 ToolDef {
1296 name: "memory_get_procedures",
1297 description: "List procedural memories (learned patterns/workflows). Optionally filter by trigger pattern.",
1298 schema: r#"{
1299 "type": "object",
1300 "properties": {
1301 "trigger_pattern": {"type": "string", "description": "Filter by trigger pattern (partial match)"},
1302 "workspace": {"type": "string", "description": "Filter by workspace"},
1303 "min_success_rate": {"type": "number", "minimum": 0, "maximum": 1, "description": "Minimum success rate (successes / (successes + failures))"},
1304 "limit": {"type": "integer", "default": 50, "description": "Maximum results to return"}
1305 }
1306 }"#,
1307 annotations: ToolAnnotations::read_only(),
1308 },
1309 ToolDef {
1310 name: "memory_record_procedure_outcome",
1311 description: "Record a success or failure for a procedural memory. Increments the corresponding counter.",
1312 schema: r#"{
1313 "type": "object",
1314 "properties": {
1315 "id": {"type": "integer", "description": "Procedural memory ID"},
1316 "success": {"type": "boolean", "description": "true = success, false = failure"}
1317 },
1318 "required": ["id", "success"]
1319 }"#,
1320 annotations: ToolAnnotations::mutating(),
1321 },
1322 ToolDef {
1323 name: "memory_boost",
1324 description: "Temporarily boost a memory's importance score. The boost can optionally decay over time.",
1325 schema: r#"{
1326 "type": "object",
1327 "properties": {
1328 "id": {"type": "integer", "description": "Memory ID to boost"},
1329 "boost_amount": {"type": "number", "default": 0.2, "description": "Amount to increase importance (0-1)"},
1330 "duration_seconds": {"type": "integer", "description": "Optional: duration before boost decays (omit for permanent boost)"}
1331 },
1332 "required": ["id"]
1333 }"#,
1334 annotations: ToolAnnotations::mutating(),
1335 },
1336 ToolDef {
1338 name: "memory_summarize",
1339 description: "Create a summary of one or more memories. Returns a new Summary-type memory with summary_of_id set.",
1340 schema: r#"{
1341 "type": "object",
1342 "properties": {
1343 "memory_ids": {
1344 "type": "array",
1345 "items": {"type": "integer"},
1346 "description": "IDs of memories to summarize"
1347 },
1348 "summary": {"type": "string", "description": "The summary text (provide this or let the system generate one)"},
1349 "max_length": {"type": "integer", "default": 500, "description": "Maximum length for auto-generated summary"},
1350 "workspace": {"type": "string", "description": "Workspace for the summary memory"},
1351 "tags": {"type": "array", "items": {"type": "string"}, "description": "Tags for the summary memory"}
1352 },
1353 "required": ["memory_ids"]
1354 }"#,
1355 annotations: ToolAnnotations::mutating(),
1356 },
1357 ToolDef {
1358 name: "memory_get_full",
1359 description: "Get the full/original content of a memory. If the memory is a Summary, returns the original content from summary_of_id.",
1360 schema: r#"{
1361 "type": "object",
1362 "properties": {
1363 "id": {"type": "integer", "description": "Memory ID to get full content for"}
1364 },
1365 "required": ["id"]
1366 }"#,
1367 annotations: ToolAnnotations::read_only(),
1368 },
1369 ToolDef {
1370 name: "context_budget_check",
1371 description: "Check token usage of memories against a budget. Returns token counts and suggestions if over budget.",
1372 schema: r#"{
1373 "type": "object",
1374 "properties": {
1375 "memory_ids": {
1376 "type": "array",
1377 "items": {"type": "integer"},
1378 "description": "IDs of memories to check"
1379 },
1380 "model": {
1381 "type": "string",
1382 "description": "Model name for tokenization (gpt-4, gpt-4o, gpt-4o-mini, claude-3-opus, etc.)"
1383 },
1384 "encoding": {
1385 "type": "string",
1386 "description": "Override encoding (cl100k_base, o200k_base). Optional if model is known."
1387 },
1388 "budget": {"type": "integer", "description": "Token budget to check against"}
1389 },
1390 "required": ["memory_ids", "model", "budget"]
1391 }"#,
1392 annotations: ToolAnnotations::read_only(),
1393 },
1394 ToolDef {
1395 name: "memory_archive_old",
1396 description: "Archive old, low-importance memories by creating summaries. Moves originals to archived state.",
1397 schema: r#"{
1398 "type": "object",
1399 "properties": {
1400 "max_age_days": {"type": "integer", "default": 90, "description": "Archive memories older than this many days"},
1401 "max_importance": {"type": "number", "default": 0.5, "description": "Only archive memories with importance below this"},
1402 "min_access_count": {"type": "integer", "default": 5, "description": "Skip memories accessed more than this many times"},
1403 "workspace": {"type": "string", "description": "Limit to specific workspace"},
1404 "dry_run": {"type": "boolean", "default": true, "description": "If true, only report what would be archived"}
1405 }
1406 }"#,
1407 annotations: ToolAnnotations::destructive(),
1408 },
1409 #[cfg(feature = "langfuse")]
1411 ToolDef {
1412 name: "langfuse_connect",
1413 description: "Configure Langfuse connection for observability integration. Stores config in metadata.",
1414 schema: r#"{
1415 "type": "object",
1416 "properties": {
1417 "public_key": {"type": "string", "description": "Langfuse public key (or use LANGFUSE_PUBLIC_KEY env var)"},
1418 "secret_key": {"type": "string", "description": "Langfuse secret key (or use LANGFUSE_SECRET_KEY env var)"},
1419 "base_url": {"type": "string", "default": "https://cloud.langfuse.com", "description": "Langfuse API base URL"}
1420 }
1421 }"#,
1422 annotations: ToolAnnotations::mutating(),
1423 },
1424 #[cfg(feature = "langfuse")]
1425 ToolDef {
1426 name: "langfuse_sync",
1427 description: "Start background sync from Langfuse traces to memories. Returns task_id for status checking.",
1428 schema: r#"{
1429 "type": "object",
1430 "properties": {
1431 "since": {"type": "string", "format": "date-time", "description": "Sync traces since this timestamp (default: 24h ago)"},
1432 "limit": {"type": "integer", "default": 100, "description": "Maximum traces to sync"},
1433 "workspace": {"type": "string", "description": "Workspace to create memories in"},
1434 "dry_run": {"type": "boolean", "default": false, "description": "Preview what would be synced without creating memories"}
1435 }
1436 }"#,
1437 annotations: ToolAnnotations::mutating(),
1438 },
1439 #[cfg(feature = "langfuse")]
1440 ToolDef {
1441 name: "langfuse_sync_status",
1442 description: "Check the status of a Langfuse sync task.",
1443 schema: r#"{
1444 "type": "object",
1445 "properties": {
1446 "task_id": {"type": "string", "description": "Task ID returned from langfuse_sync"}
1447 },
1448 "required": ["task_id"]
1449 }"#,
1450 annotations: ToolAnnotations::read_only(),
1451 },
1452 #[cfg(feature = "langfuse")]
1453 ToolDef {
1454 name: "langfuse_extract_patterns",
1455 description: "Extract patterns from Langfuse traces without saving. Preview mode for pattern discovery.",
1456 schema: r#"{
1457 "type": "object",
1458 "properties": {
1459 "since": {"type": "string", "format": "date-time", "description": "Analyze traces since this timestamp"},
1460 "limit": {"type": "integer", "default": 50, "description": "Maximum traces to analyze"},
1461 "min_confidence": {"type": "number", "default": 0.7, "description": "Minimum confidence for patterns"}
1462 }
1463 }"#,
1464 annotations: ToolAnnotations::read_only(),
1465 },
1466 #[cfg(feature = "langfuse")]
1467 ToolDef {
1468 name: "memory_from_trace",
1469 description: "Create a memory from a specific Langfuse trace ID.",
1470 schema: r#"{
1471 "type": "object",
1472 "properties": {
1473 "trace_id": {"type": "string", "description": "Langfuse trace ID"},
1474 "memory_type": {"type": "string", "enum": ["note", "episodic", "procedural", "learning"], "default": "episodic", "description": "Type of memory to create"},
1475 "workspace": {"type": "string", "description": "Workspace for the memory"},
1476 "tags": {"type": "array", "items": {"type": "string"}, "description": "Additional tags"}
1477 },
1478 "required": ["trace_id"]
1479 }"#,
1480 annotations: ToolAnnotations::mutating(),
1481 },
1482 ToolDef {
1484 name: "search_cache_feedback",
1485 description: "Report feedback on search results quality. Helps tune the adaptive cache threshold.",
1486 schema: r#"{
1487 "type": "object",
1488 "properties": {
1489 "query": {"type": "string", "description": "The search query"},
1490 "positive": {"type": "boolean", "description": "True if results were helpful, false otherwise"},
1491 "workspace": {"type": "string", "description": "Workspace filter used (if any)"}
1492 },
1493 "required": ["query", "positive"]
1494 }"#,
1495 annotations: ToolAnnotations::mutating(),
1496 },
1497 ToolDef {
1498 name: "search_cache_stats",
1499 description: "Get search result cache statistics including hit rate, entry count, and current threshold.",
1500 schema: r#"{
1501 "type": "object",
1502 "properties": {}
1503 }"#,
1504 annotations: ToolAnnotations::read_only(),
1505 },
1506 ToolDef {
1507 name: "search_cache_clear",
1508 description: "Clear the search result cache. Useful after bulk operations.",
1509 schema: r#"{
1510 "type": "object",
1511 "properties": {
1512 "workspace": {"type": "string", "description": "Only clear cache for this workspace (optional)"}
1513 }
1514 }"#,
1515 annotations: ToolAnnotations::destructive(),
1516 },
1517 ToolDef {
1519 name: "lifecycle_status",
1520 description: "Get lifecycle statistics (active/stale/archived counts by workspace).",
1521 schema: r#"{
1522 "type": "object",
1523 "properties": {
1524 "workspace": {"type": "string", "description": "Filter by workspace (optional)"}
1525 }
1526 }"#,
1527 annotations: ToolAnnotations::read_only(),
1528 },
1529 ToolDef {
1530 name: "lifecycle_run",
1531 description: "Manually trigger a lifecycle cycle (mark stale, archive old). Dry run by default.",
1532 schema: r#"{
1533 "type": "object",
1534 "properties": {
1535 "dry_run": {"type": "boolean", "default": true, "description": "Preview changes without applying"},
1536 "workspace": {"type": "string", "description": "Limit to specific workspace"},
1537 "stale_days": {"type": "integer", "default": 30, "description": "Mark memories older than this as stale"},
1538 "archive_days": {"type": "integer", "default": 90, "description": "Archive memories older than this"},
1539 "min_importance": {"type": "number", "default": 0.5, "description": "Only process memories below this importance"}
1540 }
1541 }"#,
1542 annotations: ToolAnnotations::idempotent(),
1543 },
1544 ToolDef {
1545 name: "memory_set_lifecycle",
1546 description: "Manually set the lifecycle state of a memory.",
1547 schema: r#"{
1548 "type": "object",
1549 "properties": {
1550 "id": {"type": "integer", "description": "Memory ID"},
1551 "state": {"type": "string", "enum": ["active", "stale", "archived"], "description": "New lifecycle state"}
1552 },
1553 "required": ["id", "state"]
1554 }"#,
1555 annotations: ToolAnnotations::mutating(),
1556 },
1557 ToolDef {
1558 name: "lifecycle_config",
1559 description: "Get or set lifecycle configuration (intervals, thresholds).",
1560 schema: r#"{
1561 "type": "object",
1562 "properties": {
1563 "stale_days": {"type": "integer", "description": "Days before marking as stale"},
1564 "archive_days": {"type": "integer", "description": "Days before auto-archiving"},
1565 "min_importance": {"type": "number", "description": "Importance threshold for lifecycle"},
1566 "min_access_count": {"type": "integer", "description": "Access count threshold"}
1567 }
1568 }"#,
1569 annotations: ToolAnnotations::read_only(),
1570 },
1571 ToolDef {
1573 name: "retention_policy_set",
1574 description: "Set a retention policy for a workspace. Controls auto-compression, max memory count, and auto-deletion.",
1575 schema: r#"{
1576 "type": "object",
1577 "properties": {
1578 "workspace": {"type": "string", "description": "Workspace name"},
1579 "max_age_days": {"type": "integer", "description": "Hard age limit — auto-delete after this many days"},
1580 "max_memories": {"type": "integer", "description": "Maximum active memories in this workspace"},
1581 "compress_after_days": {"type": "integer", "description": "Auto-compress memories older than this"},
1582 "compress_max_importance": {"type": "number", "description": "Only compress memories with importance <= this (default 0.3)"},
1583 "compress_min_access": {"type": "integer", "description": "Skip compression if access_count >= this (default 3)"},
1584 "auto_delete_after_days": {"type": "integer", "description": "Auto-delete archived memories older than this"},
1585 "exclude_types": {"type": "array", "items": {"type": "string"}, "description": "Memory types exempt from policy (e.g. [\"decision\", \"checkpoint\"])"}
1586 },
1587 "required": ["workspace"]
1588 }"#,
1589 annotations: ToolAnnotations::mutating(),
1590 },
1591 ToolDef {
1592 name: "retention_policy_get",
1593 description: "Get the retention policy for a workspace.",
1594 schema: r#"{
1595 "type": "object",
1596 "properties": {
1597 "workspace": {"type": "string", "description": "Workspace name"}
1598 },
1599 "required": ["workspace"]
1600 }"#,
1601 annotations: ToolAnnotations::read_only(),
1602 },
1603 ToolDef {
1604 name: "retention_policy_list",
1605 description: "List all retention policies across all workspaces.",
1606 schema: r#"{
1607 "type": "object",
1608 "properties": {}
1609 }"#,
1610 annotations: ToolAnnotations::read_only(),
1611 },
1612 ToolDef {
1613 name: "retention_policy_delete",
1614 description: "Delete a retention policy for a workspace.",
1615 schema: r#"{
1616 "type": "object",
1617 "properties": {
1618 "workspace": {"type": "string", "description": "Workspace name"}
1619 },
1620 "required": ["workspace"]
1621 }"#,
1622 annotations: ToolAnnotations::destructive(),
1623 },
1624 ToolDef {
1625 name: "retention_policy_apply",
1626 description: "Apply all retention policies now. Compresses, caps, and deletes per workspace rules.",
1627 schema: r#"{
1628 "type": "object",
1629 "properties": {
1630 "dry_run": {"type": "boolean", "default": false, "description": "Preview what would happen without making changes"}
1631 }
1632 }"#,
1633 annotations: ToolAnnotations::idempotent(),
1634 },
1635 ToolDef {
1637 name: "memory_events_poll",
1638 description: "Poll for memory events (create, update, delete, etc.) since a given point. Useful for syncing and monitoring.",
1639 schema: r#"{
1640 "type": "object",
1641 "properties": {
1642 "since_id": {"type": "integer", "description": "Return events after this event ID"},
1643 "since_time": {"type": "string", "format": "date-time", "description": "Return events after this timestamp (RFC3339)"},
1644 "agent_id": {"type": "string", "description": "Filter events for specific agent"},
1645 "limit": {"type": "integer", "default": 100, "description": "Maximum events to return"}
1646 }
1647 }"#,
1648 annotations: ToolAnnotations::read_only(),
1649 },
1650 ToolDef {
1651 name: "memory_events_clear",
1652 description: "Clear old events from the event log. Helps manage storage for long-running systems.",
1653 schema: r#"{
1654 "type": "object",
1655 "properties": {
1656 "before_id": {"type": "integer", "description": "Delete events before this ID"},
1657 "before_time": {"type": "string", "format": "date-time", "description": "Delete events before this timestamp"},
1658 "keep_recent": {"type": "integer", "description": "Keep only the N most recent events"}
1659 }
1660 }"#,
1661 annotations: ToolAnnotations::destructive(),
1662 },
1663 ToolDef {
1665 name: "sync_version",
1666 description: "Get the current sync version and metadata. Used to check if local data is up-to-date.",
1667 schema: r#"{
1668 "type": "object",
1669 "properties": {}
1670 }"#,
1671 annotations: ToolAnnotations::read_only(),
1672 },
1673 ToolDef {
1674 name: "sync_delta",
1675 description: "Get changes (delta) since a specific version. Returns created, updated, and deleted memories.",
1676 schema: r#"{
1677 "type": "object",
1678 "properties": {
1679 "since_version": {"type": "integer", "description": "Version to get changes from"}
1680 },
1681 "required": ["since_version"]
1682 }"#,
1683 annotations: ToolAnnotations::read_only(),
1684 },
1685 ToolDef {
1686 name: "sync_state",
1687 description: "Get or update sync state for a specific agent. Tracks what each agent has synced.",
1688 schema: r#"{
1689 "type": "object",
1690 "properties": {
1691 "agent_id": {"type": "string", "description": "Agent identifier"},
1692 "update_version": {"type": "integer", "description": "If provided, updates the agent's last synced version"}
1693 },
1694 "required": ["agent_id"]
1695 }"#,
1696 annotations: ToolAnnotations::read_only(),
1697 },
1698 ToolDef {
1699 name: "sync_cleanup",
1700 description: "Clean up old sync data (events, etc.) older than specified days.",
1701 schema: r#"{
1702 "type": "object",
1703 "properties": {
1704 "older_than_days": {"type": "integer", "default": 30, "description": "Delete sync data older than this many days"}
1705 }
1706 }"#,
1707 annotations: ToolAnnotations::destructive(),
1708 },
1709 ToolDef {
1711 name: "memory_share",
1712 description: "Share a memory with another agent. The target agent can poll for shared memories.",
1713 schema: r#"{
1714 "type": "object",
1715 "properties": {
1716 "memory_id": {"type": "integer", "description": "ID of memory to share"},
1717 "from_agent": {"type": "string", "description": "Sender agent identifier"},
1718 "to_agent": {"type": "string", "description": "Recipient agent identifier"},
1719 "message": {"type": "string", "description": "Optional message to include with share"}
1720 },
1721 "required": ["memory_id", "from_agent", "to_agent"]
1722 }"#,
1723 annotations: ToolAnnotations::mutating(),
1724 },
1725 ToolDef {
1726 name: "memory_shared_poll",
1727 description: "Poll for memories shared with this agent.",
1728 schema: r#"{
1729 "type": "object",
1730 "properties": {
1731 "agent_id": {"type": "string", "description": "Agent identifier to check shares for"},
1732 "include_acknowledged": {"type": "boolean", "default": false, "description": "Include already acknowledged shares"}
1733 },
1734 "required": ["agent_id"]
1735 }"#,
1736 annotations: ToolAnnotations::read_only(),
1737 },
1738 ToolDef {
1739 name: "memory_share_ack",
1740 description: "Acknowledge receipt of a shared memory.",
1741 schema: r#"{
1742 "type": "object",
1743 "properties": {
1744 "share_id": {"type": "integer", "description": "Share ID to acknowledge"},
1745 "agent_id": {"type": "string", "description": "Agent acknowledging the share"}
1746 },
1747 "required": ["share_id", "agent_id"]
1748 }"#,
1749 annotations: ToolAnnotations::mutating(),
1750 },
1751 ToolDef {
1753 name: "memory_grant_access",
1754 description: "Grant an agent access to a scope path. Supports read, write, and admin permissions. Access also applies to all descendant scopes.",
1755 schema: r#"{
1756 "type": "object",
1757 "properties": {
1758 "agent_id": {"type": "string", "description": "Agent ID to grant access to"},
1759 "scope_path": {"type": "string", "description": "Scope path to grant access to (e.g. 'global/org:acme')"},
1760 "permissions": {"type": "string", "enum": ["read", "write", "admin"], "default": "read", "description": "Permission level"},
1761 "granted_by": {"type": "string", "description": "Optional: ID of the granting agent"}
1762 },
1763 "required": ["agent_id", "scope_path"]
1764 }"#,
1765 annotations: ToolAnnotations::mutating(),
1766 },
1767 ToolDef {
1768 name: "memory_revoke_access",
1769 description: "Revoke an agent's access to a specific scope path.",
1770 schema: r#"{
1771 "type": "object",
1772 "properties": {
1773 "agent_id": {"type": "string", "description": "Agent ID to revoke access from"},
1774 "scope_path": {"type": "string", "description": "Scope path to revoke access from"}
1775 },
1776 "required": ["agent_id", "scope_path"]
1777 }"#,
1778 annotations: ToolAnnotations::destructive(),
1779 },
1780 ToolDef {
1781 name: "memory_list_grants",
1782 description: "List all scope access grants for a given agent.",
1783 schema: r#"{
1784 "type": "object",
1785 "properties": {
1786 "agent_id": {"type": "string", "description": "Agent ID to list grants for"}
1787 },
1788 "required": ["agent_id"]
1789 }"#,
1790 annotations: ToolAnnotations::read_only(),
1791 },
1792 ToolDef {
1793 name: "memory_check_access",
1794 description: "Check whether an agent has a required permission level on a scope path (including ancestor grants).",
1795 schema: r#"{
1796 "type": "object",
1797 "properties": {
1798 "agent_id": {"type": "string", "description": "Agent ID to check"},
1799 "scope_path": {"type": "string", "description": "Scope path to check access for"},
1800 "permissions": {"type": "string", "enum": ["read", "write", "admin"], "default": "read", "description": "Required permission level"}
1801 },
1802 "required": ["agent_id", "scope_path"]
1803 }"#,
1804 annotations: ToolAnnotations::read_only(),
1805 },
1806 ToolDef {
1808 name: "memory_search_by_identity",
1809 description: "Search memories by identity (person, entity, or alias). Finds all mentions of a specific identity across memories.",
1810 schema: r#"{
1811 "type": "object",
1812 "properties": {
1813 "identity": {"type": "string", "description": "Identity name or alias to search for"},
1814 "workspace": {"type": "string", "description": "Optional: limit search to specific workspace"},
1815 "limit": {"type": "integer", "default": 50, "description": "Maximum results to return"}
1816 },
1817 "required": ["identity"]
1818 }"#,
1819 annotations: ToolAnnotations::mutating(),
1820 },
1821 ToolDef {
1822 name: "memory_session_search",
1823 description: "Search within session transcript chunks. Useful for finding content from past conversations.",
1824 schema: r#"{
1825 "type": "object",
1826 "properties": {
1827 "query": {"type": "string", "description": "Search query"},
1828 "session_id": {"type": "string", "description": "Optional: limit to specific session"},
1829 "workspace": {"type": "string", "description": "Optional: limit to specific workspace"},
1830 "limit": {"type": "integer", "default": 20, "description": "Maximum results to return"}
1831 },
1832 "required": ["query"]
1833 }"#,
1834 annotations: ToolAnnotations::mutating(),
1835 },
1836 ToolDef {
1838 name: "memory_upload_image",
1839 description: "Upload an image file and attach it to a memory. The image will be stored locally and linked to the memory's metadata.",
1840 schema: r#"{
1841 "type": "object",
1842 "properties": {
1843 "memory_id": {"type": "integer", "description": "ID of the memory to attach the image to"},
1844 "file_path": {"type": "string", "description": "Path to the image file to upload"},
1845 "image_index": {"type": "integer", "default": 0, "description": "Index for ordering multiple images (0-based)"},
1846 "caption": {"type": "string", "description": "Optional caption for the image"}
1847 },
1848 "required": ["memory_id", "file_path"]
1849 }"#,
1850 annotations: ToolAnnotations::mutating(),
1851 },
1852 ToolDef {
1853 name: "memory_migrate_images",
1854 description: "Migrate existing base64-encoded images in memories to file storage. Scans all memories and uploads any embedded data URIs to storage, replacing them with file references.",
1855 schema: r#"{
1856 "type": "object",
1857 "properties": {
1858 "dry_run": {"type": "boolean", "default": false, "description": "If true, only report what would be migrated without making changes"}
1859 }
1860 }"#,
1861 annotations: ToolAnnotations::idempotent(),
1862 },
1863 ToolDef {
1865 name: "memory_suggest_tags",
1866 description: "Suggest tags for a memory based on AI content analysis. Uses pattern matching, keyword extraction, and structure detection to suggest relevant tags with confidence scores.",
1867 schema: r#"{
1868 "type": "object",
1869 "properties": {
1870 "id": {"type": "integer", "description": "Memory ID to analyze (alternative to content)"},
1871 "memory_id": {"type": "integer", "description": "Memory ID to analyze (alias for id)"},
1872 "content": {"type": "string", "description": "Content to analyze (alternative to id/memory_id)"},
1873 "type": {"type": "string", "enum": ["note", "todo", "issue", "decision", "preference", "learning", "context", "credential"], "description": "Memory type (used when providing content directly)"},
1874 "existing_tags": {"type": "array", "items": {"type": "string"}, "description": "Tags already on the memory (excluded from suggestions)"},
1875 "min_confidence": {"type": "number", "minimum": 0, "maximum": 1, "default": 0.5, "description": "Minimum confidence threshold for suggestions"},
1876 "max_tags": {"type": "integer", "default": 5, "description": "Maximum number of tags to suggest"},
1877 "enable_patterns": {"type": "boolean", "default": true, "description": "Use pattern-based tagging"},
1878 "enable_keywords": {"type": "boolean", "default": true, "description": "Use keyword-based tagging"},
1879 "enable_entities": {"type": "boolean", "default": true, "description": "Use entity-based tagging"},
1880 "enable_type_tags": {"type": "boolean", "default": true, "description": "Add tags based on memory type"},
1881 "keyword_mappings": {"type": "object", "description": "Custom keyword-to-tag mappings (e.g., {\"ibvi\": \"project/ibvi\"})"}
1882 }
1883 }"#,
1884 annotations: ToolAnnotations::read_only(),
1885 },
1886 ToolDef {
1887 name: "memory_auto_tag",
1888 description: "Automatically suggest and optionally apply tags to a memory. Analyzes content using AI heuristics and can merge suggested tags with existing ones.",
1889 schema: r#"{
1890 "type": "object",
1891 "properties": {
1892 "id": {"type": "integer", "description": "Memory ID to auto-tag"},
1893 "memory_id": {"type": "integer", "description": "Memory ID (alias for id)"},
1894 "apply": {"type": "boolean", "default": false, "description": "If true, apply the suggested tags to the memory. If false, only return suggestions."},
1895 "merge": {"type": "boolean", "default": true, "description": "If true and apply=true, merge with existing tags. If false, replace existing tags."},
1896 "min_confidence": {"type": "number", "minimum": 0, "maximum": 1, "default": 0.5, "description": "Minimum confidence threshold"},
1897 "max_tags": {"type": "integer", "default": 5, "description": "Maximum tags to suggest/apply"},
1898 "keyword_mappings": {"type": "object", "description": "Custom keyword-to-tag mappings"}
1899 },
1900 "required": ["id"]
1901 }"#,
1902 annotations: ToolAnnotations::mutating(),
1903 },
1904 ToolDef {
1906 name: "salience_get",
1907 description: "Get the salience score for a memory. Returns recency, frequency, importance, and feedback components with the combined score and lifecycle state.",
1908 schema: r#"{
1909 "type": "object",
1910 "properties": {
1911 "id": {"type": "integer", "description": "Memory ID to get salience for"},
1912 "feedback_signal": {"type": "number", "minimum": -1, "maximum": 1, "default": 0, "description": "Optional feedback signal (-1 to 1) to include in calculation"}
1913 },
1914 "required": ["id"]
1915 }"#,
1916 annotations: ToolAnnotations::read_only(),
1917 },
1918 ToolDef {
1919 name: "salience_set_importance",
1920 description: "Set the importance score for a memory. This is the static importance component of salience.",
1921 schema: r#"{
1922 "type": "object",
1923 "properties": {
1924 "id": {"type": "integer", "description": "Memory ID"},
1925 "importance": {"type": "number", "minimum": 0, "maximum": 1, "description": "Importance score (0-1)"}
1926 },
1927 "required": ["id", "importance"]
1928 }"#,
1929 annotations: ToolAnnotations::mutating(),
1930 },
1931 ToolDef {
1932 name: "salience_boost",
1933 description: "Boost a memory's salience score temporarily or permanently. Useful for marking memories as contextually relevant.",
1934 schema: r#"{
1935 "type": "object",
1936 "properties": {
1937 "id": {"type": "integer", "description": "Memory ID to boost"},
1938 "boost_amount": {"type": "number", "minimum": 0, "maximum": 1, "default": 0.2, "description": "Amount to boost (0-1)"},
1939 "reason": {"type": "string", "description": "Optional reason for boosting"}
1940 },
1941 "required": ["id"]
1942 }"#,
1943 annotations: ToolAnnotations::mutating(),
1944 },
1945 ToolDef {
1946 name: "salience_demote",
1947 description: "Demote a memory's salience score. Useful for marking memories as less relevant.",
1948 schema: r#"{
1949 "type": "object",
1950 "properties": {
1951 "id": {"type": "integer", "description": "Memory ID to demote"},
1952 "demote_amount": {"type": "number", "minimum": 0, "maximum": 1, "default": 0.2, "description": "Amount to demote (0-1)"},
1953 "reason": {"type": "string", "description": "Optional reason for demoting"}
1954 },
1955 "required": ["id"]
1956 }"#,
1957 annotations: ToolAnnotations::mutating(),
1958 },
1959 ToolDef {
1960 name: "salience_decay_run",
1961 description: "Run temporal decay on all memories. Updates lifecycle states (Active → Stale → Archived) based on salience scores.",
1962 schema: r#"{
1963 "type": "object",
1964 "properties": {
1965 "dry_run": {"type": "boolean", "default": false, "description": "If true, compute changes without persisting updates"},
1966 "record_history": {"type": "boolean", "default": true, "description": "Record salience history entries while updating"},
1967 "workspace": {"type": "string", "description": "Limit to specific workspace"},
1968 "stale_threshold_days": {"type": "integer", "minimum": 1, "description": "Days of inactivity before marking stale"},
1969 "archive_threshold_days": {"type": "integer", "minimum": 1, "description": "Days of inactivity before suggesting archive"}
1970 }
1971 }"#,
1972 annotations: ToolAnnotations::destructive(),
1973 },
1974 ToolDef {
1975 name: "salience_stats",
1976 description: "Get salience statistics across all memories. Returns distribution, percentiles, and state counts.",
1977 schema: r#"{
1978 "type": "object",
1979 "properties": {
1980 "workspace": {"type": "string", "description": "Limit to specific workspace"}
1981 }
1982 }"#,
1983 annotations: ToolAnnotations::read_only(),
1984 },
1985 ToolDef {
1986 name: "salience_history",
1987 description: "Get salience score history for a memory. Shows how salience has changed over time.",
1988 schema: r#"{
1989 "type": "object",
1990 "properties": {
1991 "id": {"type": "integer", "description": "Memory ID"},
1992 "limit": {"type": "integer", "default": 50, "description": "Maximum history entries to return"}
1993 },
1994 "required": ["id"]
1995 }"#,
1996 annotations: ToolAnnotations::read_only(),
1997 },
1998 ToolDef {
1999 name: "salience_top",
2000 description: "Get top memories by salience score. Useful for context injection.",
2001 schema: r#"{
2002 "type": "object",
2003 "properties": {
2004 "limit": {"type": "integer", "default": 20, "description": "Maximum memories to return"},
2005 "workspace": {"type": "string", "description": "Limit to specific workspace"},
2006 "min_score": {"type": "number", "minimum": 0, "maximum": 1, "description": "Minimum salience score"},
2007 "memory_type": {"type": "string", "description": "Filter by memory type"}
2008 }
2009 }"#,
2010 annotations: ToolAnnotations::read_only(),
2011 },
2012 ToolDef {
2014 name: "session_context_create",
2015 description: "Create a new session context for tracking related memories during a conversation or task.",
2016 schema: r#"{
2017 "type": "object",
2018 "properties": {
2019 "name": {"type": "string", "description": "Session name"},
2020 "description": {"type": "string", "description": "Session description"},
2021 "workspace": {"type": "string", "description": "Workspace for the session"},
2022 "metadata": {"type": "object", "description": "Additional session metadata"}
2023 },
2024 "required": ["name"]
2025 }"#,
2026 annotations: ToolAnnotations::mutating(),
2027 },
2028 ToolDef {
2029 name: "session_context_add_memory",
2030 description: "Add a memory to a session context with relevance score and role.",
2031 schema: r#"{
2032 "type": "object",
2033 "properties": {
2034 "session_id": {"type": "string", "description": "Session ID"},
2035 "memory_id": {"type": "integer", "description": "Memory ID to add"},
2036 "relevance_score": {"type": "number", "minimum": 0, "maximum": 1, "default": 1.0, "description": "How relevant this memory is to the session"},
2037 "context_role": {"type": "string", "enum": ["referenced", "created", "updated", "pinned"], "default": "referenced", "description": "Role of the memory in the session"}
2038 },
2039 "required": ["session_id", "memory_id"]
2040 }"#,
2041 annotations: ToolAnnotations::mutating(),
2042 },
2043 ToolDef {
2044 name: "session_context_remove_memory",
2045 description: "Remove a memory from a session context.",
2046 schema: r#"{
2047 "type": "object",
2048 "properties": {
2049 "session_id": {"type": "string", "description": "Session ID"},
2050 "memory_id": {"type": "integer", "description": "Memory ID to remove"}
2051 },
2052 "required": ["session_id", "memory_id"]
2053 }"#,
2054 annotations: ToolAnnotations::mutating(),
2055 },
2056 ToolDef {
2057 name: "session_context_get",
2058 description: "Get a session context with its linked memories.",
2059 schema: r#"{
2060 "type": "object",
2061 "properties": {
2062 "session_id": {"type": "string", "description": "Session ID"}
2063 },
2064 "required": ["session_id"]
2065 }"#,
2066 annotations: ToolAnnotations::read_only(),
2067 },
2068 ToolDef {
2069 name: "session_context_list",
2070 description: "List all session contexts with optional filtering.",
2071 schema: r#"{
2072 "type": "object",
2073 "properties": {
2074 "workspace": {"type": "string", "description": "Filter by workspace"},
2075 "active_only": {"type": "boolean", "default": false, "description": "Only return active sessions"},
2076 "limit": {"type": "integer", "default": 50, "description": "Maximum sessions to return"},
2077 "offset": {"type": "integer", "default": 0, "description": "Offset for pagination"}
2078 }
2079 }"#,
2080 annotations: ToolAnnotations::read_only(),
2081 },
2082 ToolDef {
2083 name: "session_context_search",
2084 description: "Search memories within a specific session context.",
2085 schema: r#"{
2086 "type": "object",
2087 "properties": {
2088 "session_id": {"type": "string", "description": "Session ID to search within"},
2089 "query": {"type": "string", "description": "Search query"},
2090 "limit": {"type": "integer", "default": 20, "description": "Maximum results"}
2091 },
2092 "required": ["session_id", "query"]
2093 }"#,
2094 annotations: ToolAnnotations::read_only(),
2095 },
2096 ToolDef {
2097 name: "session_context_update_summary",
2098 description: "Update the summary of a session context.",
2099 schema: r#"{
2100 "type": "object",
2101 "properties": {
2102 "session_id": {"type": "string", "description": "Session ID"},
2103 "summary": {"type": "string", "description": "New session summary"}
2104 },
2105 "required": ["session_id", "summary"]
2106 }"#,
2107 annotations: ToolAnnotations::mutating(),
2108 },
2109 ToolDef {
2110 name: "session_context_end",
2111 description: "End a session context, marking it as inactive.",
2112 schema: r#"{
2113 "type": "object",
2114 "properties": {
2115 "session_id": {"type": "string", "description": "Session ID to end"},
2116 "summary": {"type": "string", "description": "Optional final summary"}
2117 },
2118 "required": ["session_id"]
2119 }"#,
2120 annotations: ToolAnnotations::mutating(),
2121 },
2122 ToolDef {
2123 name: "session_context_export",
2124 description: "Export a session context with all its memories for archival or sharing.",
2125 schema: r#"{
2126 "type": "object",
2127 "properties": {
2128 "session_id": {"type": "string", "description": "Session ID to export"},
2129 "include_content": {"type": "boolean", "default": true, "description": "Include full memory content"},
2130 "format": {"type": "string", "enum": ["json", "markdown"], "default": "json", "description": "Export format"}
2131 },
2132 "required": ["session_id"]
2133 }"#,
2134 annotations: ToolAnnotations::read_only(),
2135 },
2136 ToolDef {
2138 name: "quality_score",
2139 description: "Get the quality score for a memory with detailed breakdown of clarity, completeness, freshness, consistency, and source trust components.",
2140 schema: r#"{
2141 "type": "object",
2142 "properties": {
2143 "id": {"type": "integer", "description": "Memory ID to score"}
2144 },
2145 "required": ["id"]
2146 }"#,
2147 annotations: ToolAnnotations::read_only(),
2148 },
2149 ToolDef {
2150 name: "quality_report",
2151 description: "Generate a comprehensive quality report for a workspace. Includes quality distribution, top issues, conflict and duplicate counts.",
2152 schema: r#"{
2153 "type": "object",
2154 "properties": {
2155 "workspace": {"type": "string", "description": "Workspace to analyze (default: 'default')"}
2156 }
2157 }"#,
2158 annotations: ToolAnnotations::read_only(),
2159 },
2160 ToolDef {
2161 name: "quality_find_duplicates",
2162 description: "Find near-duplicate memories using text similarity. Returns pairs of similar memories above the threshold.",
2163 schema: r#"{
2164 "type": "object",
2165 "properties": {
2166 "threshold": {"type": "number", "minimum": 0, "maximum": 1, "default": 0.85, "description": "Similarity threshold (0-1)"},
2167 "limit": {"type": "integer", "default": 100, "description": "Maximum memories to compare"}
2168 }
2169 }"#,
2170 annotations: ToolAnnotations::read_only(),
2171 },
2172 ToolDef {
2173 name: "quality_get_duplicates",
2174 description: "Get pending duplicate candidates that need review.",
2175 schema: r#"{
2176 "type": "object",
2177 "properties": {
2178 "limit": {"type": "integer", "default": 50, "description": "Maximum duplicates to return"}
2179 }
2180 }"#,
2181 annotations: ToolAnnotations::read_only(),
2182 },
2183 ToolDef {
2184 name: "quality_find_conflicts",
2185 description: "Detect conflicts for a memory against existing memories. Finds contradictions, staleness, and semantic overlaps.",
2186 schema: r#"{
2187 "type": "object",
2188 "properties": {
2189 "id": {"type": "integer", "description": "Memory ID to check for conflicts"}
2190 },
2191 "required": ["id"]
2192 }"#,
2193 annotations: ToolAnnotations::read_only(),
2194 },
2195 ToolDef {
2196 name: "quality_get_conflicts",
2197 description: "Get unresolved conflicts that need attention.",
2198 schema: r#"{
2199 "type": "object",
2200 "properties": {
2201 "limit": {"type": "integer", "default": 50, "description": "Maximum conflicts to return"}
2202 }
2203 }"#,
2204 annotations: ToolAnnotations::read_only(),
2205 },
2206 ToolDef {
2207 name: "quality_resolve_conflict",
2208 description: "Resolve a conflict between memories. Options: keep_a, keep_b, merge, keep_both, delete_both, false_positive.",
2209 schema: r#"{
2210 "type": "object",
2211 "properties": {
2212 "conflict_id": {"type": "integer", "description": "Conflict ID to resolve"},
2213 "resolution": {"type": "string", "enum": ["keep_a", "keep_b", "merge", "keep_both", "delete_both", "false_positive"], "description": "How to resolve the conflict"},
2214 "notes": {"type": "string", "description": "Optional notes about the resolution"}
2215 },
2216 "required": ["conflict_id", "resolution"]
2217 }"#,
2218 annotations: ToolAnnotations::destructive(),
2219 },
2220 ToolDef {
2221 name: "quality_source_trust",
2222 description: "Get or update trust score for a source type. Higher trust means memories from this source are weighted more in quality calculations.",
2223 schema: r#"{
2224 "type": "object",
2225 "properties": {
2226 "source_type": {"type": "string", "description": "Source type (user, seed, extraction, inference, external)"},
2227 "source_identifier": {"type": "string", "description": "Optional specific source identifier"},
2228 "trust_score": {"type": "number", "minimum": 0, "maximum": 1, "description": "New trust score (omit to just get current score)"},
2229 "notes": {"type": "string", "description": "Notes about this source"}
2230 },
2231 "required": ["source_type"]
2232 }"#,
2233 annotations: ToolAnnotations::read_only(),
2234 },
2235 ToolDef {
2236 name: "quality_improve",
2237 description: "Get suggestions for improving a memory's quality. Returns actionable recommendations.",
2238 schema: r#"{
2239 "type": "object",
2240 "properties": {
2241 "id": {"type": "integer", "description": "Memory ID to analyze"}
2242 },
2243 "required": ["id"]
2244 }"#,
2245 annotations: ToolAnnotations::mutating(),
2246 },
2247 #[cfg(feature = "meilisearch")]
2249 ToolDef {
2250 name: "meilisearch_search",
2251 description: "Search memories using Meilisearch (typo-tolerant, fast full-text). Requires Meilisearch to be configured. Falls back to hybrid search if unavailable.",
2252 schema: r#"{
2253 "type": "object",
2254 "properties": {
2255 "query": {"type": "string", "description": "Search query text"},
2256 "limit": {"type": "integer", "default": 20, "description": "Maximum results to return"},
2257 "offset": {"type": "integer", "default": 0, "description": "Number of results to skip"},
2258 "workspace": {"type": "string", "description": "Filter by workspace"},
2259 "tags": {"type": "array", "items": {"type": "string"}, "description": "Filter by tags (AND logic)"},
2260 "memory_type": {"type": "string", "description": "Filter by memory type"}
2261 },
2262 "required": ["query"]
2263 }"#,
2264 annotations: ToolAnnotations::read_only(),
2265 },
2266 #[cfg(feature = "meilisearch")]
2267 ToolDef {
2268 name: "meilisearch_reindex",
2269 description: "Trigger a full re-sync from SQLite to Meilisearch. Use after bulk imports or if the index is out of sync.",
2270 schema: r#"{
2271 "type": "object",
2272 "properties": {}
2273 }"#,
2274 annotations: ToolAnnotations::idempotent(),
2275 },
2276 #[cfg(feature = "meilisearch")]
2277 ToolDef {
2278 name: "meilisearch_status",
2279 description: "Get Meilisearch index status including document count, indexing state, and health.",
2280 schema: r#"{
2281 "type": "object",
2282 "properties": {}
2283 }"#,
2284 annotations: ToolAnnotations::read_only(),
2285 },
2286 #[cfg(feature = "meilisearch")]
2287 ToolDef {
2288 name: "meilisearch_config",
2289 description: "Show current Meilisearch configuration (URL, sync interval, enabled status).",
2290 schema: r#"{
2291 "type": "object",
2292 "properties": {}
2293 }"#,
2294 annotations: ToolAnnotations::read_only(),
2295 },
2296 ToolDef {
2298 name: "agent_register",
2299 description: "Register an AI agent with capabilities and namespace isolation. Upserts if agent_id already exists.",
2300 schema: r#"{
2301 "type": "object",
2302 "properties": {
2303 "agent_id": {"type": "string", "description": "Unique identifier for the agent"},
2304 "display_name": {"type": "string", "description": "Human-readable name (defaults to agent_id)"},
2305 "capabilities": {"type": "array", "items": {"type": "string"}, "description": "List of capabilities (e.g., 'search', 'create', 'analyze')"},
2306 "namespaces": {"type": "array", "items": {"type": "string"}, "description": "Namespaces the agent operates in (default: ['default'])"},
2307 "metadata": {"type": "object", "description": "Additional metadata as key-value pairs"}
2308 },
2309 "required": ["agent_id"]
2310 }"#,
2311 annotations: ToolAnnotations::mutating(),
2312 },
2313 ToolDef {
2314 name: "agent_deregister",
2315 description: "Deregister an AI agent (soft delete — sets status to 'inactive').",
2316 schema: r#"{
2317 "type": "object",
2318 "properties": {
2319 "agent_id": {"type": "string", "description": "ID of the agent to deregister"}
2320 },
2321 "required": ["agent_id"]
2322 }"#,
2323 annotations: ToolAnnotations::destructive(),
2324 },
2325 ToolDef {
2326 name: "agent_heartbeat",
2327 description: "Update an agent's heartbeat timestamp to indicate it is still alive.",
2328 schema: r#"{
2329 "type": "object",
2330 "properties": {
2331 "agent_id": {"type": "string", "description": "ID of the agent sending heartbeat"}
2332 },
2333 "required": ["agent_id"]
2334 }"#,
2335 annotations: ToolAnnotations::mutating(),
2336 },
2337 ToolDef {
2338 name: "agent_list",
2339 description: "List registered agents, optionally filtered by status or namespace.",
2340 schema: r#"{
2341 "type": "object",
2342 "properties": {
2343 "status": {"type": "string", "enum": ["active", "inactive"], "description": "Filter by agent status"},
2344 "namespace": {"type": "string", "description": "Filter by namespace (returns agents that include this namespace)"}
2345 }
2346 }"#,
2347 annotations: ToolAnnotations::read_only(),
2348 },
2349 ToolDef {
2350 name: "agent_get",
2351 description: "Get details of a specific registered agent by ID.",
2352 schema: r#"{
2353 "type": "object",
2354 "properties": {
2355 "agent_id": {"type": "string", "description": "ID of the agent to retrieve"}
2356 },
2357 "required": ["agent_id"]
2358 }"#,
2359 annotations: ToolAnnotations::read_only(),
2360 },
2361 ToolDef {
2362 name: "agent_capabilities",
2363 description: "Update the capabilities list of a registered agent.",
2364 schema: r#"{
2365 "type": "object",
2366 "properties": {
2367 "agent_id": {"type": "string", "description": "ID of the agent to update"},
2368 "capabilities": {"type": "array", "items": {"type": "string"}, "description": "New capabilities list (replaces existing)"}
2369 },
2370 "required": ["agent_id", "capabilities"]
2371 }"#,
2372 annotations: ToolAnnotations::mutating(),
2373 },
2374
2375 #[cfg(feature = "agent-portability")]
2377 ToolDef {
2378 name: "snapshot_create",
2379 description: "Create a portable .egm snapshot of memories filtered by workspace, tags, date range, or importance. Optionally encrypt with AES-256-GCM or sign with Ed25519.",
2380 schema: r#"{
2381 "type": "object",
2382 "properties": {
2383 "output_path": {"type": "string", "description": "File path for the .egm snapshot"},
2384 "workspace": {"type": "string", "description": "Filter by workspace"},
2385 "tags": {"type": "array", "items": {"type": "string"}, "description": "Filter by tags"},
2386 "importance_min": {"type": "number", "description": "Minimum importance score"},
2387 "memory_types": {"type": "array", "items": {"type": "string"}, "description": "Filter by memory types"},
2388 "description": {"type": "string", "description": "Human-readable description"},
2389 "creator": {"type": "string", "description": "Creator name"},
2390 "encrypt_key": {"type": "string", "description": "Hex-encoded 32-byte AES key"},
2391 "sign_key": {"type": "string", "description": "Hex-encoded 32-byte Ed25519 secret key"}
2392 },
2393 "required": ["output_path"]
2394 }"#,
2395 annotations: ToolAnnotations::mutating(),
2396 },
2397 #[cfg(feature = "agent-portability")]
2398 ToolDef {
2399 name: "snapshot_load",
2400 description: "Load a .egm snapshot into the memory store. Strategies: merge (skip duplicates), replace (clear workspace first), isolate (new workspace), dry_run (preview only).",
2401 schema: r#"{
2402 "type": "object",
2403 "properties": {
2404 "path": {"type": "string", "description": "Path to .egm file"},
2405 "strategy": {"type": "string", "enum": ["merge", "replace", "isolate", "dry_run"], "description": "Load strategy"},
2406 "target_workspace": {"type": "string", "description": "Target workspace (defaults to snapshot's workspace)"},
2407 "decrypt_key": {"type": "string", "description": "Hex-encoded 32-byte AES key for encrypted snapshots"}
2408 },
2409 "required": ["path", "strategy"]
2410 }"#,
2411 annotations: ToolAnnotations::mutating(),
2412 },
2413 #[cfg(feature = "agent-portability")]
2414 ToolDef {
2415 name: "snapshot_inspect",
2416 description: "Inspect a .egm snapshot without loading it. Returns manifest, file list, and size.",
2417 schema: r#"{
2418 "type": "object",
2419 "properties": {
2420 "path": {"type": "string", "description": "Path to .egm file"}
2421 },
2422 "required": ["path"]
2423 }"#,
2424 annotations: ToolAnnotations::read_only(),
2425 },
2426
2427 #[cfg(feature = "agent-portability")]
2429 ToolDef {
2430 name: "attestation_log",
2431 description: "Log a document ingestion with cryptographic attestation. Creates a chained record proving the document was processed.",
2432 schema: r#"{
2433 "type": "object",
2434 "properties": {
2435 "content": {"type": "string", "description": "Document content to attest"},
2436 "document_name": {"type": "string", "description": "Name of the document"},
2437 "agent_id": {"type": "string", "description": "ID of the attesting agent"},
2438 "memory_ids": {"type": "array", "items": {"type": "integer"}, "description": "IDs of memories created from this document"},
2439 "sign_key": {"type": "string", "description": "Hex-encoded 32-byte Ed25519 secret key"}
2440 },
2441 "required": ["content", "document_name"]
2442 }"#,
2443 annotations: ToolAnnotations::mutating(),
2444 },
2445 #[cfg(feature = "agent-portability")]
2446 ToolDef {
2447 name: "attestation_verify",
2448 description: "Verify whether a document has been attested (ingested and recorded).",
2449 schema: r#"{
2450 "type": "object",
2451 "properties": {
2452 "content": {"type": "string", "description": "Document content to verify"}
2453 },
2454 "required": ["content"]
2455 }"#,
2456 annotations: ToolAnnotations::read_only(),
2457 },
2458 #[cfg(feature = "agent-portability")]
2459 ToolDef {
2460 name: "attestation_chain_verify",
2461 description: "Verify the integrity of the entire attestation chain. Returns valid, broken (with location), or empty.",
2462 schema: r#"{
2463 "type": "object",
2464 "properties": {}
2465 }"#,
2466 annotations: ToolAnnotations::read_only(),
2467 },
2468 #[cfg(feature = "agent-portability")]
2469 ToolDef {
2470 name: "attestation_list",
2471 description: "List attestation records with optional filters. Supports JSON, CSV, and Merkle proof export formats.",
2472 schema: r#"{
2473 "type": "object",
2474 "properties": {
2475 "limit": {"type": "integer", "description": "Maximum records to return", "default": 50},
2476 "offset": {"type": "integer", "description": "Number of records to skip", "default": 0},
2477 "agent_id": {"type": "string", "description": "Filter by agent ID"},
2478 "document_name": {"type": "string", "description": "Filter by document name"},
2479 "export_format": {"type": "string", "enum": ["json", "csv", "merkle_proof"], "description": "Export format"}
2480 }
2481 }"#,
2482 annotations: ToolAnnotations::read_only(),
2483 },
2484
2485 #[cfg(feature = "duckdb-graph")]
2487 ToolDef {
2488 name: "memory_graph_path",
2489 description: "Finds how two entities are connected in the knowledge graph via DuckDB OLAP engine. Discovers hidden relationships across multiple hops using recursive path-finding.",
2490 schema: r#"{
2491 "type": "object",
2492 "properties": {
2493 "scope": {"type": "string", "description": "Tenant scope prefix, e.g., 'global/org/user'"},
2494 "source_id": {"type": "integer", "description": "Starting node ID"},
2495 "target_id": {"type": "integer", "description": "Target node ID"},
2496 "max_depth": {"type": "integer", "description": "Maximum hops to traverse (default: 4, max: 10)", "default": 4}
2497 },
2498 "required": ["scope", "source_id", "target_id"]
2499 }"#,
2500 annotations: ToolAnnotations {
2501 read_only_hint: Some(true),
2502 destructive_hint: None,
2503 idempotent_hint: Some(true),
2504 open_world_hint: None,
2505 },
2506 },
2507 #[cfg(feature = "duckdb-graph")]
2508 ToolDef {
2509 name: "memory_temporal_snapshot",
2510 description: "Retrieves the exact facts and relationships that were true at a specific historical point in time. Uses DuckDB OLAP engine for fast columnar scans over temporal edges.",
2511 schema: r#"{
2512 "type": "object",
2513 "properties": {
2514 "scope": {"type": "string", "description": "Tenant scope prefix"},
2515 "timestamp": {"type": "string", "description": "ISO-8601 timestamp for the point-in-time query"}
2516 },
2517 "required": ["scope", "timestamp"]
2518 }"#,
2519 annotations: ToolAnnotations {
2520 read_only_hint: Some(true),
2521 destructive_hint: None,
2522 idempotent_hint: Some(true),
2523 open_world_hint: None,
2524 },
2525 },
2526 #[cfg(feature = "duckdb-graph")]
2527 ToolDef {
2528 name: "memory_scope_snapshot",
2529 description: "Compares the knowledge graph between two timestamps, showing what relationships were added, removed, or changed. Uses DuckDB OLAP engine for efficient temporal diff.",
2530 schema: r#"{
2531 "type": "object",
2532 "properties": {
2533 "scope": {"type": "string", "description": "Tenant scope prefix"},
2534 "from_timestamp": {"type": "string", "description": "Start of comparison window (ISO-8601)"},
2535 "to_timestamp": {"type": "string", "description": "End of comparison window (ISO-8601)"}
2536 },
2537 "required": ["scope", "from_timestamp", "to_timestamp"]
2538 }"#,
2539 annotations: ToolAnnotations {
2540 read_only_hint: Some(true),
2541 destructive_hint: None,
2542 idempotent_hint: Some(true),
2543 open_world_hint: None,
2544 },
2545 },
2546
2547 ToolDef {
2549 name: "memory_get_public",
2550 description: "Get a memory with all <private>...</private> tagged sections removed. Safe for sharing in multi-agent contexts.",
2551 schema: r#"{
2552 "type": "object",
2553 "properties": {
2554 "id": {"type": "integer", "description": "Memory ID"}
2555 },
2556 "required": ["id"]
2557 }"#,
2558 annotations: ToolAnnotations::read_only(),
2559 },
2560 ToolDef {
2561 name: "memory_search_compact",
2562 description: "Token-efficient search returning only id, title (first line, max 80 chars), created_at, and tags. Use memory_expand to get full content for specific IDs.",
2563 schema: r#"{
2564 "type": "object",
2565 "properties": {
2566 "query": {"type": "string", "description": "Search query"},
2567 "limit": {"type": "integer", "description": "Max results (default: 10)"},
2568 "workspace": {"type": "string", "description": "Filter to workspace"}
2569 },
2570 "required": ["query"]
2571 }"#,
2572 annotations: ToolAnnotations::read_only(),
2573 },
2574 ToolDef {
2575 name: "memory_expand",
2576 description: "Fetch full memory content for specific IDs. Used after memory_search_compact to get full content only for memories you need.",
2577 schema: r#"{
2578 "type": "object",
2579 "properties": {
2580 "ids": {"type": "array", "items": {"type": "integer"}, "description": "Memory IDs to expand"}
2581 },
2582 "required": ["ids"]
2583 }"#,
2584 annotations: ToolAnnotations::read_only(),
2585 },
2586 ToolDef {
2587 name: "memory_get_injection_prompt",
2588 description: "Assembles the most relevant memories into a ready-to-inject system prompt block. Uses hybrid search to find relevant memories and formats them as markdown, respecting a token budget.",
2589 schema: r#"{
2590 "type": "object",
2591 "properties": {
2592 "query": {"type": "string", "description": "Search query to find relevant memories"},
2593 "token_budget": {"type": "integer", "description": "Max tokens for output (default: 2000)"},
2594 "workspace": {"type": "string", "description": "Filter to specific workspace"},
2595 "include_types": {"type": "array", "items": {"type": "string"}, "description": "Filter by memory types"}
2596 },
2597 "required": ["query"]
2598 }"#,
2599 annotations: ToolAnnotations::read_only(),
2600 },
2601 ToolDef {
2602 name: "memory_observe_tool_use",
2603 description: "Store a tool observation as an episodic memory for session continuity. Automatically compresses large inputs/outputs.",
2604 schema: r#"{
2605 "type": "object",
2606 "properties": {
2607 "tool_name": {"type": "string", "description": "Name of the tool that was used"},
2608 "tool_input": {"type": "object", "description": "Tool input parameters"},
2609 "tool_output": {"type": "string", "description": "Tool output/result"},
2610 "session_id": {"type": "string", "description": "Session identifier for grouping observations"},
2611 "compress": {"type": "boolean", "description": "Compress to 200-char previews (default: true)"}
2612 },
2613 "required": ["tool_name", "tool_input", "tool_output"]
2614 }"#,
2615 annotations: ToolAnnotations::mutating(),
2616 },
2617 ToolDef {
2619 name: "memory_archive_tool_output",
2620 description: "Archives a tool's full raw output to memory and returns a compressed summary (~500 tokens) for use in the active context. Transforms O(N²) context growth to O(N) by keeping only summaries in the working context while preserving full outputs for on-demand retrieval.",
2621 schema: r#"{
2622 "type": "object",
2623 "properties": {
2624 "tool_name": {"type": "string", "description": "Name of the tool whose output is being archived"},
2625 "raw_output": {"type": "string", "description": "Full raw output to archive"},
2626 "session_id": {"type": "string", "description": "Session identifier for grouping archived outputs (default: 'unknown')"},
2627 "compress_summary": {"type": "boolean", "description": "Whether to generate a compressed summary (default: true)"},
2628 "summary_tokens": {"type": "integer", "description": "Max tokens for the compressed summary (default: 500)"}
2629 },
2630 "required": ["tool_name", "raw_output"]
2631 }"#,
2632 annotations: ToolAnnotations::mutating(),
2633 },
2634 ToolDef {
2635 name: "memory_get_archived_output",
2636 description: "Retrieves the full raw output for an archived tool observation by its archive ID. Use when you need the complete output that was previously compressed for context efficiency.",
2637 schema: r#"{
2638 "type": "object",
2639 "properties": {
2640 "archive_id": {"type": "integer", "description": "Archive ID returned by memory_archive_tool_output"}
2641 },
2642 "required": ["archive_id"]
2643 }"#,
2644 annotations: ToolAnnotations::read_only(),
2645 },
2646 ToolDef {
2647 name: "memory_get_working_memory",
2648 description: "Assembles all compressed tool observations for a session into a token-budgeted working memory block. Includes archive references for retrieving full outputs on demand. This is the core of the Endless Mode context management system.",
2649 schema: r#"{
2650 "type": "object",
2651 "properties": {
2652 "session_id": {"type": "string", "description": "Session identifier to retrieve observations for"},
2653 "token_budget": {"type": "integer", "description": "Max tokens for the working memory block (default: 4000)"},
2654 "include_tool_names": {"type": "array", "items": {"type": "string"}, "description": "Whitelist of tool names to include (default: all)"},
2655 "since_minutes": {"type": "integer", "description": "Only include observations from the last N minutes (default: all time)"}
2656 },
2657 "required": ["session_id"]
2658 }"#,
2659 annotations: ToolAnnotations::read_only(),
2660 },
2661];
2662
2663pub fn get_tool_definitions() -> Vec<ToolDefinition> {
2665 TOOL_DEFINITIONS
2666 .iter()
2667 .map(|def| ToolDefinition {
2668 name: def.name.to_string(),
2669 description: def.description.to_string(),
2670 input_schema: serde_json::from_str(def.schema).unwrap_or(json!({})),
2671 annotations: Some(def.annotations.clone()),
2672 })
2673 .collect()
2674}
2675
2676#[cfg(test)]
2677mod tests {
2678 use super::*;
2679
2680 #[test]
2681 fn test_tool_definitions_all_parseable() {
2682 let tools = get_tool_definitions();
2683 assert!(!tools.is_empty(), "TOOL_DEFINITIONS must not be empty");
2684 for tool in &tools {
2685 assert!(!tool.name.is_empty(), "tool name must not be empty");
2686 assert!(
2687 !tool.description.is_empty(),
2688 "tool description must not be empty"
2689 );
2690 assert!(
2691 tool.input_schema.is_object(),
2692 "tool '{}' schema must be a JSON object",
2693 tool.name
2694 );
2695 }
2696 }
2697
2698 #[test]
2699 fn test_read_only_tools_have_annotation() {
2700 let tools = get_tool_definitions();
2701 let read_only_names = ["memory_get", "memory_list", "memory_search", "memory_stats"];
2702 for name in read_only_names {
2703 let tool = tools
2704 .iter()
2705 .find(|t| t.name == name)
2706 .unwrap_or_else(|| panic!("tool '{}' not found", name));
2707 let ann = tool
2708 .annotations
2709 .as_ref()
2710 .expect("annotations must be present");
2711 assert_eq!(
2712 ann.read_only_hint,
2713 Some(true),
2714 "tool '{}' should have readOnlyHint=true",
2715 name
2716 );
2717 }
2718 }
2719
2720 #[test]
2721 fn test_destructive_tools_have_annotation() {
2722 let tools = get_tool_definitions();
2723 let destructive_names = [
2724 "memory_delete",
2725 "memory_cleanup_expired",
2726 "embedding_cache_clear",
2727 ];
2728 for name in destructive_names {
2729 let tool = tools
2730 .iter()
2731 .find(|t| t.name == name)
2732 .unwrap_or_else(|| panic!("tool '{}' not found", name));
2733 let ann = tool
2734 .annotations
2735 .as_ref()
2736 .expect("annotations must be present");
2737 assert_eq!(
2738 ann.destructive_hint,
2739 Some(true),
2740 "tool '{}' should have destructiveHint=true",
2741 name
2742 );
2743 }
2744 }
2745
2746 #[test]
2747 fn test_idempotent_tools_have_annotation() {
2748 let tools = get_tool_definitions();
2749 let idempotent_names = [
2750 "memory_extract_entities",
2751 "memory_rebuild_embeddings",
2752 "memory_rebuild_crossrefs",
2753 "lifecycle_run",
2754 "retention_policy_apply",
2755 ];
2756 for name in idempotent_names {
2757 let tool = tools
2758 .iter()
2759 .find(|t| t.name == name)
2760 .unwrap_or_else(|| panic!("tool '{}' not found", name));
2761 let ann = tool
2762 .annotations
2763 .as_ref()
2764 .expect("annotations must be present");
2765 assert_eq!(
2766 ann.idempotent_hint,
2767 Some(true),
2768 "tool '{}' should have idempotentHint=true",
2769 name
2770 );
2771 }
2772 }
2773
2774 #[test]
2775 fn test_annotations_serialize_with_camel_case_keys() {
2776 let tools = get_tool_definitions();
2777 let memory_get = tools.iter().find(|t| t.name == "memory_get").unwrap();
2778 let json = serde_json::to_string(memory_get).expect("serialization must succeed");
2779 assert!(
2780 json.contains("readOnlyHint"),
2781 "should serialize as readOnlyHint"
2782 );
2783 assert!(
2784 !json.contains("read_only_hint"),
2785 "must not use snake_case key"
2786 );
2787 }
2788
2789 #[test]
2790 fn test_mutating_tool_has_no_hints() {
2791 let tools = get_tool_definitions();
2792 let memory_create = tools.iter().find(|t| t.name == "memory_create").unwrap();
2793 let ann = memory_create
2794 .annotations
2795 .as_ref()
2796 .expect("annotations must be present");
2797 assert!(ann.read_only_hint.is_none());
2798 assert!(ann.destructive_hint.is_none());
2799 assert!(ann.idempotent_hint.is_none());
2800 let json = serde_json::to_string(ann).expect("serialization must succeed");
2802 assert_eq!(json, "{}");
2804 }
2805}