How Mental Models Differ From Directives in Hindsight: Dynamic Knowledge vs Static Rules

Mental models are dynamic, synthesized summaries of learned knowledge generated through reflection, while directives are static, hard-coded rules injected verbatim into LLM prompts to enforce constraints.

Understanding how mental models differ from directives in Hindsight is essential for architecting effective memory systems. In the vectorize-io/hindsight repository, these two constructs represent complementary approaches to influencing LLM behavior—one offering fluid, derived insights while the other imposes rigid, unbreakable constraints. This guide breaks down their architectural distinctions, lifecycle management, and practical implementation using the official Python client.

Core Architectural Distinctions

Purpose and Knowledge Type

Mental models capture derived knowledge about topics, such as "The team prefers async Slack." They are generated by running a reflect operation over stored facts and observations, producing markdown-formatted summaries stored in the bank. Directives encode hard rules that must appear verbatim in every reflect prompt, such as "Always answer in formal English," functioning as immutable behavioral constraints.

Data Models and Lifecycle Management

The MentalModelResponse data model (defined in hindsight-clients/python/hindsight_client_api/models/mental_model_response.py) includes fields like source_query, content, tags, trigger, and last_refreshed_at, supporting automatic refreshes via refresh_after_consolidation triggers. In contrast, DirectiveResponse (from hindsight-clients/python/hindsight_client_api/models/directive_response.py) contains content, priority, and is_active flags, offering no auto-refresh capability—content remains immutable until manually edited via client.update_directive().

Effect on the Reflection Process

During reflection, these entities occupy distinct sections in the ReflectBasedOn payload (defined in hindsight-clients/python/hindsight_client_api/models/reflect_based_on.py). Mental models appear in the mental_models array as ReflectMentalModel instances, allowing the LLM to reason with synthesized knowledge. Directives populate the directives array as ReflectDirective instances, forcing compliance without reasoning.

class ReflectBasedOn(BaseModel):
    memories: Optional[List[ReflectFact]] = ...
    mental_models: Optional[List[ReflectMentalModel]] = ...
    directives: Optional[List[ReflectDirective]] = ...

Working with Mental Models

Creating Dynamic Knowledge Summaries

Use client.create_mental_model() to launch a background reflect job that generates a knowledge summary. This operation stores the result in your bank as a refreshable entity.


# hindsight-docs/examples/api/mental-models.py

result = client.create_mental_model(
    bank_id=BANK_ID,
    name="Team Communication Preferences",
    source_query="How does the team prefer to communicate?",
    tags=["team", "communication"]
)
print(f"Operation ID: {result.operation_id}")  # Background reflect job launched

Configuring Auto-Refresh Triggers

Mental models support lifecycle automation through the MentalModelTrigger configuration (defined in hindsight-clients/python/hindsight_client_api/models/mental_model_trigger.py). Set refresh_after_consolidation to True to automatically regenerate the model when new memories consolidate.

result = client.create_mental_model(
    bank_id=BANK_ID,
    name="Project Status",
    source_query="What is the current project status?",
    trigger={"refresh_after_consolidation": True}
)

Working with Directives

Creating Static Compliance Rules

Directives are created using client.create_directive() and store static text immediately. Unlike mental models, no background processing occurs—the content is ready for prompt injection.


# hindsight-docs/examples/api/directives.py

directive = client.create_directive(
    bank_id=BANK_ID,
    name="Formal Language",
    content="Always respond in formal English, avoiding slang and colloquialisms."
)
print(f"Created directive: {directive.id}")

Updating Directive Status

Modify directive behavior using client.update_directive() to toggle the is_active flag without deleting the record. This provides a reversible way to disable rules.

updated = client.update_directive(
    bank_id=BANK_ID,
    directive_id=directive.id,
    is_active=False
)
print(f"Directive active: {updated.is_active}")

How They Appear in Reflection Responses

When the reflect operation completes, the server returns a ReflectBasedOn structure that segregates these knowledge types. This separation ensures the LLM receives derived insights for reasoning and static rules for compliance.

{
  "based_on": {
    "mental_models": [{...}],  
    "directives": [{...}]       
  }
}

The mental_models array contains evolving summaries, while the directives array holds immutable constraints that shape prompt construction.

Summary

  • Mental models represent dynamic, derived knowledge generated through reflection and stored as markdown summaries that can auto-refresh via triggers configured in MentalModelTrigger.
  • Directives enforce static, hard-coded rules injected verbatim into prompts, controlled by priority and is_active flags defined in DirectiveResponse.
  • The ReflectBasedOn model explicitly separates these entities into mental_models and directives arrays to handle reasoning versus compliance differently.
  • Use client.create_mental_model() for evolving knowledge slices and client.create_directive() for unbreakable behavioral constraints.

Frequently Asked Questions

Can a mental model be converted into a directive?

No. Mental models and directives serve fundamentally different purposes in the Hindsight architecture. Mental models contain synthesized content generated by the reflection engine, while directives contain static text written by developers. You would need to manually copy content from a mental model's content field and create a new directive using client.create_directive().

Why do directives appear in the ReflectBasedOn response if they are input prompts?

Directives appear in ReflectBasedOn (defined in hindsight-clients/python/hindsight_client_api/models/reflect_based_on.py) for observability and debugging purposes. This allows you to verify which static rules were active and injected into the specific reflection operation, even though the LLM processes them as mandatory constraints rather than reasoning material.

How does auto-refresh affect mental model content?

When refresh_after_consolidation triggers execute, the system runs a new reflect job using the original source_query. The content field updates to reflect newly consolidated memories, and the last_refreshed_at timestamp updates. The model ID and metadata remain constant, but the synthesized knowledge evolves to incorporate new observations.

Can directives have multiple priority levels?

Yes. The DirectiveResponse model includes a priority field that controls injection order when multiple directives exist. Higher priority directives appear earlier in the prompt structure, ensuring critical safety or compliance rules take precedence over stylistic guidelines.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →