Reflect
Generate disposition-aware responses using retrieved memories.
When you call reflect, Hindsight performs a multi-step reasoning process:
- Recalls relevant memories from the bank based on your query
- Applies the bank's disposition traits to shape the reasoning style
- Generates a contextual answer grounded in the retrieved facts
- 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.
Learn about disposition-driven reasoning and opinion formation in the Reflect Architecture guide.
Make sure you've completed the Quick Start to install the client and start the server.
Basic Usage
- Python
- Node.js
- CLI
client.reflect(bank_id="my-bank", query="What should I know about Alice?")
await client.reflect('my-bank', 'What should I know about Alice?');
hindsight memory reflect my-bank "What do you know about Alice?"
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | required | Question or prompt |
budget | string | "low" | Budget level: low, mid, high |
context | string | None | Additional context for the query |
max_tokens | int | 4096 | Maximum tokens for the response |
response_schema | object | None | JSON Schema for structured output |
tags | list | None | Filter memories by tags during reflection |
tags_match | string | "any" | How to match tags: any, all, any_strict, all_strict |
Response Fields
| Field | Type | Description |
|---|---|---|
text | string | The generated answer text |
based_on | array | Facts used to generate the response |
structured_output | object | Parsed structured output (when response_schema provided) |
usage | TokenUsage | Token usage metrics for the LLM call |
The usage field contains:
input_tokens: Number of input/prompt tokens consumedoutput_tokens: Number of output/completion tokens generatedtotal_tokens: Sum of input and output tokens
- Python
- Node.js
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"
)
const response = await client.reflect('my-bank', '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
- Python
- Node.js
# 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"
)
// Context helps the LLM understand the current situation
const contextResponse = await client.reflect('my-bank', '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:
| Trait | Low (1) | High (5) |
|---|---|---|
| Skepticism | Trusting, accepts claims | Questions and doubts claims |
| Literalism | Flexible interpretation | Exact, literal interpretation |
| Empathy | Detached, fact-focused | Considers emotional context |
- Python
- Node.js
# 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
// Create a bank with specific disposition
await client.createBank('cautious-advisor', {
name: 'Cautious Advisor',
background: 'I am a risk-aware financial advisor',
disposition: {
skepticism: 5,
literalism: 4,
empathy: 2
}
});
// Reflect responses will reflect this disposition
const advisorResponse = await client.reflect('cautious-advisor', 'Should I invest in crypto?');
Using Sources
The based_on field shows which memories informed the response:
- Python
- Node.js
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}")
const sourcesResponse = await client.reflect('my-bank', 'Tell me about Alice');
console.log('Response:', sourcesResponse.text);
console.log('\nBased on:');
for (const fact of sourcesResponse.based_on || []) {
console.log(` - [${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:
- Python
- Node.js
- CLI
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}")
import { Hindsight } from "@anthropic-ai/hindsight";
const client = new Hindsight();
// Define JSON schema directly
const responseSchema = {
type: "object",
properties: {
recommendation: { type: "string" },
confidence: { type: "string", enum: ["low", "medium", "high"] },
key_factors: { type: "array", items: { type: "string" } },
risks: { type: "array", items: { type: "string" } },
},
required: ["recommendation", "confidence", "key_factors"],
};
const response = await client.reflect({
bankId: "hiring-team",
query: "Should we hire Alice for the ML team lead position?",
responseSchema: responseSchema,
});
// Structured output
console.log(response.structuredOutput.recommendation);
console.log(response.structuredOutput.keyFactors);
First, create a JSON schema file schema.json:
{
"type": "object",
"properties": {
"recommendation": {"type": "string"},
"confidence": {"type": "string", "enum": ["low", "medium", "high"]},
"key_factors": {"type": "array", "items": {"type": "string"}}
},
"required": ["recommendation", "confidence", "key_factors"]
}
Then use the --schema flag:
hindsight memory reflect hiring-team \
"Should we hire Alice for the ML team lead position?" \
--schema schema.json
| Use Case | Why Structured Output Helps |
|---|---|
| Decision pipelines | Parse recommendations into workflow systems |
| Dashboards | Extract confidence scores, risk factors for visualization |
| Multi-agent systems | Pass structured data between agents |
| Auditing | Log 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
Optionalfields 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.
- Python
# 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:
| Mode | Behavior |
|---|---|
any | OR matching, includes untagged memories |
all | AND matching, includes untagged memories |
any_strict | OR matching, excludes untagged memories |
all_strict | AND matching, excludes untagged memories |
See Retain API for how to tag memories and Recall API for more details on tag matching modes.