# Content Limits for Different Observation Types in ai-memory: A Complete Technical Guide

> Discover ai-memory content limits for raw inputs UI excerpts consolidation projections and auto-improvement outputs. Understand size restrictions from 1500 characters to 16 KB in this technical guide.

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

---

**The ai-memory crate enforces strict size restrictions ranging from 1,500 characters to 16 KB depending on whether observations represent raw inputs, UI excerpts, consolidation projections, or auto-improvement outputs.**

Understanding the content limits for different types of observations in ai-memory is essential for developers building memory-intensive AI applications. The `akitaonrails/ai-memory` repository implements multiple boundary constraints across its crates to ensure stored data remains bounded, privacy-protected, and optimized for LLM processing. These limits vary significantly based on the observation's lifecycle stage—from initial ingestion through sanitization to downstream consolidation pipelines.

## Raw Observation Body Limit (16 KB)

All observations entering the system face a hard ceiling of **16 KB** (`16 × 1024 bytes`) after sanitization. This limit is defined by the constant `OBSERVATION_BODY_MAX_BYTES` in the core sanitation module.

In [`crates/ai-memory-core/src/sanitize.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/sanitize.rs), the `Sanitizer` struct applies this constraint to every observation body using the `truncate_utf8_bytes` function. This ensures valid UTF-8 encoding while preventing memory bloat from oversized inputs.

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

fn create_user_prompt(obs_body: &str) -> Sanitized<NewObservation> {
    // The sanitizer trims the body to OBSERVATION_BODY_MAX_BYTES (16 KB).
    let sanitizer = Sanitizer::default();
    let sanitized_body = sanitizer.scrub(obs_body);
    let observation = NewObservation {
        kind: ObservationKind::UserPrompt,
        title: "Example prompt".into(),
        body: sanitized_body,
        ..Default::default()
    };
    // `Sanitized` guarantees the body respects the limit.
    Sanitized::new(observation).expect("Body exceeds limit")
}

```

## UI Excerpt Limits for Display Observations

When observations are displayed in user interfaces, they retain the same **16 KB** constraint applied to raw bodies. The hook payload handlers in [`crates/ai-memory-hooks/src/payload.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-hooks/src/payload.rs) enforce this for specific observation types:

- **UserPrompt excerpts**: Limited to `OBSERVATION_BODY_MAX_BYTES` (line 12)
- **PostToolUse excerpts**: Limited to `OBSERVATION_BODY_MAX_BYTES` (line 15)

This consistency ensures that excerpts shown in UI listings never exceed the underlying storage limit, preventing truncation mismatches between stored data and displayed previews.

## Consolidation Pipeline Limits

The consolidation process—where ai-memory projects observations forward for summarization—operates under two distinct constraints defined in [`crates/ai-memory-consolidate/src/consolidator.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-consolidate/src/consolidator.rs):

**Batch Size Limit**: A consolidation job may project a maximum of **256 observations** per batch (line 1083). This prevents unbounded memory usage during large consolidation operations.

**Projected Body Limit**: Each individual observation projected during consolidation is truncated to **3,000 characters** (line 1084). This character-based limit (distinct from the byte-based storage limits) optimizes context windows for summarization tasks.

```rust
// Conceptual representation of the consolidator limits
const MAX_PROJECTED_OBSERVATIONS: usize = 256;
const MAX_PROJECTED_OBSERVATION_BODY_CHARS: usize = 3000;

```

## Auto-Improvement Observation Constraints

The auto-improvement pipeline—which generates new observations through LLM calls—imposes the strictest limit. In [`crates/ai-memory-consolidate/src/auto_improve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-consolidate/src/auto_improve.rs) (line 60), observations are capped at **1,500 characters** per body.

This aggressive constraint serves a specific architectural purpose: keeping prompts short and focused for LLM processing during the auto-improvement workflow. The system prioritizes brevity over completeness in this context to minimize token usage and latency.

```rust
// Demonstrating the auto-improvement limit (1,500 chars).
fn truncate_for_auto_improve(text: &str) -> String {
    const LIMIT: usize = 1_500;
    if text.chars().count() > LIMIT {
        text.chars().take(LIMIT).collect()
    } else {
        text.to_string()
    }
}

```

## Technical Implementation and UTF-8 Safety

All truncation operations utilize **`truncate_utf8_bytes`** to guarantee valid UTF-8 boundaries. The system avoids simple byte-splitting that could corrupt multi-byte characters.

The limit hierarchy flows through the codebase as follows:

1. **Core sanitation** (`ai-memory-core`): Defines the base 16 KB constraint
2. **Hook payloads** (`ai-memory-hooks`): Re-exports limits for UI components
3. **Consolidation** (`ai-memory-consolidate`): Applies batch and character limits for projection
4. **Auto-improvement** (`ai-memory-consolidate`): Enforces the 1,500-character ceiling for generated content

## Summary

- **Raw storage**: 16 KB maximum per observation body (bytes)
- **UI excerpts**: 16 KB for UserPrompt and PostToolUse displays
- **Consolidation batches**: 256 observations maximum per projection cycle
- **Consolidation content**: 3,000 characters per projected observation
- **Auto-improvement**: 1,500 characters per generated observation
- **Safety**: All truncation uses `truncate_utf8_bytes` to preserve valid UTF-8 encoding
- **Key source**: [`crates/ai-memory-core/src/sanitize.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/sanitize.rs) defines the primary constraint constant

## Frequently Asked Questions

### What happens if an observation exceeds the 16 KB raw body limit?

The `Sanitizer` struct in [`crates/ai-memory-core/src/sanitize.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/sanitize.rs) automatically truncates the content to exactly 16 KB using UTF-8 safe truncation. The `Sanitized<NewObservation>` wrapper ensures that any observation passing through the type system respects this constraint before reaching storage.

### Why does auto-improvement use a 1,500 character limit instead of 16 KB?

The auto-improvement pipeline in [`crates/ai-memory-consolidate/src/auto_improve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-consolidate/src/auto_improve.rs) enforces a stricter 1,500-character limit to optimize LLM token usage and reduce latency during the improvement workflow. Shorter observations generate more focused prompts, making the auto-improvement process more efficient and cost-effective than using the full 16 KB storage limit.

### How do consolidation limits differ from raw observation limits?

Consolidation limits serve different architectural purposes than storage limits. While raw observations are capped at 16 KB (16,384 bytes) for storage efficiency, consolidation projections use a **3,000-character limit** (line 1084 in [`consolidator.rs`](https://github.com/akitaonrails/ai-memory/blob/main/consolidator.rs)) to fit within LLM context windows during summarization. Additionally, the consolidation batch limit of **256 observations** prevents memory exhaustion when processing large memory histories.

### Are content limits configurable at runtime?

Based on the source code analysis, these limits are defined as compile-time constants (`OBSERVATION_BODY_MAX_BYTES`, `MAX_PROJECTED_OBSERVATIONS`, etc.) rather than runtime configuration options. To modify these boundaries, developers must adjust the constant definitions in the respective crate source files ([`sanitize.rs`](https://github.com/akitaonrails/ai-memory/blob/main/sanitize.rs), [`consolidator.rs`](https://github.com/akitaonrails/ai-memory/blob/main/consolidator.rs), and [`auto_improve.rs`](https://github.com/akitaonrails/ai-memory/blob/main/auto_improve.rs)) and recompile the project.