Skip to main content

Reflect

Generate disposition-aware responses using retrieved memories.

When you call reflect, Hindsight performs a multi-step reasoning process:

  1. Recalls relevant memories from the bank based on your query
  2. Applies the bank's disposition traits to shape the reasoning style
  3. Generates a contextual answer grounded in the retrieved facts
  4. Forms opinions in the background based on the reasoning (available in subsequent calls)

The response includes the generated answer along with the facts that were used, providing full transparency into how the answer was derived.

How Reflect Works

Learn about disposition-driven reasoning and opinion formation in the Reflect Architecture guide.

Prerequisites

Make sure you've completed the Quick Start to install the client and start the server.

Basic Usage

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

Parameters

ParameterTypeDefaultDescription
querystringrequiredQuestion or prompt
budgetstring"low"Budget level: low, mid, high
contextstringNoneAdditional context for the query
max_tokensint4096Maximum tokens for the response
response_schemaobjectNoneJSON Schema for structured output
tagslistNoneFilter memories by tags during reflection
tags_matchstring"any"How to match tags: any, all, any_strict, all_strict

Response Fields

FieldTypeDescription
textstringThe generated answer text
based_onarrayFacts used to generate the response
structured_outputobjectParsed structured output (when response_schema provided)
usageTokenUsageToken usage metrics for the LLM call

The usage field contains:

  • input_tokens: Number of input/prompt tokens consumed
  • output_tokens: Number of output/completion tokens generated
  • total_tokens: Sum of input and output tokens
response = client.reflect(
bank_id="my-bank",
query="What do you think about remote work?",
budget="mid",
context="We're considering a hybrid work policy"
)

The Role of Context

The context parameter steers how the reflection is performed without impacting the memory recall. It provides situational information that helps shape the reasoning and response.

How context is used:

  • Shapes reasoning: Helps understand the situation when formulating an answer
  • Disambiguates intent: Clarifies what aspect of the query matters most
  • Does not affect recall: The same memories are retrieved regardless of context
# Context is passed to the LLM to help it understand the situation
response = client.reflect(
bank_id="my-bank",
query="What do you think about the proposal?",
context="We're in a budget review meeting discussing Q4 spending"
)

Opinion Formation

When reflect reasons about a question, it may form new opinions based on the evidence in the memory bank. These opinions are created in the background and become available in subsequent reflect and recall calls.

Why opinions matter:

  • Consistent thinking: Opinions ensure the memory bank maintains a coherent perspective over time
  • Evolving viewpoints: As more information is retained, opinions can be refined or updated
  • Grounded reasoning: Opinions are always derived from factual evidence in the memory bank

Opinions are stored as a special memory type and are automatically retrieved when relevant to future queries. This creates a natural evolution of the bank's perspective, similar to how humans form and refine their views based on accumulated experience.

Disposition Influence

The bank's disposition affects reflect responses:

TraitLow (1)High (5)
SkepticismTrusting, accepts claimsQuestions and doubts claims
LiteralismFlexible interpretationExact, literal interpretation
EmpathyDetached, fact-focusedConsiders emotional context
# Create a bank with specific disposition
client.create_bank(
bank_id="cautious-advisor",
name="Cautious Advisor",
mission="I am a risk-aware financial advisor",
disposition={
"skepticism": 5, # Very skeptical of claims
"literalism": 4, # Focuses on exact requirements
"empathy": 2 # Prioritizes facts over feelings
}
)

# Reflect responses will reflect this disposition
response = client.reflect(
bank_id="cautious-advisor",
query="Should I invest in crypto?"
)
# Response will likely emphasize risks and caution

Using Sources

The based_on field shows which memories informed the response:

response = client.reflect(bank_id="my-bank", query="Tell me about Alice")

print("Response:", response.text)
print("\nBased on:")
for fact in response.based_on or []:
print(f" - [{fact.type}] {fact.text}")

This enables:

  • Transparency — users see why the bank said something
  • Verification — check if the response is grounded in facts
  • Debugging — understand retrieval quality

Structured Output

For applications that need to process responses programmatically, you can request structured output by providing a JSON Schema via response_schema. When provided, the response includes a structured_output field with the LLM response parsed according to the schema. The text field will be empty since only a single LLM call is made for efficiency.

The easiest way to define a schema is using Pydantic models:

from pydantic import BaseModel
from hindsight_client import Hindsight

# Define your response structure with Pydantic
class HiringRecommendation(BaseModel):
recommendation: str
confidence: str # "low", "medium", "high"
key_factors: list[str]
risks: list[str] = []

with Hindsight() as client:
response = client.reflect(
bank_id="hiring-team",
query="Should we hire Alice for the ML team lead position?",
response_schema=HiringRecommendation.model_json_schema(),
)

# Parse structured output into Pydantic model
result = HiringRecommendation.model_validate(response.structured_output)
print(f"Recommendation: {result.recommendation}")
print(f"Confidence: {result.confidence}")
print(f"Key factors: {result.key_factors}")
Use CaseWhy Structured Output Helps
Decision pipelinesParse recommendations into workflow systems
DashboardsExtract confidence scores, risk factors for visualization
Multi-agent systemsPass structured data between agents
AuditingLog structured decisions with clear reasoning

Tips:

  • Use Pydantic's model_json_schema() for type-safe schema generation
  • Use model_validate() to parse the response back into your Pydantic model
  • Keep schemas focused — extract only what you need
  • Use Optional fields for data that may not always be available

Filter by Tags

Like recall, reflect supports tag filtering to scope which memories are considered during reasoning. This is essential for multi-user scenarios where reflection should only consider memories relevant to a specific user.

# Filter reflection to only consider memories for a specific user
response = client.reflect(
bank_id="my-bank",
query="What does this user think about our product?",
tags=["user:alice"],
tags_match="any_strict" # Only use memories tagged for this user
)

The tags_match parameter works the same as in recall:

ModeBehavior
anyOR matching, includes untagged memories
allAND matching, includes untagged memories
any_strictOR matching, excludes untagged memories
all_strictAND matching, excludes untagged memories

See Retain API for how to tag memories and Recall API for more details on tag matching modes.