Long-term memory for Microsoft Agent Framework agents, backed by a Hindsight memory bank.
Attach one AIContextProvider and memory happens on its own, every turn:
- before each run — memories relevant to the user's message are recalled from the bank and injected into the agent's instructions;
- after each run — the turn's transcript is retained, so future runs build on it.
No MCP server. No tool the model has to remember to call.
This is an independent, community .NET port of Vectorize's Python package
hindsight-agent-framework. It is not affiliated with, endorsed by, or supported by Vectorize AI, Inc. — please raise issues here, not on their tracker. It is also unrelated to the similarly-namedHindsight.Behavepackage, which is a behaviour-tree library by a different author. See NOTICE.
dotnet add package Hindsight.AgentFramework.Net
Targets net8.0 and net10.0.
using Hindsight.AgentFramework;
using var http = new HttpClient();
var client = new HindsightClient(http, new HindsightOptions
{
ApiKey = Environment.GetEnvironmentVariable("HINDSIGHT_API_KEY"),
});
var memory = new HindsightMemoryProvider(client, new HindsightOptions
{
BankId = "user-123", // one bank per user is the usual shape
Mission = "Remember this user's preferences and ongoing projects.",
});
AIAgent agent = chatClient.CreateAIAgent(new ChatClientAgentOptions
{
Name = "assistant",
Instructions = "You are a helpful assistant.",
AIContextProviderFactory = _ => memory,
});builder.Services.AddHttpClient<IHindsightClient, HindsightClient>()
.ConfigureHttpClient(c => c.Timeout = TimeSpan.FromSeconds(30));Then resolve IHindsightClient and build a HindsightMemoryProvider per user, giving each its own
BankId.
| Option | Default | What it does |
|---|---|---|
BankId |
(required) | The memory bank to recall from and retain into. |
ApiKey |
null |
Sent as Authorization: Bearer …. Omit for an unauthenticated self-hosted server. |
BaseAddress |
https://api.hindsight.vectorize.io |
Self-hosted default is http://localhost:8888. |
Budget |
mid |
Recall budget — low, mid or high. |
MaxTokens |
4096 |
Cap on the recalled text injected into instructions. |
Context |
agent-framework |
Source label stamped on retained memories. |
Tags |
null |
Tags applied to retained memories. |
RecallTags / RecallTagsMatch |
null / any |
Tag filter for recall. Match modes: any, all, any_strict, all_strict, exact. |
Mission |
null |
When set, the bank is created on first use with this mission. |
AutoRecall / AutoRetain |
true / true |
Turn either half off. |
MaxRetainLength |
32768 |
Transcripts longer than this are truncated before retain. |
IsEnabled |
null (always on) |
Evaluated per invocation. Return false to skip both recall and retain for this run. |
A provider is typically built once and reused across many runs, while "should this particular
exchange be remembered?" is a per-run question — an incognito or off-the-record conversation, a
user who has opted out, a health-check run. Capturing that decision as a value at construction
would be wrong on every later run. IsEnabled is read at invoke time:
new HindsightOptions { BankId = userId, IsEnabled = () => !conversationIsEphemeral }- Nothing here can break your agent. Every recall and retain is wrapped; a failure is logged at debug and swallowed. A memory outage degrades the agent to no memory, never to an exception.
- Retain is sent with
async: true. Hindsight's retain performs LLM fact extraction inline otherwise, which would stall the turn by seconds while the agent waits. - A failed run is not retained. If
InvokedContext.InvokeExceptionis set, the transcript is dropped — a broken turn is not a memory worth keeping. (The Python original has no equivalent; its context provider API exposes no such signal.) - No feedback loop. Recalled memories are injected as
AIContext.Instructions, which the framework composes into a per-run copy of the agent's options. They never become messages, so they are not visible to retain and are never written back to the bank.
Recall, retain, create-bank and health. Hindsight's other surfaces — reflect, entities, mental models, knowledge base, documents, directives, observations — are out of scope, as is deleting or inspecting memories.
Tag a commit vX.Y.Z and push it. .github/workflows/release.yml tests, packs with the version
taken from the tag, and publishes to nuget.org using
trusted publishing — there is
no long-lived API key stored in this repository. The trusted publishing policy on nuget.org names
this owner, this repository, and the workflow file release.yml; the only repository secret is
NUGET_USER, the nuget.org profile name (not an email address).
MIT — see LICENSE. Portions derived from https://github.com/vectorize-io/hindsight (MIT, Copyright (c) 2025 Vectorize AI, Inc.); the full upstream notice is reproduced in NOTICE.