Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Agent Memory System

v1.0.0

Agent 记忆系统设计助手。构建长期记忆、短期记忆、情景记忆架构。触发词:记忆、memory、上下文管理、上下文窗口。

0· 161·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for sky-lv/openclaw-agent-memory-system.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Agent Memory System" (sky-lv/openclaw-agent-memory-system) from ClawHub.
Skill page: https://clawhub.ai/sky-lv/openclaw-agent-memory-system
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install openclaw-agent-memory-system

ClawHub CLI

Package manager switcher

npx clawhub@latest install openclaw-agent-memory-system
Security Scan
Capability signals
Crypto
These labels describe what authority the skill may exercise. They are separate from suspicious or malicious moderation verdicts.
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The name and description (agent memory design assistant) align with the provided implementation guidance: SQLite for long-term storage, a vector store (Chroma) for embeddings, short-term maps, and calls to an embeddings API. However, the SKILL.md contains concrete implementation code that implies runtime dependencies (Node runtime, SQLite bindings, Chroma client, crypto, fetch) and use of an OPENAI_API_KEY, none of which are declared in the skill metadata. This mismatch between declared requirements (none) and implied runtime needs is noteworthy.
!
Instruction Scope
The instructions include code that calls an external embeddings API (https://api.openai.com/v1/embeddings) using process.env.OPENAI_API_KEY, persists data to a SQLite DB and a local Chroma store, deletes vector entries, and constructs SQL queries by interpolating user-provided text (content LIKE '%${k}%') — which is vulnerable to SQL injection if executed as-is. The SKILL.md does not limit or sanitize what data gets stored; it instructs storing arbitrary 'content' and metadata, which could lead to sensitive data being persisted or sent to the external embedding endpoint.
Install Mechanism
This is an instruction-only skill with no install spec and no code files executed by the platform. That minimizes direct install risk. However, the guidance implies installing/using packages (SQLite client, Chroma client) if a developer implements it — those steps are not provided here.
!
Credentials
The implementation explicitly uses process.env.OPENAI_API_KEY but the skill declares no required environment variables. Requesting an API key would be proportionate for embeddings, but the omission in metadata is an inconsistency and a potential surprise to users. The skill would also require filesystem write access (SQLite DB and './chroma') — that access is not declared.
Persistence & Privilege
The skill is not always-enabled and is user-invocable, and does not request elevated platform privileges. The described behavior stores data to a local DB and vector store (its own data), but does not attempt to modify other skills or global settings.
What to consider before installing
This skill provides a coherent design and sample code for an agent memory system, but there are several red flags you should consider before using it: - Missing credential declaration: The code calls the OpenAI embeddings endpoint using process.env.OPENAI_API_KEY, yet the skill metadata does not declare any required environment variables. If you supply an API key, the skill's instructions will send content (potentially sensitive) to OpenAI. - Data persistence and exfiltration risk: The design persists arbitrary 'content' to a SQLite DB and a local Chroma vector store, and will send high-importance content to the external embeddings API. Review what you store and avoid putting secrets (passwords, tokens, PII) into memories. - Insecure SQL: The sample code builds SQL with string interpolation (content LIKE '%${k}%'), which is vulnerable to SQL injection. If you implement this, use parameterized queries or proper sanitization. - Missing dependency/runtime notes: The SKILL.md assumes a Node-like environment and libraries (SQLite client, Chroma client, fetch, crypto). The skill metadata doesn't list these — confirm the runtime and add explicit dependency/installation steps before implementation. Recommendations: only use or implement this guidance if you (or a developer you trust) will: 1) Explicitly declare and protect the OPENAI_API_KEY and never store secrets in the memory store; 2) Replace string-interpolated SQL with parameterized queries; 3) Add clear dependency and install instructions; 4) Audit what data will be persisted and sent to external services; and 5) Verify the linked repository (skill.json references a GitHub repo) to inspect full source and history. If you cannot verify these items, treat the skill as potentially unsafe.

Like a lobster shell, security has layers — review code before you run it.

Runtime requirements

🧬 Clawdis
latestvk97f61necx34h11qaedyxh7rf184hssf
161downloads
0stars
1versions
Updated 2w ago
v1.0.0
MIT-0

Agent Memory System

功能说明

设计 Agent 持久化记忆系统,优化上下文管理。

记忆分层架构

