Hefesto: The Blacksmith Cat That Remembers Everyone I Meet
A relationship memory built on Cognee Cloud — voice capture, multi-hop recall, a Telegram bot, and a very alive pixel cat
Somewhere around the third day without proper sleep, I taught a pixel cat to remember people better than I do. This is the story of Hefesto — a relationship memory app I built for the Cognee hackathon this July, and honestly one of the few hackathons I've ever taken dead seriously.
#The problem, which is me
Here's an embarrassing pattern. I meet someone great at an event. We talk twenty minutes about their startup, their dog, the intro they need. We swap contacts, I walk away feeling like a functioning adult — and three weeks later all I've got is a name in my phone that might as well belong to a stranger. Was she the one hiring designers? Did I promise him something? No idea.
Now multiply that by every meetup, every afterparty, every call where your mom mentions a doctor's appointment and you nod like you'll remember. You won't. I won't. Nobody does. Our relationships generate a constant stream of small, important facts, and we drop almost all of them.
Hefesto never forgets — unless you ask him to.
That line ships in the product, on the screen where you delete someone. I'll get there. First, the cat.
#The hackathon
In July 2026, WeMakeDevs ran a hackathon with Cognee called "The Hangover Part AI: Where's My Context?" — the whole theme was memory. Give an AI agent a memory that survives across sessions, build whatever you want on top. The theme was open, the memory layer was not: Cognee had to power it. I picked the Cloud track, which meant building on Cognee Cloud, their hosted knowledge-graph platform.
I've done a lot of hackathons. Most of them I treat like a weekend sprint: scope brutally, hardcode the happy path, polish the demo. This one was different — I wanted a real product at the end, not a demo that falls over if a judge types the wrong thing. So I planned it in phases, designed every screen in Figma before writing the frontend (that part got intense — hours and hours of pushing pixels), and wrote gates that test the whole thing end to end against production. More on that later.
#The cat almost didn't happen
My first sketch had no cat. It was a clean, sensible memory app. My brother looked at it and would not let it go: put the little cat in, he kept saying, that's what gives the thing a personality. His actual argument was better than mine — a cat is the animal that stays with you. It lives in your house, sits on your desk, watches your life happen and keeps its own quiet record of it. Which is more or less exactly what a memory does.
I said no. Animating a pixel sprite properly — frame data, state machines, timing curves — is a stupid amount of work to take on mid-hackathon. Two days later I caved and started drawing frames. He was right, and I'm putting it in writing so he can link people here forever: the cat is the soul of the product. Judges don't remember APIs. They remember the little blacksmith who pulls out a laptop when he's thinking.
One detail I'm genuinely proud of: gestures wait. When a blink or a tail flick wants to play, it doesn't interrupt the breathing mid-frame — it waits for the rest pose, fires, and returns to that exact pose. Zero jump cuts. I call it the anchor rule and it's the difference between "animated sprite" and "small creature that seems alive".
#What Hefesto actually does
You tell it about people the way you'd tell a friend — by voice, fifteen seconds, walking out of the venue. It transcribes, pulls out the structure (who, where, what they care about, what you promised), shows you a confirmation card, and then forges the note into a knowledge graph. Later you just... ask. In plain language. And it answers from your own memories, with receipts.
That's the sell, honestly. Networking tools treat people like leads in a pipeline. Hefesto treats your whole life as one graph — the founder you met once, your best friend's dog, your mom's knee — and just colors them differently. Work is blue, personal is orange, family is green. Open a person and the interface quietly adopts their color. The cat, for the record, never changes color. He has his own palette and he's keeping it.
#The ember: how it decides who needs you
Every person in your graph glows. Talked recently — bright orange ember. Go quiet and the ember cools toward gray. It's a dead-simple recency model with one job: make neglect visible before it becomes awkward.
When someone crosses into cold, Hefesto nudges you — once, on opening the app, and on Telegram if you've linked it. Maximum one proactive push a day, with a seven-day cooldown per person. I was strict about this: a memory app that spams you is just a to-do list with extra steps.
#A field guide to actually using it
It's live at hefesto.org. Here's the whole loop, start to finish.
flowchart LR
A["🎙 Capture — 15s voice note"] --> B["✓ Confirm card"]
B --> C["⚒ Forge — ~15s"]
C --> D["🕸 Your graph"]
D --> E["💬 Ask anything"]
D --> F["📋 Briefing"]
D --> G["🔔 Nudge"]
E --> H["🤝 Reconnect"]
F --> H
G --> H
H --> A
- Sign up at hefesto.org — email and password, no verification dance. On your phone it's a full app (add it to your home screen); on desktop it's a dashboard.
- Capture your first person. Hold the mic and talk like a human: "Met Diego at the padel club, he's a chef, offered to cook for my birthday." Hefesto transcribes it with Whisper and shows you a card with everything it extracted — name, cluster, facts, commitments. Nothing touches your memory until you hit Save. Fix anything that's off, or discard it.
- Watch the forge. The cat pulls out a tiny gray laptop and types while Cognee builds the graph — usually 10 to 20 seconds. The speech bubble pulses "Forging your memory…" and then the person exists.
- Ask questions. The rule is simple: statements get captured, anything with a "?" gets answered. Start with the suggested chips in Chat. There's also a "Think deeper" toggle that runs a slower chain-of-thought recall (~40 seconds) for the genuinely hard multi-hop stuff.
- Browse People and the Graph. Filter by cluster, watch the embers, tap any node to open the person. Every card shows what you know and a timeline of every note you ever captured about them.
- Before you meet someone, open their Briefing: a summary, key points, and what you promised them. Hit "Draft message" and Hefesto writes you an opener grounded in your actual shared history — copy it into whatever app you text from.
- Connect Telegram (Account → Connect Telegram, scan the QR or tap the button). From then on the bot is the fastest path: send it a voice note from the bar and confirm with one tap, ask it questions with a "?", type /briefing Ana on the way to the café. Nudges land there too.
- And when you want something gone — a person, or absolutely everything — Forget is real deletion, from the graph and the registry both. You can export all your data as JSON first. Your memories are yours.
| You say / do | What happens |
|---|---|
| "Met Sara at DevFest, she does ML at a bank" | Confirmation card → Save → she joins your graph |
| "Who did I meet at DevFest?" | Answer grounded in your notes, with sources |
| "What should I talk about with Sara?" | Her details + anything you promised her |
| A voice note to the Telegram bot | Same pipeline, inline ✅ / ✏️ / ❌ buttons |
| /briefing Sara (in Telegram) | Full pre-meeting brief in the chat |
| Forget person | Every memory of them deleted — graph included |
#Under the hood
One Next.js app. The route handlers are the entire backend — the Cognee API key never gets anywhere near a browser. Supabase handles auth plus a deliberately small registry (people, warmth timestamps, capture notes). Groq runs the fast parts: Whisper large-v3-turbo for voice (I benchmarked it against the regular large-v3 — about 30% faster for the same accuracy at these clip lengths) and Llama 3.3 70B for turning rambling voice notes into structured fields. Cognee Cloud is the memory itself.
flowchart TB
subgraph Client
W["Web · PWA"]
T["Telegram bot"]
end
subgraph Backend["Next.js route handlers — the whole backend"]
C["capture + voice"]
Q["chat · briefing · draft"]
N["nudge · forget · export"]
TG["telegram webhook"]
end
subgraph Services
G["Groq — Whisper + Llama 3.3"]
S[("Supabase — auth + registry")]
K[("Cognee Cloud — per-user graphs")]
end
W --> C
W --> Q
W --> N
T --> TG
TG --> C
C --> G
C --> K
Q --> K
Q --> G
N --> S
C --> S
Every user gets their own Cognee dataset, and every capture goes in through remember with a hand-written OWL ontology — Person, Company, Role, Interest, Event, Commitment, and the relationships between them. The ontology is what makes recall precise instead of vibes-based: the graph knows that "wants an intro to a designer" is a Commitment hanging off a Person, not just a sentence.
# every capture becomes a small markdown blob → remember (multipart)
capture_9c01badd.md
ontology_key: hefesto_relationships_v1
node_set: [work]
run_in_background: true # then poll status while the cat types
# recall is one call
GRAPH_COMPLETION ~4s # default — handles multi-hop with evidence
GRAPH_COMPLETION_COT ~40s # the "Think deeper" button
Two honest engineering notes. First: Cognee Cloud's REST surface doesn't expose per-user principals on the data plane, so isolation is enforced app-side — every single Cognee call derives its dataset from the session user, never from anything the client sends. I verified this with cross-user tests in the gate suite (user B polling user A's capture gets a 404, user B asking about user A's contacts gets an honest "no idea"). Second: same-name entities fuse deterministically in the graph — two different Anas would merge. So the app disambiguates before remember: the confirmation card asks "save as new, or same as Ana García?" and keeps its own person → data_ids index, which is also what makes real per-person deletion possible.
#The multi-hop moment
The demo beat I built everything around: ask "who can introduce me to someone who runs a gaming studio?" when no single note contains the answer. One note says Leo is a game designer who knows Maya. Another mentions Maya runs Ember Works. The graph connects them, and the UI draws the walk: You → Leo → Maya, with the exact quotes it used as evidence underneath.
// The answer names a connector — walk the path from the sentence itself.
const REFERRAL_PATTERNS = [
/\b(NAME)\s+can\s+introduce\s+you\s+to\s+(NAME)/u,
/\b(NAME)\s+can\s+put\s+you\s+in\s+touch\s+with\s+(NAME)/u,
/\b(NAME)\s+can\s+connect\s+you\s+(?:with|to)\s+(NAME)/u,
];
// ...then resolve each cited data_id → person, so every answer
// ships with its receipts: quotes, sources, and the path.
Evidence was non-negotiable for me. A memory you can't audit is a liability — so every answer shows via whom it knows what it knows, and the recall prompt is pinned to the user's own notes. Ask a fresh account about people it never met and it says so. No hallucinated friends.
#The sprite workshop
The cat deserved his own section because he ate a full day of the build — and this is where the Figma hours really went. He's a 32×36 grid with a five-color palette, seven clips, and some hard-won anatomy rules. The glasses are a rigid 7-row box that moves as one piece when he breathes. The bridge is a single pixel that rides with the frame. And the whiskers — three pairs — are glued to the face, not the glasses.
I know that last rule because I broke it. For one build the bottom whiskers rode up with the glasses on every breath, and the cat spent two seconds of every cycle looking like he was raising his eyebrows at my code. Fair, honestly. Fixing it meant going back to the original frames pixel by pixel and writing down the invariant: head up, whiskers on rows 11/13/15; head down, rows 12/14/16. Forever.
| Clip | Timing | When |
|---|---|---|
| idle | 200 / 2000 / 200 / 2000 ms | Always — the breath |
| blink | 70 ms | Ambient, every 2.6–6 s |
| tail | 5 random variants | Ambient, every 3.5–8 s |
| typing | gray laptop, 380 ms gaze scan | Thinking / forging |
| listening | ears up + sound waves | While you record |
| alert | a black "!" | Briefing ready |
| doubt | a black "?" | Errors, or ambient every 45–90 s |
There were two more clips planned — a wave and a happy bounce. They died in review. RIP. Seven expressive clips beat nine mediocre ones.
#One bot, everybody's memory
The Telegram side was a hard requirement I set for myself: not a demo bot wired to my own chat, but one bot any user can link. The handshake is a one-time token — the app generates it, shows it as a QR (desktop) or a tap-to-open button (phone), and the bot resolves /start <token> back to your account. Tokens hash with SHA-256, expire in ten minutes, and burn on first use. I wrote a gate that literally replays a used token from a second chat to make sure it bounces.
sequenceDiagram
participant U as You
participant A as hefesto.org
participant B as Telegram bot
U->>A: Connect Telegram
A-->>U: QR / button (one-time token, 10 min)
U->>B: /start <token>
B->>A: resolve token → your account
A-->>B: linked ✓
B-->>U: welcome — send me someone you met
U->>B: 🎙 voice note
B-->>U: card with ✅ Save · ✏️ Edit · ❌ Discard
My favorite interaction detail: the ✏️ Edit button doesn't open a form, because forms in chat are misery. It just claims your next message. Tap Edit, type "actually she teaches pilates, not yoga", and the card re-extracts with the correction merged in. And questions work the same as the web — anything with a "?" goes through the exact same recall pipeline, because I pulled that logic into one shared module. Same brain, different mouth.
#The bugs I'll admit to
That last audit became a small philosophy. The photo button in the composer? Decorative — deleted. "Draft message"? Was a stub — became a real feature that writes openers from your memories. "Export my data" and "Forget everything"? Both real now. And my favorite fix of the whole project: when the QR wouldn't render in production because an env var was missing, instead of documenting the variable harder, I made the bot discover its own username by asking Telegram's getMe. The best fixes delete a way to fail.
#Testing like a paranoid
Every phase ended with a gate: a script that creates throwaway users against production, walks the entire product, asserts everything, and deletes all traces of itself. By the end there were six of them, and the final one runs the complete judge journey — sign up, link Telegram, capture through the bot, forge, multi-hop, mode change, nudge, feedback, forget — twice, timed, with fresh data each run.
| Step | Run 1 | Run 2 |
|---|---|---|
| Sign up + provision | 6.0s | 1.9s |
| Link Telegram (token handshake) | 3.9s | 3.4s |
| Capture via bot → in the graph | 18.8s | 19.0s |
| Multi-hop answer with path | 8.7s | 7.2s |
| Mode change (Ana vs Carlos) | 17.2s | 15.1s |
| Nudge · feedback · forget | ~6s | ~5s |
| Whole journey | ≈88s | ≈85s |
One more honesty note, because it matters: Cognee's API accepts feedback entries chained to each answer (that's the 👍/👎 in the chat), but I ran a controlled experiment — eight recalls around an explicit negative feedback — and couldn't observe it changing retrieval yet. So the UI says "feedback saved" and nothing more, because that's what's true. If your product claims learning, it should be able to show it.
#The numbers
#What I took from it
Design before code paid for itself twice over — the Figma grind up front is why the build never stalled on "what does this screen even look like". The gates paid for themselves the first time a refactor would have silently broken isolation. And the cat paid for himself the moment anyone saw the app for the first time and smiled before they understood what it did. My brother gets full credit for that one.
A very good experience, all of it. Exhausting in the way only self-inflicted deadlines are, but the thing at the end is real: it's live, it's multi-user, and it remembers your mom's knee. Go meet someone worth remembering — hefesto.org.