The MentisDB Agent Memory Cookbook

Patterns and recipes for building AI agents that remember

1.4 Long-Running Project Memory

Long-running agent work fails when the only project state is the current prompt. A project memory chain should preserve the goal, active plan, completed actions, and a resumable checkpoint. The next session should be able to ask one query and reconstruct where to continue.

The Pattern

use mentisdb::{
    BinaryStorageAdapter, MentisDb, ThoughtInput, ThoughtQuery,
    ThoughtRole, ThoughtType,
};

fn build_long_running_project_memory() -> io::Result<()> {
    let dir = tempfile::tempdir()?;
    let adapter = BinaryStorageAdapter::for_chain_key(
        dir.path(),
        "cookbook-long-project",
    );
    let mut chain = MentisDb::open_with_storage(Box::new(adapter))?;

    chain.upsert_agent(
        "planner",
        Some("Planner"),
        Some("product-team"),
        Some("Owns durable project checkpoints"),
        None,
    )?;

    let goal = chain.append_thought(
        "planner",
        ThoughtInput::new(
            ThoughtType::Goal,
            "Ship the checkout redesign without breaking invoice export.",
        )
        .with_concepts(["checkout-redesign", "invoice-export"])
        .with_tags(["project", "goal"])
        .with_importance(0.95),
    )?.index;

    let plan = chain.append_thought(
        "planner",
        ThoughtInput::new(
            ThoughtType::Plan,
            "Audit current checkout flow, migrate the payment step, then run invoice export regression tests.",
        )
        .with_refs(vec![goal])
        .with_concepts(["checkout-redesign"])
        .with_tags(["project", "plan"])
        .with_importance(0.85),
    )?.index;

    let action = chain.append_thought(
        "planner",
        ThoughtInput::new(
            ThoughtType::ActionTaken,
            "Moved payment step behind the new feature flag. Invoice export tests still need to run.",
        )
        .with_refs(vec![plan])
        .with_concepts(["checkout-redesign", "feature-flag"])
        .with_tags(["project", "progress"])
        .with_importance(0.75),
    )?.index;

    let checkpoint = chain.append_thought(
        "planner",
        ThoughtInput::new(
            ThoughtType::Checkpoint,
            "Resume by running invoice export regression tests, then remove the old payment-step branch if green.",
        )
        .with_role(ThoughtRole::Checkpoint)
        .with_refs(vec![goal, plan, action])
        .with_concepts(["checkout-redesign", "resume-point"])
        .with_tags(["project", "checkpoint"])
        .with_importance(0.9),
    )?.index;

    let resume_points = chain.query(
        &ThoughtQuery::new()
            .with_roles(vec![ThoughtRole::Checkpoint])
            .with_concepts_any(["checkout-redesign"])
            .with_limit(1),
    );

    assert_eq!(resume_points.len(), 1);
    assert_eq!(resume_points[0].index, checkpoint);
    Ok(())
}
Rule of thumb: a checkpoint should say what is done, what is not done, and the exact first command or investigation the next session should perform.

Why It Works

refs turn the checkpoint into a compact project map. A future agent can read the checkpoint first, then follow references back to the goal, plan, and latest action only when more context is needed.