┌─────────────────────────────────────┐
│         Working Memory (上下文)        │  ← 当前对话,LLM直接访问
├─────────────────────────────────────┤
│      Short-Term (会话记忆)            │  ← 当前会话,SESSION
├─────────────────────────────────────┤
│      Long-Term (持久记忆)             │  ← 跨会话,数据库/文件
├─────────────────────────────────────┤
│      Semantic (向量记忆)               │  ← RAG,向量检索
├─────────────────────────────────────┤
│      Procedural (程序记忆)             │  ← 工具/Skill定义
└─────────────────────────────────────┘

完整实现

1. 记忆核心类

interface MemoryEntry {
  id: string;
  type: 'episodic' | 'semantic' | 'procedural';
  content: string;
  timestamp: number;
  importance: number;        // 0-10,重要程度
  accessCount: number;      // 访问次数
  tags: string[];
  metadata: Record<string, any>;
}

class AgentMemory {
  private shortTerm: Map<string, MemoryEntry[]> = new Map();
  private longTerm: SQLiteDatabase;
  private vectorStore: ChromaClient;
  private sessionId: string;
  
  constructor(sessionId: string, dbPath: string) {
    this.sessionId = sessionId;
    this.longTerm = new SQLiteDatabase(dbPath);
    this.vectorStore = new ChromaClient({ path: './chroma' });
    this.initDatabase();
  }
  
  private initDatabase() {
    this.longTerm.exec(`
      CREATE TABLE IF NOT EXISTS memories (
        id TEXT PRIMARY KEY,
        type TEXT NOT NULL,
        content TEXT NOT NULL,
        timestamp INTEGER NOT NULL,
        importance INTEGER DEFAULT 5,
        access_count INTEGER DEFAULT 0,
        tags TEXT,
        metadata TEXT
      );
      CREATE INDEX IF NOT EXISTS idx_timestamp ON memories(timestamp);
      CREATE INDEX IF NOT EXISTS idx_importance ON memories(importance);
      CREATE INDEX IF NOT EXISTS idx_type ON memories(type);
    `);
  }
  
