Memento is a local-first knowledge layer over your email archive, built as a showcase of the Gemini Interactions API. Instead of being yet another email client, it turns years of correspondence into source-attributed, living documents across five dimensions: People, Projects, Newsletters, Concepts, and a unified Dashboard — all powered by streaming, multi-turn Gemini agents.
This submission demonstrates end-to-end use of the Gemini Interactions API: multi-turn agentic loops, server-sent event streaming, tool-call orchestration, and previous_interaction_id-based conversation chaining — all running locally against your own email archive, with zero data sent to a third-party backend.
- Dashboard — executive brief with an "Ask Memento" chat. Ask about a person, project, or topic and watch the agent call tools, surface entity summaries in a live side panel, and synthesize an answer across your full email history.
- People — relationship wikis for meaningful contacts, resolved across email aliases. An enrich agent writes facets (role, affiliation, expertise) and narrative sections (summary, interaction arc, current status) backed by cited messages.
- Projects — bounded narratives for work/life projects curated via a collector agent chat flow, then compiled section-by-section with citations by the project compile agent.
- Newsletters — auto-detected broadcast sources with Gemini-generated summaries.
- Concepts — opt-in evergreen topics curated and compiled the same way as projects.
Every factual claim traces back to source messages via citations. User edits to generated documents survive re-compiles.
# 1. Build the Go backend
cd backend && go build -o ../memento ./cmd/memento && cd ..
# 2. One-time setup (runs migrations, prompts for Gemini API key)
./memento init
# 3. Boot the backend
./memento serve --port 8787 &
# 4. Boot the Next.js UI
pnpm install && pnpm run dev
# 5. Open http://localhost:3000Type a question in the "Ask Memento" box on the dashboard. The Gemini Interactions API streams tool calls and text deltas in real time; the side panel materializes entity cards as the agent surfaces them.
Runtime:
- Go 1.26+
- Node.js 22+, pnpm
- A Gemini API key — get one free at aistudio.google.com
Email archive (msgvault):
Memento reads from a SQLite archive managed by the msgvault CLI. You need msgvault installed and configured at ~/.msgvault/config.toml pointing at a populated archive for the People, Projects, Newsletters, and Concepts dimensions to populate with real data.
# ~/.msgvault/config.toml
[data]
data_dir = "/absolute/path/to/your/vault"Useful read-only msgvault commands to verify your setup:
msgvault stats
msgvault list-senders --limit 10 --json
msgvault query "SELECT COUNT(*) FROM v_messages".env at the repo root (created by ./memento init):
GO_BACKEND_URL=http://127.0.0.1:8787
GEMINI_API_KEY=<from Google AI Studio>
INTERNAL_TOKEN=<generated by init>
AGENT_STEP_LIMIT=40
MEMENTO_AGENT_MODEL=gemini-3.5-flash- Frontend: Next.js 16 (App Router), React 19, TypeScript 5, Tailwind CSS 4,
@google/genai2.6.0 (Gemini Interactions API) - Backend: Go 1.26,
modernc.org/sqlite(pure Go, no CGO),github.com/google/generative-ai-go(newsletter summaries) - Design system: Archive Atlas —
#12362eprimary,#faf9f7background, Source Serif 4 + Inter
src/ Next.js UI + agent runtime
server/agents/ Gemini Interactions API client, loop, SSE controller
components/ UI components including agent cards and chat
backend/ Go HTTP server + SQLite migrations
cmd/memento/ CLI subcommands (init, serve, migrate, refresh, …)
internal/ msgvault reader, person resolver, dimension stores
The core of this demo is src/server/agents/loop.ts, which implements the canonical streaming loop:
const stream = await client.interactions.create({
model: agent.model,
input: [{ type: "text", text: userMessage }],
tools: agent.tools,
system_instruction: agent.system,
previous_interaction_id: prevId, // chains turns server-side
stream: true,
generation_config: { thinking_level: "high" },
});
for await (const ev of stream) {
// ev.event_type: "step.start" | "step.delta" | "interaction.completed"
// Tool calls arrive as steps; results are fed back to continue the loop
}Each agent (person enrich, project compile, concept compile, Memento router) is a thin wrapper around this loop with its own system prompt and tool set. The Next.js API routes stream SSE events to the browser; the client renders them live.
┌────────────────┐
│ memento-agent │ ← dashboard hero chat (router)
└───────┬────────┘
│ tool calls
┌───────────────┼───────────────────┐
│ │ │
┌───────▼──────┐ ┌──────▼───────┐ ┌─────────▼────────┐
│ collector- │ │ person-agent │ │ project-agent / │
│ agent │ │ (facets + │ │ concept-agent │
│ (draft flow) │ │ narrative) │ │ (narratives) │
└───────┬──────┘ └──────┬───────┘ └─────────┬────────┘
│ │ │
└───────────────┼───────────────────┘
▼
┌─────────────────────┐
│ msgvault (SQLite) │ ← local, read-only
│ memento_* tables │ ← local, Memento-owned
└─────────────────────┘