# What Is the Purpose of the ai-memory-core Crate in the ai-memory Project?

> Discover the purpose of the ai-memory-core crate, the stable I/O-free foundation for the ai-memory project, offering essential types and utilities.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: deep-dive
- Published: 2026-09-05

---

**The `ai-memory-core` crate serves as the domain-model layer of the ai-memory project, providing a stable, I/O-free foundation of core types, identifiers, and utilities that all other crates depend on.**

This crate defines the fundamental vocabulary of the system—from workspace and page identifiers to observation kinds and sanitization rules—while enforcing strict architectural boundaries that keep business logic pure and testable. If you're working with the akitaonrails/ai-memory codebase, understanding this crate is essential to navigating its modular architecture.

---

## Core Responsibilities of ai-memory-core

The crate centralizes eight key responsibilities that together form the project's shared language:

| Responsibility | Description |
|---------------|-------------|
| **Core vocabulary** | Defines identifiers (`WorkspaceId`, `ProjectId`, `PageId`), enums (`AgentKind`, `PageKind`, `ObservationKind`), and structs representing system entities |
| **Error handling** | Provides the unified `MemoryError` type and `MemoryResult` alias via [`src/error.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/error.rs) |
| **Pure-compute constraint** | Contains **no I/O logic**—no file access, network calls, or OS-specific code |
| **Sanitization & privacy** | Implements `Sanitizer` and `Sanitized<T>` types for stripping private data before persistence |
| **Page & observation modeling** | Supplies `Page`, `NewPage`, `Observation`, `NewObservation`, and related validation helpers |
| **Slot handling** | Defines slot utilities (`SlotPlacement`, `is_slot_path`) for wiki slot syntax |
| **Routing snippets** | Provides `MARKER_START`, `MARKER_END`, and `find_marker_line` for embedded code snippets |
| **Workstream primitives** | Holds data structures for workstream events processed by downstream crates |

This design creates a **single source of truth** for identifiers and enforces the invariant that core types remain I/O-free, making them trivially unit-testable and safe to use from any context.

---

## Why ai-memory-core Contains No I/O

The module comment in [`src/lib.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/lib.rs) explicitly documents this architectural decision. By prohibiting file access, network calls, and OS-specific code, the crate achieves:

- **Deterministic testing**—all functions are pure Rust computations
- **Cross-crate safety**—downstream crates can depend on core types without pulling in I/O side effects
- **Clean architecture boundaries**—storage and networking concerns are pushed to dedicated crates like `ai-memory-store`

This mirrors patterns found in domain-driven design, where the domain layer remains isolated from infrastructure concerns.

---

## Key Types and Where to Find Them

### Identifiers ([`src/ids.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/ids.rs))

All system identifiers are centralized in [`crates/ai-memory-core/src/ids.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/ids.rs). The `PageId` type uses UUID v7 for time-sortable identifiers:

```rust
use ai_memory_core::ids::PageId;

let page_id = PageId::new(); // Generates UUID v7

```

Other identifiers include `WorkspaceId`, `ProjectId`, `AgentId`, `ThreadId`, and `EmbeddingId`.

### Observations ([`src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/observation.rs))

The `Observation` and `NewObservation` structs, plus the `ObservationKind` enum, model user messages, agent responses, and system events:

```rust
use ai_memory_core::{ObservationKind, NewObservation};

let obs = NewObservation {
    body: "User query here".into(),
    kind: ObservationKind::UserMessage,
    metadata: None,
};

```

### Sanitization ([`src/sanitize.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/sanitize.rs))

Before observations reach persistent storage, the `Sanitizer` strips sensitive data:

```rust
use ai_memory_core::{Sanitizer, SanitizeConfig, NewObservation};

let config = SanitizeConfig::default();
let sanitizer = Sanitizer::new(config);

let sanitized = sanitizer.sanitize_new_observation(
    NewObservation {
        body: "password: secret123".into(),
        kind: ObservationKind::UserMessage,
        ..Default::default()
    }
).expect("sanitization succeeds");

```

### Routing Snippets ([`src/routing_snippet.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/routing_snippet.rs))

The routing-skill system embeds code snippets in wiki pages using marker constants:

