Read vs Write Safety — The Permission Model, Destructive-Tool Gating, Idempotency
A destructive tool that fires automatically is a liability, not a feature. Three safety tiers, explicit confirmation gates, and two idempotency patterns that make write tools safe to retry.
Why Safety Tiers Matter for Agent Loops
When a human uses a REST API, they read the documentation, think about consequences, and click deliberately. When an agent model uses an MCP tool, it may call the tool multiple times in a loop, retry on network failure, and make decisions about tool invocation based on context that may be incomplete or incorrect.
This means MCP tool safety requirements are higher than REST API safety requirements. A REST endpoint that is slightly dangerous is manageable — humans apply judgment. An MCP tool that is slightly dangerous is a liability — agents apply instructions, and instructions can be wrong.
The three-tier safety model is the solution. You classify every tool on your server as read-safe, elevated (writes with limited blast radius), or destructive (irreversible or high blast radius). Destructive tools get explicit confirmation gates. Elevated tools get scope restrictions. Read-safe tools run freely.
The Three-Tier Safety Model
The safety tier classification is not about the caller's identity — it is about the tool's effect on system state. memory_query is always read-safe regardless of who calls it. memory_forget is always destructive regardless of who calls it.
This matters because the scoped access model (from the previous lesson) restricts who can call write tools. But even callers with write access should face confirmation gates on destructive tools. The two protections work together: scope restricts access, gates restrict automation.
For Semantic Memory Layer in production:
- Claude Code sessions (read-only scope): can only call read-safe tools, not elevated or destructive
- Agent Gateway (full scope): can call elevated tools freely; destructive tools (memory_forget) require
confirmed=trueparameter - Manual admin calls: all tools available; destructive tools log to a separate audit trail
Idempotency: The Write Safety Foundation
Two idempotency patterns cover almost every write tool:
Content-hash keys for memory_remember: hash the content and namespace into a deterministic ID. The same content in the same namespace always produces the same ID. On retry, the tool finds the existing record and returns without writing — same response shape, zero state change. Callers cannot tell the difference between a first write and a retry.
Soft delete for memory_forget: instead of physically removing the record, mark it as deleted: true in the metadata. The record stays in ChromaDB but is filtered from all search results. A scheduled reindex physically purges deleted records. This makes deletions recoverable for up to the next reindex cycle — typically 24 hours in Knox's setup.
Together, these two patterns make the write surface safe for agent loops. An agent that retries memory_remember three times due to network instability writes exactly one memory. An agent that calls memory_forget with the wrong ID can have the deletion reversed by a human within 24 hours.
The Confirmation Gate Pattern
The confirmation gate for memory_forget is implemented as a two-step interaction:
- The agent calls
memory_forget(memory_id)without aconfirmedflag. The server returns{ would_delete: { memory_id, content_preview, namespace } }— showing what would be deleted without deleting it. - The agent reads the preview, verifies it matches the intended target, and calls
memory_forget(memory_id, confirmed=true). The server executes the soft delete.
This pattern prevents the most common agent mistake: calling memory_forget with an ID retrieved from a search result that was semantically close but not the intended target. The preview step forces the agent to see the content before deletion — it cannot skip this without explicitly passing confirmed=true after verifying the preview.
Now build the gate yourself: a tool router where a read-only caller can never reach the destructive tool, and even a write-scoped caller must pass confirmed: true before the soft-delete fires.
Read-After-Write Verification
The single most reliable check for write tool correctness is read-after-write: after calling memory_remember, immediately call memory_recall(returned_id) and verify the content matches.
This catches:
- Writes that return 200 but fail to embed (the DB write succeeded but ChromaDB embedding failed)
- Writes that land on a different server instance in a split-brain scenario
- Writes with incorrect namespace routing
In Knox's lessons.md, this pattern appears as: "read-after-write surfaces ownership boundaries — only read-after-write surfaces the boundary between what you think you wrote and what actually persisted." It is the most reliable correctness check for any write surface.
What's Next
The next lesson is the build lesson — constructing a real knowledge-OS MCP server with all 12 tools, namespaces, and the query/remember/recall pattern. The architecture is modeled directly on Semantic Memory Layer.