Title: The Memory That Knows When It Is Wrong
Description: Perfect recall is dangerous without discrimination. How one agent stores the signal that separates look-alike incidents, flags stale memories, and hedges instead of guessing.
Most conversations about agent memory focus on recall. Can the agent find the right thing? That is the easy half.
The harder half is knowing when the thing it found is not the right thing.
Incident response is full of look-alikes. A p99 spike is a symptom, not a cause. Connection-pool exhaustion can come from a missing database index, a connection leak in a retry wrapper, a config rollout that lowered the pool ceiling, or a retry storm multiplying requests. The dashboards look similar. The fixes are completely different. An agent with perfect recall and no discrimination is dangerous, because it will confidently apply last month's fix to this month's failure.
Déjà Vu, an on-call SRE agent built on Hindsight, treats discrimination as a first-class part of memory rather than an afterthought.
Every memory carries its own disambiguator
When an incident is retained, it does not only store the symptom and the fix. It stores the signal that distinguishes this failure class from its nearest neighbour. A missing-index incident records that pool wait was high, database CPU was moderate, and the deploy touched only the orders schema. A connection-leak incident records that connections climbed monotonically and never dropped. A config incident records that the pool size itself changed.
That field is called the discriminator, and it is retained alongside the narrative:
doc = f"""
INCIDENT {iid} | {service} | {severity}
SYMPTOM: {symptom}
SIGNALS: {signals}
ROOT CAUSE: {root}
FIX: {fix}
HOW WE TOLD IT APART: {discriminator}
OUTCOME: {outcome} in {minutes} min by {engineer}
"""
During recall, the agent does not just retrieve candidates. It re-ranks them against the live alert fingerprint, then asks a second question: does the evidence actually rule out the obvious alternative? The answer is shown to the engineer, not hidden in a chain of thought. If the agent says this is a missing index, it also says why it is not a connection leak.
This is the difference between a search result and a diagnosis.
Stale memory is worse than no memory
Memory decays. Services get rewritten. A fix that worked in August can be actively harmful in November if the schema, the runtime or the deployment pipeline changed underneath it.
A bank that only grows becomes a museum of outdated advice. So memory needs an expiry model, even a simple one. Déjà Vu flags memories for revalidation when they are old or when their outcome was not a clean resolution, and it applies a penalty during ranking rather than treating every recalled paragraph as equally authoritative. The Memory tab exposes the count directly: retained incidents, learned live, and stale.
The stale counter is not decoration. It is a promise that the agent knows the difference between we solved this once and we still believe this.
The contradiction guard
The most useful behaviour in the whole system is the contradiction pass. After the hypothesis is formed, a critic role checks it against the strongest competing memory. If the evidence for the proposed cause is weak, or if the look-alike explains the signals better, the answer changes.
On a checkout alert, the database index story is compelling: high pool wait, moderate database CPU, a deploy minutes earlier. But a connection-leak memory has almost the same surface. The discriminator settles it. The agent states which one the signals support and which one it ruled out.
That check is also why the system does not always answer with maximum confidence. A confident wrong answer is the worst possible output for an on-call engineer. A slightly hedged answer with a stated contradiction is far more useful, because it tells the human what to verify.
Graceful degradation is part of correctness
Retrieval can fail. The memory server can be down, the network can be partitioned, the bank can be empty. A system that collapses in those moments is not production software.
If Hindsight is unreachable, Déjà Vu falls back to a BM25 index over the same SQLite mirror. The answer still carries receipts from the local corpus. The header badge changes from HINDSIGHT to BM25 FALLBACK, and the trace shows which path served the answer. The quality drops, but the honesty does not.
That design choice came from a simple test: would I trust this thing during an actual incident? Only if it tells me when it is operating in a degraded mode. Silent fallback is how agents lose trust.
What this looks like in practice
The same alert, answered twice, is the clearest demonstration. Without memory, the agent produces generic triage at roughly 31% confidence: restart the pods, check the deploy dashboard, no owner, no fix time, nothing to audit. With memory and the contradiction check, it names the missing composite index, cites three incidents, identifies the engineer who fixed it in six minutes, and explains why the connection-leak theory was rejected.
The improvement is not only in the answer. It is in the shape of the answer. Verifiable, scoped, and aware of its own uncertainty.
If you are building agents that act on operational systems, treat memory as two problems: what to remember, and how to know when the memory does not apply. The first gets the demo. The second gets production trust.
The Hindsight project provides the retention and recall primitives; the Hindsight docs cover the API; and the Vectorize memory primer is a useful grounding in the underlying ideas. Build the discrimination layer yourself. It is where the product lives.
The running agent is at dejavu-tau.vercel.app, and the source is at abinivesh-m/dejavu.
1 reaction
33% to 83%: Measuring whether agent memory works
Description: Most memory products claim to improve. This is the replay harness that measures it, with no future knowledge, 22 graded incidents, 33% early and 83% late.
Every memory product claims to get better over time. Very few show the curve.
That is a problem, because "it remembers" is easy to demo and hard to prove. A retrieved paragraph can look impressive in a screenshot while adding nothing to the answer. The only honest question is: compared with the same agent before it had this memory, does it solve the next problem better?
Déjà Vu is an on-call SRE agent built on Hindsight. To answer that question we built a replay harness instead of a highlight reel.
The replay rule: no future memories
The corpus contains incidents ordered by time, many of which share failure classes. The replay walks that corpus chronologically. At each incident, the agent may only use memories that existed before that incident. Nothing from the future. No LLM in the grading loop. The retrieval path is a deterministic BM25 index over the same documents the production system would have had at that moment.
That single constraint turns a demo into an experiment. If the agent scores well, it is not because it saw the answer earlier in the list. It is because earlier incidents taught it something that transferred.
A simplified version of the loop:
for i, incident in enumerate(corpus):
known = corpus[:i] # as-of memory only
predicted = rank(incident.query, known)
actual = incident.cause_class
correct = predicted[0].cause_class == actual
graded.append({
"n": i + 1,
"predicted": predicted[0].title,
"actual": incident.title,
"correct": correct,
"accuracy": mean(g["correct"] for g in graded),
})
The output is a sequence of predictions with a running accuracy, not a single aggregate that hides the shape of learning.
What the numbers say
Across 22 graded incidents:
- top-1 accuracy: 50% — the correct failure class on the first guess
- top-3 accuracy: 64% — the correct class in the top three
- first six graded alerts: 33%
- last six graded alerts: 83%
The aggregate is deliberately unglamorous. Fifty percent top-1 is not a victory lap. But the gap between the first six and the last six is the product thesis: as the bank accumulates specific, structured incidents, the agent stops guessing generically and starts recognising patterns.
The early failures are instructive. The first graded alert is a Redis eviction problem. The agent predicts a Kafka consumer rebalance loop, because it has no relevant precedent and the surface vocabulary points at streaming infrastructure. That is what a cold start looks like. By the end of the replay, a config-driven pool ceiling is matched to the same failure class seen earlier, and a month-end reporting query is recognised immediately.
We surface both sides in the product. The Learning tab shows the cumulative curve, the early and late windows, and a "Same agent, three moments" strip: alert #1 with zero memories, a middle alert with eleven, and the final alert with twenty-one. The first card is a cold miss. The last two are matches. That progression is more convincing than any single accuracy number, because it shows the mechanism.
Why not just ask an LLM to grade it?
Because the point is to test memory, not model capability. An LLM grader introduces its own priors, its own variance and its own cost. A deterministic ranker over the as-of corpus is reproducible: the same corpus produces the same curve. If the curve improves, the improvement came from retrieval, which is what the memory layer controls.
This does not mean the production agent is deterministic. In production, Hindsight recalls candidates by meaning, the application re-ranks them against the live signal fingerprint, and a language model writes the final hypothesis from the receipts. The replay isolates one variable — whether the right past incident was available and ranked highly — so the rest of the system can be evaluated separately.
Measure the failure modes too
A learning curve that only shows wins is marketing. The interesting questions are about what goes wrong.
Three failure modes matter in practice. First, cold start: with an empty bank, the agent is generic, and it should say so rather than invent confidence. Second, look-alikes: two incidents with similar symptoms and different causes. Re-ranking by signals and forcing a stated contradiction is what prevents a confident wrong answer. Third, stale memory: an old fix that no longer applies. A bank that never expires becomes a source of harm, so stale memories are flagged and penalised rather than trusted.
We also test degradation. If Hindsight is unreachable, the agent falls back to the local BM25 index and labels the path. The receipts remain; the quality drops; the user is told. A memory system that hides its failure mode is not measurable, because you cannot tell when it is lying.
What we would measure next
The replay measures cause-class retrieval, which is the core of the value proposition. The next step is outcome-weighted evaluation: did the recalled fix actually resolve the incident, and how many minutes did it save compared with the generic baseline? That requires more resolved incidents and a way to attribute time saved without confounding variables.
Until then, the honest claim is narrow and testable: on a chronological replay with no future knowledge, the same agent improves from 33% to 83% as its memory bank grows, and every prediction is backed by a retrievable incident.
That is a better claim than "it remembers." It is falsifiable.
The Hindsight repository is open source, the documentation covers retention and recall, and the Vectorize primer is a good conceptual starting point. Build the replay harness before you build the landing page. The curve will tell you whether you have a product.
The running agent is at dejavu-tau.vercel.app, and the source, including the replay harness, is at abinivesh-m/dejavu.
"Receipts, Not Vibes: Why Agent Memory Needs Provenance"
Description: Agent memory is only useful if every claim traces back to a real incident. A practical look at provenance, structured metadata, and retrieval that shows its receipts.
It is 02:14 and checkout is failing. A generic model looks at the alert and says something reasonable: restart the affected pods, check the deploy dashboard, watch the error rate. It is not wrong. It is also not useful. It has no idea that this exact failure happened six weeks ago, that the cause was a missing composite index, that Priya fixed it in six minutes, or that restarting only buys forty minutes.
The difference between those two answers is not model quality. It is provenance.
When an agent claims to remember, the first question an on-call engineer should ask is: show me. Show me the incident. Show me the signals that matched. Show me who fixed it and whether the fix held. Without that, "memory" is just confident improvisation with extra steps.
That constraint shaped Déjà Vu, an on-call SRE agent built on Hindsight. Every answer is assembled from retained incidents, and every claim carries a receipt back to one.
Memory is a data model problem before it is a retrieval problem
The usual approach is to store chat transcripts and hope semantic search finds something useful. That works for a demo and fails an audit. A paragraph of postmortem prose does not tell you which incident it came from, which engineer owned it, how long the fix took, or whether the fix actually held.
So each incident is retained as a structured document. The narrative is there, because meaning matters, but so is the metadata that survives retrieval: incident id, service, root cause, fix, outcome, duration, engineer, severity and tags. Hindsight's memory documentation describes this as retaining what the system should remember, not just what was said. That distinction is the whole game.
A retain payload from the project looks roughly like this:
memory.retain({
"bank": "dejavu-oncall",
"content": f"{title}. {symptom}\n\nROOT CAUSE: {root}\nFIX: {fix}",
"metadata": {
"incident_id": iid,
"service": service,
"root_cause": root,
"fix": fix,
"outcome": outcome,
"fix_minutes": minutes,
"engineer": engineer,
"severity": severity,
"source": "seed" if seeded else "live",
},
"tags": [service, severity, outcome],
})
Because the metadata is stored alongside the text, a recalled paragraph becomes a citation instead of a suggestion.
Retrieval is a ranking problem
Semantic similarity alone is not enough for incidents. Two alerts can read almost identically and have completely different causes. A checkout latency spike caused by a missing index looks a lot like a checkout latency spike caused by a connection leak — until you compare the signals.
Déjà Vu builds its recall query from the alert fingerprint: service, title, body, and every key=value signal. Candidates come back from Hindsight by meaning, then the application re-ranks them against the live fingerprint. Signal similarity carries the most weight, text similarity next, coverage after that. Outcome, recency and support act as tie-breakers, and stale memories are penalised rather than silently trusted.
That last part matters. A memory bank that never forgets becomes a liability. An incident from fourteen months ago, before an architecture change, should not outrank last week's lesson just because the wording is close.
The UI has to make the receipt visible
Provenance is not a backend property. If the engineer cannot see it in three seconds, it does not exist.
In Déjà Vu, every answer carries a receipt strip: incident id, date, service, the fix that worked, the engineer, the minutes, and the outcome. The answer also states which look-alike incident it ruled out and why. The memory bus at the bottom of the screen shows the actual retain and recall operations with backend, latency and result count, so the claim is observable rather than asserted.
This is also where the honest failure mode lives. If Hindsight is unreachable, the app does not pretend. It serves the same corpus through a BM25 index over the SQLite mirror, changes the header badge from HINDSIGHT to BM25 FALLBACK, and records the path in the trace. An agent that hides its retrieval path is not trustworthy at 3 a.m.
What provenance buys you
The practical result is a different kind of answer. Without memory: generic triage, roughly 31% confidence, no owner, no time estimate, nothing to audit. With memory: the missing index, the receipts, a named engineer, a six-minute fix, and a stated reason the connection-leak theory was rejected — around 97% confidence.
The second answer is not better because the model is smarter. It is better because the model was handed evidence.
That is the case for agent memory in production systems. Not a chatbot with a longer context window. A system that remembers specific incidents, cites them, learns from resolutions, and can be checked afterwards.
If you are building in this space, start with the receipt. Decide what a citation must contain, then design retention and retrieval backwards from it. The Hindsight repository is open source, and the Vectorize primer on agent memory is a good place to pressure-test the model. Memory is only valuable when someone can verify it.
The running agent is at dejavu-tau.vercel.app, and the source is at abinivesh-m/dejavu.
Your On-Call Agent Needs Hindsight, Not a Bigger Model
Description: An on-call SRE agent is only as good as the incidents it can recall. Structured retention, evidence-backed ranking, and a contradiction guard built on Hindsight.
It is 02:14. Checkout p99 has gone from 400 ms to 3.9 seconds, the payment provider is retrying, and an alert is burning through the error budget.
The engineer who fixed this exact failure six weeks ago is asleep. The migration that solved it was applied by hand and never written down. So the person on call searches, guesses, and restarts the pods.
The restart works for forty minutes.
I kept coming back to that gap. The model is not the bottleneck. A good model has read every runbook and every public postmortem. What it does not have is your history: this failure, on this service, with these signals, fixed in six minutes by a specific person, and whether the fix held.
I built Déjà Vu to test that claim seriously — an on-call SRE agent whose entire value comes from remembering incidents, and whose memory layer is Hindsight.
What the system actually does
Déjà Vu watches an alert queue. When one fires, it builds a query from the service, title, body and signal fingerprint, recalls candidates from a Hindsight bank called dejavu-oncall, re-ranks them, and answers with evidence. One bank per team: your incidents only, never another team's.
The answer is not a paragraph. It is a hypothesis plus receipts:
- INC-1006 — missing composite index on orders(created_at, status) — 6 minutes — Priya Raman — resolved
- INC-1001 — same cause class — resolved
- INC-1002 — same class — resolved
Same alert, memory off: "generic triage, restart the affected pods", 31% confidence, no incident, no owner, no fix time. Memory on: the index migration, 97% confidence, the receipts, a named engineer. The second answer is not smarter. It is informed.
Making memory the actual product
The naive version of this is a vector store full of postmortems with a prompt that says "use the context below." It demos well and fails quietly, for three reasons.
It retrieves paragraphs, not incidents — so nothing is auditable. It treats similarity as identity — so a look-alike incident with a different cause gets recommended with full confidence. And it never learns from what happened after the fix.
So the memory is structured, not chunked. One document per incident, with metadata that survives retrieval:
resp = client().retain(
bank_id="dejavu-oncall",
content=text, # symptom, signals, cause, fix, time, outcome
document_id=incident_id,
context=f"{inc.get('service')} {inc.get('severity')} incident on {ts[:10]}",
metadata={
"incident_id": incident_id,
"service": inc.get("service"),
"root_cause": inc.get("root_cause"),
"fix": inc.get("fix"),
"outcome": inc.get("outcome"),
"fix_minutes": str(inc.get("fix_minutes")),
"engineer": inc.get("engineer"),
"severity": inc.get("severity"),
},
tags=[inc["service"], inc["severity"], inc["outcome"]],
)
That metadata is the difference between a receipt and a rumour. When the agent says "six minutes, Priya Raman, resolved," those values came from memory, not the model's imagination.
Recall is deliberate: the alert's fingerprint becomes the query, Hindsight returns candidates by meaning, and the application re-ranks them — retrieval similarity and operational similarity are not the same thing:
similarity = 0.50 * signal_similarity + 0.45 * text_similarity + 0.05 * coverage
score = 0.82 * similarity
score += 0.10 * min(1.0, support / 3) # how many incidents back this cause
score += 0.08 * success_rate # did the fix actually hold
score += 0.02 * recency # recent precedent wins ties
if stale:
score -= 0.06 # flag it, do not trust it
Fifty percent of the decision is the signal fingerprint — the numbers, not the prose. p99_ms 3900 against 3800. pool_wait_ms 1240 against 1180. cert_age_days 2 against 61. That last one is why a certificate incident gets ruled out even when the text looks identical.
The part that matters: the contradiction guard
Two incidents can share every word and need opposite fixes. Incident INC-1009 has the same service, the same pool timeout, the same graph shape, and 53% similarity to the live alert. But its cause was a pool size capped during a config rollout, and its fix was a config change plus a redeploy — not an index.
Before committing, Déjà Vu checks the runner-up failure class. If a different cause is close, it surfaces the look-alike explicitly: the incident ID, the similarity, the one signal that separates them, and the different fix it required.
This is the failure mode of every naive retrieval system. A text search returns the nearest paragraph. The agent has to tell you what it ruled out, and why.
Measurement, not a claim
Every memory product says it improves. Almost none measure it, because honest measurement is uncomfortable.
The repo includes a replay that walks the incident corpus in chronological order. At each incident, the agent may only use memories that existed before that timestamp. No peeking. No LLM in the grading loop.
Across 22 graded incidents: 50% top-1, 64% top-3. First six graded alerts: 33%. Last six: 83%.
That pair is the thesis. The agent is measurably better at the end of the quarter than at the start, because it lived through the quarter. The Learning screen plots every graded incident, including the ones it got wrong. A memory system that only shows its wins is a marketing surface.
The loop has to close
Resolving an alert is not the end of the interaction. It is the write. When an engineer resolves an incident, Déjà Vu stores a postmortem, retains it with source: live, and marks the alert closed. Fire the same fingerprint again and the first receipt is the incident that was just created, answered in milliseconds.
That closed loop is also where a second agent earns its place. In the Band room, DejaVu-Recall posts the hypothesis and receipts, then DejaVu-Critic answers the recall — not the alert — with four deterministic checks: at least two receipts, no stale precedent, precedent fixes that held, confidence above threshold. It can block the fix from ever reaching a human.
I wrote the critic as code, not a model call: a reviewer should check evidence, not generate more of it.
What I got wrong
Three things, in order of embarrassment.
First, I scoped recall to the same service. That hid the lesson: a missing index on payments-api is the same failure as one on checkout-api. Cross-service transfer drove most of the late-corpus accuracy.
Second, I graded at string level before switching to failure classes. "Missing index on orders" and "missing index on settlement_date" are different strings and the same lesson. String-level grading made the agent look worse than it was.
Third, I trusted retrieval scores for too long. The signal fingerprint is weighted above text on purpose now. The text is how you find candidates; the numbers are how you decide.
Where it still breaks
First-time failures cannot be recalled. If the team has never seen it, memory has nothing, and the Learning screen shows exactly those incidents as misses.
Per-service histories hold eight to ten incidents, so cross-service transfer helps but is not evidence of production-scale performance. The corpus is synthetic — real incident data is confidential — and the weights were tuned on it. A production deployment needs re-tuning against real signals and a plan for the long tail of incidents that happen once.
And memory can be wrong. Precedent is not proof. That is why every answer carries confidence, receipts, and a visible trace of which path served it. When Hindsight is unreachable, the app serves from a BM25 index over the same SQLite mirror and the header badge changes from HINDSIGHT to BM25 FALLBACK. A demo should not die because a service did not start, but it should never pretend which path answered.
What I took away
The next improvement in on-call tooling is not a bigger context window. It is a memory that is specific to your systems, weighted by what actually worked, honest about what it does not know, and measured against its own past.
Hindsight made the memory layer the easy part: a bank, a retain with real metadata, a recall that returns meaning. The hard part was deciding what counts as the same failure — and being willing to show the moment the agent gets it wrong.
At 2 a.m., the question is not "what does a good SRE do?" It is "what did we do last time, did it work, and who can I ask?"
If you are building agents with memory, start with Hindsight's open-source memory engine and read the Hindsight documentation. It is also worth getting clear on what agent memory actually means before you design a schema you will regret.
Running agent: dejavu-tau.vercel.app. Source, including the replay harness: abinivesh-m/dejavu.
2 reactions
エージェントの記憶喪失を治す:OSS「Hindsight」をClaude APIに繋いで長期記憶を持たせる
セッションが終わるたびに、エージェントは全部忘れる
Claude APIでエージェントを組んでいると、必ずぶつかる壁がある。会話が終わってプロセスが落ちれば、そこまでの文脈は綺麗さっぱり消える。ユーザーの好みも、過去に失敗したアプローチも、次のセッションでは「初対面」からやり直しだ。
RAGでドキュメントを検索させるのとは話が別で、これは「エージェント自身の経験」を覚えさせたいという要求になる。自前でPostgres+pgvectorのテーブルを設計してretain/recallのロジックを書いてもいいが、まず既製品で試して足りない部分だけ自作する方が早い。
今回はOSSのエージェント向け長期記憶システム Hindsight(vectorize-io製、MITライセンス)を、素のClaude APIエージェントに繋ぎ込むところまで手を動かす。
Hindsightとは何か
Hindsightは2026年4月にGitHub Star数1万を突破し、直近のリリースは v0.10.1(2026年9月21日、50件超のPRと22人以上のコントリビューターがマージされた)。エージェントメモリのベンチマークであるLongMemEvalでSOTA相当のスコアを主張しており、記憶を「world facts(事実)」「experiences(経験)」「observations(観察)」「mental models(メンタルモデル)」に分けて構造化して持つ点が特徴になっている。
APIはシンプルで3つしかない。
retain — 記憶を書き込む
recall — 記憶を検索する
reflect — 蓄積した記憶を分析し、上位の理解(メンタルモデル)を形成する
単純なベクトル検索のラッパーではなく、reflect で「経験の積み重ねから学習する」層を持っているのが他のシンプルなメモリストアとの違いだ。
1. サーバーを立てる
Docker一発で立ち上がる。ローカル検証ならこれが一番早い。
docker run -it --pull always --name hindsight \
--restart unless-stopped \
-p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-v hindsight-data:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
HINDSIGHT_API_LLM_API_KEY は記憶の抽出・要約に内部で使うLLM用のキーで、エージェント本体がClaudeでもHindsight側は別プロバイダーで構わない。8888 がREST API、9999 は管理系ポート。起動したら疎通確認する。
curl -s localhost
2. クライアントを入れて最小構成で試す
pip install hindsight-client anthropic
まず生のretain/recallだけで感覚を掴む。
from hindsight_client import Hindsight
client = Hindsight(base_url="localhost")
client.retain(
bank_id="user-yukito",
content="ユーザーはDockerのlatestタグを避ける方針。ピン留めしたバージョンを使う。",
)
result = client.recall(bank_id="user-yukito", query="Dockerタグの方針は?")
print(result)
bank_id が記憶の名前空間になる。マルチユーザー・マルチプロジェクトで運用するなら、ここをユーザーIDやプロジェクトIDで切るのがそのまま権限分離にもなる。
3. Claudeエージェントに組み込む
ここからが本題。セッションの開始時に関連する記憶をrecallしてシステムプロンプトに注入し、セッション終了時に得られた新しい事実をretainする、という往復を1つのクラスにまとめる。
import anthropic
from hindsight_client import Hindsight
class MemoryAgent:
def init(self, bank_id: str):
self.bank_id = bank_id
self.memory = Hindsight(base_url="localhost")
self.claude = anthropic.Anthropic()
def _recall_context(self, query: str, limit: int = 5) -> str:
hits = self.memory.recall(bank_id=self.bank_id, query=query, limit=limit)
if not hits:
return ""
facts = "\n".join(f"- {h['content']}" for h in hits)
return f"過去のやり取りから分かっている事実:\n{facts}"
def ask(self, user_message: str) -> str:
context = self._recall_context(user_message)
system = "あなたは開発アシスタントです。" + (f"\n\n{context}" if context else "")
response = self.claude.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system=system,
messages=[{"role": "user", "content": user_message}],
)
answer = response.content[0].text
このやり取り自体を経験として書き戻す
self.memory.retain(
bank_id=self.bank_id,
content=f"Q: {user_message}\nA: {answer}",
)
return answer
動作確認は別プロセス(別セッション)で行うのが重要。プロセスを一度落として、記憶がDBに残っていることを確かめる。
セッション1(プロセスA)
agent = MemoryAgent(bank_id="user-yukito")
agent.ask("このプロジェクトではpnpmを使う。npmは使わない。")
ここでプロセス終了
セッション2(別プロセス)
agent = MemoryAgent(bank_id="user-yukito")
print(agent.ask("パッケージマネージャは何を使えばいい?"))
→ recallでpnpmの方針を拾ってからClaudeが回答する
これでプロセスをまたいだ記憶が機能する。RAGのドキュメント検索と違い、ここに入るのは「このエージェントが実際にやり取りした内容」なので、事実確認ではなく方針・好み・過去の失敗の再現防止に効く。
4. reflectで経験を要約させる
retainを積み重ねただけだと、生の会話ログが線形に溜まっていくだけでrecallのノイズが増える。定期的にreflectを呼んで上位の理解を作らせるのが公式の使い方だ。
client.reflect(bank_id="user-yukito")
これを1日1回のcronなどで回しておくと、個別のQ&Aペアから「このユーザーはDockerのlatestタグを嫌う」「pnpmを優先する」といったメンタルモデル的な記憶に集約されていく。リリースノート(v0.10.1)でも「コーディングエージェント向けにautomatic reflectの予算制限を修正」という変更が入っており、reflectを回しすぎるとLLM呼び出しコストが積み上がる点は運用上のパラメータとして意識しておく必要がある。
つまずいたところ
recallは空配列を返すことがある(まだ何もretainしていない、またはbank_idの綴りミス)。ガードを外して素通しすると、システムプロンプトに空文字列の見出しだけが残ってClaudeが混乱するので、上のコードのように空なら注入自体をスキップする。
bank_idを適当な固定文字列にすると、複数ユーザーの記憶が混ざる。最初から「誰の記憶か」をbank_idの設計に落とし込んでおく。
retainのcontentを生の会話ログそのまま入れ続けるとreflect前は検索ノイズが増える。要約してからretainする運用にした方が精度は安定した。
まとめ
HindsightはREST経由のretain/recall/reflectという最小限のAPIで、Claude Agentに「セッションをまたぐ記憶」を持たせられる。自前でpgvectorスキーマを設計する前に、まずこの3操作で要件を満たせるか試す価値はある。今回はローカルDocker+Python SDKでの最小構成だったが、本番運用するならbank_idの権限分離とreflectの実行頻度(コスト)の2点を先に設計しておくと手戻りが少ない。
参考
vectorize-io/hindsight (GitHub)
Hindsight Releases — v0.10.1
Hindsight Reaches 10,000 Stars
I built OptMem plugin for Hermes. It's one of the 24 in the official catalog.
Zero dependencies. No database, no embeddings, no API key.
An append-only log: summaries keep context small, the raw record is never deleted. OptMem from @VictorTaelin
rarf/optmem-hermes-plugin
2 likes · 1 repost · 297 views
Adding Recall to GatherIt Without Blocking Guest Uploads
Adding Recall to GatherIt Without Blocking Guest Uploads
The problem: an event creates more information than people can keep track of
When I started building GatherIt, I wanted to make sharing memories at an event feel effortless. Guests should be able to join without installing an app, upload photos and videos, leave voice notes, and see moments collected in one place. Hosts should be able to manage the experience without constantly asking everyone to send their media through separate messaging apps.
The challenge is that an event produces much more than a collection of files. It creates context.
A guest might upload a photo from a particular moment, add a voice note explaining what happened, or join an event after several activities have already taken place. Later, the host might want to recall a particular moment or understand what people shared. A conventional gallery can store and display media, but it does not automatically provide a useful way to recall the surrounding context.
That led me to explore a question: Could I give GatherIt a memory layer without slowing down the experience that makes it useful in the first place?
I explored Hindsight, an open-source memory system designed to help AI applications retain and recall information. Instead of treating every interaction as an isolated request, a memory system can make relevant information available when an application needs it again.
For GatherIt, the interesting part was not simply adding another AI feature. It was exploring how event context could be captured in the background and retrieved later when a host wanted to look back.
Why memory needs to be separate from the main user experience
One of the most important engineering decisions in an application like GatherIt is deciding what must happen immediately and what can happen later.
When a guest uploads a photo, the main experience should focus on accepting the upload, handling the media, and giving the guest clear feedback. The guest should not have to wait for an additional memory operation to finish before continuing.
If memory processing is placed directly in the critical upload path, it introduces another dependency. A slow memory service or a temporary network problem could affect a feature that should otherwise work independently.
I therefore approached memory as a supporting capability rather than the centre of the upload workflow.
The basic flow I was working toward was:
1. A guest joins an event or shares media.
2. GatherIt performs the normal application work.
3. Relevant event context is passed to a memory operation separately.
4. The host can request a recall when they need that context.
This separation matters because a memory system should improve an application without becoming a single point of failure for its core features.
It also encourages a useful engineering principle: optional intelligence should not make essential functionality unnecessarily fragile.
Where Hindsight fits
Hindsight provides a way to retain information and later retrieve relevant context. Its repository and documentation were useful starting points for understanding how a memory layer could fit into an existing application.
References:
- Hindsight on GitHub: vectorize-io/hindsight
- Hindsight documentation: hindsight.vectorize.io
- Background on agent memory: vectorize.io
For GatherIt, the conceptual mapping was straightforward. Each event has its own context, and memory operations need to be associated with the correct event. A host asking about one event should not accidentally retrieve information belonging to another.
That makes event-level separation important. It also makes authorization important: a recall operation should be available only to an appropriately authenticated host, and the server should determine which event the host is allowed to access.
I explored an integration pattern in which the server handles memory operations rather than exposing memory-service credentials to the browser. This keeps credentials on the backend and gives the application a single place to apply authorization, validation, and error handling.
The important distinction is that Hindsight does not replace GatherIt’s database or media storage. Those systems have different jobs. The application database manages structured application records, media storage holds files, and a memory layer can help retrieve useful context from retained information.
Designing the integration around failure
A third-party service can be unavailable, slow, or temporarily unreachable. A resilient integration should anticipate those conditions instead of treating them as exceptional surprises.
A simplified example of the pattern looks like this:
// Illustrative example — adapt names and types
// to the actual GatherIt implementation.
async function handleGuestUpload(upload: Upload) {
const savedMedia = await saveMedia(upload);
// Memory processing is separate from the
// essential media-saving operation.
void retainEventContext({
eventId: upload.eventId,
mediaId: savedmedia.id,
}).catch((error) => {
logger.warn(
{ error, eventId: upload.eventId },
"Could not retain event context"
);
});
return savedMedia;
}
This snippet illustrates the design principle, not a verified copy of GatherIt’s source code. The actual implementation must use the project’s existing upload types, storage logic, logger, and memory service.
There is also an important limitation: a detached promise is not the same as a durable background job. If the server process stops at the wrong time, work that has not completed can be lost. For a production system where every memory operation matters, a persistent queue, retry policy, and idempotent processing may be more appropriate.
For an early integration, the first priority is to make sure memory-service failures do not incorrectly turn a successful media save into a failed upload. The next priority is to make background processing observable and recoverable.
I also considered how a recall endpoint should be structured. It should validate incoming requests, authenticate the host, check access to the relevant event, and handle failures from the memory service. It should not accept an arbitrary event identifier and assume that the requester is entitled to see the result.
These checks are especially important for an application where different groups create private event spaces.
Keeping credentials and event boundaries secure
An integration can work correctly in a local demo and still be unsafe if its credentials or access boundaries are handled poorly.
A memory-service API key belongs on the server, in an environment variable or the hosting platform’s secret configuration. It should not be embedded in frontend code, committed to a public repository, or returned in an API response.
Event isolation is equally important. If memory is organized around event identifiers, those identifiers must be consistently associated with authorization checks. Knowing or guessing an identifier should not be enough to retrieve another event’s context.
I also need to be careful about what gets retained. An event can contain personal conversations, faces, locations, and other sensitive information. Retaining every available detail by default may create unnecessary privacy risks.
A responsible implementation should minimize retained information, explain relevant data practices to users, and provide an appropriate way to manage or delete stored context. It should also avoid sending unnecessary personal information to an external service.
These are not secondary details to add after the feature works. They are part of the integration itself.
What this changes for the host
The goal of a memory layer is not to add AI terminology to an interface. It is to make an existing task easier.
In GatherIt, the host already has a reason to revisit event content after guests have shared it. A recall interface could eventually help the host find relevant context without manually searching through every upload or note.
For example, a host might want to find information related to a particular activity or understand the context around something that was shared. The quality of the result would depend on what was retained, how the memory system indexed it, and how the request was phrased.
That last point matters. A memory system should not be presented as an infallible record of everything that happened. It can return incomplete or irrelevant results, especially when the information was never retained or the available context is ambiguous. The interface should communicate those limits instead of presenting every response as a verified fact.
It is also important to distinguish retrieval from authorization. A technically relevant memory is not necessarily a memory that the current user is permitted to see.
How I would evaluate the feature
I would not evaluate this integration only by asking whether a recall request returns text. I would test the complete experience around it.
First, normal guest uploads should continue to work if the memory service is unavailable. Second, a host should only be able to recall information for events they are authorized to access. Third, memory failures should be logged in a way that helps debugging without leaking secrets or unnecessary personal information.
I would also test whether retained context can actually be retrieved with realistic questions, whether duplicate events or retries create confusing records, and whether the system handles missing or incomplete information gracefully.
Finally, I would measure the user-facing impact. Does the integration make it easier to find context? Does it add noticeable delay? Are the results relevant enough to be useful? Those questions need real tests and observations, not assumptions.
I do not want to claim a particular speed improvement or accuracy rate without measurements. A good engineering story should distinguish between a design goal, an implemented feature, and a result demonstrated through testing.
What I learned
The biggest lesson from exploring this integration is that adding memory is not simply a matter of connecting an API.
The harder work is deciding what information should be retained, when it should be processed, who is allowed to retrieve it, and what the application should do when the memory system is unavailable.
Separating optional memory work from essential user actions is a useful design pattern beyond AI. It applies to analytics, notifications, search indexing, and other supporting services. A system becomes more resilient when a failure in an optional capability does not automatically break its primary workflow.
I also came away with a clearer view of what makes an AI feature useful. The goal is not to insert a model into every interaction. It is to introduce a capability where it solves a real problem, keep the surrounding system understandable, and evaluate the result honestly.
GatherIt is an ongoing project, and there is still work to do before any memory feature should be treated as production-ready. Testing failure cases, strengthening background-job reliability, reviewing data retention, and validating recall quality are all part of that work.
For me, the most interesting part of Hindsight is the possibility of making event information more useful over time. Photos and videos preserve moments. Context can help people make sense of them later. The engineering challenge is connecting those two things without compromising reliability, privacy, or the simplicity of sharing in the first place.
That is the direction I want to keep exploring with GatherIt: not AI for its own sake, but technology that helps people return to the moments they care about.
Further reading
- Hindsight source code: vectorize-io/hindsight
- Hindsight documentation: hindsight.vectorize.io
- What is agent memory?: vectorize.io
1 point
Portable Local LLM
# I built PortLLM to explore portable local AI with persistent memory
## The problem I’m exploring
Running an LLM locally gives you more control over your data, but it doesn’t automatically give the assistant persistent memory across sessions. I wanted to explore how a portable local AI environment could work with a memory layer to make interactions more continuous.
That’s the idea behind PortLLM.
## How it works
PortLLM is designed as a portable environment for running local AI models, with a shared interface and support for different platforms. The project explores local inference through backends such as Ollama and llama.cpp, depending on the configuration.
I’m also exploring Hindsight as a persistent memory layer. Its core operations are:
- Retain: Save useful information from interactions.
- Recall: Retrieve relevant information when a new question comes in.
- Reflect: Reason over stored memories to build a more informed response.
The main technical challenge is not simply storing conversation history. It’s deciding what information is worth keeping, when to retrieve it, and how to avoid irrelevant or outdated memories.
## Architecture and limitations
The project separates local model inference from the memory layer. This distinction matters because local inference alone doesn’t guarantee that memory storage, retrieval, or synchronization will work offline. Those capabilities depend on how the memory component is configured.
I’m interested in making the experience portable while handling cases where network access is unavailable or relevant memories cannot be retrieved.
## What I’ve learned so far
Working on this has made me think more carefully about the trade-offs between context windows and persistent memory. A larger context window can hold more information in one session, while a memory layer can potentially carry useful details across sessions. However, poor retrieval can introduce irrelevant information, and stale memories can lead to incorrect responses.
Useful next steps include testing memory retrieval across separate sessions, checking how conflicting facts are handled, and measuring whether retrieved memories actually improve answers.
## Resources
- Project website: port-llm.vercel.app
- Source code: Keshav-pro1/PORT-LLM-
- Hindsight: vectorize-io/hindsight
I’d appreciate feedback from people working with local LLMs or agent memory:
What test cases would you use to evaluate a persistent memory system, especially when memories are missing, outdated, or contradictory?
I’m sharing this to get technical feedback and learn how to improve the design.
2 points
toktok is the first library to have a @typesafeai jev tokenizer
vectorize-io/toktok t.co
3 likes · 2 reposts · 162 views
한 달에 ★45,470 붙은 GitHub 저장소의 정체 (10월 트렌딩 TOP 5)
이번 달 GitHub 트렌딩(월간)에서 스타가 가장 많이 늘어난 저장소 5개를, 뭘 하는 건지·왜 뜨는지까지 설명합니다.
0:00 한 달에 스타 4만 5천 개가 붙은 저장소?
0:10 5위 ai-engineering-from-scratch
0:28 4위 ECC
0:50 3위 paperclip
1:12 2위 hindsight
1:33 1위 VoiceStudio
1:55 한 줄 정리
■ 이번 영상의 저장소
5위 rohitg00/ai-engineering-from-scratch
4위 affaan-m/ECC
3위 paperclipai/paperclip
2위 vectorize-io/hindsight
1위 debpalash/VoiceStudio
■ 데이터 기준
- 순위·이번 달 증가 스타: GitHub 트렌딩(monthly) 2026-10-21 스냅샷. 증가량은 트렌딩 페이지 값이며 별도로 검증하지 못했습니다.
- 총 스타·라이선스·설명: GitHub API 2026-10-21 확인.
- "개발사 주장"과 "제 해석"은 영상에서 구분해 표시했습니다. hindsight의 LongMemEval 91.4%는 개발사가 논문에 밝힌 자체 결과입니다.
- 스타 수는 품질을 보장하지 않습니다.
- VoiceStudio는 AGPL-3.0 라이선스입니다. 상업적으로 쓰기 전에 직접 확인하세요.
■ 음성
내레이션은 AI 음성(Gemini TTS)입니다.
#GitHub #깃허브 #GitHub트렌딩 #오픈소스 #AI에이전트 #개발자 #AI개발
109 likes · 3 comments · 36 views
Mentions
Title: The Memory That Knows When It Is Wrong Description: Perfect recall is dangerous without discrimination. How one agent stores the signal that separates look-alike incidents, flags stale memories, and hedges instead of guessing. Most conversations about agent memory focus on recall. Can the agent find the right thing? That is the easy half. The harder half is knowing when the thing it found is not the right thing. Incident response is full of look-alikes. A p99 spike is a symptom, not a cause. Connection-pool exhaustion can come from a missing database index, a connection leak in a retry wrapper, a config rollout that lowered the pool ceiling, or a retry storm multiplying requests. The dashboards look similar. The fixes are completely different. An agent with perfect recall and no discrimination is dangerous, because it will confidently apply last month's fix to this month's failure. Déjà Vu, an on-call SRE agent built on Hindsight, treats discrimination as a first-class part of memory rather than an afterthought. Every memory carries its own disambiguator When an incident is retained, it does not only store the symptom and the fix. It stores the signal that distinguishes this failure class from its nearest neighbour. A missing-index incident records that pool wait was high, database CPU was moderate, and the deploy touched only the orders schema. A connection-leak incident records that connections climbed monotonically and never dropped. A config incident records that the pool size itself changed. That field is called the discriminator, and it is retained alongside the narrative: doc = f""" INCIDENT {iid} | {service} | {severity} SYMPTOM: {symptom} SIGNALS: {signals} ROOT CAUSE: {root} FIX: {fix} HOW WE TOLD IT APART: {discriminator} OUTCOME: {outcome} in {minutes} min by {engineer} """ During recall, the agent does not just retrieve candidates. It re-ranks them against the live alert fingerprint, then asks a second question: does the evidence actually rule out the obvious alternative? The answer is shown to the engineer, not hidden in a chain of thought. If the agent says this is a missing index, it also says why it is not a connection leak. This is the difference between a search result and a diagnosis. Stale memory is worse than no memory Memory decays. Services get rewritten. A fix that worked in August can be actively harmful in November if the schema, the runtime or the deployment pipeline changed underneath it. A bank that only grows becomes a museum of outdated advice. So memory needs an expiry model, even a simple one. Déjà Vu flags memories for revalidation when they are old or when their outcome was not a clean resolution, and it applies a penalty during ranking rather than treating every recalled paragraph as equally authoritative. The Memory tab exposes the count directly: retained incidents, learned live, and stale. The stale counter is not decoration. It is a promise that the agent knows the difference between we solved this once and we still believe this. The contradiction guard The most useful behaviour in the whole system is the contradiction pass. After the hypothesis is formed, a critic role checks it against the strongest competing memory. If the evidence for the proposed cause is weak, or if the look-alike explains the signals better, the answer changes. On a checkout alert, the database index story is compelling: high pool wait, moderate database CPU, a deploy minutes earlier. But a connection-leak memory has almost the same surface. The discriminator settles it. The agent states which one the signals support and which one it ruled out. That check is also why the system does not always answer with maximum confidence. A confident wrong answer is the worst possible output for an on-call engineer. A slightly hedged answer with a stated contradiction is far more useful, because it tells the human what to verify. Graceful degradation is part of correctness Retrieval can fail. The memory server can be down, the network can be partitioned, the bank can be empty. A system that collapses in those moments is not production software. If Hindsight is unreachable, Déjà Vu falls back to a BM25 index over the same SQLite mirror. The answer still carries receipts from the local corpus. The header badge changes from HINDSIGHT to BM25 FALLBACK, and the trace shows which path served the answer. The quality drops, but the honesty does not. That design choice came from a simple test: would I trust this thing during an actual incident? Only if it tells me when it is operating in a degraded mode. Silent fallback is how agents lose trust. What this looks like in practice The same alert, answered twice, is the clearest demonstration. Without memory, the agent produces generic triage at roughly 31% confidence: restart the pods, check the deploy dashboard, no owner, no fix time, nothing to audit. With memory and the contradiction check, it names the missing composite index, cites three incidents, identifies the engineer who fixed it in six minutes, and explains why the connection-leak theory was rejected. The improvement is not only in the answer. It is in the shape of the answer. Verifiable, scoped, and aware of its own uncertainty. If you are building agents that act on operational systems, treat memory as two problems: what to remember, and how to know when the memory does not apply. The first gets the demo. The second gets production trust. The Hindsight project provides the retention and recall primitives; the Hindsight docs cover the API; and the Vectorize memory primer is a useful grounding in the underlying ideas. Build the discrimination layer yourself. It is where the product lives. The running agent is at dejavu-tau.vercel.app, and the source is at abinivesh-m/dejavu.
33% to 83%: Measuring whether agent memory works Description: Most memory products claim to improve. This is the replay harness that measures it, with no future knowledge, 22 graded incidents, 33% early and 83% late. Every memory product claims to get better over time. Very few show the curve. That is a problem, because "it remembers" is easy to demo and hard to prove. A retrieved paragraph can look impressive in a screenshot while adding nothing to the answer. The only honest question is: compared with the same agent before it had this memory, does it solve the next problem better? Déjà Vu is an on-call SRE agent built on Hindsight. To answer that question we built a replay harness instead of a highlight reel. The replay rule: no future memories The corpus contains incidents ordered by time, many of which share failure classes. The replay walks that corpus chronologically. At each incident, the agent may only use memories that existed before that incident. Nothing from the future. No LLM in the grading loop. The retrieval path is a deterministic BM25 index over the same documents the production system would have had at that moment. That single constraint turns a demo into an experiment. If the agent scores well, it is not because it saw the answer earlier in the list. It is because earlier incidents taught it something that transferred. A simplified version of the loop: for i, incident in enumerate(corpus): known = corpus[:i] # as-of memory only predicted = rank(incident.query, known) actual = incident.cause_class correct = predicted[0].cause_class == actual graded.append({ "n": i + 1, "predicted": predicted[0].title, "actual": incident.title, "correct": correct, "accuracy": mean(g["correct"] for g in graded), }) The output is a sequence of predictions with a running accuracy, not a single aggregate that hides the shape of learning. What the numbers say Across 22 graded incidents: - top-1 accuracy: 50% — the correct failure class on the first guess - top-3 accuracy: 64% — the correct class in the top three - first six graded alerts: 33% - last six graded alerts: 83% The aggregate is deliberately unglamorous. Fifty percent top-1 is not a victory lap. But the gap between the first six and the last six is the product thesis: as the bank accumulates specific, structured incidents, the agent stops guessing generically and starts recognising patterns. The early failures are instructive. The first graded alert is a Redis eviction problem. The agent predicts a Kafka consumer rebalance loop, because it has no relevant precedent and the surface vocabulary points at streaming infrastructure. That is what a cold start looks like. By the end of the replay, a config-driven pool ceiling is matched to the same failure class seen earlier, and a month-end reporting query is recognised immediately. We surface both sides in the product. The Learning tab shows the cumulative curve, the early and late windows, and a "Same agent, three moments" strip: alert #1 with zero memories, a middle alert with eleven, and the final alert with twenty-one. The first card is a cold miss. The last two are matches. That progression is more convincing than any single accuracy number, because it shows the mechanism. Why not just ask an LLM to grade it? Because the point is to test memory, not model capability. An LLM grader introduces its own priors, its own variance and its own cost. A deterministic ranker over the as-of corpus is reproducible: the same corpus produces the same curve. If the curve improves, the improvement came from retrieval, which is what the memory layer controls. This does not mean the production agent is deterministic. In production, Hindsight recalls candidates by meaning, the application re-ranks them against the live signal fingerprint, and a language model writes the final hypothesis from the receipts. The replay isolates one variable — whether the right past incident was available and ranked highly — so the rest of the system can be evaluated separately. Measure the failure modes too A learning curve that only shows wins is marketing. The interesting questions are about what goes wrong. Three failure modes matter in practice. First, cold start: with an empty bank, the agent is generic, and it should say so rather than invent confidence. Second, look-alikes: two incidents with similar symptoms and different causes. Re-ranking by signals and forcing a stated contradiction is what prevents a confident wrong answer. Third, stale memory: an old fix that no longer applies. A bank that never expires becomes a source of harm, so stale memories are flagged and penalised rather than trusted. We also test degradation. If Hindsight is unreachable, the agent falls back to the local BM25 index and labels the path. The receipts remain; the quality drops; the user is told. A memory system that hides its failure mode is not measurable, because you cannot tell when it is lying. What we would measure next The replay measures cause-class retrieval, which is the core of the value proposition. The next step is outcome-weighted evaluation: did the recalled fix actually resolve the incident, and how many minutes did it save compared with the generic baseline? That requires more resolved incidents and a way to attribute time saved without confounding variables. Until then, the honest claim is narrow and testable: on a chronological replay with no future knowledge, the same agent improves from 33% to 83% as its memory bank grows, and every prediction is backed by a retrievable incident. That is a better claim than "it remembers." It is falsifiable. The Hindsight repository is open source, the documentation covers retention and recall, and the Vectorize primer is a good conceptual starting point. Build the replay harness before you build the landing page. The curve will tell you whether you have a product. The running agent is at dejavu-tau.vercel.app, and the source, including the replay harness, is at abinivesh-m/dejavu.
"Receipts, Not Vibes: Why Agent Memory Needs Provenance" Description: Agent memory is only useful if every claim traces back to a real incident. A practical look at provenance, structured metadata, and retrieval that shows its receipts. It is 02:14 and checkout is failing. A generic model looks at the alert and says something reasonable: restart the affected pods, check the deploy dashboard, watch the error rate. It is not wrong. It is also not useful. It has no idea that this exact failure happened six weeks ago, that the cause was a missing composite index, that Priya fixed it in six minutes, or that restarting only buys forty minutes. The difference between those two answers is not model quality. It is provenance. When an agent claims to remember, the first question an on-call engineer should ask is: show me. Show me the incident. Show me the signals that matched. Show me who fixed it and whether the fix held. Without that, "memory" is just confident improvisation with extra steps. That constraint shaped Déjà Vu, an on-call SRE agent built on Hindsight. Every answer is assembled from retained incidents, and every claim carries a receipt back to one. Memory is a data model problem before it is a retrieval problem The usual approach is to store chat transcripts and hope semantic search finds something useful. That works for a demo and fails an audit. A paragraph of postmortem prose does not tell you which incident it came from, which engineer owned it, how long the fix took, or whether the fix actually held. So each incident is retained as a structured document. The narrative is there, because meaning matters, but so is the metadata that survives retrieval: incident id, service, root cause, fix, outcome, duration, engineer, severity and tags. Hindsight's memory documentation describes this as retaining what the system should remember, not just what was said. That distinction is the whole game. A retain payload from the project looks roughly like this: memory.retain({ "bank": "dejavu-oncall", "content": f"{title}. {symptom}\n\nROOT CAUSE: {root}\nFIX: {fix}", "metadata": { "incident_id": iid, "service": service, "root_cause": root, "fix": fix, "outcome": outcome, "fix_minutes": minutes, "engineer": engineer, "severity": severity, "source": "seed" if seeded else "live", }, "tags": [service, severity, outcome], }) Because the metadata is stored alongside the text, a recalled paragraph becomes a citation instead of a suggestion. Retrieval is a ranking problem Semantic similarity alone is not enough for incidents. Two alerts can read almost identically and have completely different causes. A checkout latency spike caused by a missing index looks a lot like a checkout latency spike caused by a connection leak — until you compare the signals. Déjà Vu builds its recall query from the alert fingerprint: service, title, body, and every key=value signal. Candidates come back from Hindsight by meaning, then the application re-ranks them against the live fingerprint. Signal similarity carries the most weight, text similarity next, coverage after that. Outcome, recency and support act as tie-breakers, and stale memories are penalised rather than silently trusted. That last part matters. A memory bank that never forgets becomes a liability. An incident from fourteen months ago, before an architecture change, should not outrank last week's lesson just because the wording is close. The UI has to make the receipt visible Provenance is not a backend property. If the engineer cannot see it in three seconds, it does not exist. In Déjà Vu, every answer carries a receipt strip: incident id, date, service, the fix that worked, the engineer, the minutes, and the outcome. The answer also states which look-alike incident it ruled out and why. The memory bus at the bottom of the screen shows the actual retain and recall operations with backend, latency and result count, so the claim is observable rather than asserted. This is also where the honest failure mode lives. If Hindsight is unreachable, the app does not pretend. It serves the same corpus through a BM25 index over the SQLite mirror, changes the header badge from HINDSIGHT to BM25 FALLBACK, and records the path in the trace. An agent that hides its retrieval path is not trustworthy at 3 a.m. What provenance buys you The practical result is a different kind of answer. Without memory: generic triage, roughly 31% confidence, no owner, no time estimate, nothing to audit. With memory: the missing index, the receipts, a named engineer, a six-minute fix, and a stated reason the connection-leak theory was rejected — around 97% confidence. The second answer is not better because the model is smarter. It is better because the model was handed evidence. That is the case for agent memory in production systems. Not a chatbot with a longer context window. A system that remembers specific incidents, cites them, learns from resolutions, and can be checked afterwards. If you are building in this space, start with the receipt. Decide what a citation must contain, then design retention and retrieval backwards from it. The Hindsight repository is open source, and the Vectorize primer on agent memory is a good place to pressure-test the model. Memory is only valuable when someone can verify it. The running agent is at dejavu-tau.vercel.app, and the source is at abinivesh-m/dejavu.
Your On-Call Agent Needs Hindsight, Not a Bigger Model Description: An on-call SRE agent is only as good as the incidents it can recall. Structured retention, evidence-backed ranking, and a contradiction guard built on Hindsight. It is 02:14. Checkout p99 has gone from 400 ms to 3.9 seconds, the payment provider is retrying, and an alert is burning through the error budget. The engineer who fixed this exact failure six weeks ago is asleep. The migration that solved it was applied by hand and never written down. So the person on call searches, guesses, and restarts the pods. The restart works for forty minutes. I kept coming back to that gap. The model is not the bottleneck. A good model has read every runbook and every public postmortem. What it does not have is your history: this failure, on this service, with these signals, fixed in six minutes by a specific person, and whether the fix held. I built Déjà Vu to test that claim seriously — an on-call SRE agent whose entire value comes from remembering incidents, and whose memory layer is Hindsight. What the system actually does Déjà Vu watches an alert queue. When one fires, it builds a query from the service, title, body and signal fingerprint, recalls candidates from a Hindsight bank called dejavu-oncall, re-ranks them, and answers with evidence. One bank per team: your incidents only, never another team's. The answer is not a paragraph. It is a hypothesis plus receipts: - INC-1006 — missing composite index on orders(created_at, status) — 6 minutes — Priya Raman — resolved - INC-1001 — same cause class — resolved - INC-1002 — same class — resolved Same alert, memory off: "generic triage, restart the affected pods", 31% confidence, no incident, no owner, no fix time. Memory on: the index migration, 97% confidence, the receipts, a named engineer. The second answer is not smarter. It is informed. Making memory the actual product The naive version of this is a vector store full of postmortems with a prompt that says "use the context below." It demos well and fails quietly, for three reasons. It retrieves paragraphs, not incidents — so nothing is auditable. It treats similarity as identity — so a look-alike incident with a different cause gets recommended with full confidence. And it never learns from what happened after the fix. So the memory is structured, not chunked. One document per incident, with metadata that survives retrieval: resp = client().retain( bank_id="dejavu-oncall", content=text, # symptom, signals, cause, fix, time, outcome document_id=incident_id, context=f"{inc.get('service')} {inc.get('severity')} incident on {ts[:10]}", metadata={ "incident_id": incident_id, "service": inc.get("service"), "root_cause": inc.get("root_cause"), "fix": inc.get("fix"), "outcome": inc.get("outcome"), "fix_minutes": str(inc.get("fix_minutes")), "engineer": inc.get("engineer"), "severity": inc.get("severity"), }, tags=[inc["service"], inc["severity"], inc["outcome"]], ) That metadata is the difference between a receipt and a rumour. When the agent says "six minutes, Priya Raman, resolved," those values came from memory, not the model's imagination. Recall is deliberate: the alert's fingerprint becomes the query, Hindsight returns candidates by meaning, and the application re-ranks them — retrieval similarity and operational similarity are not the same thing: similarity = 0.50 * signal_similarity + 0.45 * text_similarity + 0.05 * coverage score = 0.82 * similarity score += 0.10 * min(1.0, support / 3) # how many incidents back this cause score += 0.08 * success_rate # did the fix actually hold score += 0.02 * recency # recent precedent wins ties if stale: score -= 0.06 # flag it, do not trust it Fifty percent of the decision is the signal fingerprint — the numbers, not the prose. p99_ms 3900 against 3800. pool_wait_ms 1240 against 1180. cert_age_days 2 against 61. That last one is why a certificate incident gets ruled out even when the text looks identical. The part that matters: the contradiction guard Two incidents can share every word and need opposite fixes. Incident INC-1009 has the same service, the same pool timeout, the same graph shape, and 53% similarity to the live alert. But its cause was a pool size capped during a config rollout, and its fix was a config change plus a redeploy — not an index. Before committing, Déjà Vu checks the runner-up failure class. If a different cause is close, it surfaces the look-alike explicitly: the incident ID, the similarity, the one signal that separates them, and the different fix it required. This is the failure mode of every naive retrieval system. A text search returns the nearest paragraph. The agent has to tell you what it ruled out, and why. Measurement, not a claim Every memory product says it improves. Almost none measure it, because honest measurement is uncomfortable. The repo includes a replay that walks the incident corpus in chronological order. At each incident, the agent may only use memories that existed before that timestamp. No peeking. No LLM in the grading loop. Across 22 graded incidents: 50% top-1, 64% top-3. First six graded alerts: 33%. Last six: 83%. That pair is the thesis. The agent is measurably better at the end of the quarter than at the start, because it lived through the quarter. The Learning screen plots every graded incident, including the ones it got wrong. A memory system that only shows its wins is a marketing surface. The loop has to close Resolving an alert is not the end of the interaction. It is the write. When an engineer resolves an incident, Déjà Vu stores a postmortem, retains it with source: live, and marks the alert closed. Fire the same fingerprint again and the first receipt is the incident that was just created, answered in milliseconds. That closed loop is also where a second agent earns its place. In the Band room, DejaVu-Recall posts the hypothesis and receipts, then DejaVu-Critic answers the recall — not the alert — with four deterministic checks: at least two receipts, no stale precedent, precedent fixes that held, confidence above threshold. It can block the fix from ever reaching a human. I wrote the critic as code, not a model call: a reviewer should check evidence, not generate more of it. What I got wrong Three things, in order of embarrassment. First, I scoped recall to the same service. That hid the lesson: a missing index on payments-api is the same failure as one on checkout-api. Cross-service transfer drove most of the late-corpus accuracy. Second, I graded at string level before switching to failure classes. "Missing index on orders" and "missing index on settlement_date" are different strings and the same lesson. String-level grading made the agent look worse than it was. Third, I trusted retrieval scores for too long. The signal fingerprint is weighted above text on purpose now. The text is how you find candidates; the numbers are how you decide. Where it still breaks First-time failures cannot be recalled. If the team has never seen it, memory has nothing, and the Learning screen shows exactly those incidents as misses. Per-service histories hold eight to ten incidents, so cross-service transfer helps but is not evidence of production-scale performance. The corpus is synthetic — real incident data is confidential — and the weights were tuned on it. A production deployment needs re-tuning against real signals and a plan for the long tail of incidents that happen once. And memory can be wrong. Precedent is not proof. That is why every answer carries confidence, receipts, and a visible trace of which path served it. When Hindsight is unreachable, the app serves from a BM25 index over the same SQLite mirror and the header badge changes from HINDSIGHT to BM25 FALLBACK. A demo should not die because a service did not start, but it should never pretend which path answered. What I took away The next improvement in on-call tooling is not a bigger context window. It is a memory that is specific to your systems, weighted by what actually worked, honest about what it does not know, and measured against its own past. Hindsight made the memory layer the easy part: a bank, a retain with real metadata, a recall that returns meaning. The hard part was deciding what counts as the same failure — and being willing to show the moment the agent gets it wrong. At 2 a.m., the question is not "what does a good SRE do?" It is "what did we do last time, did it work, and who can I ask?" If you are building agents with memory, start with Hindsight's open-source memory engine and read the Hindsight documentation. It is also worth getting clear on what agent memory actually means before you design a schema you will regret. Running agent: dejavu-tau.vercel.app. Source, including the replay harness: abinivesh-m/dejavu.
エージェントの記憶喪失を治す:OSS「Hindsight」をClaude APIに繋いで長期記憶を持たせる セッションが終わるたびに、エージェントは全部忘れる Claude APIでエージェントを組んでいると、必ずぶつかる壁がある。会話が終わってプロセスが落ちれば、そこまでの文脈は綺麗さっぱり消える。ユーザーの好みも、過去に失敗したアプローチも、次のセッションでは「初対面」からやり直しだ。 RAGでドキュメントを検索させるのとは話が別で、これは「エージェント自身の経験」を覚えさせたいという要求になる。自前でPostgres+pgvectorのテーブルを設計してretain/recallのロジックを書いてもいいが、まず既製品で試して足りない部分だけ自作する方が早い。 今回はOSSのエージェント向け長期記憶システム Hindsight(vectorize-io製、MITライセンス)を、素のClaude APIエージェントに繋ぎ込むところまで手を動かす。 Hindsightとは何か Hindsightは2026年4月にGitHub Star数1万を突破し、直近のリリースは v0.10.1(2026年9月21日、50件超のPRと22人以上のコントリビューターがマージされた)。エージェントメモリのベンチマークであるLongMemEvalでSOTA相当のスコアを主張しており、記憶を「world facts(事実)」「experiences(経験)」「observations(観察)」「mental models(メンタルモデル)」に分けて構造化して持つ点が特徴になっている。 APIはシンプルで3つしかない。 retain — 記憶を書き込む recall — 記憶を検索する reflect — 蓄積した記憶を分析し、上位の理解(メンタルモデル)を形成する 単純なベクトル検索のラッパーではなく、reflect で「経験の積み重ねから学習する」層を持っているのが他のシンプルなメモリストアとの違いだ。 1. サーバーを立てる Docker一発で立ち上がる。ローカル検証ならこれが一番早い。 docker run -it --pull always --name hindsight \ --restart unless-stopped \ -p 8888:8888 -p 9999:9999 \ -e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \ -v hindsight-data:/home/hindsight/.pg0 \ ghcr.io/vectorize-io/hindsight:latest HINDSIGHT_API_LLM_API_KEY は記憶の抽出・要約に内部で使うLLM用のキーで、エージェント本体がClaudeでもHindsight側は別プロバイダーで構わない。8888 がREST API、9999 は管理系ポート。起動したら疎通確認する。 curl -s localhost 2. クライアントを入れて最小構成で試す pip install hindsight-client anthropic まず生のretain/recallだけで感覚を掴む。 from hindsight_client import Hindsight client = Hindsight(base_url="localhost") client.retain( bank_id="user-yukito", content="ユーザーはDockerのlatestタグを避ける方針。ピン留めしたバージョンを使う。", ) result = client.recall(bank_id="user-yukito", query="Dockerタグの方針は?") print(result) bank_id が記憶の名前空間になる。マルチユーザー・マルチプロジェクトで運用するなら、ここをユーザーIDやプロジェクトIDで切るのがそのまま権限分離にもなる。 3. Claudeエージェントに組み込む ここからが本題。セッションの開始時に関連する記憶をrecallしてシステムプロンプトに注入し、セッション終了時に得られた新しい事実をretainする、という往復を1つのクラスにまとめる。 import anthropic from hindsight_client import Hindsight class MemoryAgent: def init(self, bank_id: str): self.bank_id = bank_id self.memory = Hindsight(base_url="localhost") self.claude = anthropic.Anthropic() def _recall_context(self, query: str, limit: int = 5) -> str: hits = self.memory.recall(bank_id=self.bank_id, query=query, limit=limit) if not hits: return "" facts = "\n".join(f"- {h['content']}" for h in hits) return f"過去のやり取りから分かっている事実:\n{facts}" def ask(self, user_message: str) -> str: context = self._recall_context(user_message) system = "あなたは開発アシスタントです。" + (f"\n\n{context}" if context else "") response = self.claude.messages.create( model="claude-sonnet-5", max_tokens=1024, system=system, messages=[{"role": "user", "content": user_message}], ) answer = response.content[0].text このやり取り自体を経験として書き戻す self.memory.retain( bank_id=self.bank_id, content=f"Q: {user_message}\nA: {answer}", ) return answer 動作確認は別プロセス(別セッション)で行うのが重要。プロセスを一度落として、記憶がDBに残っていることを確かめる。 セッション1(プロセスA) agent = MemoryAgent(bank_id="user-yukito") agent.ask("このプロジェクトではpnpmを使う。npmは使わない。") ここでプロセス終了 セッション2(別プロセス) agent = MemoryAgent(bank_id="user-yukito") print(agent.ask("パッケージマネージャは何を使えばいい?")) → recallでpnpmの方針を拾ってからClaudeが回答する これでプロセスをまたいだ記憶が機能する。RAGのドキュメント検索と違い、ここに入るのは「このエージェントが実際にやり取りした内容」なので、事実確認ではなく方針・好み・過去の失敗の再現防止に効く。 4. reflectで経験を要約させる retainを積み重ねただけだと、生の会話ログが線形に溜まっていくだけでrecallのノイズが増える。定期的にreflectを呼んで上位の理解を作らせるのが公式の使い方だ。 client.reflect(bank_id="user-yukito") これを1日1回のcronなどで回しておくと、個別のQ&Aペアから「このユーザーはDockerのlatestタグを嫌う」「pnpmを優先する」といったメンタルモデル的な記憶に集約されていく。リリースノート(v0.10.1)でも「コーディングエージェント向けにautomatic reflectの予算制限を修正」という変更が入っており、reflectを回しすぎるとLLM呼び出しコストが積み上がる点は運用上のパラメータとして意識しておく必要がある。 つまずいたところ recallは空配列を返すことがある(まだ何もretainしていない、またはbank_idの綴りミス)。ガードを外して素通しすると、システムプロンプトに空文字列の見出しだけが残ってClaudeが混乱するので、上のコードのように空なら注入自体をスキップする。 bank_idを適当な固定文字列にすると、複数ユーザーの記憶が混ざる。最初から「誰の記憶か」をbank_idの設計に落とし込んでおく。 retainのcontentを生の会話ログそのまま入れ続けるとreflect前は検索ノイズが増える。要約してからretainする運用にした方が精度は安定した。 まとめ HindsightはREST経由のretain/recall/reflectという最小限のAPIで、Claude Agentに「セッションをまたぐ記憶」を持たせられる。自前でpgvectorスキーマを設計する前に、まずこの3操作で要件を満たせるか試す価値はある。今回はローカルDocker+Python SDKでの最小構成だったが、本番運用するならbank_idの権限分離とreflectの実行頻度(コスト)の2点を先に設計しておくと手戻りが少ない。 参考 vectorize-io/hindsight (GitHub) Hindsight Releases — v0.10.1 Hindsight Reaches 10,000 Stars
I built OptMem plugin for Hermes. It's one of the 24 in the official catalog. Zero dependencies. No database, no embeddings, no API key. An append-only log: summaries keep context small, the raw record is never deleted. OptMem from @VictorTaelin rarf/optmem-hermes-plugin
Adding Recall to GatherIt Without Blocking Guest Uploads Adding Recall to GatherIt Without Blocking Guest Uploads The problem: an event creates more information than people can keep track of When I started building GatherIt, I wanted to make sharing memories at an event feel effortless. Guests should be able to join without installing an app, upload photos and videos, leave voice notes, and see moments collected in one place. Hosts should be able to manage the experience without constantly asking everyone to send their media through separate messaging apps. The challenge is that an event produces much more than a collection of files. It creates context. A guest might upload a photo from a particular moment, add a voice note explaining what happened, or join an event after several activities have already taken place. Later, the host might want to recall a particular moment or understand what people shared. A conventional gallery can store and display media, but it does not automatically provide a useful way to recall the surrounding context. That led me to explore a question: Could I give GatherIt a memory layer without slowing down the experience that makes it useful in the first place? I explored Hindsight, an open-source memory system designed to help AI applications retain and recall information. Instead of treating every interaction as an isolated request, a memory system can make relevant information available when an application needs it again. For GatherIt, the interesting part was not simply adding another AI feature. It was exploring how event context could be captured in the background and retrieved later when a host wanted to look back. Why memory needs to be separate from the main user experience One of the most important engineering decisions in an application like GatherIt is deciding what must happen immediately and what can happen later. When a guest uploads a photo, the main experience should focus on accepting the upload, handling the media, and giving the guest clear feedback. The guest should not have to wait for an additional memory operation to finish before continuing. If memory processing is placed directly in the critical upload path, it introduces another dependency. A slow memory service or a temporary network problem could affect a feature that should otherwise work independently. I therefore approached memory as a supporting capability rather than the centre of the upload workflow. The basic flow I was working toward was: 1. A guest joins an event or shares media. 2. GatherIt performs the normal application work. 3. Relevant event context is passed to a memory operation separately. 4. The host can request a recall when they need that context. This separation matters because a memory system should improve an application without becoming a single point of failure for its core features. It also encourages a useful engineering principle: optional intelligence should not make essential functionality unnecessarily fragile. Where Hindsight fits Hindsight provides a way to retain information and later retrieve relevant context. Its repository and documentation were useful starting points for understanding how a memory layer could fit into an existing application. References: - Hindsight on GitHub: vectorize-io/hindsight - Hindsight documentation: hindsight.vectorize.io - Background on agent memory: vectorize.io For GatherIt, the conceptual mapping was straightforward. Each event has its own context, and memory operations need to be associated with the correct event. A host asking about one event should not accidentally retrieve information belonging to another. That makes event-level separation important. It also makes authorization important: a recall operation should be available only to an appropriately authenticated host, and the server should determine which event the host is allowed to access. I explored an integration pattern in which the server handles memory operations rather than exposing memory-service credentials to the browser. This keeps credentials on the backend and gives the application a single place to apply authorization, validation, and error handling. The important distinction is that Hindsight does not replace GatherIt’s database or media storage. Those systems have different jobs. The application database manages structured application records, media storage holds files, and a memory layer can help retrieve useful context from retained information. Designing the integration around failure A third-party service can be unavailable, slow, or temporarily unreachable. A resilient integration should anticipate those conditions instead of treating them as exceptional surprises. A simplified example of the pattern looks like this: // Illustrative example — adapt names and types // to the actual GatherIt implementation. async function handleGuestUpload(upload: Upload) { const savedMedia = await saveMedia(upload); // Memory processing is separate from the // essential media-saving operation. void retainEventContext({ eventId: upload.eventId, mediaId: savedmedia.id, }).catch((error) => { logger.warn( { error, eventId: upload.eventId }, "Could not retain event context" ); }); return savedMedia; } This snippet illustrates the design principle, not a verified copy of GatherIt’s source code. The actual implementation must use the project’s existing upload types, storage logic, logger, and memory service. There is also an important limitation: a detached promise is not the same as a durable background job. If the server process stops at the wrong time, work that has not completed can be lost. For a production system where every memory operation matters, a persistent queue, retry policy, and idempotent processing may be more appropriate. For an early integration, the first priority is to make sure memory-service failures do not incorrectly turn a successful media save into a failed upload. The next priority is to make background processing observable and recoverable. I also considered how a recall endpoint should be structured. It should validate incoming requests, authenticate the host, check access to the relevant event, and handle failures from the memory service. It should not accept an arbitrary event identifier and assume that the requester is entitled to see the result. These checks are especially important for an application where different groups create private event spaces. Keeping credentials and event boundaries secure An integration can work correctly in a local demo and still be unsafe if its credentials or access boundaries are handled poorly. A memory-service API key belongs on the server, in an environment variable or the hosting platform’s secret configuration. It should not be embedded in frontend code, committed to a public repository, or returned in an API response. Event isolation is equally important. If memory is organized around event identifiers, those identifiers must be consistently associated with authorization checks. Knowing or guessing an identifier should not be enough to retrieve another event’s context. I also need to be careful about what gets retained. An event can contain personal conversations, faces, locations, and other sensitive information. Retaining every available detail by default may create unnecessary privacy risks. A responsible implementation should minimize retained information, explain relevant data practices to users, and provide an appropriate way to manage or delete stored context. It should also avoid sending unnecessary personal information to an external service. These are not secondary details to add after the feature works. They are part of the integration itself. What this changes for the host The goal of a memory layer is not to add AI terminology to an interface. It is to make an existing task easier. In GatherIt, the host already has a reason to revisit event content after guests have shared it. A recall interface could eventually help the host find relevant context without manually searching through every upload or note. For example, a host might want to find information related to a particular activity or understand the context around something that was shared. The quality of the result would depend on what was retained, how the memory system indexed it, and how the request was phrased. That last point matters. A memory system should not be presented as an infallible record of everything that happened. It can return incomplete or irrelevant results, especially when the information was never retained or the available context is ambiguous. The interface should communicate those limits instead of presenting every response as a verified fact. It is also important to distinguish retrieval from authorization. A technically relevant memory is not necessarily a memory that the current user is permitted to see. How I would evaluate the feature I would not evaluate this integration only by asking whether a recall request returns text. I would test the complete experience around it. First, normal guest uploads should continue to work if the memory service is unavailable. Second, a host should only be able to recall information for events they are authorized to access. Third, memory failures should be logged in a way that helps debugging without leaking secrets or unnecessary personal information. I would also test whether retained context can actually be retrieved with realistic questions, whether duplicate events or retries create confusing records, and whether the system handles missing or incomplete information gracefully. Finally, I would measure the user-facing impact. Does the integration make it easier to find context? Does it add noticeable delay? Are the results relevant enough to be useful? Those questions need real tests and observations, not assumptions. I do not want to claim a particular speed improvement or accuracy rate without measurements. A good engineering story should distinguish between a design goal, an implemented feature, and a result demonstrated through testing. What I learned The biggest lesson from exploring this integration is that adding memory is not simply a matter of connecting an API. The harder work is deciding what information should be retained, when it should be processed, who is allowed to retrieve it, and what the application should do when the memory system is unavailable. Separating optional memory work from essential user actions is a useful design pattern beyond AI. It applies to analytics, notifications, search indexing, and other supporting services. A system becomes more resilient when a failure in an optional capability does not automatically break its primary workflow. I also came away with a clearer view of what makes an AI feature useful. The goal is not to insert a model into every interaction. It is to introduce a capability where it solves a real problem, keep the surrounding system understandable, and evaluate the result honestly. GatherIt is an ongoing project, and there is still work to do before any memory feature should be treated as production-ready. Testing failure cases, strengthening background-job reliability, reviewing data retention, and validating recall quality are all part of that work. For me, the most interesting part of Hindsight is the possibility of making event information more useful over time. Photos and videos preserve moments. Context can help people make sense of them later. The engineering challenge is connecting those two things without compromising reliability, privacy, or the simplicity of sharing in the first place. That is the direction I want to keep exploring with GatherIt: not AI for its own sake, but technology that helps people return to the moments they care about. Further reading - Hindsight source code: vectorize-io/hindsight - Hindsight documentation: hindsight.vectorize.io - What is agent memory?: vectorize.io
Portable Local LLM # I built PortLLM to explore portable local AI with persistent memory ## The problem I’m exploring Running an LLM locally gives you more control over your data, but it doesn’t automatically give the assistant persistent memory across sessions. I wanted to explore how a portable local AI environment could work with a memory layer to make interactions more continuous. That’s the idea behind PortLLM. ## How it works PortLLM is designed as a portable environment for running local AI models, with a shared interface and support for different platforms. The project explores local inference through backends such as Ollama and llama.cpp, depending on the configuration. I’m also exploring Hindsight as a persistent memory layer. Its core operations are: - Retain: Save useful information from interactions. - Recall: Retrieve relevant information when a new question comes in. - Reflect: Reason over stored memories to build a more informed response. The main technical challenge is not simply storing conversation history. It’s deciding what information is worth keeping, when to retrieve it, and how to avoid irrelevant or outdated memories. ## Architecture and limitations The project separates local model inference from the memory layer. This distinction matters because local inference alone doesn’t guarantee that memory storage, retrieval, or synchronization will work offline. Those capabilities depend on how the memory component is configured. I’m interested in making the experience portable while handling cases where network access is unavailable or relevant memories cannot be retrieved. ## What I’ve learned so far Working on this has made me think more carefully about the trade-offs between context windows and persistent memory. A larger context window can hold more information in one session, while a memory layer can potentially carry useful details across sessions. However, poor retrieval can introduce irrelevant information, and stale memories can lead to incorrect responses. Useful next steps include testing memory retrieval across separate sessions, checking how conflicting facts are handled, and measuring whether retrieved memories actually improve answers. ## Resources - Project website: port-llm.vercel.app - Source code: Keshav-pro1/PORT-LLM- - Hindsight: vectorize-io/hindsight I’d appreciate feedback from people working with local LLMs or agent memory: What test cases would you use to evaluate a persistent memory system, especially when memories are missing, outdated, or contradictory? I’m sharing this to get technical feedback and learn how to improve the design.
toktok is the first library to have a @typesafeai jev tokenizer vectorize-io/toktok t.co
한 달에 ★45,470 붙은 GitHub 저장소의 정체 (10월 트렌딩 TOP 5) 이번 달 GitHub 트렌딩(월간)에서 스타가 가장 많이 늘어난 저장소 5개를, 뭘 하는 건지·왜 뜨는지까지 설명합니다. 0:00 한 달에 스타 4만 5천 개가 붙은 저장소? 0:10 5위 ai-engineering-from-scratch 0:28 4위 ECC 0:50 3위 paperclip 1:12 2위 hindsight 1:33 1위 VoiceStudio 1:55 한 줄 정리 ■ 이번 영상의 저장소 5위 rohitg00/ai-engineering-from-scratch 4위 affaan-m/ECC 3위 paperclipai/paperclip 2위 vectorize-io/hindsight 1위 debpalash/VoiceStudio ■ 데이터 기준 - 순위·이번 달 증가 스타: GitHub 트렌딩(monthly) 2026-10-21 스냅샷. 증가량은 트렌딩 페이지 값이며 별도로 검증하지 못했습니다. - 총 스타·라이선스·설명: GitHub API 2026-10-21 확인. - "개발사 주장"과 "제 해석"은 영상에서 구분해 표시했습니다. hindsight의 LongMemEval 91.4%는 개발사가 논문에 밝힌 자체 결과입니다. - 스타 수는 품질을 보장하지 않습니다. - VoiceStudio는 AGPL-3.0 라이선스입니다. 상업적으로 쓰기 전에 직접 확인하세요. ■ 음성 내레이션은 AI 음성(Gemini TTS)입니다. #GitHub #깃허브 #GitHub트렌딩 #오픈소스 #AI에이전트 #개발자 #AI개발