Cogitator
Advanced

Reflection Engine

Enable agents to reflect on their own outputs, extract insights from past executions, and continuously improve through self-evaluation loops.

Overview

The Reflection Engine lets agents analyze their own actions, learn from mistakes, and build up a knowledge base of insights over time. Every tool call, error, and completed run can be reflected upon — producing structured learnings that inform future decisions.

The reflection cycle follows four phases: generate a response, evaluate its quality, reflect on what worked or failed, and improve through accumulated insights.

Reflection in a Cogitator

import { Cogitator } from '@cogitator-ai/core';

const cog = new Cogitator({
  reflection: {
    enabled: true,
    reflectAfterToolCall: true,
    reflectAfterError: true,
    reflectAtEnd: true,
    reflectionModel: 'openai/gpt-6-luna', // defaults to the running agent's model
    minConfidenceToStore: 0.3,
    maxInsightsPerAgent: 100,
  },
});

const result = await cog.run(agent, { input: 'Find the best TypeScript learning resources' });

result.reflections; // the reflections made during this run
await cog.getInsights(agent.id); // everything learned so far
await cog.getReflectionSummary(agent.id);

With reflection.enabled, every run starts by appending the agent's most relevant insights to its system prompt ("Past learnings that may help"). Then, depending on the flags:

FlagWhenEffect
reflectAfterToolCallAfter every tool callA reflection on the call; when its confidence is low, its suggestion joins the conversation
reflectAfterErrorAfter a failed tool callAn error reflection instead of the general one; its suggestion joins the conversation
reflectAtEndAfter the final answerA reflection on the whole run

Each reflection is one extra model call, and failed reflections are logged without failing the run. Insights live in an in-memory store for the lifetime of the Cogitator; use a standalone engine (below) for a store of your own.

Setting Up a Standalone Engine

import { ReflectionEngine, InMemoryInsightStore } from '@cogitator-ai/core';

const insightStore = new InMemoryInsightStore();

const reflectionEngine = new ReflectionEngine({
  llm: backend,
  insightStore,
  config: {
    enabled: true,
    reflectionModel: 'gpt-6-luna',
    storeInsights: true,
    minConfidenceToStore: 0.3,
    maxInsightsPerAgent: 100,
  },
});

The ReflectionEngine requires an LLM backend for generating reflections, an InsightStore for persistence, and a config that controls quality thresholds. A standalone engine sends reflectionModel to the backend as is, so pass the provider's own model id; it is required. Insights with a confidence below minConfidenceToStore (default 0.3) are not stored, storeInsights: false stores none, and the store is pruned to maxInsightsPerAgent (default 100) per agent.

Reflecting on Tool Calls

After a tool executes, the engine can evaluate whether it was the right choice:

const result = await reflectionEngine.reflectOnToolCall(
  {
    type: 'tool_call',
    toolName: 'web_search',
    input: { query: 'TypeScript generics tutorial' },
    output: '10 results found...',
  },
  {
    agentId: 'research-agent',
    agentName: 'Researcher',
    runId: 'run_abc123',
    threadId: 'thread_1',
    goal: 'Find the best TypeScript learning resources',
    iterationIndex: 0,
    availableTools: ['web_search', 'web_scrape'],
    previousActions: [],
  }
);

if (result.shouldAdjustStrategy) {
  console.log('Suggested adjustment:', result.suggestedAction);
}

The result includes a Reflection object with confidence scores, reasoning, and extracted insights. When confidence drops below 0.5, the engine signals that the agent should adjust its strategy.

Reflecting on Errors

Error reflection is particularly valuable — it helps agents avoid repeating the same mistakes:

const errorResult = await reflectionEngine.reflectOnError(
  {
    type: 'tool_call',
    toolName: 'sql_query',
    input: { query: 'SELECT * FROM users WEHRE id = 1' },
    error: 'Syntax error near WEHRE',
  },
  context
);

Error reflections always set shouldAdjustStrategy: true and provide a suggested alternative approach.

In a Cogitator with reflectAfterError: true, every failed tool call gets this error reflection instead of the general one; its suggested action is added to the conversation before the next model call.

End-of-Run Reflection

After a complete agent run, reflect on the entire execution to capture high-level patterns:

const runResult = await reflectionEngine.reflectOnRun(
  context,
  allActions,
  finalOutput,
  true // success
);

This produces insights about the overall strategy — what worked, what was inefficient, and what could be done differently next time.

Working with Insights

Insights are the persistent output of reflection. They're categorized by type: pattern, mistake, success, tip, or warning.

const insights = await reflectionEngine.getRelevantInsights(context, 5);

for (const insight of insights) {
  console.log(`[${insight.type}] ${insight.content}`);
  console.log(`  Confidence: ${insight.confidence}`);
  console.log(`  Used ${insight.usageCount} times`);
}

Insights are ranked by relevance using word overlap with the context's goal, confidence scores, recency, and type priority (mistakes and warnings rank higher to prevent repeated errors). Every insight returned is marked as used.

getRunReflections(runId) returns the reflections the engine made during a run (it remembers the last 100 runs).

Reflection Summary

Get an aggregate view of an agent's learning progress:

const summary = await reflectionEngine.getSummary('research-agent');

console.log(`Total reflections: ${summary.totalReflections}`);
console.log(`Success rate: ${(summary.successRate * 100).toFixed(1)}%`);
console.log(`Avg confidence: ${summary.averageConfidence.toFixed(2)}`);
console.log('Common mistakes:', summary.commonMistakes);
console.log('Learned patterns:', summary.learnedPatterns);
console.log(
  'Top insights:',
  summary.topInsights.map((i) => i.content)
);

Insight Store

The InMemoryInsightStore provides the default storage. It supports relevance-based retrieval, usage tracking, and automatic pruning to keep the insight count within configured limits.

const store = new InMemoryInsightStore();

await store.store(insight);
await store.storeMany(insights);

const relevant = await store.findRelevant('agent-id', 'current task context', 5);

await store.prune('agent-id', 100);

const stats = store.getStats();
console.log(`${stats.totalInsights} insights across ${stats.agentCount} agents`);

For production use, implement the InsightStore interface backed by a database to persist insights across restarts, and pass it to a standalone ReflectionEngine.

Integration with Other Systems

The Reflection Engine integrates with Tree-of-Thought Reasoning — the BranchEvaluator uses past insights to score tool-call branches. It also feeds into the Agent Learning system: an AgentOptimizer given an insightStore includes those insights when it generates instruction candidates.

On this page