Skip to content

feat: add memory_purge_scope tool for batch scope cleanup#144

Closed
baizenghu wants to merge 1 commit intoCortexReach:mainfrom
baizenghu:feat/memory-purge-scope-tool
Closed

feat: add memory_purge_scope tool for batch scope cleanup#144
baizenghu wants to merge 1 commit intoCortexReach:mainfrom
baizenghu:feat/memory-purge-scope-tool

Conversation

@baizenghu
Copy link

Problem

Currently there is no way to delete all memories within a specific scope at once. Users who want to clean up stale or test data from a particular scope must delete entries one by one using memory_delete, which is tedious and error-prone.

This becomes especially painful when:

  • An agent accumulates outdated memories in a scope and needs a fresh start
    • Administrators need to clean up test/debug scopes
    • A scope becomes polluted with low-quality auto-captured memories

Solution

Add a new memory_purge_scope tool that deletes all memories within a given scope in a single operation.

Safety Features

  • Scope accessibility check: Validates the agent has access to the target scope via scopeManager.isAccessible() before deletion
    • Explicit confirmation: Requires confirm: true parameter to prevent accidental purges
    • Clear feedback: Returns the count of deleted memories

Tool Signature

memory_purge_scope(scope: string, confirm: boolean)

Example Usage

memory_purge_scope({ scope: "agent:my-agent", confirm: true })
// → "Successfully purged scope 'agent:my-agent': 42 memories deleted."

Implementation

  • Added registerMemoryPurgeScopeTool() in src/tools.ts
    • Uses existing store.bulkDelete([scope]) under the hood
    • Registered alongside other tools in the plugin entry point

Testing

Verified in production — agents can clean up their own scopes but cannot purge scopes they don't have access to.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AliceLJY
Copy link
Collaborator

Review: feat: add memory_purge_scope tool for agent-level scope cleanup

Verdict: Fix-then-merge — zero test coverage on a destructive operation is the blocking issue.


✅ What's working

  • Four-layer safety design is correct in order: confirm guard → empty-scope check → isAccessible() access control → try/catch around bulkDelete
  • bulkDelete([scope]) correctly matches the bulkDelete(scopeFilter: string[], ...) signature; SQL injection is mitigated by the existing escapeSqlLiteral call inside store.ts
  • agentId resolution via resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main" is consistent with all 6 other tools in the file
  • enableManagementTools: true gate means zero behavior change for existing deployments
  • Error responses are structured and LLM-readable (not_confirmed, invalid_scope, scope_access_denied, purge_failed)

🔴 Blocking

No test file. memory_purge_scope is a destructive, irreversible operation with zero test coverage. No test for the confirm=false path, no test for scope_access_denied, no happy-path test. CI has no regression protection for this tool.

Minimum coverage needed in a new test/memory-purge-scope.test.mjs:

// confirm guard
assert: calling with confirm=false  returns { error: "not_confirmed" }

// empty scope guard
assert: calling with scope=""  returns { error: "invalid_scope" }

// access control
assert: calling with an out-of-scope scope  returns { error: "scope_access_denied" }

// happy path
assert: calling with a valid scope  deletedCount matches actual records purged

Also wire into package.json test script (same issue as #148, #141, #149).

🟡 Suggested before merge

No audit log on success. bulkDelete deletes silently. For an admin tool that permanently destroys data, the success path should record {agentId, scope, deletedCount, timestamp} at debug/info level so operators can investigate accidental purges.

// after deletedCount is returned
context.logger?.debug?.(`memory_purge_scope: agentId=${agentId} scope=${scope} deleted=${deletedCount}`);

⚪ Non-blocking

  • Tool description example only shows the agent: namespace — worth listing valid namespaces (agent:, session:, global) so LLMs don't guess incorrectly
  • confirm: Type.Boolean(...) has no default: false declaration — adding one makes the intent explicit

The four-layer guard sequence and escapeSqlLiteral protection are solid. The blocking issue is purely test coverage — a destructive tool with no tests is not safe to ship regardless of how clean the logic is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants