fleet-memory/hindsight-docs/blog/2026-01-28-learning-capabilities.md
Derek Bouius ee4510a762
fix(deps): address critical and high severity security vulnerabilities (#827)
* fix(deps): address critical and high severity security vulnerabilities

Bump vulnerable dependencies to patched versions across the monorepo:

Python (critical/high):
- fastmcp >=2.14.0 → >=3.2.0 (SSRF, path traversal, OAuth confused deputy, command injection)
- langchain-core >=1.2.11 → >=1.2.22 (path traversal in legacy load_prompt)

Python (low):
- cryptography >=46.0.5 → >=46.0.6 (incomplete DNS name constraint enforcement)
- pygments: add >=2.20.0 pin (ReDoS via GUID regex)

Node.js:
- serialize-javascript ^7.0.3 → ^7.0.5 (CPU exhaustion DoS)
- handlebars: add >=4.7.9 override (JS injection via AST type confusion)
- path-to-regexp: add >=0.1.13 override (ReDoS via route params)
- brace-expansion: add version range override (process hang/memory exhaustion)

Also adds type: ignore comments for FastMCP 2.x private attribute access that
ty now flags since FastMCP 3.x removed _tool_manager (guarded by try/except
and hasattr at runtime).

Regenerated all lock files across API, integrations, and tests.

* fix(deps): add ajv v8 scoped overrides for schema-utils and ajv-keywords

The global ajv ^6.14.0 override caused schema-utils and ajv-keywords to
receive ajv v6, but they require ajv v8 (for dist/compile/codegen). Add
scoped overrides to ensure these packages get ajv v8 while the global
override remains for packages that need v6.

* fix(tests): remove stateless_http from FastMCP() constructor calls

FastMCP 3.x no longer accepts stateless_http in the constructor. The
tests call tools directly without HTTP transport, so the parameter is
not needed.

* fix: update MCP tests for FastMCP 3.x _tool_manager removal

FastMCP 3.x removed _tool_manager. Tests now use
_local_provider._components for sync tool dict access and
mcp.list_tools() for async filtered tool listing.

* fix: resolve docusaurus build failures (ajv overrides + missing blog date)

- Remove global ajv ^6.14.0 override and scoped ajv-keywords/schema-utils
  overrides that caused webpack compilation errors manifesting as
  "Cannot read properties of undefined (reading 'date')" during SSR
  and "these parameters are deprecated" warnings. Natural version
  resolution (v6.12.6+ for v6 consumers, v8+ for v8 consumers) already
  satisfies the security fix (>= 6.12.3).
- Add missing date frontmatter to learning-capabilities blog post.

* chore: regenerate openapi spec and docs skill
2026-04-01 09:20:34 +02:00

285 lines
12 KiB
Markdown

---
slug: learning-capabilities
title: "Agent memory that learns: observations and mental models"
authors: [nicoloboschi]
image: /img/reflect-operation.webp
date: 2026-01-28T12:00
hide_table_of_contents: true
---
Today we're releasing Hindsight 0.4.0, which introduces two powerful learning capabilities for AI agents: **Observations** for automatic knowledge consolidation, and **Mental Models** for user-curated summaries.
<!-- truncate -->
## Two Levels of Learning
Hindsight 0.4.0 introduces a hierarchical learning system:
| Level | What It Is | How It's Created |
|-------|------------|------------------|
| **Mental Models** | User-curated summaries for common queries | Manually created via API |
| **Observations** | Consolidated knowledge from facts | Automatically after retain |
During `reflect`, the agent checks these in priority order — mental models first (your curated knowledge), then observations (automatic synthesis), then raw facts.
---
## Observations: Automatic Knowledge Consolidation
### Evolution from Entity Summaries and Opinions
In Hindsight 0.3.0, we had two separate systems for synthesized knowledge:
- **Entity summaries**: Per-entity summaries synthesized from related facts. Generated automatically for frequently-mentioned entities — if "Alice" appeared in many facts, you'd get a summary like "Alice is a software engineer at Google who joined in 2020 and leads the search team." Objective and entity-scoped.
- **Opinions**: Beliefs formed during `reflect` operations, influenced by the bank's disposition traits. These captured subjective judgments with confidence scores, like "Python is best for data science" (confidence: 0.85).
Both systems served their purpose well, but they operated independently. Entity summaries were entity-centric, opinions were belief-centric, and neither captured the full picture of how knowledge evolves over time.
**Observations** unify these concepts into a single, more expressive system that captures patterns, preferences, and learnings as they emerge from accumulated evidence.
### What Are Observations?
Observations are **consolidated knowledge** synthesized from multiple facts. Unlike raw facts which are individual pieces of information, observations represent patterns and insights that emerge from accumulated evidence.
| Raw Facts | Observation |
|-----------|--------------|
| "Alice prefers Python" | "Alice is a Python-focused developer who values readability and simplicity, recommends type hints, and prefers pytest for testing" |
| "Alice dislikes verbose code" | |
| "Alice recommends type hints" | |
### Automatic Background Consolidation
After every `retain()` call, Hindsight's consolidation engine runs automatically:
1. **Analyzes new facts** against existing knowledge
2. **Detects patterns** across related information
3. **Synthesizes observations** that capture higher-order insights
4. **Tracks evidence** linking each observation to its supporting facts
```mermaid
graph LR
A[New Facts] --> B[Consolidation Engine]
B --> C{Existing Observation?}
C -->|Yes| D[Refine Observation]
C -->|No| E[Create Observation]
D --> F[Observations]
E --> F
```
### Evidence-Based Evolution
Observations evolve as new evidence arrives, capturing the full journey rather than just the current state:
| Time | Fact | Observation |
|------|------|--------------|
| Week 1 | "User loves React" | "User prefers React for frontend development" |
| Week 2 | "User praises React's component model" | "User is enthusiastic about React, particularly its component model" |
| Week 3 | "User switched to Vue and won't use React anymore" | "User was previously a React enthusiast who appreciated its component model, but has now switched to Vue" |
Notice how the final observation captures the **full journey** — not just "User prefers Vue" but the complete evolution. Your agent now understands:
- The user deliberately moved away from React (it wasn't ignorance)
- They previously appreciated React's component model (relevant context)
- Recommending React tutorials would be inappropriate
### Mission-Oriented Consolidation
Observations are influenced by your bank's **mission**. When you set a mission, the consolidation engine focuses on extracting knowledge that serves that purpose:
```python
client.create_bank(
bank_id="support-agent",
mission="You're a customer support agent - track customer preferences, "
"past issues, and communication styles."
)
```
With this mission, the engine prioritizes customer-relevant observations while skipping ephemeral details. Without a mission, it performs general-purpose consolidation.
---
## Mental Models: User-Curated Knowledge
While observations are created automatically, **mental models** give you explicit control over how your agent answers common questions.
### What Are Mental Models?
Mental models are **saved reflect responses** that you curate for your memory bank. When you create a mental model, Hindsight runs a reflect operation with your source query and stores the result. During future reflect calls, these pre-computed summaries are checked first.
```mermaid
graph LR
A[Create Mental Model] --> B[Run Reflect]
B --> C[Store Result]
C --> D[Future Queries]
D --> E{Match Found?}
E -->|Yes| F[Return Mental Model]
E -->|No| G[Run Full Reflect]
```
### Why Use Mental Models?
| Benefit | Description |
|---------|-------------|
| **Consistency** | Same answer every time for common questions |
| **Speed** | Pre-computed responses are returned instantly |
| **Quality** | Manually curated summaries you've reviewed |
| **Control** | Define exactly how key topics should be answered |
### Two Ways to Use Mental Models
Mental models work in two ways:
1. **Automatic via Reflect**: During `reflect` calls, the agent automatically checks mental models first. If a relevant one exists, it's used to inform the response.
2. **Direct Lookup**: Mental models work like a key-value store — you can retrieve them instantly by ID, bypassing the reflect reasoning loop entirely.
```python
# Direct lookup by ID — instant response, no LLM call
mental_model = client.get_mental_model(
bank_id="my-bank",
mental_model_id="team-communication"
)
print(mental_model.content) # Pre-computed answer, ready to use
```
This is useful when you know exactly what mental model you need and want the fastest possible response — no LLM reasoning required, just a simple database lookup.
### Creating Mental Models
```python
# Create a mental model for a common question
response = client.create_mental_model(
bank_id="my-bank",
name="Team Communication Preferences",
source_query="How does the team prefer to communicate?",
tags=["team"]
)
```
### Automatic Refresh
Mental models can automatically stay in sync with your observations:
```python
# Mental model that refreshes when observations update
response = client.create_mental_model(
bank_id="my-bank",
name="Project Status",
source_query="What is the current project status?",
trigger={"refresh_after_consolidation": True}
)
```
---
## Directives: Compliance and Guardrails
In addition to learning capabilities, **directives** provide hard rules that your agent must always follow during reflect operations. Unlike disposition traits which *influence* reasoning style, directives are absolute requirements that are enforced in every response.
Use directives for compliance, privacy, and safety constraints:
- "Never provide medical diagnoses or treatment advice"
- "Always respond in formal English"
- "Never share personally identifiable information"
- "Always cite sources when making factual claims"
Directives are injected into reflect prompts as hard constraints and are included in the response's `based_on` field. See the [Directives documentation](../developer/api/memory-banks#directives) for how to create and manage them.
---
## What Changes from 0.3.0
### Unified Memory Types
Opinions and entity summaries are now consolidated into observations:
```python
# 0.3.0 - opinions via types, entity summaries via include_entities
response = client.recall(
bank_id="my-bank",
query="What do you think about Python?",
types=["opinion"],
include_entities=True # to get entity summaries
)
# 0.4.0 - observations unify both
response = client.recall(
bank_id="my-bank",
query="What do you think about Python?",
types=["observation"]
)
```
### From Confidence Scores to Evidence Tracking
Opinions had numeric confidence scores (0.0-1.0). Observations instead track:
- **Supporting facts**: The evidence behind the observation
- **Last updated**: When the observation was last refined
- **Freshness**: Whether the observation reflects recent information
This shift from a single score to evidence tracking means your agent can explain *why* it believes something, not just *how confident* it is.
### Automatic vs On-Demand
Entity summaries were created automatically for top entities, but opinions only formed during `reflect`. Observations are always consolidated automatically after `retain`, ensuring knowledge stays current without explicit queries.
### Background Becomes Mission
The bank's `background` field has been renamed to `mission`. During the migration, your existing background text is automatically copied to the mission field — no action needed.
### Agentic Reflect
The `reflect` operation is now agentic — it reasons more deeply by iteratively retrieving memories and consulting mental models and observations before formulating a response. This makes reflect significantly smarter, especially for complex questions that require synthesizing information across multiple topics.
The trade-off is that reflect may take longer to respond. For latency-sensitive use cases, consider using `recall` directly when you just need to retrieve facts.
### Data Migration
**Important:** When upgrading to 0.4.0, existing opinions and entity summaries will be deleted. The consolidation engine will automatically create new observations from your existing facts. This is a one-time migration — your raw facts are preserved, and observations will be synthesized from them after the upgrade.
### Migration Checklist
**If you were using `types=["opinion"]` in recall:**
1. Update to `types=["observation"]`
2. Observations combine both entity-centric summaries and belief-based insights
**If you were using `include_entities=True` in recall:**
1. Entity summaries are now included in observations
2. Use `types=["observation"]` to retrieve them
**If you were relying on confidence scores:**
1. Use the `based_on` field to access supporting evidence
2. The number and recency of supporting facts indicates strength
**If you were setting `background` on banks:**
1. The field is now called `mission`
2. Existing values are migrated automatically
**No changes needed for reflect:**
Observations are automatically included in reflect responses via the `based_on` field.
---
## What's Next
These learning capabilities are the foundation for more sophisticated agent memory capabilities we're exploring:
- **Temporal reasoning**: Better understanding of how knowledge evolves over time
- **Selective consolidation**: Fine-grained control over what gets synthesized into observations
- **Consolidation insights**: Visibility into how observations are formed and updated
---
**Resources:**
- [Recall API](../developer/api/recall) — retrieve observations alongside facts
- [Reflect API](../developer/api/reflect) — responses now include supporting observations
- [Mental Models API](../developer/api/mental-models) — create and manage curated summaries
- [Observations Guide](../developer/observations) — deep dive into knowledge consolidation
- [Directives](../developer/api/memory-banks#directives) — hard rules for compliance and guardrails
- [Full Changelog](../changelog)