Files
vectorize-io__hindsight/README.md
T
Nicolò Boschi 30ce3b8d11 feat(llm): add Meta Model API as a first-class provider (#4081)
* feat(llm): add Meta Model API as a first-class provider

Meta Model API (https://ai.developer.meta.com) serves the Muse family over an
OpenAI-compatible chat/completions endpoint, so it slots into the existing
OpenAICompatibleLLM path exactly like deepseek / zai / atlas.

Set `HINDSIGHT_API_LLM_PROVIDER=meta` to route fact extraction, reflection and
consolidation through it. The base URL defaults to https://api.meta.ai/v1 and
the default model is muse-spark-1.3 (1M context).

Two Meta-specific behaviours are worth knowing, and are documented rather than
worked around:

- Muse Spark always reasons. `reasoning_effort: "none"` is rejected with HTTP
  400 — only minimal/low/medium/high/xhigh are accepted, or omit it. Reasoning
  tokens are billed against the output budget, so the per-operation max-token
  limits need headroom.
- Chat Completions documents `max_tokens`, not `max_completion_tokens`. Muse
  Spark is a reasoning model but not one of the OpenAI products the frozen
  `_supports_reasoning_model` name list recognises, so the parameter name comes
  from the provider default. A test pins that, and pins that a configured
  reasoning_effort still reaches the request (the #3449 drop list only covers
  OpenAI's own non-reasoning products).

The provider is registered on the chat/completions path only. Meta also serves
a Responses and an Anthropic-Messages endpoint; a `meta-responses` variant
mirroring openai/openai-responses was considered and deliberately left out.

Capability flags are left off deliberately: Meta has no batch endpoint, and its
prompt caching is automatic (no key, flag, or breakpoints), so it does not fit
the explicit `get_or_create_cached_prefix` contract `supports_prompt_caching`
describes — the benefit applies for free either way.

Changes:
- engine/llm_wrapper.py: register "meta" in create_llm_provider(),
  LLMProvider.valid_providers, and the default base_url map
- engine/providers/openai_compatible_llm.py: register "meta" in
  valid_providers, default base_url, and the API-key-required check
- config.py: PROVIDER_DEFAULT_MODELS["meta"] = muse-spark-1.3
- tests/test_meta_provider.py: default model/base URL, API-key requirement,
  the max_tokens parameter name, and reasoning_effort pass-through
- hindsight-embed control center: add Meta Model API to the provider wizard
- docs: add Meta to llmProviders.json (drives the providers grid, the
  capability table and the default-models table) and config examples in
  developer/models.mdx + developer/configuration.md
- README + .env.example (+ the bundled embed copy): document the new provider

Also colours the docs provider grid, which was previously monochrome. Each tile
now carries its brand colour, taken from the Simple Icons dataset — the same
project the marks themselves come from, so a tile's colour matches its mark.
Near-black brands (OpenAI, Ollama, Anthropic, ...) get a dark-theme override so
they do not vanish against the dark surface. Providers with no Simple Icons
entry (Groq, Fireworks, Atlas Cloud, Requesty, opencode-go, Nous, llama.cpp,
LiteLLM) keep the neutral inherited colour rather than an invented hex. The
fallback is `inherit`, so the other IconGrid caller (ClientsGrid) is unchanged.

Meta uses its own mark (SiMeta) rather than the generic OpenAI-compatible glyph.

Not verified against the live API — no Meta API key was available — so
muse-spark-1.3 is deliberately absent from the "Tested Models" table, which
means models verified to work. Worth probing first with a real key: Meta
rejects recursive JSON schemas in structured output with HTTP 400.

* docs(llm): mark muse-spark-1.3 tested against the live Meta API

Verified end-to-end through Hindsight's own create_llm_provider() against
https://api.meta.ai/v1 (HTTP 200, valid content, token usage parsed including
reasoning tokens), so muse-spark-1.3 now belongs in the Tested Models table.

Four behaviours confirmed live, all matching the published docs:

- Structured output with a flat json_schema works, and classified the probe
  input correctly (world vs experience).
- Recursive JSON schemas are rejected: HTTP 400 "Recursive JSON schemas are not
  currently supported". Audited every Pydantic response model in
  engine/response_models.py for self-reference through $defs — none is
  recursive, so no Hindsight path is affected.
- reasoning_effort "none" is rejected: HTTP 400 '"reasoning_effort" does not
  support "none" with this model.' Other levels are accepted.
- Reasoning tokens are substantial and come out of the output budget: a trivial
  prompt spent 87 reasoning tokens against 11 visible output tokens, and at
  max_tokens=64 the response comes back with no content at all. Hindsight's
  defaults leave ample room (retain 64000; consolidation and reflect unbounded),
  so this only bites an operator who lowers the cap — which is what the
  configuration note added with the provider already warns about.

Also records in the max-tokens test that Meta accepts max_completion_tokens as
well, so sending max_tokens is a choice between two working names rather than a
correctness fix.

* fix(llm): reflect failed outright on Meta — tool_choice is auto-only

Found by running a real Hindsight instance against Meta Model API and
exercising retain, recall, reflect and consolidation end to end. Reflect
returned HTTP 400 on every call:

    only `"auto"` is supported for `tool_choice`. `"none"`, `"required"`,
    and named function choices are not currently supported

Reflect's agent loop forces a retrieval tool on its first turns, so the whole
reflect surface was unusable on this provider. The unit tests could not have
caught it: they cover provider construction and parameter naming, not the
tool-calling path.

This is the opposite failure mode to the one `_drops_tool_choice_required`
handles. LM Studio and Ollama accept the field and silently ignore it, so
reflect answers badly (#1563/#1179); Meta rejects the request outright, so
reflect answers not at all. The two need separate predicates, hence
`_rejects_non_auto_tool_choice` alongside the existing check rather than a
widening of it.

The field is dropped for any non-auto mode. A named choice has already been
narrowed to a single tool by the block above, so the call stays practically
forced under auto — the same reasoning the DeepSeek branch relies on. "none"
cannot be expressed by omission and would become "auto"; no caller reaches
this path with it (only the gemini, claude-code and github-copilot providers
handle NONE), so that is documented in place rather than given an untested
tools-stripping branch.

tests/test_meta_tool_choice.py covers required, named and auto, and asserts the
carve-out does not leak to other OpenAI-compatible endpoints. The LM Studio and
required-downgrade suites still pass unchanged.

Also documents the latency finding from the same run: Muse Spark reasons before
every reply, and reflect's 30s default deadline is too short for its final
synthesis — it timed out four times before failing. Raising
HINDSIGHT_API_REFLECT_LLM_TIMEOUT and HINDSIGHT_API_LLM_TIMEOUT to 300 makes
reflect return a correct grounded answer in ~60s.

Verified end to end on the fixed build: retain 26s (3 facts, entities and a
March 2026 temporal range), recall 1.7s (3 hits, correctly ranked), reflect 60s
(grounded answer), consolidation completed (4 observations, 15 links, 0 failed
operations).

* docs(models): give Meta Model API its own setup section with the required knobs

The provider's settings were inline comments inside the shared 20-provider
config block, which is the wrong place for something an operator must act on:
three of the four are required, not tuning, and one of them (the reflect
deadline) is the difference between reflect working and reflect returning
nothing at all.

Adds a "Meta Model API Setup" section alongside the other providers that need
one, with the required knobs as a table that states why each is required —
every one of them a consequence of Muse Spark always reasoning before it
replies. Also records the model lineup, the contributor-tier trade-off, and the
four things worth knowing up front: prompt caching is automatic (which is why
the capability table shows none), there is no batch or embeddings endpoint,
recursive JSON schemas are rejected, and calls are slow.

The shared config block keeps the two timeout exports, since they are required
to be set, and now points at the section for the reasoning.
2026-09-04 12:08:55 +02:00

24 KiB


What is Hindsight?

Hindsight™ is an agent memory system built to create smarter agents that learn over time. Most agent memory systems focus on recalling conversation history. Hindsight is focused on making agents that learn, not just remember.

It eliminates the shortcomings of alternative techniques such as RAG and knowledge graph and delivers state-of-the-art performance on long term memory tasks.

Contents


Memory Performance & Accuracy

Hindsight is the most accurate agent memory system ever tested according to benchmark performance. It has achieved state-of-the-art performance on the LongMemEval benchmark, widely used to assess memory system performance across a variety of conversational AI scenarios. The current reported performance of Hindsight and other agent memory solutions as of January 2026 is shown here:

Overview

Live, continuously updated results — including per-model accuracy, latency and cost — are published at benchmarks.hindsight.vectorize.io.

The benchmark performance data for Hindsight has been independently reproduced by research collaborators at the Virginia Tech Sanghani Center for Artificial Intelligence and Data Analytics and The Washington Post. Other scores are self-reported by software vendors.

Hindsight is being used in production at Fortune 500 enterprises and by a growing number of AI startups.


🤖 Using a coding agent? Install the Hindsight documentation skill for instant access to docs while you code:

npx skills add https://github.com/vectorize-io/hindsight --skill hindsight-docs

Works with Claude Code, Cursor, and other AI coding assistants.


Quick Start

1. Start a server

export OPENAI_API_KEY=sk-xxx

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

API: http://localhost:8888 UI: http://localhost:9999

Hindsight works with 25+ LLM providers via HINDSIGHT_API_LLM_PROVIDER — hosted (openai, anthropic, gemini, groq, bedrock, vertexai, minimax, deepseek, atlas, meta, …), fully local (ollama, lmstudio, llamacpp), any OpenAI-compatible endpoint, and gateways (litellm, litellmrouter) that reach the rest. Existing subscriptions work too: openai-codex (ChatGPT Plus/Pro), claude-code (Claude Pro/Max) and github-copilot (GitHub Copilot) need no API key. See supported models.

Docker (external PostgreSQL)

export OPENAI_API_KEY=sk-xxx
export HINDSIGHT_DB_PASSWORD=choose-a-password
cd docker/docker-compose
docker compose up

Oracle AI Database is also supported for enterprise deployments with full feature parity. See the storage documentation for details.

Bare metal (pip)

pip install hindsight-api
export HINDSIGHT_API_LLM_API_KEY=sk-xxx

hindsight-api

Kubernetes (Helm)

helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
  --set api.llm.provider=openai \
  --set api.llm.apiKey=sk-xxx \
  --set postgresql.enabled=true

Managed (no server)

Hindsight Cloud is the hosted option: managed infrastructure that scales automatically, plus a dashboard, backups, team collaboration and a 99.9% uptime SLA. Billing is usage-based with free credits to start — no fixed monthly or per-seat fee. Point any client at https://api.hindsight.vectorize.io with your API key and skip the deployment entirely.

Compare self-hosted, Cloud and Enterprise → · Sign up →

All options, including Windows and air-gapped setups, are covered in the installation guide.

2. Connect a client

pip install hindsight-client -U                                  # Python
npm install @vectorize-io/hindsight-client                        # Node.js / TypeScript
go get github.com/vectorize-io/hindsight/hindsight-clients/go     # Go
curl -fsSL https://hindsight.vectorize.io/get-cli | bash          # CLI

Python

from hindsight_client import Hindsight

client = Hindsight(base_url="http://localhost:8888")

# Retain: Store information
client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer")

# Recall: Search memories
client.recall(bank_id="my-bank", query="What does Alice do?")

# Reflect: Generate disposition-aware response
client.reflect(bank_id="my-bank", query="Tell me about Alice")

Node.js / TypeScript

const { HindsightClient } = require('@vectorize-io/hindsight-client');

const main = async () => {
  const client = new HindsightClient({ baseUrl: 'http://localhost:8888' });

  await client.retain('my-bank', 'Alice loves hiking in Yosemite');

  const results = await client.recall('my-bank', 'What does Alice like?');
  console.log(results);
}

main();

Full reference: Python · Node.js · Go · CLI · REST API

Supported Platforms

Platform Docker Bare Metal (pip) Embedded DB (pg0)
Linux (x86_64, ARM64)
macOS (Apple Silicon / arm64)
macOS (Intel / x86_64) ⚠️
Windows (x86_64)

⚠️ Intel Macs: use hindsight-all-slim — see the installation guide for details.

Python Embedded (no server required)

pip install hindsight-all -U

On Intel (x86_64) Macs, install hindsight-all-slim instead — see Supported Platforms.

import os
from hindsight import HindsightServer, HindsightClient

with HindsightServer(
    llm_provider="openai",
    llm_model="gpt-5-mini",
    llm_api_key=os.environ["OPENAI_API_KEY"]
) as server:
    client = HindsightClient(base_url=server.url)
    client.retain(bank_id="my-bank", content="Alice works at Google")
    results = client.recall(bank_id="my-bank", query="Where does Alice work?")

A Node.js equivalent and a daemon CLI are also available.


Adding Hindsight to Your Agent

LLM Wrapper (2 lines of code)

The easiest way to add memory to an existing agent is the LLM Wrapper. Swap your LLM client for a wrapped one — memories are then stored and retrieved automatically on every call, with no other changes to your code.

pip install hindsight-litellm
from openai import OpenAI
from hindsight_litellm import wrap_openai

# Wrap your existing LLM client and you're done.
# Defaults to Hindsight Cloud; pass hindsight_api_url for a self-hosted server.
client = wrap_openai(
    OpenAI(),
    bank_id="user-123",
    hindsight_api_url="http://localhost:8888",
)

# Hindsight recalls relevant memories before the call
# and retains the conversation after it.
response = client.chat.completions.create(
    model="gpt-5-mini",
    messages=[{"role": "user", "content": "What do you know about me?"}],
)

wrap_anthropic() does the same for the Anthropic SDK, and every setting — bank, recall budget, fact types, reflect instead of recall — can be overridden per call with hindsight_* kwargs. LiteLLM sits underneath, so the same integration covers 100+ models. See the LiteLLM integration.

If you need explicit control over when memories are stored and recalled, use the SDKs or REST API directly instead.

Integrations

60+ integrations — most need no code changes.

Coding agents Claude Code · Codex · Cursor · GitHub Copilot · opencode · Cline · Aider · Zed · Continue · Roo Code · OpenHands
Agent frameworks LangGraph / LangChain · LlamaIndex · CrewAI · Pydantic AI · OpenAI Agents SDK · Google ADK · Agno · Strands · AutoGen · Microsoft Agent Framework · Vercel AI SDK · Haystack
No-code / low-code n8n · Zapier · Dify · Flowise
Apps & tools ChatGPT · Perplexity · Obsidian · Pipecat · Vapi

👉 Browse all integrations

Coding Agents

One package gives CLI coding agents long-term project memory: a per-repo bank built automatically from git history and past sessions, injected into the agent as it starts working, plus curated knowledge pages covering architecture, conventions and in-flight work.

npx @vectorize-io/hindsight-coding-agents install all          # every detected agent, wired natively
npx @vectorize-io/hindsight-coding-agents install claude-code  # or just one

Supports Claude Code, Codex CLI, Cursor CLI, GitHub Copilot CLI, opencode, Kilo CLI, Cline CLI, Antigravity CLI, Devin CLI, pi, Prime Agent, Grok Build and DeepSeek Harness. Ingestion is automatic — there is no setup command. See the coding agents integration.

MCP Server

Every server ships a built-in Model Context Protocol endpoint, one per bank, enabled by default:

http://localhost:8888/mcp/{bank_id}/

Point any MCP client at it to expose retain, recall and reflect as tools. See the MCP server docs.


Core Concepts

Overview

Memory Types

Most agent memory implementations rely on basic vector search or sometimes use a knowledge graph. Hindsight uses biomimetic data structures to organize agent memories in a way that is more like how human memory works:

  • World facts: facts about the world ("The stove gets hot")
  • Experiences: the agent's own experiences ("I touched the stove and it really hurt")
  • Observations: consolidated, evidence-backed beliefs formed from many memories
  • Mental models: learned understanding of the agent's world, synthesized from observations and facts

Memories live in banks. When memories are added, they are pushed into either the world facts or the experiences pathway, then represented as a combination of entities, relationships, and time series with sparse/dense vector representations to aid in later recall.

The Three Operations

Retain

The retain operation is used to push new memories into Hindsight. It tells Hindsight to retain the information you pass in as an input.

client.retain(
    bank_id="my-bank",
    content="Alice got promoted to senior engineer",
    context="career update",
    timestamp="2025-06-15T10:00:00Z",
)

Behind the scenes, retain uses an LLM to extract key facts, temporal data, entities, and relationships. It passes these through a normalization process to transform extracted data into canonical entities, time series, and search indexes along with metadata. These representations create the pathways for accurate memory retrieval in the recall and reflect operations.

Retain Operation

Retain docs →

Recall

The recall operation is used to retrieve memories. These memories can come from any of the memory types (world, experiences, etc.)

client.recall(bank_id="my-bank", query="What does Alice do?")
client.recall(bank_id="my-bank", query="What happened in June?")   # temporal

Recall performs 4 retrieval strategies in parallel:

  • Semantic: Vector similarity
  • Keyword: BM25 exact matching
  • Graph: Entity/temporal/causal links
  • Temporal: Time range filtering

Recall Operation

The individual results are merged, ordered by relevance using reciprocal rank fusion and a cross-encoder reranking model, then trimmed as needed to fit within the token limit.

Recall docs →

Reflect

The reflect operation performs a more thorough analysis of existing memories. This allows the agent to form new connections between memories and build a more thorough understanding of its world — or to answer a question that needs deep thinking rather than lookup.

client.reflect(bank_id="my-bank", query="What should I know about Alice?")

For example, reflect supports use cases such as:

  • An AI Project Manager reflecting on what risks need to be mitigated on a project.
  • A Sales Agent reflecting on why certain outreach messages have gotten responses while others haven't.
  • A Support Agent reflecting on opportunities where customers have questions not answered by current product documentation.

Reflect Operation

Reflect docs →

Observations

Retained facts don't stay a flat pile. In the background, Hindsight consolidates related facts into observations — deduplicated beliefs the bank has built up over time. Each observation keeps its supporting evidence with exact quotes and a proof count, and is refined rather than overwritten when new evidence arrives, so new information strengthens, weakens or extends an existing belief instead of silently replacing it.

Observations docs →

Mental Models & Knowledge Pages

A mental model is a standing answer to a question about a bank ("What are this user's preferences?"). You define the question once; Hindsight writes the answer, stores it, and rewrites it in the background as the bank learns more. Reading one is a database read — no retrieval, no LLM call — so an agent can boot with a page of settled knowledge instead of rediscovering it every session.

Knowledge pages are mental models with the mechanics hidden: living documents a bank writes about itself, organized in folders like a wiki, searchable, and projectable onto disk as ordinary markdown. Supply a name and a question; every other decision is a default you can override.

Mental models → · Knowledge pages →

Memory Banks

A bank is an isolated memory store — one "brain" for one user, agent, or project. Isolation is strict: no cross-bank leakage. Banks carry background context and disposition traits (skepticism, literalism, empathy) that shape how reflect reasons over their memories, and can be created from declarative bank templates.

Two more things worth knowing:

  • Multilingual by default. Input language is detected and preserved end to end — facts stay in their original language and entities keep their native script (张伟 stays 张伟, not "Zhang Wei"). Docs →
  • Memory Defense. An opt-in, per-bank policy that scans every retain for secrets and PII against 45 patterns and either redacts the match ([REDACTED:github_token]) or blocks the item before it reaches storage. Docs →

Use Cases

Hindsight is built to support conversational AI agents as well as agents that are intended to perform tasks autonomously. The ideal use case for Hindsight are agents that require a blend of these features such as AI employees that need to handle open-ended tasks, change behavior based on user feedback, and learn to perform complex tasks to automate work at a level that approximates a human work. Hindsight can be used with simple AI workflows like those built with n8n and other similar tools, but may be overkill for such applications.

Per-User Memories and Chat History

One of the simpler use cases you can use Hindsight for is to personalize AI chatbots and other conversational agents by storing and recalling memories associated with individual users.

The requirements for this use case usually look something like this:

Per-User Memories

Satisfying these requirements in Hindsight is straightforward. When new user inputs and tool calls are ingested into Hindsight using the retain operation, custom metadata can be used to enrich the new memories. Metadata provides a convenient way to isolate memories that need to be restricted to a given user. Once these are fed into the retain operation, any raw memories and mental models that get created can be filtered when retrieving relevant memories.

Per-User Memories

More patterns in the Cookbook and Best Practices.


Running in Production

Storage PostgreSQL + pgvector, or Oracle AI Database 23ai with full feature parity — storage
Configuration Hierarchical: global env vars → per-tenant → per-bank — configuration
Monitoring Prometheus metrics and dashboards for LLM calls, tokens and latency — monitoring
Operations Admin CLI for migrations, bank repair and stuck operations — admin CLI
Events Webhooks for retain, consolidation and refresh lifecycle events — webhooks
Extensibility Tenant, auth and storage extension points — extensions
Managed Skip all of it with Hindsight Cloud — managed, usage-based, 99.9% uptime SLA

Resources

Documentation:

Clients:

Community:


Star History

Star history


Contributing

See CONTRIBUTING.md.

License

MIT — see LICENSE


Built by Vectorize.io