Capture
Conversations are kept as episodic records, so the source of a belief is never lost.
Personal agent · Persistent memory
A cited record of what you’ve decided — the role you’re aiming for, the people you promised, the places you’d go back to. Change your mind, and the old decision stays on the record, dated.
01Said
ChatThis blue-door biryani place off Lad Bazaar is unreal. Mutton biryani, mirchi ka salan. I was there with my sister. Next time Mom and Dad visit, we’re bringing them here.
Remember this.
Kept — because you asked. The place, the dish, your sister, and the promise. I’ll bring it up when they’re in Hyderabad.
Stored as spoken — the source stays attached.
Not a live account
01 — How it remembers
The same loop you just watched, on a career record: capture what you say, turn it into facts, cite every answer, and keep the old version when you change your mind.
Conversations are kept as episodic records, so the source of a belief is never lost.
Facts are extracted with a subject, a predicate, an object and a confidence score.
aiming for Staff+ backend
§ conversation-042 · CONF 0.91Answers carry inline citations that open the provenance of every fact they used.
Facts carry a validity window. New truth supersedes old, and any fact can be edited or retracted.
02 — The record
Every fact carries a window. A newer fact closes the old one’s window; the old one stays on the record, dated, and still readable. Nothing is written without you: the agent proposes the goal or agenda item and asks for confirmation; a create is saved only when you confirm.
The principle
A record that forgets
is not a record.
03 — What holds
A personal record is only useful if you can trust where it lives. These are the defaults, not an enterprise add-on.
Provider keys are encrypted with AES-256-GCM before they are stored, and the deployment reports whether its data key is configured.
const cipher = crypto.createCipheriv("aes-256-gcm", encKey, iv);
const tag = cipher.getAuthTag().toString("hex");
// Authenticated ciphertext envelope
prefix: "enc:v1:${iv}:${tag}:${ciphertext}"Memory is partitioned per account, so one tenant’s facts are never visible to another.
const store = UserFactStoreRegistry.getStore(accountId);
// Multi-tenant partition filter
assert(store.tenantId === caller.accountId);
isolation: 0 cross-tenant reads;The API and the web app are containerized and run against a local store or a hosted one, from the same build.
FROM node:22-alpine
USER 1001:1001 (non-root)
ENTRY node apps/api/dist/index.js
targets: ["local_store", "cloud_firestore"]Every model call is logged with its task, model, tokens, cost and duration, so spend is attributable rather than estimated.
recordPrompt({
taskType: "chat", model: "gemini-2.5-flash",
tokens: { in: 1180, out: 240 },
durationMs: 412, costUSD: 0.0071
});04 — Early beta
Create your account — Agent Pandu is in early beta, and account creation is invitation-only for now.
Account creation is invitation-only during the early beta. Leave your email; to confirm the address is yours we may send a link first. Every confirmed request is read by a person.