  // 添加记忆
  async add(entry: Omit<MemoryEntry, 'id' | 'accessCount'>) {
    const id = crypto.randomUUID();
    const full: MemoryEntry = { ...entry, id, accessCount: 0 };
    
    // 短期记忆
    if (!this.shortTerm.has(this.sessionId)) {
      this.shortTerm.set(this.sessionId, []);
    }
    this.shortTerm.get(this.sessionId)!.push(full);
    
    // 持久化
    this.longTerm.prepare(
      `INSERT OR REPLACE INTO memories VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
    ).run(
      full.id, full.type, full.content, full.timestamp,
      full.importance, full.accessCount,
      JSON.stringify(full.tags), JSON.stringify(full.metadata)
    );
    
    // 向量化(重要记忆)
    if (full.importance >= 7) {
      await this.vectorStore.add({
        ids: [full.id],
        embeddings: [await this.embed(full.content)],
        documents: [full.content],
        metadatas: [{ type: full.type, tags: full.tags.join(',') }]
      });
    }
    
    return full;
  }
  
  // 检索记忆
  async retrieve(query: string, limit = 10): Promise<MemoryEntry[]> {
    // 1. 语义检索
    const queryEmbedding = await this.embed(query);
    const semantic = await this.vectorStore.search({
      query_embeddings: [queryEmbedding],
      n_results: limit
    });
    
    // 2. 关键词检索
    const keywords = query.toLowerCase().split(/\s+/);
    let sql = `SELECT * FROM memories WHERE `;
    sql += keywords.map(k => `content LIKE '%${k}%'`).join(' OR ');
    sql += ` ORDER BY importance DESC, timestamp DESC LIMIT ${limit}`;
    const keyword = this.longTerm.exec(sql).all() as MemoryEntry[];
    
    // 3. 去重合并
    const seen = new Set<string>();
    const results: MemoryEntry[] = [];
    [...semantic.results, ...keyword].forEach(m => {
      if (!seen.has(m.id)) {
        seen.add(m.id);
        m.accessCount++;
        results.push(m);
      }
    });
    
    // 更新访问计数
    results.forEach(m => {
      this.longTerm.prepare(
        `UPDATE memories SET access_count = ? WHERE id = ?`
      ).run(m.accessCount, m.id);
    });
    
    return results;
  }
  
  // 获取短期记忆(当前会话)
  getShortTerm(): MemoryEntry[] {
    return this.shortTerm.get(this.sessionId) || [];
  }
  
  // 压缩短期记忆到长期
  async consolidate() {
    const shortTerm = this.getShortTerm();
    
    // 保留最重要的记忆
    const important = shortTerm
      .filter(m => m.importance >= 6)
      .sort((a, b) => b.importance - a.importance)
      .slice(0, 50);
    
    // 合并重复
    const merged = this.mergeSimilar(important);
    
    // 更新短期记忆
    this.shortTerm.set(this.sessionId, merged);
  }
  
  // 遗忘低价值记忆
  async forget(threshold = 2) {
    // 遗忘低重要度、低访问的记忆
    this.longTerm.prepare(
      `DELETE FROM memories WHERE importance < ? AND access_count < ?`
    ).run(threshold, threshold);
    
    // 清理向量库
    await this.vectorStore.delete({
      where: { importance: { $lt: threshold } }
    });
  }
  
  // 构建上下文
  async buildContext(query: string, maxTokens = 6000): Promise<string> {
    const memories = await this.retrieve(query, 20);
    const shortTerm = this.getShortTerm();
    
    const parts: string[] = [];
    let totalTokens = 0;
    
    // 短期记忆优先
    for (const m of [...shortTerm.reverse(), ...memories]) {
      const text = `[${m.type}] ${m.content}`;
      const tokens = Math.ceil(text.length / 4);
      if (totalTokens + tokens > maxTokens) break;
      parts.unshift(text);
      totalTokens += tokens;
    }
    
    return `## 记忆上下文\n\n${parts.join('\n')}`;
  }
  
  private async embed(text: string): Promise<number[]> {
    // 调用 embedding API
    const response = await fetch('https://api.openai.com/v1/embeddings', {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}` },
      body: JSON.stringify({ model: 'text-embedding-3-small', input: text })
    });
    const data = await response.json();
    return data.data[0].embedding;
  }
  
  private mergeSimilar(memories: MemoryEntry[]): MemoryEntry[] {
    const merged: MemoryEntry[] = [];
    for (const m of memories) {
      const similar = merged.find(g => 
        g.type === m.type && 
        this.similarity(g.content, m.content) > 0.8
      );
      if (similar) {
        // 合并,保留最新的时间戳和最高的importance
        similar.importance = Math.max(similar.importance, m.importance);
        similar.timestamp = Math.max(similar.timestamp, m.timestamp);
      } else {
        merged.push(m);
      }
    }
    return merged;
  }
  
  private similarity(a: string, b: string): number {
    const setA = new Set(a.toLowerCase());
    const setB = new Set(b.toLowerCase());
    const intersection = new Set([...setA].filter(x => setB.has(x)));
    const union = new Set([...setA, ...setB]);
    return intersection.size / union.size;
  }
}

2. 使用示例

// 初始化
const memory = new AgentMemory(sessionId, './memory.db');

// 对话时注入记忆
async function chat(message: string) {
  const context = await memory.buildContext(message);
  
  const response = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: [
      { role: 'system', content: '你是助手的记忆系统使用指南。' },
      { role: 'system', content: context },
      { role: 'user', content: message }
    ]
  });
  
  const answer = response.choices[0].message.content;
  
  // 自动存储重要信息
  if (containsActionableInfo(message, answer)) {
    await memory.add({
      type: 'semantic',
      content: extractKeyInfo(answer),
      timestamp: Date.now(),
      importance: 7,
      tags: ['用户问答'],
      metadata: { source: 'chat' }
    });
  }
  
  return answer;
}

// 定期压缩
setInterval(() => memory.consolidate(), 30 * 60 * 1000);  // 每30分钟
setInterval(() => memory.forget(), 24 * 60 * 60 * 1000);   // 每天

3. 重要性评估

function evaluateImportance(text: string, context: string): number {
  let score = 5; // 基础分
  
  // 明确的重要词
  const importantKeywords = [
    '记住', '重要', '必须', '关键', '别忘了', '优先',
    'deadline', '截止', '紧急', '用户偏好', '账号', '密码'
  ];
  for (const kw of importantKeywords) {
    if (text.includes(kw)) score += 1;
  }
  
  // 用户明确要求记住
  if (text.match(/记住|remember|save|存储/)) score += 3;
  
  // 重复出现
  if (context.includes(text)) score += 2;
  
  // 限制范围
  return Math.min(10, Math.max(0, score));
}

存储策略

类型存储容量TTL
工作记忆上下文窗口128K tokens会话内
短期记忆Redis/Memory100条24小时
长期记忆SQLite无限制永久
向量记忆Chroma/Milvus按需定期清理

最佳实践

  1. 自动摘要:长记忆定期压缩成摘要
  2. 分层索引:按类型、时间、重要性多维索引
  3. 增量更新:避免重复存储相似内容
  4. 隐私保护:敏感信息加密存储
  5. 容量管理:设置token预算,定期清理

Comments

Loading comments...