```rust
use ai_memory_core::routing_snippet::{MARKER_START, MARKER_END, find_marker_line};

let content = format!(
    "{}\nfn helper() {{}}\n{}",
    MARKER_START, MARKER_END
);

```

The `find_marker_line` helper locates these markers within page content for extraction.

---

## Error Handling Strategy

Rather than allowing each crate to define its own error types, `ai-memory-core` provides a unified error system in [`src/error.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/error.rs):

- **`MemoryError`**—the workspace-wide error enum
- **`MemoryResult<T>`**—type alias for `Result<T, MemoryError>`

This ensures that errors propagate consistently across crate boundaries without forcing downstream code to handle multiple error representations.

---

## How Other Crates Use ai-memory-core

The crate acts as a **dependency root** for the workspace. For example:

- **`ai-memory-store`**—imports core types to implement persistence logic
- **`ai-memory-wiki`**—uses `Page`, `SlotPlacement`, and routing snippet utilities
- **`ai-memory-workstream`**—processes `WorkstreamEvent` primitives defined in core
- **`ai-memory-mcp`**—depends on user models and credentials from [`src/user.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/user.rs)

This dependency graph ensures that changes to core types propagate predictably, while the no-I/O guarantee prevents accidental coupling between domain logic and infrastructure.

---

## File Structure Reference

| File Path | Purpose |
|-----------|---------|
| [`crates/ai-memory-core/Cargo.toml`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/Cargo.toml) | Crate metadata and public description |
| [`crates/ai-memory-core/src/lib.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/lib.rs) | Public façade and design documentation |
| [`crates/ai-memory-core/src/ids.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/ids.rs) | All identifier types (`PageId`, `WorkspaceId`, etc.) |
| [`crates/ai-memory-core/src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observation.rs) | Observation payloads and kinds |
| [`crates/ai-memory-core/src/page.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/page.rs) | Page model structs and validation |
| [`crates/ai-memory-core/src/sanitize.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/sanitize.rs) | Privacy-preserving sanitizer implementation |
| [`crates/ai-memory-core/src/routing_snippet.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/routing_snippet.rs) | Routing marker constants and helpers |
| [`crates/ai-memory-core/src/user.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/user.rs) | User accounts and API credentials |
| [`crates/ai-memory-core/src/error.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/error.rs) | Unified `MemoryError` and `MemoryResult` |

---

## Summary

- **`ai-memory-core`** is the **domain-model layer** of the ai-memory project, providing a stable foundation for all other crates
- It enforces **zero I/O**—all functions are pure computations, making testing trivial and dependencies safe
- It centralizes **identifiers**, **errors**, **observations**, **pages**, **sanitization**, **routing snippets**, and **user models**
- Downstream crates (`ai-memory-store`, `ai-memory-wiki`, etc.) build on this **contract** without duplicating type definitions or importing side effects
- The design follows **domain-driven architecture** principles, isolating core vocabulary from infrastructure concerns

---

## Frequently Asked Questions

### What makes ai-memory-core different from other crates in the project?

Unlike `ai-memory-store` (persistence) or `ai-memory-wiki` (wiki operations), `ai-memory-core` contains **only pure data types and computation**. It has no file system access, no database connections, and no network code. This makes it the safest dependency in the workspace—any crate can use it without worrying about side effects or test mocking complexity.

### How do I add a new identifier type to the system?

Define it in [`crates/ai-memory-core/src/ids.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/ids.rs) following the existing pattern. Most identifiers are newtype wrappers around UUIDs with `#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]` and a `new()` constructor. Once added, the type becomes available workspace-wide without modifying any other crate.

### Why is there a single MemoryError type instead of per-crate errors?

A unified `MemoryError` in [`src/error.rs`](https://github.com/akitaonrails/ai-memory/blob/main/src/error.rs) eliminates error conversion boilerplate when crossing crate boundaries. When `ai-memory-store` returns an error that `ai-memory-wiki` needs to handle, both speak the same error language. This reduces `From` implementations and improves debuggability through consistent error formatting.

### Can I use ai-memory-core in my own Rust project?

Yes—the crate is pure Rust with no I/O dependencies, making it suitable for any project needing similar domain types. However, it's designed specifically for the ai-memory ecosystem. For external use, you'd likely want to fork and adapt the identifier and observation models to your own domain requirements.