Most AI agents forget. They process a request, answer it, then drop the context. Google Cloud’s generative-ai repository now ships a sample that tackles this directly. It is the Always-On Memory Agent, a reference implementation that treats memory as a running process.
Always-On Memory Agent
Fundamentally, the project is a lightweight background agent that never stops. It runs 24/7 as a continuous process, not a one-shot call. It is built with Google ADK (Agent Development Kit) and Gemini 3.1 Flash-Lite. Notably, it uses no vector database and no embeddings. Instead, an LLM reads, thinks, and writes structured memory into SQLite. The model choice targets low latency and low cost for continuous background work.
How It Works: Ingest, Consolidate, Query
Architecturally, an orchestrator routes every request to one of three specialist sub-agents. Each sub-agent owns its own tools for reading or writing the memory store.
First, the IngestAgent handles incoming content. It uses Gemini’s multimodal capabilities to extract a summary, entities, topics, and an importance score. That structured record then lands in the memories table.
Next, the ConsolidateAgent runs on a timer, every 30 minutes by default. Like sleep cycles, it reviews unconsolidated memories and finds connections between them. Then it writes a synthesized summary, one key insight, and those connections to the database. Consequently, the agent builds new understanding while idle, with no prompt.
Finally, the QueryAgent answers questions. It reads all memories and consolidation insights, then synthesizes a response. Importantly, it cites the memory IDs it used as sources.
function reset(){
i=0; consolidated=false; store.innerHTML=””; $(“wires”).innerHTML=””;
$(“insight”).className=”insight”; $(“insight”).innerHTML=””;
$(“qbox”).className=”qbox”; $(“qans”).innerHTML=””; $(“qask”).textContent=””;
$(“bCons”).disabled=true; $(“bQuery”).disabled=true; activate(null);
log(“Reset. Drop a file into the agent’s inbox to begin.”);
}
$(“bIngest”).onclick=ingest;
$(“bCons”).onclick=consolidate;
$(“bQuery”).onclick=query;
$(“bReset”).onclick=reset;
window.addEventListener(“load”,post);
window.addEventListener(“resize”,post);
if(window.ResizeObserver){ new ResizeObserver(post).observe(document.body); }
setTimeout(post,150);
})();

