How LLM-Driven Page Rewrite Works with `memory_consolidate`
The memory_consolidate subsystem rewrites wiki pages by feeding a session's raw observations to an LLM and persisting the generated markdown as a new atomic version, preserving the complete supersession chain through Git-backed versioning.
The ai-memory repository by akitaonrails implements this LLM-driven page rewrite mechanism in Rust, enabling autonomous agents to transform scattered session observations into coherent, structured documentation. The system guarantees atomicity and version control by treating each rewrite as a new revision rather than a destructive overwrite.
Single-Page Consolidation Pipeline
The consolidate_session function in crates/ai-memory-consolidate/src/consolidator.rs orchestrates the rewrite through a rigorous twelve-step workflow.
Observation Retrieval and Context Resolution
First, the consolidator loads all observations belonging to the target session_id. At lines 138-140, if the session contains no data, the function returns EmptySession:
let observations = self.reader.observations_for_session(session_id).await?;
Next, the system resolves the target workspace and project via resolve_target (lines 143-144), then fetches the originating AgentKind for front-matter attribution (lines 144-146):
let (ws, proj) = self.resolve_target(session_id).await?;
let agent_kind = self.resolve_agent_origin(session_id).await?;
Permission Preflight and Dry-Run Mode
Before invoking the LLM, the system performs an admission check at lines 150-154 via preflight_admission to verify the caller's authorization for Consolidate operations. This cheap-fails mechanism prevents unnecessary API costs on permission errors.
If dry_run is enabled (lines 158-169), the function returns a preview ConsolidationOutcome without contacting the LLM, allowing clients to validate the operation beforehand.
LLM Request Construction and Invocation
The consolidator reads the current page body at lines 171-176, defaulting to empty if the page does not exist:
let current_body = self.wiki.read_page(...).map(|md| md.body).unwrap_or_default();
At lines 177-182, build_request assembles a ChatRequest containing the session ID, token-budgeted observations, optional project-wide instructions, and the current page body. The system prompt is loaded from crates/ai-memory-consolidate/prompts/single_consolidate_system.md at compile time. The function then invokes the LLM at lines 190-191:
let page: ConsolidatedPage = complete_structured(&*self.llm, request).await?;
The complete_structured helper, defined in crates/ai-memory-llm/src/lib.rs, deserializes the response into a strongly-typed ConsolidatedPage struct defined in crates/ai-memory-consolidate/src/types.rs.
Atomic Page Persistence
The system constructs JSON front-matter at lines 192-199, stamping the session origin via stamp_session_origin and setting consolidated: true. The actual write occurs at lines 204-218 through Wiki::write_page in crates/ai-memory-wiki/src/wiki.rs:
let id = self.wiki.write_page(WritePageRequest { ... }).await?;
This creates a new revision of sessions/<id>.md within an atomic write-then-commit flow. Finally, lines 222-227 auto-commit the change with a message like consolidate(session …): <title>, ensuring the rewrite is permanently recorded in Git.
Multi-Page Batch Consolidation
For complex sessions requiring multiple page updates, consolidate_session_multi processes batches atomically. This function utilizes build_batch_request_with_slots to request up to five ConsolidatedPageUpdate objects from the LLM, using the system prompt at crates/ai-memory-consolidate/prompts/batch_consolidate_system.md.
Key differences from single-page mode include:
- Slot Snapshots: The LLM receives
slot_snapshotsto decide whether to update_slots/…pages - Project Instructions: The request includes project-wide instructions via
render_slot_snapshots - Path Override: For rule pages, the LLM-generated path is canonicalized to
_rules/<slug>.md - All-or-Nothing Semantics: The
Wiki::apply_batchmethod ensures that if any write fails, the entire transaction rolls back
Prompt Budgeting and Truncation
Both consolidation modes employ PromptBudgets to constrain input size within the provider's context window. The system uses clip_project_instructions and clip_current_body_for_prompt to safely truncate content while maintaining valid JSON schema structure. The render_current_body_section function handles projection of the current page state, ensuring the LLM always receives well-formed requests even with large observation sets.
Safety Mechanisms and Versioning
The implementation enforces several critical invariants:
- Admission Pre-flight: Unauthorized rewrites are blocked before LLM invocation via
preflight_admission - Supersession Chain: Git-based versioning through
Wiki::write_pageguarantees no data loss - Slot Update Guards:
should_skip_high_resistance_slot_updateprotects invariant slots and per-user namespaces - Summary Validation: The
usable_summaryfilter discards malformed LLM outputs before persistence
Implementation Examples
The following example demonstrates initializing the consolidator and executing a single-page rewrite:
use ai_memory_consolidate::Consolidator;
use ai_memory_store::{ReaderPool, WriterHandle};
use ai_memory_wiki::Wiki;
use std::sync::Arc;
use ai_memory_llm::LlmProvider;
async fn rewrite_session_example(
reader: ReaderPool,
writer: WriterHandle,
wiki: Wiki,
llm: Arc<dyn LlmProvider>,
workspace_id: ai_memory_core::WorkspaceId,
project_id: ai_memory_core::ProjectId,
session_id: ai_memory_core::SessionId,
) -> anyhow::Result<()> {
// Construct the consolidator (reuse across many sessions)
let consolidator = Consolidator::new(reader, writer, wiki, llm, workspace_id, project_id);
// Run a real consolidation (dry_run = false)
let outcome = consolidator
.consolidate_session(
session_id,
false, // not a dry-run
ai_memory_core::ActorContext::default(),
None, // no explicit author
None, // no per-call instructions
)
.await?;
println!("Session rewritten to {}", outcome.path);
println!("New title: {}", outcome.new_title);
Ok(())
}
For batch operations involving multiple pages:
async fn batch_consolidate_example(
consolidator: &Consolidator,
session_id: ai_memory_core::SessionId,
) -> anyhow::Result<()> {
let outcomes = consolidator
.consolidate_session_multi(
session_id,
false,
ai_memory_core::ActorContext::default(),
None,
None,
)
.await?;
for o in outcomes {
println!("Updated {} ({} bytes)", o.path, o.new_body_markdown.len());
}
Ok(())
}
Summary
- The
memory_consolidatesystem transforms raw session observations into structured markdown via LLM processing incrates/ai-memory-consolidate/src/consolidator.rs - Single-page rewrites follow a twelve-step atomic pipeline from observation loading to Git-commit versioning
- Multi-page batches guarantee all-or-nothing consistency through
Wiki::apply_batchand atomic transactions - Prompt budgeting via
PromptBudgetsand truncation functions ensures reliable operation within LLM context limits - Safety mechanisms including admission pre-flight, supersession chains, and slot guards prevent unauthorized or destructive operations
Frequently Asked Questions
What happens if a session has no observations when consolidating?
The consolidate_session function returns EmptySession immediately after querying the store at consolidator.rs#L138-L140, preventing unnecessary LLM calls and preserving system resources.
How does the system handle partial failures in batch consolidation?
Batch operations use Wiki::apply_batch which implements all-or-nothing semantics. If any single page write fails within the batch, the entire transaction is rolled back, ensuring consistency across the multi-page update.
Is the original page content preserved during an LLM-driven rewrite?
Yes. The system treats each rewrite as a new Git revision through Wiki::write_page and commit_all. The supersession chain is automatically recorded, allowing complete version history recovery and preventing destructive overwrites.
What prevents unauthorized agents from triggering consolidations?
An admission pre-flight check at consolidator.rs#L150-L154 validates the caller's scope and actor permissions via preflight_admission before any LLM invocation occurs, providing cheap-fail security for Consolidate operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →