MemoryRead: Session Memory Access
MemoryRead retrieves information stored in a persistent memory system, enabling state preservation across conversations.
Note: An interesting pattern in this code - the tool is included in an
ANT_ONLY_TOOLS
array intools.ts
with empty prompts defined in their respectiveprompt.ts
files. The tools are disabled by default as evidenced by theisEnabled()
method returningfalse
.When building an agentic system, persistent memory like this provides critical functionality. The filesystem-based approach shown here is straightforward to implement yet powerful - enabling agents to retain information across sessions without complex infrastructure. The tool's separation of read/write operations and simple directory-based structure makes it easy to debug and maintain.
Complete Prompt
// Actual prompt and description are defined elsewhere in the application
export const PROMPT = ''
export const DESCRIPTION = ''
Tool Prompt: MemoryRead
Accesses the Claude memory system to retrieve stored information from previous sessions. The memory system allows Claude to maintain context and data across conversations. When called without a file path, lists all available memory files along with the contents of the root index.md file.
How It Works
MemoryRead provides a simple interface to access persistent memory:
const inputSchema = z.strictObject({
file_path: z
.string()
.optional()
.describe('Optional path to a specific memory file to read'),
})
The implementation enables two modes of operation - listing available memory files or reading a specific file:
async *call({ file_path }) {
mkdirSync(MEMORY_DIR, { recursive: true })
// If a specific file is requested, return its contents
if (file_path) {
const fullPath = join(MEMORY_DIR, file_path)
if (!existsSync(fullPath)) {
throw new Error('Memory file does not exist')
}
const content = readFileSync(fullPath, 'utf-8')
yield {
type: 'result',
data: { content },
resultForAssistant: this.renderResultForAssistant({ content }),
}
return
}
// Otherwise return the index and file list
const files = readdirSync(MEMORY_DIR, { recursive: true })
.map(f => join(MEMORY_DIR, f.toString()))
.filter(f => !lstatSync(f).isDirectory())
.map(f => `- ${f}`)
.join('\n')
const indexPath = join(MEMORY_DIR, 'index.md')
const index = existsSync(indexPath) ? readFileSync(indexPath, 'utf-8') : ''
const quotes = "'''"
const content = `Here are the contents of the root memory file, \`${indexPath}\`:
${quotes}
${index}
${quotes}
Files in the memory directory:
${files}`
yield {
type: 'result',
data: { content },
resultForAssistant: this.renderResultForAssistant({ content }),
}
}
Key Features
MemoryRead provides these important capabilities:
-
Query Modes
- Index listing: Shows all available memory files
- File access: Reads a specific memory file
- Index content: Returns the main index.md content
-
Storage System
- Files stored in
~/.koding/memory
directory - Creates directory structure as needed
- Supports nested subdirectories
- Files stored in
-
Security Measures
- Path validation to prevent traversal attacks
async validateInput({ file_path }) { if (file_path) { const fullPath = join(MEMORY_DIR, file_path) if (!fullPath.startsWith(MEMORY_DIR)) { return { result: false, message: 'Invalid memory file path' } } if (!existsSync(fullPath)) { return { result: false, message: 'Memory file does not exist' } } } return { result: true } }
- Existence verification before access
- Read-only operation (paired with MemoryWrite)
-
Configuration
- Currently disabled by default
async isEnabled() { // TODO: Use a statsig gate // TODO: Figure out how to do that without regressing app startup perf return false }
- Read-only functionality
- No permissions required
Architecture
The MemoryRead tool follows a simple, filesystem-based architecture:
MemoryReadTool
↓
Input Validation → Checks path safety and file existence
↓
Storage Access → Directory creation and file reading
↓
Content Formatting → Index listing or individual file content
↓
Result Generation → Well-formatted output for Claude
Design priorities include:
- Simplicity: Direct filesystem access without caching
- Persistence: Files stored on disk for longevity
- Flexibility: Support for both listing and targeted reading
- Security: Path validation to prevent directory traversal
Integration
MemoryRead works with MemoryWrite as a complementary pair:
// No explicit permissions required
needsPermissions() {
return false
}
// Read-only operation
isReadOnly() {
return true
}
Together, these tools provide a simple but effective persistent storage system that maintains state between conversations. If enabled, these tools would:
- Allow users to maintain persistent data across multiple sessions
- Not require permission prompts (
needsPermissions()
returnsfalse
) - Store data files in the
~/.koding/memory
directory - Support structured information organization with directories and an index file
Usage Examples
Typical use cases:
-
Retrieving memory index
MemoryRead()
-
Reading specific files
MemoryRead(file_path: "user_preferences.md")
-
Accessing nested data
MemoryRead(file_path: "projects/my_project/notes.md")
Key benefits of the memory system:
- Persists information across different sessions
- Maintains context for recurring tasks
- Stores user preferences and settings
- Builds knowledge specific to the user
Memory System Design Patterns
The memory implementation here offers several patterns useful for agentic systems:
-
Hierarchical Storage: Using a directory structure creates natural organization for different types of memory (preferences, project context, etc.)
-
Index-based Access: The root index.md provides a table of contents, making memory contents discoverable and self-documenting
-
Plain Text Storage: Using Markdown files keeps data human-readable and easy to inspect/debug
-
Path Validation: Security checks prevent directory traversal attacks while allowing flexible memory structures
-
Minimal Dependencies: The filesystem-based approach works across platforms with no external databases
For developers building similar systems, this demonstrates how to implement long-term memory with minimal overhead while maintaining security and extensibility.