
Mem0 Memory
- 30 installs
- 213 repo stars
- Updated August 4, 2026
- yonatangross/orchestkit
Helps with ai & agent building tasks.
About
mem0-memory is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- mem0-memory
- AI & Agent Building
- AI-coding skill
Mem0 Memory by the numbers
- 30 all-time installs (skills.sh)
- Ranked #9,276 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/yonatangross/orchestkit --skill mem0-memoryAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 30 |
|---|---|
| repo stars | ★ 213 |
| Last updated | August 4, 2026 |
| Repository | yonatangross/orchestkit ↗ |
What it does
Helps with ai & agent building tasks.
Files
Mem0 Memory Management
Persist and retrieve semantic memories across Claude sessions.
Memory Scopes
Organize memories by scope for efficient retrieval:
| Scope | Purpose | Examples |
|---|---|---|
project-decisions | Architecture and design decisions | "Use PostgreSQL with pgvector for RAG" |
project-patterns | Code patterns and conventions | "Components use kebab-case filenames" |
project-continuity | Session handoff context | "Working on auth refactor, PR #123 pending" |
Project Isolation
Memories are isolated by project name extracted from CLAUDE_PROJECT_DIR:
- Project name:
basename($CLAUDE_PROJECT_DIR)(sanitized to lowercase, dashes) - Format:
{project-name}-{scope}
Edge Case: If two different repositories have the same directory name, they will share the same user_id scope. To avoid this:
1. Use unique directory names for each project 2. Or use MEM0_ORG_ID environment variable for additional namespace
Example:
/Users/alice/my-app→my-app-decisions✅/Users/bob/my-app→my-app-decisions⚠️ (collision if same mem0.ai project)- With
MEM0_ORG_ID=acme:/Users/alice/my-app→acme-my-app-decisions✅
Memory Categories
Memories are automatically categorized based on content. Available categories:
| Category | Keywords | Use Case |
|---|---|---|
pagination | pagination, cursor, offset | API pagination patterns |
security | security, vulnerability, OWASP | Security patterns and vulnerabilities |
authentication | auth, JWT, OAuth, token | Authentication patterns |
testing | test, pytest, jest, coverage | Testing strategies |
deployment | deploy, CI/CD, Docker, Kubernetes | Deployment patterns |
observability | monitoring, logging, tracing, metrics | Observability patterns |
performance | performance, cache, optimize | Performance optimization |
ai-ml | LLM, RAG, embedding, LangChain | AI/ML patterns |
data-pipeline | ETL, streaming, batch processing | Data pipeline patterns |
database | database, SQL, PostgreSQL, schema | Database patterns |
api | API, endpoint, REST, GraphQL | API design patterns |
frontend | React, component, UI, CSS | Frontend patterns |
architecture | architecture, design, system | Architecture patterns |
pattern | pattern, convention, style | General patterns |
blocker | blocked, issue, bug | Blockers and issues |
constraint | must, cannot, required | Constraints |
decision | chose, decided, selected | Decisions (default) |
Cross-Tool Memory
Memories include source_tool metadata to support cross-tool memory sharing:
source_tool: "orchestkit-claude"- Memories from Claude Codesource_tool: "orchestkit-cursor"- Memories from Cursor (future)
Query memories by tool:
# Query Claude Code memories
filters={"AND": [{"metadata.source_tool": "orchestkit-claude"}]}
# Query all memories (any tool)
filters={"AND": [{"user_id": "my-project-decisions"}]}Setup
Install mem0 Python SDK:
# Install the mem0ai package and dependencies
pip install mem0ai python-dotenv
# Or install from requirements file
pip install -r skills/mem0-memory/scripts/requirements.txtOptional - Install mem0-skill-lib package (recommended for development):
# Install as editable package for proper type checking
pip install -e skills/mem0-memory/scripts/Note: Scripts work in both modes:
- Standalone mode (default): Scripts dynamically add
lib/to sys.path. Type checkers require# type: ignorecomments for these dynamic imports. - Installed mode: If
mem0-skill-libis installed, scripts import from the installed package without type ignore comments.
Set environment variables:
Option 1: Using `.env` file (Recommended)
Create a .env file in your project root:
# Copy the example file
cp .env.example .env
# Edit .env and add your API key
MEM0_API_KEY=sk-your-api-key-here
MEM0_ORG_ID=org_... # Optional (for organization-level scoping)
MEM0_PROJECT_ID=proj_... # Optional (Pro feature)
MEM0_WEBHOOK_URL=https://your-domain.com/webhook/mem0 # OptionalThe scripts automatically load from .env if it exists.
Option 2: Shell environment variables
export MEM0_API_KEY="sk-..."
export MEM0_ORG_ID="org_..." # Optional (for organization-level scoping)
export MEM0_PROJECT_ID="proj_..." # Optional (Pro feature)Verify installation:
python3 -c "from mem0 import MemoryClient; print('✓ mem0ai installed successfully')"Core Operations
Adding Memories
Execute the script via Bash tool:
!bash skills/mem0-memory/scripts/crud/add-memory.py \
--text "Decided to use FastAPI over Flask for async support" \
--user-id "project-decisions" \
--metadata '{"scope":"project-decisions","category":"backend","date":"2026-01-12"}' \
--enable-graphBest practices for adding:
- Be specific and actionable
- Include rationale ("because...")
- Add scope and category metadata
- Timestamp important decisions
Searching Memories
!bash skills/mem0-memory/scripts/crud/search-memories.py \
--query "authentication approach" \
--user-id "project-decisions" \
--limit 5 \
--enable-graphSearch tips:
- Use natural language queries
- Search by topic, not exact phrases
- Combine with scope filters when available
- Enable graph (
--enable-graph) to get relationship information in results
Graph Relationships in Search Results:
When --enable-graph is enabled, search results include:
relationsarray with relationship informationrelated_viafield showing how results are connectedrelationship_summarywith relation types found
Graph Relationship Queries
Get Related Memories:
Query memories related to a given memory via graph traversal:
!bash skills/mem0-memory/scripts/graph/get-related-memories.py \
--memory-id "mem_abc123" \
--depth 2 \
--relation-type "recommends"Traverse Graph:
Multi-hop graph traversal for complex relationship queries:
!bash skills/mem0-memory/scripts/graph/traverse-graph.py \
--memory-id "mem_abc123" \
--depth 2 \
--relation-type "recommends"Example Use Cases:
1. Multi-hop queries:
"What did database-engineer recommend about pagination?"
→ Traverses: database-engineer → recommends → cursor-pagination
→ Returns related memories with relationship context2. Context expansion:
Find a memory about "authentication"
→ Get related memories via graph (depth 2)
→ Discover related decisions, patterns, and recommendations3. Relationship filtering:
--relation-type "recommends" # Only follow "recommends" relationships
--relation-type "uses" # Only follow "uses" relationshipsListing Memories
!bash skills/mem0-memory/scripts/crud/get-memories.py \
--user-id "project-orchestkit" \
--filters '{"limit":100}'Getting Single Memory
!bash skills/mem0-memory/scripts/crud/get-memory.py \
--memory-id "mem_abc123"Updating Memories
!bash skills/mem0-memory/scripts/crud/update-memory.py \
--memory-id "mem_abc123" \
--text "Updated decision text" \
--metadata '{"updated":true}'Deleting Memories
!bash skills/mem0-memory/scripts/crud/delete-memory.py \
--memory-id "mem_abc123"When to delete:
- Outdated decisions that were reversed
- Incorrect information
- Duplicate or redundant entries
What to Remember
Good candidates:
- Architecture decisions with rationale
- API contracts and interfaces
- Naming conventions adopted
- Technical debt acknowledged
- Blockers and their resolutions
- User preferences and style
Avoid storing:
- Temporary debugging context
- Large code blocks (use Git)
- Secrets or credentials
- Highly volatile information
Memory Patterns
Decision Memory
"Decision: Use cursor-based pagination for all list endpoints.
Rationale: Better performance for large datasets, consistent UX.
Date: 2026-01-12. Scope: API design."Pattern Memory
"Pattern: All React components export default function.
Convention: Use named exports only for utilities.
Applies to: frontend/src/components/**"Continuity Memory
"Session handoff: Completed hybrid search implementation.
Next steps: Add metadata boosting, write integration tests.
PR #456 ready for review. Blocked on: DB migration approval."Advanced Operations (Pro Features)
Batch Operations
Batch update up to 1000 memories:
!bash skills/mem0-memory/scripts/batch/batch-update.py \
--memories '[{"memory_id":"mem_123","text":"updated"},{"memory_id":"mem_456","metadata":{"updated":true}}]'Batch delete:
!bash skills/mem0-memory/scripts/batch/batch-delete.py \
--memory-ids '["mem_123","mem_456","mem_789"]'Memory History (Audit Trail)
!bash skills/mem0-memory/scripts/utils/memory-history.py \
--memory-id "mem_abc123"Exports (Data Portability)
Create export:
!bash skills/mem0-memory/scripts/export/export-memories.py \
--filters '{"user_id":"project-decisions"}' \
--schema '{"format":"json"}'Retrieve export:
!bash skills/mem0-memory/scripts/export/get-export.py \
--user-id "project-decisions"Analytics
Get memory statistics:
!bash skills/mem0-memory/scripts/utils/memory-summary.py \
--filters '{"user_id":"project-decisions"}'List all users:
!bash skills/mem0-memory/scripts/utils/get-users.pyWebhooks (Automation)
!bash skills/mem0-memory/scripts/webhooks/create-webhook.py \
--url "https://example.com/webhook" \
--name "Memory Webhook" \
--event-types '["memory.created","memory.updated"]'Integration with OrchestKit
Use memories to maintain context across plugin sessions:
# At session start - recall project context
!bash skills/mem0-memory/scripts/crud/search-memories.py \
--query "current sprint priorities" \
--user-id "project-continuity"
# During work - persist decisions
!bash skills/mem0-memory/scripts/crud/add-memory.py \
--text "Implemented feature using approach because reason" \
--user-id "project-decisions" \
--metadata '{"scope":"project-decisions"}'
# At session end - save continuity
!bash skills/mem0-memory/scripts/crud/add-memory.py \
--text "Session end: summary. Next: next_steps" \
--user-id "project-continuity" \
--metadata '{"scope":"project-continuity"}'Scripts Available
All scripts are located in skills/mem0-memory/scripts/:
Core Scripts:
add-memory.py- Store new memorysearch-memories.py- Semantic searchget-memories.py- List all memories (with filters)get-memory.py- Get single memory by IDupdate-memory.py- Update memory content/metadatadelete-memory.py- Remove memory
Advanced Scripts (Pro Features):
batch-update.py- Bulk update up to 1000 memoriesbatch-delete.py- Bulk delete multiple memoriesmemory-history.py- Get audit trail for a memoryexport-memories.py- Create structured exportget-export.py- Retrieve export datamemory-summary.py- Get statistics/analyticsget-events.py- Track async operationsget-users.py- List all users (analytics)create-webhook.py- Setup webhooks for automation
Note: Mem0 uses CLI scripts via Bash (not MCP). Scripts provide full control, versioning, and access to all 30+ API methods. The primary memory layer is the knowledge graph (mcp__memory__*); mem0 CLI scripts serve as an optional cloud enhancement for semantic search across sessions.
Related Skills
semantic-caching- Semantic caching patterns that complement long-term memoryembeddings- Embedding strategies used by Mem0 for semantic searchlanggraph-checkpoints- State persistence patterns for workflow continuitycontext-compression- Compress context when memory retrieval adds too many tokens
Key Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Memory scope | project-decisions, project-patterns, project-continuity | Clear separation of memory types |
| Storage format | Natural language with metadata | Semantic search works best with descriptive text |
| MCP integration | Mem0 MCP server | Native Claude Desktop integration |
| What to avoid | Secrets, large code blocks, volatile info | Keep memories clean and safe |
Capability Details
memory-add
Keywords: add memory, remember, store, persist, save context Solves:
- How do I save information for later sessions?
- Persist a decision or pattern
- Store project context across sessions
memory-search
Keywords: search memory, recall, find, retrieve, what did we Solves:
- How do I find previous decisions?
- Recall context from past sessions
- Search for specific patterns or conventions
memory-list
Keywords: list memories, show all, get memories, view stored Solves:
- How do I see all stored memories?
- List project decisions
- Review stored patterns
memory-delete
Keywords: delete memory, forget, remove, clear Solves:
- How do I remove outdated memories?
- Delete incorrect information
- Clean up duplicate entries
Agent-as-User Architecture for Mem0
Overview
Each OrchestKit agent should be a separate user_id in mem0, creating isolated memory spaces per agent. This enables:
1. Agent-specific knowledge graphs - Each agent's memories form their own graph 2. Better querying - "What does backend-system-architect know?" queries a specific user_id 3. Isolated learning - Agents don't pollute each other's memory space 4. Clearer visualization - Agent-specific graphs show what each agent knows
Current Architecture
All memories → user_id: "orchestkit-plugin-structure"
├── Agent memories (backend-system-architect, frontend-ui-developer, etc.)
├── Skill memories
├── Technology memories
└── Category memoriesProblem: All agents share the same memory space, making it hard to:
- Query agent-specific knowledge
- Visualize per-agent graphs
- Isolate agent learning
Proposed Architecture
Each agent → Separate user_id
├── user_id: "agent:backend-system-architect"
│ ├── Agent metadata memory
│ ├── Skills this agent uses
│ ├── Decisions this agent made
│ └── Patterns this agent learned
│
├── user_id: "agent:frontend-ui-developer"
│ ├── Agent metadata memory
│ ├── Skills this agent uses
│ └── Frontend-specific decisions
│
└── Shared memories → user_id: "orchestkit:shared"
├── Skill definitions (shared across agents)
├── Technology definitions
└── Category definitionsImplementation Plan
1. Update Memory Creation Scripts
File: skills/mem0-memory/scripts/create/create-all-agent-memories.py
# OLD
USER_ID = "orchestkit-plugin-structure"
# NEW
def get_agent_user_id(agent_name: str) -> str:
"""Generate user_id for agent-specific memories."""
return f"agent:{agent_name}"
def get_shared_user_id() -> str:
"""Generate user_id for shared memories (skills, tech, categories)."""
return "orchestkit:shared"2. Update Hook for Agent Context
File: hooks/src/skill/decision-processor.ts
# Detect if we're in an agent context
if [[ -n "${CLAUDE_AGENT_ID:-}" ]]; then
# Use agent-specific user_id
AGENT_USER_ID="agent:${CLAUDE_AGENT_ID}"
DECISIONS_USER_ID=$(mem0_user_id "$AGENT_USER_ID")
else
# Fallback to project scope
DECISIONS_USER_ID=$(mem0_user_id "$MEM0_SCOPE_DECISIONS")
fi3. Update Visualization Scripts
File: skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py
def export_multi_agent_graph(agent_names: List[str] = None) -> Dict[str, Any]:
"""Export graph data for multiple agents."""
if agent_names is None:
# Get all agents from mem0
agent_names = get_all_agent_user_ids()
all_nodes = []
all_edges = []
for agent_name in agent_names:
user_id = f"agent:{agent_name}"
graph_data = export_graph_data(user_id)
all_nodes.extend(graph_data['nodes'])
all_edges.extend(graph_data['edges'])
return {
"nodes": all_nodes,
"edges": all_edges
}4. User ID Naming Convention
agent:{agent-name} # Agent-specific memories
orchestkit:shared # Shared definitions (skills, tech, categories)
orchestkit:decisions # Global decisions (if needed)Migration Strategy
Phase 1: Dual-Write (Backward Compatible)
1. Keep writing to orchestkit-plugin-structure for existing memories 2. Start writing new agent memories to agent:{agent-name} 3. Update visualization to read from both
Phase 2: Migration Script
# Migrate existing memories to agent-specific user_ids
def migrate_agent_memories():
# Read all memories from old user_id
old_memories = client.search(
query="agent specialized",
filters={"user_id": "orchestkit-plugin-structure", "metadata.entity_type": "Agent"}
)
for memory in old_memories['results']:
agent_name = memory['metadata'].get('agent_name') or memory['metadata'].get('name')
if agent_name:
new_user_id = f"agent:{agent_name}"
# Create new memory with agent user_id
client.add(
messages=[{"role": "user", "content": memory['memory']}],
user_id=new_user_id,
metadata=memory['metadata'],
enable_graph=True
)Phase 3: Cleanup
1. Archive old orchestkit-plugin-structure memories 2. Update all scripts to use new user_id pattern 3. Update documentation
Benefits
1. Agent-Specific Queries
# Query what backend-system-architect knows
memories = client.search(
query="authentication patterns",
filters={"user_id": "agent:backend-system-architect"}
)2. Agent-Specific Visualizations
# Visualize backend-system-architect's knowledge graph
python visualize-mem0-graph.py --user-id "agent:backend-system-architect"3. Cross-Agent Analysis
# Compare what different agents know
backend_memories = get_agent_memories("backend-system-architect")
frontend_memories = get_agent_memories("frontend-ui-developer")
# Find shared knowledge
shared_skills = set(backend_memories['skills']) & set(frontend_memories['skills'])4. Better Graph Structure
Each agent's graph shows:
- Which skills they use
- What decisions they've made
- What patterns they've learned
- Their specific knowledge domain
Example: Backend System Architect Graph
user_id: "agent:backend-system-architect"
├── Node: backend-system-architect (Agent, Blue)
│ ├── Edge: uses → auth-patterns (Skill, Green)
│ ├── Edge: uses → api-versioning (Skill, Green)
│ ├── Edge: uses → streaming-api-patterns (Skill, Green)
│ └── Edge: belongs_to → Backend Skills (Category, Purple)
│
└── Node: Decision: "Use cursor pagination" (Architecture, Red)
└── Edge: implements → api-versioningImplementation Checklist
- [ ] Update
create-all-agent-memories.pyto useagent:{name}user_id - [ ] Update
decision-processor.tshook to detect agent context - [ ] Update visualization scripts to support multi-agent graphs
- [ ] Create migration script for existing memories
- [ ] Update documentation with new user_id patterns
- [ ] Test agent-specific queries and visualizations
- [ ] Update CI/CD workflows if needed
Related Files
skills/mem0-memory/scripts/create/create-all-agent-memories.pyhooks/src/skill/decision-processor.tsskills/mem0-memory/scripts/visualization/visualize-mem0-graph.pyskills/mem0-memory/SKILL.md
Mem0 Data Structure Reference
Complete reference for entity types, categories, relationships, metadata schema, and example queries for OrchestKit plugin structure in Mem0.
Entity Types
Agent
- Description: Specialized AI agent personas (34 total)
- Color: Blue (#3B82F6)
- Category:
agents - Metadata Fields:
entity_type: "Agent"color_group: "agent"category: "agents"name: <agent-name>agent_name: <agent-id>skills: [<skill-list>]model: <sonnet|opus|haiku>(optional)description: <agent-description>(optional)
Examples: backend-system-architect, frontend-ui-developer, database-engineer, llm-integrator
Skill
- Description: Reusable knowledge modules (161 total)
- Color: Green (#10B981)
- Category:
backend-skills,frontend-skills,ai-llm-skills, etc. - Metadata Fields:
entity_type: "Skill"color_group: "skill"category: <category-slug>name: <skill-name>skill_name: <skill-id>implements: <technology>(optional)tags: [<tag-list>](optional)description: <skill-description>(optional)
Examples: fastapi-advanced, react-server-components-framework, langgraph-state, rag-retrieval
Technology
- Description: Core technologies and frameworks (24+ total)
- Color: Orange (#F59E0B)
- Category:
technologies - Metadata Fields:
entity_type: "Technology"color_group: "technology"category: "technologies"name: <technology-name>version: <version>(optional)tech_category: <Backend Framework|Frontend Framework|Language|etc.>(optional)
Examples: FastAPI, React 19, LangGraph, PostgreSQL, TypeScript, Python
Category
- Description: Skill/entity categories (18 total)
- Color: Purple (#8B5CF6)
- Category:
<category-slug>(self-referential) - Metadata Fields:
entity_type: "Category"color_group: "category"category: <category-slug>name: <Category Name>category_slug: <category-slug>
Examples: agents, backend-skills, frontend-skills, ai-llm-skills
Architecture
- Description: Architecture decisions and plugin root
- Color: Red (#EF4444)
- Category:
architecture-decisions - Metadata Fields:
entity_type: "Architecture"color_group: "architecture"category: "architecture-decisions"name: <decision-name>version: <version>(for plugin root)
Examples: OrchestKit Plugin, Graph-First Memory Architecture, Progressive Loading Protocol
Categories
Skill Categories
backend-skills- Backend development patternsfrontend-skills- Frontend development patternsai-llm-skills- AI and LLM patternstesting-skills- Testing patternssecurity-skills- Security patternsdevops-skills- DevOps patternsgit-github-skills- Git/GitHub operationsworkflow-skills- Workflow patternsquality-skills- Quality gates and reviewscontext-skills- Context managementevent-driven-skills- Event-driven architecturedatabase-skills- Database patternsaccessibility-skills- Accessibility patternsmcp-skills- MCP patterns
Entity Categories
agents- All 36 agentstechnologies- All technologiesarchitecture-decisions- Architecture decisionsrelationships- Relationship memories
Relationship Types
Primary Relationships
uses- Agent uses skill, Technology uses languageimplements- Skill implements technologyextends- Technology extends another technologybelongs_to- Entity belongs to categoryrecommends- Agent/skill recommends pattern
Secondary Relationships
shares_skill- Agents share common skillscollaborates_with- Agents work togethercontains- Category contains entitiesdepends_on- Technology depends on another
Metadata Schema
Common Fields (All Entities)
{
"type": "<agent|skill|technology|category|architecture|relationship>",
"entity_type": "<Agent|Skill|Technology|Category|Architecture>",
"color_group": "<agent|skill|technology|category|architecture>",
"category": "<category-slug>",
"plugin_component": true,
"name": "<entity-name>"
}Agent-Specific Fields
{
"agent_name": "<agent-id>",
"skills": ["<skill-1>", "<skill-2>", ...],
"model": "<sonnet|opus|haiku>",
"description": "<agent-description>"
}Skill-Specific Fields
{
"skill_name": "<skill-id>",
"implements": "<technology-name>",
"technology": "<technology-name>",
"tags": ["<tag-1>", "<tag-2>", ...],
"description": "<skill-description>"
}Technology-Specific Fields
{
"version": "<version>",
"tech_category": "<Backend Framework|Frontend Framework|Language|...>"
}Relationship-Specific Fields
{
"from": "<source-entity>",
"to": "<target-entity>",
"relation": "<uses|implements|extends|belongs_to|...>",
"hop": <1|2|3|4>,
"chain": "<agent→skill→technology→language>" (for multi-hop)
}Example Queries
Search by Entity Type
result = client.search(
query="agent specialized AI persona",
filters={
"user_id": "orchestkit:all-agents",
"metadata.entity_type": "Agent"
},
enable_graph=True
)Search by Category
result = client.search(
query="backend development patterns",
filters={
"user_id": "orchestkit:all-agents",
"metadata.category": "backend-skills"
},
enable_graph=True
)Find Skills for Technology
result = client.search(
query="skill implements FastAPI",
filters={
"user_id": "orchestkit:all-agents",
"metadata.implements": "FastAPI"
},
enable_graph=True
)Find Agents Using Skill
result = client.search(
query="agent uses fastapi-advanced",
filters={
"user_id": "orchestkit:all-agents",
"metadata.skill": "fastapi-advanced"
},
enable_graph=True
)Relationship Traversal Examples
1-Hop: Agent → Skills
# Get agent memory
AGENT_ID=$(python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "backend-system-architect" \
--user-id "orchestkit:all-agents" \
--limit 1 | jq -r '.results[0].id')
# Get related skills (1 hop)
python3 skills/mem0-memory/scripts/graph/get-related-memories.py \
--memory-id "$AGENT_ID" \
--depth 1 \
--relation-type "uses"2-Hop: Agent → Skill → Technology
# Traverse 2 hops
python3 skills/mem0-memory/scripts/graph/get-related-memories.py \
--memory-id "$AGENT_ID" \
--depth 23-Hop: Full Stack Chain
# Get complete technology stack
python3 skills/mem0-memory/scripts/graph/traverse-graph.py \
--memory-id "$AGENT_ID" \
--depth 3Data Creation Workflow
1. Create Entity Memories
- Categories → Technologies → Agents → Skills
- Each with proper
entity_type,color_group,category
2. Create Relationship Memories
- Agent → Skill (uses)
- Skill → Technology (implements)
- Technology → Technology (extends/uses)
- Entity → Category (belongs_to)
3. Create Multi-Hop Chains
- Explicit 4-hop chains for key workflows
- Enables deep relationship traversal
4. Wait for Processing
- Mem0 processes relationships asynchronously
- Wait 2-5 minutes after creation
- Relationships appear in search with
--enable-graph
Validation
Check Metadata Completeness
# All memories should have:
required_fields = ["entity_type", "color_group", "category", "plugin_component", "name"]Verify Entity Types
valid_entity_types = ["Agent", "Skill", "Technology", "Category", "Architecture"]Validate Category Slugs
valid_categories = [
"agents", "backend-skills", "frontend-skills", "ai-llm-skills",
"testing-skills", "security-skills", "devops-skills", "git-github-skills",
"workflow-skills", "quality-skills", "context-skills", "event-driven-skills",
"database-skills", "accessibility-skills", "mcp-skills",
"technologies", "architecture-decisions", "relationships"
]Best Practices
Creating New Memories
1. Always include entity_type, color_group, category, plugin_component: true 2. Use descriptive name field 3. Include relationship metadata (from, to, relation) for relationships 4. Enable graph: enable_graph=True
Querying
1. Always use enable_graph=True for relationship queries 2. Filter by user_id: "orchestkit:all-agents" to scope to plugin 3. Use metadata filters for precise queries 4. Wait 2-5 minutes after creating memories before querying relationships
Visualization
1. Update metadata before generating visualization 2. Use --limit for large graphs to avoid performance issues 3. Export to JSON first, then visualize filtered subset 4. Use Plotly for interactive exploration, NetworkX for static images
Metadata-Filtered Single Graph Architecture
Overview
The Metadata-Filtered Single Graph architecture uses a unified user_id with rich metadata` to enable both agent-specific and cross-agent queries efficiently. This approach provides the best balance of performance, flexibility, and simplicity.
Rating: 9.0/10 ⭐⭐⭐
Architecture
User ID Structure
# All memories use single unified user_id
user_id = "orchestkit:all-agents"Metadata Schema
Agent Memories:
metadata = {
"agent_name": "backend-system-architect",
"agent_type": "specialist",
"shared": False, # Agent-specific
"entity_type": "Agent",
"category": "agents",
# ... other fields
}Shared Knowledge (Skills, Tech, Categories):
metadata = {
"shared": True, # Shared across all agents
"entity_type": "Skill" | "Technology" | "Category",
"category": "backend-skills" | "technologies" | "categories",
# ... other fields
}Query Patterns
1. Agent-Specific Query
Query memories created by a specific agent:
from skills.mem0_memory.scripts.utils.agent_queries import search_agent_specific
results = search_agent_specific(
query="FastAPI patterns",
agent_name="backend-system-architect",
limit=10
)CLI:
python3 skills/mem0-memory/scripts/utils/agent-queries.py \
--query "FastAPI patterns" \
--agent-name "backend-system-architect"Direct API:
python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "FastAPI patterns" \
--agent-filter "backend-system-architect"2. Cross-Agent Query
Query all agent memories (default behavior):
from skills.mem0_memory.scripts.utils.agent_queries import search_cross_agent
results = search_cross_agent(
query="authentication approach",
limit=10
)CLI:
python3 skills/mem0-memory/scripts/utils/agent-queries.py \
--query "authentication approach"Direct API:
python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "authentication approach"3. Shared Knowledge Query
Query only shared knowledge (skills, technologies, categories):
from skills.mem0_memory.scripts.utils.agent_queries import search_shared_knowledge
results = search_shared_knowledge(
query="PostgreSQL schema",
limit=10
)CLI:
python3 skills/mem0-memory/scripts/utils/agent-queries.py \
--query "PostgreSQL schema" \
--shared-onlyDirect API:
python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "PostgreSQL schema" \
--shared-only4. Combined Query
Query both agent-specific and shared knowledge:
from skills.mem0_memory.scripts.utils.agent_queries import search_agent_and_shared
results = search_agent_and_shared(
query="database patterns",
agent_name="database-engineer",
limit=10
)CLI:
python3 skills/mem0-memory/scripts/utils/agent-queries.py \
--query "database patterns" \
--agent-name "database-engineer" \
--agent-and-sharedVisualization
Agent-Specific Graph
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--agent-filter "backend-system-architect" \
--format plotlyShared Knowledge Only
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--no-shared \
--format plotlyFull Graph (All Agents + Shared)
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--show-shared \
--format plotlyBenefits
Performance
- Single vector index = fastest queries (9/10)
- No aggregation overhead for cross-agent queries
- Optimized graph traversal on unified graph
Flexibility
- Native cross-agent queries without helper functions
- Agent-specific queries via simple metadata filter
- Shared knowledge queries via
shared=Truefilter
Graph Quality
- Unified graph enables better relationship traversal
- Cross-agent relationships visible in single graph
- Better graph algorithm performance
Simplicity
- Minimal code changes
- Leverages mem0's native metadata filtering
- No complex aggregation logic needed
Migration
For Existing Memories
If you have existing memories with old user_id, you can:
1. Update metadata (recommended):
python3 skills/mem0-memory/scripts/validation/update-memories-metadata.py2. Re-run creation scripts to add metadata:
python3 skills/mem0-memory/scripts/create/create-all-agent-memories.py --skip-existing
python3 skills/mem0-memory/scripts/create/create-all-skill-memories.py --skip-existingVerification
Run the verification script:
python3 skills/mem0-memory/scripts/utils/verify-architecture.pyComparison with Alternatives
| Metric | Agent-as-User | Metadata-Filtered | Hierarchical |
|---|---|---|---|
| Agent-specific query | 50ms | 55ms | 45ms |
| Cross-agent query | 200ms (aggregation) | 50ms (native) | 150ms (aggregation) |
| Graph traversal | Good (focused) | Excellent (unified) | Good (tiered) |
| Implementation complexity | Medium | Low | High |
Winner: Metadata-Filtered - Best balance of performance and simplicity.
Research Evidence
- Mem0 best practices recommend metadata filtering for multi-agent systems
- DAMCS research shows shared graphs with metadata achieve 63-74% better coordination
- G-Memory shows unified graphs improve retrieval quality by 20%
Related Files
scripts/utils/agent-queries.py- Query helper functionsscripts/crud/search-memories.py- Search with metadata filtersscripts/visualization/visualize-mem0-graph.py- Graph visualization with filteringhooks/src/skill/decision-processor.ts- Auto-detects agent context
Mem0 Graph Visualization Reference
Complete guide to Mem0 graph visualization for OrchestKit plugin structure, including setup, usage, best practices, and troubleshooting.
Overview
This system provides colorized graph visualization of the OrchestKit plugin structure stored in Mem0. Since Mem0 does not natively support multi-color node visualization, we use external tools (Plotly, NetworkX) to create custom visualizations.
Research Findings (January 2026)
Mem0 does NOT natively support multi-color node visualization in its built-in UI. However, Mem0's Graph Memory API provides all necessary data (entity types, metadata, relationships) to build custom multi-color visualizations using external tools.
What Mem0 Provides
- Entity extraction with types (person, organization, project, etc.)
- Relationship extraction with relation types
- Metadata storage (arbitrary key/value pairs)
- Graph-aware search (
search()andget_all()withenable_graph=True) - Custom prompts for entity extraction
- Filtering and thresholds
What Mem0 Does NOT Provide
- Built-in multi-color node visualization
- Custom styling based on entity types
- Color mapping in the native UI
- Edge styling based on relation types
Best Practices (2026)
Color Palette Design
1. Limit Palette Size: Use ≤ 7-10 distinct categories for categorical coloring 2. Color Discriminability: Large color differences are crucial when links connect nodes 3. Neutral Edges: Use neutral or gray links to avoid visual interference with node colors 4. Accessibility: Use colorblind-safe palettes (ColorBrewer, OKLab-based) 5. Edge Styling: Edge color should typically recede (gray or light)
Implementation Approach
1. Retrieve data from Mem0 with enable_graph=True 2. Map entity types to colors using metadata 3. Use external visualization tools (Plotly, D3.js, NetworkX, etc.)
System Architecture
Custom Categories
18 custom project-level categories defined in Mem0:
agents- All 35 specialized AI agent personasbackend-skills- Backend development patternsfrontend-skills- Frontend development patternsai-llm-skills- AI and LLM patternstesting-skills- Testing patternssecurity-skills- Security patternsdevops-skills- DevOps patternsgit-github-skills- Git/GitHub operationsworkflow-skills- Workflow patternsquality-skills- Quality gates and reviewscontext-skills- Context managementevent-driven-skills- Event-driven architecturedatabase-skills- Database patternsaccessibility-skills- Accessibility patternsmcp-skills- MCP patternstechnologies- Core technologiesarchitecture-decisions- Architecture decisionsrelationships- Entity relationships
Setup:
python3 skills/mem0-memory/scripts/setup/setup-categories.pyEnhanced Metadata Structure
All memories include:
entity_type: "Agent", "Skill", "Technology", "Category", "Architecture"color_group: "agent", "skill", "technology", "category", "architecture"category: Category slug (e.g., "backend-skills", "agents")plugin_component: true (flag for plugin structure memories)name: Entity name- Additional fields:
skills,implements,extends, etc.
Color Scheme
Following 2026 best practices:
- Agents (Blue #3B82F6): All 36 specialized AI agent personas
- Skills (Green #10B981): All 200 skills
- Technologies (Orange #F59E0B): Core technologies
- Categories (Purple #8B5CF6): Skill categories
- Architecture (Red #EF4444): Architecture decisions
- Unknown (Gray #9CA3AF): Unclassified entities
Edge Styling
Different relation types get different edge styles:
uses: Solid line, width 2implements: Dashed line, width 2extends: Dotted line, width 1.5recommends: Solid line, width 3belongs_to: Solid line, width 1
Quick Start
Complete Setup (One-Time)
# Run master setup script
skills/mem0-memory/scripts/setup/setup-complete-visualization.shThis will: 1. Check and install dependencies 2. Set up custom categories 3. Update existing memories 4. Create comprehensive memories (categories, technologies, agents, skills) 5. Create relationships 6. Generate initial visualization
Manual Setup
# 1. Install visualization dependencies
skills/mem0-memory/scripts/visualization/setup-visualization-deps.sh
# 2. Set up custom categories
python3 skills/mem0-memory/scripts/setup/setup-categories.py
# 3. Update existing memories
python3 skills/mem0-memory/scripts/validation/update-memories-metadata.py
# 4. Create comprehensive memories
python3 skills/mem0-memory/scripts/create/create-category-memories.py
python3 skills/mem0-memory/scripts/create/create-technology-memories.py
python3 skills/mem0-memory/scripts/create/create-all-agent-memories.py
python3 skills/mem0-memory/scripts/create/create-all-skill-memories.py
# 5. Create relationships
python3 skills/mem0-memory/scripts/create/create-deep-relationships.py
# 6. Generate visualization
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py --format plotlyVisualization Tool
Location
skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py
Usage
# Interactive Plotly HTML (recommended)
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--user-id "orchestkit:all-agents" \
--format plotly \
--output mem0-graph.html
# Static NetworkX image
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--format networkx \
--output mem0-graph.png
# JSON export (for custom visualizations)
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--format json \
--output mem0-graph.json
# Mermaid diagram (text-based, version-controllable)
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--format mermaid \
--output mem0-graph.mmd
# GraphML export (for Cytoscape, Gephi)
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--format graphml \
--output mem0-graph.graphml
# CSV export (nodes.csv, edges.csv)
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py \
--format csv \
--output mem0-graph.csvOutput Location
All exports go to outputs/ directory in project root.
Interactive Features (Plotly)
- Click legend items to filter by entity type
- Hover over nodes for details
- Mouse wheel to zoom
- Pan to navigate
- Search box (basic implementation)
Relationship Structure
1-Hop Relationships (Direct)
- Agent → Skill (uses):
backend-system-architect→ uses →fastapi-advanced - Skill → Technology (implements):
fastapi-advanced→ implements →FastAPI - Technology → Technology (extends/uses):
pgvector→ extends →PostgreSQL
2-Hop Relationships
- Agent → Skill → Technology:
backend-system-architect→ uses →fastapi-advanced→ implements →FastAPI
3-Hop Relationships
- Agent → Skill → Technology → Technology:
database-engineer→ uses →pgvector-search→ implements →pgvector→ extends →PostgreSQL
4-Hop Chains (Multi-Hop)
Complete technology stack chains connecting agents through skills to technologies and dependencies.
Querying Relationships
Search with Graph Enabled
python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "backend-system-architect uses fastapi-advanced" \
--user-id "orchestkit:all-agents" \
--enable-graphGet Related Memories (Multi-Hop Traversal)
# Get memory ID first
MEMORY_ID=$(python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "backend-system-architect" \
--user-id "orchestkit:all-agents" \
--limit 1 | jq -r '.results[0].id')
# Traverse relationships
python3 skills/mem0-memory/scripts/graph/get-related-memories.py \
--memory-id "$MEMORY_ID" \
--depth 3 \
--user-id "orchestkit:all-agents"Scripts Reference
All scripts are located in skills/mem0-memory/scripts/:
Setup Scripts
setup-visualization-deps.sh- Install plotly, networkx, matplotlib, kaleidosetup-categories.py- Define custom Mem0 categoriessetup-complete-visualization.sh- Master setup script (runs all steps)
Memory Creation Scripts
create-category-memories.py- Create memories for all 18 categoriescreate-technology-memories.py- Create memories for 24+ technologiescreate-all-agent-memories.py- Create memories for all 36 agentscreate-all-skill-memories.py- Create memories for all 200 skillscreate-deep-relationships.py- Create comprehensive relationships
Maintenance Scripts
update-memories-metadata.py- Update existing memories with enhanced metadatarefresh-visualization.sh- Update memories, regenerate visualization, export all formatsverify-visualization-setup.sh- Check dependencies, Mem0 connection, test exports
Visualization Scripts
visualize-mem0-graph.py- Main visualization tool (supports multiple formats)
Troubleshooting
Categories Still Show "technology" / "professional_details"
1. Check if categories were set:
python3 skills/mem0-memory/scripts/setup/setup-categories.py2. Update existing memories to trigger re-categorization:
python3 skills/mem0-memory/scripts/validation/update-memories-metadata.py3. Wait 2-5 minutes for Mem0 to process and re-categorize
Visualization Shows "Unknown" Entity Types
1. Update existing memories with enhanced metadata:
python3 skills/mem0-memory/scripts/validation/update-memories-metadata.py2. Wait for Mem0 processing (2-5 minutes)
3. Regenerate visualization:
python3 skills/mem0-memory/scripts/visualization/visualize-mem0-graph.py --format plotlyNo Relationships in Visualization
1. Check if graph is enabled when creating memories (use --enable-graph) 2. Wait for Mem0 processing - relationships are extracted asynchronously (2-5 minutes) 3. Verify relationships exist:
python3 skills/mem0-memory/scripts/crud/search-memories.py \
--query "backend-system-architect" \
--user-id "orchestkit:all-agents" \
--enable-graphDependencies Not Installing
1. Try virtual environment:
python3 -m venv .venv
source .venv/bin/activate
pip install plotly networkx matplotlib kaleido2. Or use --user flag:
pip3 install --user plotly networkx matplotlib kaleidoMem0 API Errors
1. Check API key is set in environment or config 2. Verify rate limits - batch processing may be needed for large datasets 3. Check Mem0 plan - custom categories may require Pro/Enterprise plan
Performance Tips
For Large Graphs
- Use
--limitparameter to sample nodes - Export to JSON first, then filter before visualization
- Use NetworkX for static images (faster than Plotly for large graphs)
- Consider pagination for graphs with 1000+ nodes
Optimization
- Cache graph data locally between exports
- Use batch processing for memory creation
- Wait between API calls to respect rate limits
Maintenance
Regular Refresh
# Update memories and regenerate visualization
skills/mem0-memory/scripts/visualization/refresh-visualization.shAdding New Entities
1. Create entity memory with proper metadata (entity_type, color_group, category) 2. Create relationship memories linking to existing entities 3. Wait 2-5 minutes for Mem0 processing 4. Regenerate visualization
References
- Mem0 Graph Memory Overview
- Node-Link Diagram Color Discriminability Research
- Memgraph Lab Styling Guide
- Mem0 API Reference
Files Location
All scripts: skills/mem0-memory/scripts/ All documentation: skills/mem0-memory/references/ All outputs: outputs/ (project root)
#!/usr/bin/env python3
"""
Batch delete memories from mem0.
Usage: ./batch-delete.py --memory-ids '["mem_123","mem_456"]'
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Batch delete mem0 memories")
parser.add_argument("--memory-ids", required=True, help="JSON array of memory IDs to delete")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
memory_ids = json.loads(args.memory_ids)
if not isinstance(memory_ids, list):
raise ValueError("--memory-ids must be a JSON array")
result = client.batch_delete(memories=memory_ids)
print(json.dumps({
"success": True,
"deleted_count": len(memory_ids),
"result": result
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Batch update memories in mem0 (up to 1000 at once).
Usage: ./batch-update.py --memories '[{"memory_id":"mem_123","text":"updated"}]'
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Batch update mem0 memories")
parser.add_argument("--memories", required=True, help="JSON array of memory updates")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
memories = json.loads(args.memories)
if not isinstance(memories, list):
raise ValueError("--memories must be a JSON array")
result = client.batch_update(memories=memories)
print(json.dumps({
"success": True,
"updated_count": len(memories),
"result": result
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Bulk export multiple user_ids from mem0.
Usage: ./bulk-export.py --user-ids "user1,user2,user3" --schema '{"format":"json"}'
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Bulk export multiple user_ids from mem0")
parser.add_argument("--user-ids", required=True, help="Comma-separated list of user IDs")
parser.add_argument("--schema", default='{"format":"json"}', help="Export schema JSON object")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
# Parse user IDs
user_ids = [uid.strip() for uid in args.user_ids.split(",")]
# Parse schema
try:
schema_obj = json.loads(args.schema) if args.schema else {"format": "json"}
except json.JSONDecodeError:
schema_obj = {"format": args.schema}
# Create exports for each user_id
exports = []
for user_id in user_ids:
try:
# Create export with filters for this user_id
result = client.create_memory_export(
schema=json.dumps(schema_obj) if isinstance(schema_obj, dict) else str(schema_obj),
user_id=user_id
)
exports.append({
"user_id": user_id,
"export_id": result.get("export_id") if isinstance(result, dict) else None,
"status": "created",
"result": result
})
except Exception as e:
exports.append({
"user_id": user_id,
"status": "error",
"error": str(e)
})
print(json.dumps({
"success": True,
"count": len(user_ids),
"exports": exports
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Create memories for all agents in the OrchestKit plugin.
Scans agents/ directory and creates Mem0 memories with skill relationships.
"""
import json
import re
import sys
import yaml
from pathlib import Path
from typing import Dict, Any, List
# Add mem0 scripts to path
SCRIPT_DIR = Path(__file__).parent
PROJECT_ROOT = SCRIPT_DIR.parent.parent.parent.parent
AGENTS_DIR = PROJECT_ROOT / "agents"
sys.path.insert(0, str(SCRIPT_DIR.parent / "lib"))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
USER_ID = "orchestkit:all-agents"
def extract_agent_skills(agent_file: Path) -> List[str]:
"""Extract skills list from agent markdown file."""
content = agent_file.read_text()
skills = []
in_skills = False
for line in content.split('\n'):
if line.strip().startswith('skills:'):
in_skills = True
continue
if in_skills:
if line.strip().startswith('- '):
skill = line.strip()[2:].strip()
skills.append(skill)
elif line.strip() and not line.startswith(' ') and not line.startswith('\t') and not line.startswith('#'):
break
return skills
def extract_frontmatter(content: str) -> Dict[str, Any]:
"""Extract YAML frontmatter from markdown."""
frontmatter = {}
if not content.startswith("---"):
return frontmatter
try:
end_idx = content.find("---", 3)
if end_idx == -1:
return frontmatter
yaml_content = content[3:end_idx].strip()
frontmatter = yaml.safe_load(yaml_content) or {}
except Exception as e:
print(f"Warning: Failed to parse frontmatter: {e}")
return frontmatter
def create_agent_memory(client, agent_file: Path, agent_name: str) -> Optional[Dict[str, Any]]:
"""Create a memory for a single agent."""
content = agent_file.read_text()
frontmatter = extract_frontmatter(content)
# Extract agent info
name = frontmatter.get("name", agent_name)
description = frontmatter.get("description", "")
skills = extract_agent_skills(agent_file)
# Build memory text
text_parts = [
f"{name} agent: {description}",
f"The {name} agent is a specialized AI persona in the OrchestKit plugin."
]
if skills:
text_parts.append(f"The {name} agent uses {len(skills)} skills: {', '.join(skills[:10])}.")
if len(skills) > 10:
text_parts.append(f"Additional skills include: {', '.join(skills[10:20])}.")
memory_text = ". ".join(text_parts) + "."
# Build metadata
metadata = {
"type": "agent",
"entity_type": "Agent",
"color_group": "agent",
"category": "agents",
"plugin_component": True,
"name": name,
"agent_name": agent_name,
"agent_type": "specialist", # Can be "specialist", "generalist", etc.
"shared": False, # Agent-specific memory, not shared
"skills": skills[:30] # Limit skills in metadata
}
if description:
metadata["description"] = description[:300] # Truncate long descriptions
# Add model if specified
if "model" in frontmatter:
metadata["model"] = frontmatter["model"]
try:
result = client.add(
messages=[{"role": "user", "content": memory_text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f" ✓ Created: {name} ({len(skills)} skills)")
return result
except Exception as e:
print(f" ✗ Failed: {name}: {e}", file=sys.stderr)
return None
def main():
import argparse
parser = argparse.ArgumentParser(description="Create Mem0 memories for all agents")
parser.add_argument("--dry-run", action="store_true", help="Show what would be created without making changes")
parser.add_argument("--limit", type=int, help="Limit number of agents to process")
parser.add_argument("--skip-existing", action="store_true", help="Skip agents that already have memories")
args = parser.parse_args()
try:
client = get_mem0_client()
# Get all agent files
agent_files = list(AGENTS_DIR.glob("*.md"))
agent_files.sort()
if args.limit:
agent_files = agent_files[:args.limit]
print(f"Found {len(agent_files)} agents to process\n")
if args.dry_run:
print("DRY RUN MODE - No changes will be made\n")
# Check existing memories if skip-existing
existing_agents = set()
if args.skip_existing:
print("Checking for existing agent memories...")
try:
result = client.search(
query="agent specialized AI persona",
filters={"user_id": USER_ID, "metadata.entity_type": "Agent"},
limit=1000
)
for memory in result.get("results", []):
metadata = memory.get("metadata", {})
if "agent_name" in metadata:
existing_agents.add(metadata["agent_name"])
elif "name" in metadata:
existing_agents.add(metadata["name"])
print(f"Found {len(existing_agents)} existing agent memories\n")
except Exception as e:
print(f"Warning: Could not check existing memories: {e}\n")
created_count = 0
skipped_count = 0
failed_count = 0
for agent_file in agent_files:
agent_name = agent_file.stem # filename without .md
if args.skip_existing and agent_name in existing_agents:
print(f" ⊘ Skipped (exists): {agent_name}")
skipped_count += 1
continue
if args.dry_run:
skills = extract_agent_skills(agent_file)
print(f" [DRY RUN] Would create: {agent_name} ({len(skills)} skills)")
created_count += 1
else:
result = create_agent_memory(client, agent_file, agent_name)
if result:
created_count += 1
else:
failed_count += 1
print(f"\n=== Summary ===")
print(f"Created: {created_count}")
print(f"Skipped: {skipped_count}")
print(f"Failed: {failed_count}")
print(f"Total: {len(agent_files)}")
if args.dry_run:
print("\nRun without --dry-run to create memories")
else:
print("\n✓ Agent memories creation complete!")
print("Note: Agent-skill relationships will be created separately")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Create memories for all skills in the OrchestKit plugin.
Scans skills/ directory and creates Mem0 memories with proper metadata.
"""
import json
import re
import sys
import yaml
from pathlib import Path
from typing import Dict, Any, Optional, List
# Add mem0 scripts to path
SCRIPT_DIR = Path(__file__).parent
PROJECT_ROOT = SCRIPT_DIR.parent.parent.parent.parent
SKILLS_DIR = PROJECT_ROOT / "skills"
sys.path.insert(0, str(SCRIPT_DIR.parent / "lib"))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
USER_ID = "orchestkit:all-agents"
def extract_frontmatter(content: str) -> Dict[str, Any]:
"""Extract YAML frontmatter from markdown."""
frontmatter = {}
if not content.startswith("---"):
return frontmatter
try:
# Find frontmatter boundaries
end_idx = content.find("---", 3)
if end_idx == -1:
return frontmatter
yaml_content = content[3:end_idx].strip()
frontmatter = yaml.safe_load(yaml_content) or {}
except Exception as e:
print(f"Warning: Failed to parse frontmatter: {e}")
return frontmatter
def determine_category(skill_name: str, tags: List[str], content: str) -> str:
"""Determine skill category from name, tags, and content."""
name_lower = skill_name.lower()
tags_lower = [t.lower() for t in tags]
content_lower = content.lower()
# Category mapping based on patterns
if any(tag in ["backend", "api", "fastapi", "sqlalchemy", "database", "async"] for tag in tags_lower):
return "backend-skills"
if any(tag in ["frontend", "react", "typescript", "ui", "component"] for tag in tags_lower):
return "frontend-skills"
if any(tag in ["ai", "llm", "rag", "langgraph", "embedding", "agent"] for tag in tags_lower):
return "ai-llm-skills"
if any(tag in ["test", "testing", "mock", "coverage"] for tag in tags_lower):
return "testing-skills"
if any(tag in ["security", "auth", "owasp", "validation"] for tag in tags_lower):
return "security-skills"
if any(tag in ["devops", "ci", "cd", "deployment"] for tag in tags_lower):
return "devops-skills"
if any(tag in ["git", "github", "release"] for tag in tags_lower):
return "git-github-skills"
if any(tag in ["workflow", "coordination", "implementation"] for tag in tags_lower):
return "workflow-skills"
if any(tag in ["quality", "review", "golden"] for tag in tags_lower):
return "quality-skills"
if any(tag in ["context", "memory", "compression"] for tag in tags_lower):
return "context-skills"
if any(tag in ["event", "queue", "cqrs", "saga"] for tag in tags_lower):
return "event-driven-skills"
if any(tag in ["database", "migration", "schema"] for tag in tags_lower):
return "database-skills"
if any(tag in ["accessibility", "a11y", "wcag"] for tag in tags_lower):
return "accessibility-skills"
if any(tag in ["mcp", "model-context"] for tag in tags_lower):
return "mcp-skills"
# Fallback to name patterns
if "backend" in name_lower or "api" in name_lower or "fastapi" in name_lower:
return "backend-skills"
if "frontend" in name_lower or "react" in name_lower or "ui" in name_lower:
return "frontend-skills"
if "ai" in name_lower or "llm" in name_lower or "rag" in name_lower or "langgraph" in name_lower:
return "ai-llm-skills"
if "test" in name_lower:
return "testing-skills"
if "security" in name_lower or "auth" in name_lower:
return "security-skills"
return "unknown"
def determine_technology(skill_name: str, tags: List[str], content: str) -> Optional[str]:
"""Determine which technology a skill implements."""
name_lower = skill_name.lower()
tags_lower = [t.lower() for t in tags]
content_lower = content.lower()
# Technology mapping
tech_patterns = {
"FastAPI": ["fastapi", "fast-api"],
"React 19": ["react", "react19", "react-19"],
"LangGraph": ["langgraph", "lang-graph"],
"PostgreSQL": ["postgresql", "postgres", "pgvector"],
"TypeScript": ["typescript", "ts"],
"Python": ["python", "py"],
"TanStack Query": ["tanstack", "tanstack-query", "react-query"],
"Zustand": ["zustand"],
"Zod": ["zod"],
"Pydantic": ["pydantic"],
"Playwright": ["playwright"],
"pytest": ["pytest"],
"MSW": ["msw", "mock-service-worker"],
"Redis": ["redis"],
"Celery": ["celery"],
"RabbitMQ": ["rabbitmq", "rabbit-mq"],
"Docker": ["docker"],
"GitHub Actions": ["github-actions", "github actions"]
}
# Check tags first
for tech, patterns in tech_patterns.items():
if any(pattern in tag for tag in tags_lower for pattern in patterns):
return tech
# Check skill name
for tech, patterns in tech_patterns.items():
if any(pattern in name_lower for pattern in patterns):
return tech
# Check content
for tech, patterns in tech_patterns.items():
if any(pattern in content_lower for pattern in patterns):
return tech
return None
def create_skill_memory(client, skill_dir: Path, skill_name: str) -> Optional[Dict[str, Any]]:
"""Create a memory for a single skill."""
skill_md = skill_dir / "SKILL.md"
if not skill_md.exists():
print(f" ⚠ SKILL.md not found for {skill_name}")
return None
content = skill_md.read_text()
frontmatter = extract_frontmatter(content)
# Extract skill info
name = frontmatter.get("name", skill_name)
description = frontmatter.get("description", "")
tags = frontmatter.get("tags", [])
if isinstance(tags, str):
tags = [t.strip() for t in tags.split(",")]
# Determine category and technology
category = determine_category(skill_name, tags, content)
technology = determine_technology(skill_name, tags, content)
# Build memory text
text_parts = [
f"{name} skill: {description}",
f"The {name} skill provides patterns and best practices for {skill_name.replace('-', ' ')}."
]
if tags:
text_parts.append(f"Tags: {', '.join(tags[:5])}") # Limit tags
if technology:
text_parts.append(f"The {name} skill implements {technology} technology.")
text_parts.append(f"The {name} skill belongs to {category} category.")
memory_text = ". ".join(text_parts) + "."
# Build metadata
metadata = {
"type": "skill",
"entity_type": "Skill",
"color_group": "skill",
"category": category,
"plugin_component": True,
"name": name,
"skill_name": skill_name,
"shared": True, # Skills are shared knowledge across agents
"tags": tags[:10] # Limit tags in metadata
}
if technology:
metadata["implements"] = technology
metadata["technology"] = technology
if description:
metadata["description"] = description[:200] # Truncate long descriptions
try:
result = client.add(
messages=[{"role": "user", "content": memory_text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f" ✓ Created: {name} ({category})")
if technology:
print(f" → implements {technology}")
return result
except Exception as e:
print(f" ✗ Failed: {name}: {e}", file=sys.stderr)
return None
def main():
import argparse
parser = argparse.ArgumentParser(description="Create Mem0 memories for all skills")
parser.add_argument("--dry-run", action="store_true", help="Show what would be created without making changes")
parser.add_argument("--limit", type=int, help="Limit number of skills to process")
parser.add_argument("--skip-existing", action="store_true", help="Skip skills that already have memories")
args = parser.parse_args()
try:
client = get_mem0_client()
# Get all skill directories
skill_dirs = [d for d in SKILLS_DIR.iterdir() if d.is_dir() and (d / "SKILL.md").exists()]
skill_dirs.sort()
if args.limit:
skill_dirs = skill_dirs[:args.limit]
print(f"Found {len(skill_dirs)} skills to process\n")
if args.dry_run:
print("DRY RUN MODE - No changes will be made\n")
created_count = 0
skipped_count = 0
failed_count = 0
# Check existing memories if skip-existing
existing_skills = set()
if args.skip_existing:
print("Checking for existing skill memories...")
try:
result = client.search(
query="skill provides patterns",
filters={"user_id": USER_ID, "metadata.entity_type": "Skill"},
limit=1000
)
for memory in result.get("results", []):
metadata = memory.get("metadata", {})
if "skill_name" in metadata:
existing_skills.add(metadata["skill_name"])
print(f"Found {len(existing_skills)} existing skill memories\n")
except Exception as e:
print(f"Warning: Could not check existing memories: {e}\n")
for skill_dir in skill_dirs:
skill_name = skill_dir.name
if args.skip_existing and skill_name in existing_skills:
print(f" ⊘ Skipped (exists): {skill_name}")
skipped_count += 1
continue
if args.dry_run:
print(f" [DRY RUN] Would create: {skill_name}")
created_count += 1
else:
result = create_skill_memory(client, skill_dir, skill_name)
if result:
created_count += 1
else:
failed_count += 1
print(f"\n=== Summary ===")
print(f"Created: {created_count}")
print(f"Skipped: {skipped_count}")
print(f"Failed: {failed_count}")
print(f"Total: {len(skill_dirs)}")
if args.dry_run:
print("\nRun without --dry-run to create memories")
else:
print("\n✓ Skill memories creation complete!")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Create memories for all custom categories in OrchestKit plugin.
Creates category entity memories that group related skills, agents, and technologies.
"""
import sys
from pathlib import Path
# Add mem0 scripts to path
SCRIPT_DIR = Path(__file__).parent
PROJECT_ROOT = SCRIPT_DIR.parent.parent.parent.parent
sys.path.insert(0, str(SCRIPT_DIR.parent / "lib"))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
USER_ID = "orchestkit:all-agents"
# Category definitions (matching setup-categories.py)
CATEGORIES = [
{
"slug": "agents",
"name": "Agents",
"description": "Specialized AI agent personas including backend-system-architect, frontend-ui-developer, database-engineer, llm-integrator, security-auditor, and 30 more. These agents use specific skills to accomplish their tasks."
},
{
"slug": "backend-skills",
"name": "Backend Skills",
"description": "Backend development patterns including FastAPI, async Python, SQLAlchemy, API design, REST, GraphQL, microservices, database operations, connection pooling, and backend architecture patterns."
},
{
"slug": "frontend-skills",
"name": "Frontend Skills",
"description": "Frontend development patterns including React 19, TypeScript, UI components, TanStack Query, forms, performance optimization, accessibility, animations, lazy loading, and frontend architecture patterns."
},
{
"slug": "ai-llm-skills",
"name": "AI/LLM Skills",
"description": "AI and LLM patterns including RAG, embeddings, LangGraph, agent orchestration, LLM safety, prompt engineering, function calling, streaming, semantic caching, and AI/ML integration patterns."
},
{
"slug": "testing-skills",
"name": "Testing Skills",
"description": "Testing patterns including unit tests, integration tests, E2E tests, property-based testing, test coverage, mocking, test data management, and testing best practices."
},
{
"slug": "security-skills",
"name": "Security Skills",
"description": "Security patterns including OWASP Top 10, authentication, authorization, input validation, defense-in-depth, LLM safety, MCP security, and security auditing patterns."
},
{
"slug": "devops-skills",
"name": "DevOps Skills",
"description": "DevOps patterns for CI/CD, observability, GitHub operations, deployment, monitoring, and infrastructure as code."
},
{
"slug": "git-github-skills",
"name": "Git/GitHub Skills",
"description": "Git workflow, GitHub operations, releases, recovery patterns, stacked PRs, and version control best practices."
},
{
"slug": "workflow-skills",
"name": "Workflow Skills",
"description": "Workflow patterns for implementation, exploration, coordination, multi-agent workflows, and development processes."
},
{
"slug": "quality-skills",
"name": "Quality Skills",
"description": "Quality gates, reviews, golden dataset management, code quality, and quality assurance patterns."
},
{
"slug": "context-skills",
"name": "Context Skills",
"description": "Context compression, engineering, brainstorming, planning, memory management, and context optimization patterns."
},
{
"slug": "event-driven-skills",
"name": "Event-Driven Skills",
"description": "Event sourcing, message queues, outbox patterns, CQRS, and event-driven architecture patterns."
},
{
"slug": "database-skills",
"name": "Database Skills",
"description": "Database migrations, versioning, zero-downtime patterns, schema design, and database optimization patterns."
},
{
"slug": "accessibility-skills",
"name": "Accessibility Skills",
"description": "WCAG compliance, focus management, React ARIA patterns, and accessibility best practices."
},
{
"slug": "mcp-skills",
"name": "MCP Skills",
"description": "MCP advanced patterns, server building, tool composition, and Model Context Protocol integration."
},
{
"slug": "technologies",
"name": "Technologies",
"description": "Core technologies and frameworks including FastAPI, React 19, LangGraph, PostgreSQL, pgvector, TypeScript, Python 3.11+, and Claude Code 2.1.11."
},
{
"slug": "architecture-decisions",
"name": "Architecture Decisions",
"description": "Key architectural decisions including Graph-First Memory Architecture, Progressive Loading Protocol, CC 2.1.7 Flat Skill Structure, Hook-Based Lifecycle Automation, and Multi-Worktree Coordination."
},
{
"slug": "relationships",
"name": "Relationships",
"description": "Relationships between agents, skills, and technologies including agent-skill mappings, skill-technology implementations, multi-hop chains, and cross-entity connections."
}
]
def create_category_memory(client, category: Dict[str, Any]) -> bool:
"""Create a memory for a category."""
slug = category["slug"]
name = category["name"]
description = category["description"]
# Build memory text
text = f"{name} category: {description} The {name} category groups related entities in the OrchestKit plugin structure."
# Build metadata
metadata = {
"type": "category",
"entity_type": "Category",
"color_group": "category",
"category": slug,
"plugin_component": True,
"name": name,
"category_slug": slug,
"shared": True # Categories are shared knowledge across agents
}
try:
result = client.add(
messages=[{"role": "user", "content": text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f" ✓ Created: {name} ({slug})")
return True
except Exception as e:
print(f" ✗ Failed: {name}: {e}", file=sys.stderr)
return False
def main():
import argparse
parser = argparse.ArgumentParser(description="Create Mem0 memories for categories")
parser.add_argument("--dry-run", action="store_true", help="Show what would be created without making changes")
parser.add_argument("--skip-existing", action="store_true", help="Skip categories that already have memories")
args = parser.parse_args()
try:
client = get_mem0_client()
print(f"Creating memories for {len(CATEGORIES)} categories\n")
if args.dry_run:
print("DRY RUN MODE - No changes will be made\n")
# Check existing memories if skip-existing
existing_categories = set()
if args.skip_existing:
print("Checking for existing category memories...")
try:
result = client.search(
query="category groups related",
filters={"user_id": USER_ID, "metadata.entity_type": "Category"},
limit=1000
)
for memory in result.get("results", []):
metadata = memory.get("metadata", {})
if "category_slug" in metadata:
existing_categories.add(metadata["category_slug"])
elif "category" in metadata:
existing_categories.add(metadata["category"])
print(f"Found {len(existing_categories)} existing category memories\n")
except Exception as e:
print(f"Warning: Could not check existing memories: {e}\n")
created_count = 0
skipped_count = 0
failed_count = 0
for category in CATEGORIES:
if args.skip_existing and category["slug"] in existing_categories:
print(f" ⊘ Skipped (exists): {category['name']}")
skipped_count += 1
continue
if args.dry_run:
print(f" [DRY RUN] Would create: {category['name']} ({category['slug']})")
created_count += 1
else:
if create_category_memory(client, category):
created_count += 1
else:
failed_count += 1
print(f"\n=== Summary ===")
print(f"Created: {created_count}")
print(f"Skipped: {skipped_count}")
print(f"Failed: {failed_count}")
print(f"Total: {len(CATEGORIES)}")
if args.dry_run:
print("\nRun without --dry-run to create memories")
else:
print("\n✓ Category memories creation complete!")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Create Deep Multi-Hop Relationships in Mem0
Uses OrchestKit agents and skills to build comprehensive relationship chains
"""
import json
import re
import sys
from pathlib import Path
# Add mem0 scripts to path
SCRIPT_DIR = Path(__file__).parent
PROJECT_ROOT = SCRIPT_DIR.parent.parent.parent.parent
MEM0_SCRIPT = SCRIPT_DIR.parent / "crud" / "add-memory.py"
AGENTS_DIR = PROJECT_ROOT / "agents"
SKILLS_DIR = PROJECT_ROOT / "skills"
sys.path.insert(0, str(SCRIPT_DIR.parent / "lib"))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
USER_ID = "orchestkit:all-agents"
def extract_agent_skills(agent_file: Path) -> list[str]:
"""Extract skills list from agent markdown file."""
content = agent_file.read_text()
skills = []
in_skills = False
for line in content.split('\n'):
if line.strip().startswith('skills:'):
in_skills = True
continue
if in_skills:
if line.strip().startswith('- '):
skill = line.strip()[2:].strip()
skills.append(skill)
elif line.strip() and not line.startswith(' ') and not line.startswith('\t'):
break
return skills
def get_skill_category(skill_name: str) -> str:
"""Determine skill category from skill name and directory."""
skill_dir = SKILLS_DIR / skill_name
if not skill_dir.exists():
return "Unknown"
skill_md = skill_dir / "SKILL.md"
if skill_md.exists():
content = skill_md.read_text()
# Try to extract category from tags or description
if 'tags:' in content:
tags_match = re.search(r'tags:\s*\[(.*?)\]', content)
if tags_match:
tags = [t.strip().strip('"\'') for t in tags_match.group(1).split(',')]
# Map tags to categories
if any('ai' in t.lower() or 'llm' in t.lower() or 'rag' in t.lower() for t in tags):
return "AI/LLM Skills"
if any('backend' in t.lower() or 'api' in t.lower() or 'fastapi' in t.lower() for t in tags):
return "Backend Skills"
if any('frontend' in t.lower() or 'react' in t.lower() or 'ui' in t.lower() for t in tags):
return "Frontend Skills"
if any('test' in t.lower() or 'testing' in t.lower() for t in tags):
return "Testing Skills"
if any('security' in t.lower() or 'auth' in t.lower() or 'owasp' in t.lower() for t in tags):
return "Security Skills"
if any('memory' in t.lower() or 'context' in t.lower() for t in tags):
return "Context Skills"
return "Unknown"
def get_skill_technology(skill_name: str) -> str | None:
"""Determine which technology a skill implements."""
tech_mapping = {
'fastapi-advanced': 'FastAPI',
'sqlalchemy-2-async': 'PostgreSQL',
'react-server-components-framework': 'React 19',
'langgraph-state': 'LangGraph',
'langgraph-routing': 'LangGraph',
'langgraph-parallel': 'LangGraph',
'langgraph-checkpoints': 'LangGraph',
'langgraph-supervisor': 'LangGraph',
'pgvector-search': 'pgvector',
'tanstack-query-advanced': 'TypeScript',
'form-state-patterns': 'React 19',
}
return tech_mapping.get(skill_name)
def create_agent_skill_memories(client, agent_name: str, skills: list[str]):
"""Create memories linking agent to each skill with explicit relationships."""
memories_created = []
for skill in skills:
category = get_skill_category(skill)
technology = get_skill_technology(skill)
# Build relationship text that explicitly mentions all entities
text_parts = [
f"{agent_name} agent uses {skill} skill",
]
if category != "Unknown":
text_parts.append(f"The {skill} skill belongs to {category} category")
if technology:
text_parts.append(f"The {skill} skill implements {technology} technology")
text_parts.append(f"{technology} is a core technology used in OrchestKit plugin patterns")
# Add context about what the skill does
if 'api' in skill:
text_parts.append(f"{skill} provides API design patterns")
if 'database' in skill or 'sql' in skill:
text_parts.append(f"{skill} provides database patterns")
if 'react' in skill or 'frontend' in skill:
text_parts.append(f"{skill} provides frontend patterns")
if 'langgraph' in skill:
text_parts.append(f"{skill} provides LangGraph agent orchestration patterns")
memory_text = ". ".join(text_parts) + "."
# Map category name to category slug
category_slug = category.lower().replace(" ", "-").replace("/", "-") if category != "Unknown" else "unknown"
metadata = {
"type": "relationship",
"entity_type": "Unknown", # Relationship memories are connections
"color_group": "skill", # Default to skill color for relationships
"category": category_slug,
"plugin_component": True,
"from": agent_name,
"to": skill,
"relation": "uses",
"hop": 1,
"agent": agent_name,
"skill": skill
}
if category != "Unknown":
metadata["category"] = category_slug
if technology:
metadata["technology"] = technology
metadata["implements"] = technology
try:
result = client.add(
messages=[{"role": "user", "content": memory_text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
memories_created.append({
"agent": agent_name,
"skill": skill,
"result": result
})
print(f"✓ Created: {agent_name} → uses → {skill}")
except Exception as e:
print(f"✗ Failed: {agent_name} → {skill}: {e}", file=sys.stderr)
return memories_created
def create_skill_technology_memories(client, skill_name: str, technology: str, category: str):
"""Create memories linking skill to technology."""
text = (
f"{skill_name} skill implements {technology} technology. "
f"The {skill_name} skill belongs to {category} category. "
f"{technology} is a core technology used in OrchestKit plugin patterns. "
f"Skills that implement {technology} provide patterns and best practices for working with {technology}."
)
# Map category name to category slug
category_slug = category.lower().replace(" ", "-").replace("/", "-")
metadata = {
"type": "relationship",
"entity_type": "Skill", # Skills implement technologies
"color_group": "skill",
"category": category_slug,
"plugin_component": True,
"from": skill_name,
"to": technology,
"relation": "implements",
"hop": 2,
"skill": skill_name,
"technology": technology,
"implements": technology
}
try:
result = client.add(
messages=[{"role": "user", "content": text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f"✓ Created: {skill_name} → implements → {technology}")
return result
except Exception as e:
print(f"✗ Failed: {skill_name} → {technology}: {e}", file=sys.stderr)
return None
def create_multi_hop_chains(client):
"""Create explicit multi-hop relationship chains."""
print("\n=== Creating Multi-Hop Chains ===\n")
# Chain 1: backend-system-architect → fastapi-advanced → FastAPI → Python 3.11+
text1 = (
"backend-system-architect agent uses fastapi-advanced skill for async Python API development. "
"The fastapi-advanced skill implements FastAPI technology which is a backend framework. "
"FastAPI technology uses Python 3.11+ language for modern async features. "
"This creates a 4-hop chain: agent → uses → skill → implements → technology → uses → language."
)
client.add(
messages=[{"role": "user", "content": text1}],
user_id=USER_ID,
metadata={
"type": "multi-hop",
"entity_type": "Unknown",
"color_group": "skill",
"category": "relationships",
"plugin_component": True,
"chain": "agent→skill→technology→language",
"hops": 4
},
enable_graph=True
)
print("✓ Created 4-hop chain: backend-system-architect → fastapi-advanced → FastAPI → Python 3.11+")
# Chain 2: database-engineer → pgvector-search → pgvector → PostgreSQL
text2 = (
"database-engineer agent uses pgvector-search skill for hybrid search in RAG applications. "
"The pgvector-search skill implements pgvector technology for vector similarity search. "
"pgvector technology extends PostgreSQL database by adding vector search capabilities. "
"This creates a 4-hop chain: agent → uses → skill → implements → technology → extends → database."
)
client.add(
messages=[{"role": "user", "content": text2}],
user_id=USER_ID,
metadata={
"type": "multi-hop",
"entity_type": "Unknown",
"color_group": "skill",
"category": "relationships",
"plugin_component": True,
"chain": "agent→skill→technology→database",
"hops": 4
},
enable_graph=True
)
print("✓ Created 4-hop chain: database-engineer → pgvector-search → pgvector → PostgreSQL")
# Chain 3: frontend-ui-developer → react-server-components-framework → React 19 → TypeScript
text3 = (
"frontend-ui-developer agent uses react-server-components-framework skill for Next.js 16+ apps. "
"The react-server-components-framework skill implements React 19 technology with Server Components. "
"React 19 technology uses TypeScript for type safety in frontend development. "
"This creates a 4-hop chain: agent → uses → skill → implements → technology → uses → language."
)
client.add(
messages=[{"role": "user", "content": text3}],
user_id=USER_ID,
metadata={
"type": "multi-hop",
"entity_type": "Unknown",
"color_group": "skill",
"category": "relationships",
"plugin_component": True,
"chain": "agent→skill→technology→language",
"hops": 4
},
enable_graph=True
)
print("✓ Created 4-hop chain: frontend-ui-developer → react-server-components-framework → React 19 → TypeScript")
# Chain 4: llm-integrator → langgraph-state → LangGraph → multi-agent workflows
text4 = (
"llm-integrator agent uses langgraph-state skill for LangGraph state management. "
"The langgraph-state skill implements LangGraph technology for agent orchestration. "
"LangGraph technology enables multi-agent workflows with state persistence and routing. "
"This creates a relationship chain connecting agent skills to orchestration technology."
)
client.add(
messages=[{"role": "user", "content": text4}],
user_id=USER_ID,
metadata={
"type": "multi-hop",
"entity_type": "Unknown",
"color_group": "skill",
"category": "relationships",
"plugin_component": True,
"chain": "agent→skill→technology→pattern",
"hops": 4
},
enable_graph=True
)
print("✓ Created 4-hop chain: llm-integrator → langgraph-state → LangGraph → multi-agent workflows")
def create_all_agent_skill_relationships(client):
"""Create relationships for all agents and their skills."""
print("\n=== Phase 1: Creating All Agent-Skill Relationships ===\n")
agent_files = list(AGENTS_DIR.glob("*.md"))
agent_files.sort()
total_relationships = 0
failed_relationships = 0
for idx, agent_file in enumerate(agent_files, 1):
agent_name = agent_file.stem
skills = extract_agent_skills(agent_file)
if skills:
print(f"[{idx}/{len(agent_files)}] Processing {agent_name} ({len(skills)} skills)...")
try:
memories = create_agent_skill_memories(client, agent_name, skills)
total_relationships += len(memories)
except Exception as e:
print(f" ✗ Error processing {agent_name}: {e}", file=sys.stderr)
failed_relationships += len(skills)
else:
print(f"[{idx}/{len(agent_files)}] Skipping {agent_name} (no skills found)")
print(f"\n✓ Phase 1 complete: {total_relationships} agent-skill relationships created")
if failed_relationships > 0:
print(f" ⚠ {failed_relationships} relationships failed")
return total_relationships
def create_all_skill_technology_relationships(client):
"""Create relationships for all skills and their technologies."""
print("\n=== Phase 2: Creating All Skill-Technology Relationships ===\n")
# Scan all skills to find technology mappings
skill_dirs = [d for d in SKILLS_DIR.iterdir() if d.is_dir() and (d / "SKILL.md").exists()]
created_count = 0
failed_count = 0
for skill_dir in skill_dirs:
skill_name = skill_dir.name
category = get_skill_category(skill_name)
technology = get_skill_technology(skill_name)
if technology:
try:
create_skill_technology_memories(client, skill_name, technology, category)
created_count += 1
except Exception as e:
print(f" ✗ Failed: {skill_name} → {technology}: {e}", file=sys.stderr)
failed_count += 1
print(f"\n✓ Phase 2 complete: {created_count} skill-technology relationships created")
if failed_count > 0:
print(f" ⚠ {failed_count} relationships failed")
return created_count
def create_technology_dependencies(client):
"""Create technology-to-technology dependency relationships."""
print("\n=== Phase 3: Creating Technology Dependencies ===\n")
# Technology dependency mappings
dependencies = [
("pgvector", "PostgreSQL", "extends"),
("SQLAlchemy", "PostgreSQL", "uses"),
("Alembic", "SQLAlchemy", "uses"),
("FastAPI", "Python", "uses"),
("React 19", "TypeScript", "uses"),
("TanStack Query", "React 19", "uses"),
("Zustand", "React 19", "uses"),
("Zod", "TypeScript", "uses"),
("Pydantic", "Python", "uses"),
("Celery", "Redis", "uses"),
("LangGraph", "Python", "uses"),
]
created_count = 0
for tech_from, tech_to, rel_type in dependencies:
text = (
f"{tech_from} technology {rel_type} {tech_to} technology. "
f"{tech_from} depends on {tech_to} for core functionality. "
f"Both {tech_from} and {tech_to} are core technologies in OrchestKit plugin patterns."
)
metadata = {
"type": "relationship",
"entity_type": "Technology",
"color_group": "technology",
"category": "technologies",
"plugin_component": True,
"from": tech_from,
"to": tech_to,
"relation": rel_type,
"hop": 1
}
try:
client.add(
messages=[{"role": "user", "content": text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f" ✓ Created: {tech_from} → {rel_type} → {tech_to}")
created_count += 1
except Exception as e:
print(f" ✗ Failed: {tech_from} → {tech_to}: {e}", file=sys.stderr)
print(f"\n✓ Phase 3 complete: {created_count} technology dependencies created")
return created_count
def create_category_entity_relationships(client):
"""Create category-to-entity belongs_to relationships."""
print("\n=== Phase 4: Creating Category-Entity Relationships ===\n")
# This would require querying existing memories and matching categories
# For now, we'll create a few key examples
category_entities = [
("agents", "backend-system-architect", "Agent"),
("backend-skills", "fastapi-advanced", "Skill"),
("frontend-skills", "react-server-components-framework", "Skill"),
("ai-llm-skills", "langgraph-state", "Skill"),
("technologies", "FastAPI", "Technology"),
]
created_count = 0
for category_slug, entity_name, entity_type in category_entities:
text = (
f"{entity_name} {entity_type.lower()} belongs to {category_slug} category. "
f"The {category_slug} category contains {entity_type.lower()}s related to {category_slug.replace('-', ' ')}."
)
metadata = {
"type": "relationship",
"entity_type": entity_type,
"color_group": entity_type.lower(),
"category": category_slug,
"plugin_component": True,
"from": entity_name,
"to": category_slug,
"relation": "belongs_to",
"hop": 1
}
try:
client.add(
messages=[{"role": "user", "content": text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f" ✓ Created: {entity_name} → belongs_to → {category_slug}")
created_count += 1
except Exception as e:
print(f" ✗ Failed: {entity_name} → {category_slug}: {e}", file=sys.stderr)
print(f"\n✓ Phase 4 complete: {created_count} category-entity relationships created")
return created_count
def main():
import argparse
parser = argparse.ArgumentParser(description="Create comprehensive relationships in Mem0")
parser.add_argument("--phase", choices=["1", "2", "3", "4", "all"], default="all", help="Which phase to run")
parser.add_argument("--dry-run", action="store_true", help="Show what would be created without making changes")
parser.add_argument("--batch-size", type=int, default=10, help="Batch size for processing (to avoid rate limits)")
args = parser.parse_args()
print("=== Creating Deep Multi-Hop Relationships in Mem0 ===\n")
if args.dry_run:
print("DRY RUN MODE - No changes will be made\n")
return
try:
client = get_mem0_client()
except Exception as e:
print(f"Error initializing Mem0 client: {e}", file=sys.stderr)
sys.exit(1)
total_created = 0
if args.phase in ["1", "all"]:
total_created += create_all_agent_skill_relationships(client)
if args.phase in ["2", "all"]:
total_created += create_all_skill_technology_relationships(client)
if args.phase in ["3", "all"]:
total_created += create_technology_dependencies(client)
if args.phase in ["4", "all"]:
total_created += create_category_entity_relationships(client)
# Also create multi-hop chains
print("\n=== Phase 5: Creating Multi-Hop Chains ===\n")
create_multi_hop_chains(client)
total_created += 4 # 4 multi-hop chains
print(f"\n=== Summary ===")
print(f"Total relationships created: {total_created}")
print(f"\n✓ All relationships created successfully!")
print("Note: Mem0 may take a few minutes to process and extract graph relationships")
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Create comprehensive technology memories for OrchestKit plugin.
Creates memories for all key technologies used in the plugin.
"""
import sys
from pathlib import Path
# Add mem0 scripts to path
SCRIPT_DIR = Path(__file__).parent
PROJECT_ROOT = SCRIPT_DIR.parent.parent.parent.parent
sys.path.insert(0, str(SCRIPT_DIR.parent / "lib"))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
USER_ID = "orchestkit:all-agents"
# Technology definitions with descriptions
TECHNOLOGIES = [
{
"name": "FastAPI",
"description": "Modern, fast web framework for building APIs with Python 3.11+. Used extensively in OrchestKit plugin patterns for async Python backends.",
"version": "0.115.0+",
"category": "Backend Framework"
},
{
"name": "React 19",
"description": "Frontend framework with Server Components, concurrent features, and React Compiler. Core technology for frontend skills in OrchestKit.",
"version": "19.0.0+",
"category": "Frontend Framework"
},
{
"name": "LangGraph",
"description": "Agent orchestration framework for building multi-agent workflows. Used in AI/LLM skills for agent patterns and state management.",
"version": "1.0.0+",
"category": "AI/ML Framework"
},
{
"name": "PostgreSQL",
"description": "Advanced open-source relational database. Used with pgvector extension for hybrid search in RAG applications.",
"version": "18.0+",
"category": "Database"
},
{
"name": "pgvector",
"description": "PostgreSQL extension for vector similarity search. Enables hybrid BM25 + vector search with HNSW indexing.",
"version": "0.7.0+",
"category": "Database Extension"
},
{
"name": "TypeScript",
"description": "Typed superset of JavaScript. Used throughout frontend skills for type safety and better developer experience.",
"version": "5.7+",
"category": "Language"
},
{
"name": "Python",
"description": "Python programming language. OrchestKit requires Python 3.11+ for modern async features and type hints.",
"version": "3.11+",
"category": "Language"
},
{
"name": "Claude Code",
"description": "Claude Code IDE and plugin system. OrchestKit requires CC 2.1.11+ for Setup hooks, native parallel execution, and agent features.",
"version": "2.1.11+",
"category": "IDE/Platform"
},
{
"name": "TanStack Query",
"description": "Powerful data synchronization library for React. Used in frontend skills for server state management, caching, and optimistic updates.",
"version": "5.0+",
"category": "Frontend Library"
},
{
"name": "Zustand",
"description": "Lightweight state management library for React. Used in frontend skills for client-side state with minimal boilerplate.",
"version": "5.0+",
"category": "Frontend Library"
},
{
"name": "Zod",
"description": "TypeScript-first schema validation library. Used for runtime type checking and validation in frontend and API patterns.",
"version": "3.23.0+",
"category": "Validation Library"
},
{
"name": "Pydantic",
"description": "Data validation library for Python using type annotations. Used in FastAPI for request/response validation.",
"version": "2.9+",
"category": "Validation Library"
},
{
"name": "Playwright",
"description": "End-to-end testing framework for web applications. Used in E2E testing skills for browser automation.",
"version": "1.57+",
"category": "Testing Framework"
},
{
"name": "pytest",
"description": "Testing framework for Python. Used in backend testing skills with async support and fixtures.",
"version": "8.0+",
"category": "Testing Framework"
},
{
"name": "MSW",
"description": "Mock Service Worker for API mocking in tests. Used in frontend testing skills for deterministic API responses.",
"version": "2.0+",
"category": "Testing Library"
},
{
"name": "Redis",
"description": "In-memory data structure store with built-in search and JSON modules (formerly Redis Stack). Used for caching, session storage, and distributed locking patterns.",
"version": "8.0+",
"category": "Cache/Store"
},
{
"name": "Celery",
"description": "Distributed task queue for Python. Used in background job skills for async task processing.",
"version": "5.4+",
"category": "Task Queue"
},
{
"name": "RabbitMQ",
"description": "Message broker for message queue patterns. Used in event-driven architecture skills.",
"version": "3.13+",
"category": "Message Broker"
},
{
"name": "Docker",
"description": "Containerization platform. Used in DevOps skills for containerizing applications and services.",
"version": "Latest",
"category": "Containerization"
},
{
"name": "GitHub Actions",
"description": "CI/CD platform integrated with GitHub. Used in DevOps skills for automated workflows and deployments.",
"version": "Latest",
"category": "CI/CD"
},
{
"name": "SQLAlchemy",
"description": "Python SQL toolkit and ORM. OrchestKit uses SQLAlchemy 2.0+ with async support for database operations.",
"version": "2.0+",
"category": "ORM"
},
{
"name": "Alembic",
"description": "Database migration tool for SQLAlchemy. Used in database skills for schema versioning and migrations.",
"version": "1.13+",
"category": "Migration Tool"
},
{
"name": "Vite",
"description": "Next-generation frontend build tool. Vite 7 stable with Environment API; Vite 8 beta introduces Rolldown (Rust bundler, 10-30x faster). Used in frontend skills for fast development and optimized production builds.",
"version": "7.0+ (8.0 beta)",
"category": "Build Tool"
},
{
"name": "Biome",
"description": "Fast formatter and linter for JavaScript/TypeScript. Used in frontend skills as unified replacement for ESLint/Prettier.",
"version": "2.0+",
"category": "Linting Tool"
}
]
def create_technology_memory(client, tech: Dict[str, Any]) -> bool:
"""Create a memory for a technology."""
name = tech["name"]
description = tech["description"]
version = tech.get("version", "")
category = tech.get("category", "Technology")
# Build memory text
text = f"{name} technology: {description}"
if version:
text += f" Version {version}."
text += f" {name} is a core technology used in OrchestKit plugin patterns."
# Build metadata
metadata = {
"type": "technology",
"entity_type": "Technology",
"color_group": "technology",
"category": "technologies",
"plugin_component": True,
"name": name,
"version": version,
"tech_category": category,
"shared": True # Technologies are shared knowledge across agents
}
try:
result = client.add(
messages=[{"role": "user", "content": text}],
user_id=USER_ID,
metadata=metadata,
enable_graph=True
)
print(f" ✓ Created: {name} ({version})")
return True
except Exception as e:
print(f" ✗ Failed: {name}: {e}", file=sys.stderr)
return False
def main():
import argparse
parser = argparse.ArgumentParser(description="Create Mem0 memories for technologies")
parser.add_argument("--dry-run", action="store_true", help="Show what would be created without making changes")
parser.add_argument("--skip-existing", action="store_true", help="Skip technologies that already have memories")
args = parser.parse_args()
try:
client = get_mem0_client()
print(f"Creating memories for {len(TECHNOLOGIES)} technologies\n")
if args.dry_run:
print("DRY RUN MODE - No changes will be made\n")
# Check existing memories if skip-existing
existing_techs = set()
if args.skip_existing:
print("Checking for existing technology memories...")
try:
result = client.search(
query="technology core technology",
filters={"user_id": USER_ID, "metadata.entity_type": "Technology"},
limit=1000
)
for memory in result.get("results", []):
metadata = memory.get("metadata", {})
if "name" in metadata:
existing_techs.add(metadata["name"])
print(f"Found {len(existing_techs)} existing technology memories\n")
except Exception as e:
print(f"Warning: Could not check existing memories: {e}\n")
created_count = 0
skipped_count = 0
failed_count = 0
for tech in TECHNOLOGIES:
if args.skip_existing and tech["name"] in existing_techs:
print(f" ⊘ Skipped (exists): {tech['name']}")
skipped_count += 1
continue
if args.dry_run:
print(f" [DRY RUN] Would create: {tech['name']} ({tech.get('version', 'N/A')})")
created_count += 1
else:
if create_technology_memory(client, tech):
created_count += 1
else:
failed_count += 1
print(f"\n=== Summary ===")
print(f"Created: {created_count}")
print(f"Skipped: {skipped_count}")
print(f"Failed: {failed_count}")
print(f"Total: {len(TECHNOLOGIES)}")
if args.dry_run:
print("\nRun without --dry-run to create memories")
else:
print("\n✓ Technology memories creation complete!")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Add memory to mem0 via direct API call.
Usage: ./add-memory.py --text "content" --user-id "project-decisions" [--metadata '{"key":"value"}']
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path (for standalone execution)
# If installed as package, use: from lib.mem0_client import get_mem0_client
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
try:
# Try installed package first
from lib.mem0_client import get_mem0_client
except ImportError:
# Fallback to standalone mode
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Add memory to mem0")
parser.add_argument("--text", required=True, help="Memory content")
parser.add_argument("--user-id", required=True, help="User/scope ID")
parser.add_argument("--agent-id", help="Agent ID (optional)")
parser.add_argument("--metadata", default="{}", help="JSON metadata")
parser.add_argument("--enable-graph", action="store_true", help="Enable graph memory")
parser.add_argument("--api-key", help="Mem0 API key (or use MEM0_API_KEY env)")
parser.add_argument("--org-id", help="Org ID (or use MEM0_ORG_ID env)")
parser.add_argument("--project-id", help="Project ID (or use MEM0_PROJECT_ID env)")
args = parser.parse_args()
try:
# Initialize client
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
# Parse metadata
metadata = json.loads(args.metadata) if args.metadata else {}
# Add memory
result = client.add(
messages=[{"role": "user", "content": args.text}],
user_id=args.user_id,
agent_id=args.agent_id,
metadata=metadata,
enable_graph=args.enable_graph
)
# Output JSON for Claude to parse
# Handle different response formats from mem0 API
memory_id = None
if isinstance(result, dict):
if "results" in result and result["results"]:
memory_id = result["results"][0].get("id") or result["results"][0].get("memory_id")
elif "id" in result:
memory_id = result["id"]
elif "memory_id" in result:
memory_id = result["memory_id"]
print(json.dumps({
"success": True,
"memory_id": memory_id,
"result": result
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Delete memory from mem0.
Usage: ./delete-memory.py --memory-id "mem_abc123"
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Delete mem0 memory")
parser.add_argument("--memory-id", required=True, help="Memory ID to delete")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
result = client.delete(memory_id=args.memory_id)
print(json.dumps({
"success": True,
"message": "Memory deleted successfully",
"result": result
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Get all memories from mem0 with optional filters.
Usage: ./get-memories.py [--user-id "scope"] [--filters '{"key":"value"}']
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Get all mem0 memories")
parser.add_argument("--user-id", help="Filter by user_id")
parser.add_argument("--agent-id", help="Filter by agent_id")
parser.add_argument("--filters", default="{}", help="JSON filters")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
filters = json.loads(args.filters) if args.filters else {}
if args.user_id:
filters["user_id"] = args.user_id
if args.agent_id:
filters["agent_id"] = args.agent_id
result = client.get_all(filters=filters if filters else None)
# Handle both list and dict response formats from mem0 API
if isinstance(result, dict):
memories = result.get("results", result.get("memories", []))
count = result.get("count", len(memories))
elif isinstance(result, list):
memories = result
count = len(memories)
else:
memories = []
count = 0
print(json.dumps({
"success": True,
"count": count,
"memories": memories
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Get single memory from mem0 by ID.
Usage: ./get-memory.py --memory-id "mem_abc123"
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Get single mem0 memory by ID")
parser.add_argument("--memory-id", required=True, help="Memory ID")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
result = client.get(memory_id=args.memory_id)
print(json.dumps({
"success": True,
"memory": result
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Search memories in mem0 via direct API.
Usage: ./search-memories.py --query "text" --user-id "scope" [--limit 5]
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Search mem0 memories")
parser.add_argument("--query", required=True, help="Search query")
parser.add_argument("--user-id", help="Filter by user_id")
parser.add_argument("--agent-id", help="Filter by agent_id")
parser.add_argument("--agent-filter", help="Filter by agent_name (metadata filter)")
parser.add_argument("--shared-only", action="store_true", help="Only search shared knowledge (metadata.shared=True)")
parser.add_argument("--limit", type=int, default=10, help="Max results")
parser.add_argument("--filters", default="{}", help="JSON filters")
parser.add_argument("--enable-graph", action="store_true", help="Enable graph memory")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
# Build filters - mem0 API requires filters to be non-empty
filters = json.loads(args.filters) if args.filters else {}
if args.user_id:
filters["user_id"] = args.user_id
if args.agent_id:
filters["agent_id"] = args.agent_id
if args.agent_filter:
# Add metadata filter for agent_name
if "metadata" not in filters:
filters["metadata"] = {}
filters["metadata"]["agent_name"] = args.agent_filter
if args.shared_only:
# Add metadata filter for shared knowledge
if "metadata" not in filters:
filters["metadata"] = {}
filters["metadata"]["shared"] = True
# mem0 API requires filters, so if none provided, use empty dict (API will handle)
# But better: if user_id provided, use it; otherwise use empty filters
search_filters = filters if filters else ({"user_id": args.user_id} if args.user_id else {})
result = client.search(
query=args.query,
filters=search_filters if search_filters else None,
limit=args.limit,
enable_graph=args.enable_graph
)
# Format relations array for better visibility
relations = result.get("relations", []) if args.enable_graph else []
formatted_relations = []
for rel in relations:
formatted_relations.append({
"type": rel.get("type", "unknown"),
"source_id": rel.get("source_id"),
"target_id": rel.get("target_id") or rel.get("memory_id"),
"strength": rel.get("strength", 1.0),
"description": f"{rel.get('type', 'related')} -> {rel.get('target_id', 'unknown')}"
})
# Add relationship context to results
results_with_relations = []
for res in result.get("results", []):
res_copy = res.copy()
# Find relations for this result
result_relations = [
r for r in formatted_relations
if r.get("target_id") == res.get("id") or r.get("source_id") == res.get("id")
]
if result_relations:
res_copy["related_via"] = result_relations
results_with_relations.append(res_copy)
print(json.dumps({
"success": True,
"count": len(result.get("results", [])),
"results": results_with_relations,
"relations": formatted_relations,
"graph_enabled": args.enable_graph,
"relationship_summary": {
"total_relations": len(formatted_relations),
"relation_types": list(set(r.get("type", "unknown") for r in formatted_relations))
} if formatted_relations else None
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Update memory in mem0.
Usage: ./update-memory.py --memory-id "mem_abc123" --text "updated content" [--metadata '{"key":"value"}']
"""
import argparse
import json
import sys
from pathlib import Path
# Add lib directory to path
_SCRIPT_DIR = Path(__file__).parent
_LIB_DIR = _SCRIPT_DIR.parent / "lib"
if str(_LIB_DIR) not in sys.path:
sys.path.insert(0, str(_LIB_DIR))
from mem0_client import get_mem0_client # type: ignore # noqa: E402
def main():
parser = argparse.ArgumentParser(description="Update mem0 memory")
parser.add_argument("--memory-id", required=True, help="Memory ID to update")
parser.add_argument("--text", help="Updated content")
parser.add_argument("--metadata", help="Updated metadata (JSON)")
parser.add_argument("--api-key", help="Or use MEM0_API_KEY env")
parser.add_argument("--org-id", help="Or use MEM0_ORG_ID env")
parser.add_argument("--project-id", help="Or use MEM0_PROJECT_ID env")
args = parser.parse_args()
if not args.text and not args.metadata:
print(json.dumps({
"error": "At least one of --text or --metadata must be provided",
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
try:
client = get_mem0_client(
api_key=args.api_key,
org_id=args.org_id,
project_id=args.project_id
)
# Parse metadata if provided
metadata = None
if args.metadata:
metadata = json.loads(args.metadata)
# Call update with correct API signature: update(memory_id, text, metadata)
result = client.update(
memory_id=args.memory_id,
text=args.text,
metadata=metadata
)
print(json.dumps({
"success": True,
"memory": result
}, indent=2))
except ValueError as e:
print(json.dumps({
"error": str(e),
"type": "ValueError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except ImportError as e:
print(json.dumps({
"error": str(e),
"type": "ImportError"
}, indent=2), file=sys.stderr)
sys.exit(1)
except Exception as e:
print(json.dumps({
"error": str(e),
"type": type(e).__name__
}, indent=2), file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
"""Mem0 client library for skill scripts."""
from .mem0_client import get_mem0_client
__all__ = ["get_mem0_client"]
# Mem0 Python SDK
# Install with: pip install mem0ai
mem0ai>=1.0.0,<2.0.0
# Environment variable loading from .env files
python-dotenv>=1.0.0
#!/usr/bin/env python3
"""Setup script for mem0-skill-lib package.
Install with: pip install -e skills/mem0-memory/scripts/
This makes the lib module importable without sys.path manipulation,
allowing scripts to use: from lib.mem0_client import get_mem0_client
"""
from setuptools import setup
setup(
name="mem0-skill-lib",
version="1.0.0",
description="Shared mem0 client library for OrchestKit mem0-memory scripts",
packages=["lib"],
package_dir={"": "."},
install_requires=[
"mem0ai>=1.0.0,<2.0.0",
"python-dotenv>=1.0.0",
],
python_requires=">=3.11",
)