← Back to DevBytes

AutoGen Teachability: Making Agents Learn from Interactions

What is AutoGen Teachability?

Teachability is a powerful feature in Microsoft's AutoGen framework that enables conversational agents to learn from their interactions and improve over time. Rather than treating each conversation as a clean slate, teachable agents can absorb user feedback, remember corrections, and store preferences — then apply those lessons in future conversations without explicit retraining or redeployment.

At its core, teachability relies on a memory-backed architecture where agents maintain a persistent store of learnings. When a user says "actually, that's not right" or "from now on, format dates like this," the agent records that insight and retrieves it later when relevant. This transforms agents from static prompt-followers into dynamic systems that evolve alongside their users.

The teachability mechanism is implemented through a specialized Teachability class that hooks into the agent's conversation lifecycle. It intercepts user inputs, processes feedback signals, updates the agent's long-term memory, and injects relevant learnings into subsequent prompts — all without requiring changes to the underlying LLM or agent code.

Why Teachability Matters

Without teachability, conversational agents suffer from a fundamental limitation: they forget everything between sessions. Every conversation starts from scratch, forcing users to repeat preferences, re-explain domain rules, and re-correct mistakes they've already addressed. This creates several real-world problems:

Teachability addresses these challenges by giving agents a lightweight, interaction-driven learning loop. It's particularly valuable in customer support bots, coding assistants, personal productivity agents, and any scenario where agent behavior must adapt to individual user preferences over time. The learning happens at the edge — during actual conversations — meaning no centralized retraining pipeline or manual prompt updates are needed.

How Teachability Works Under the Hood

The teachability system operates through four key components that work together seamlessly:

1. The Teachability Class

This is the central orchestrator that you attach to an AutoGen agent. It maintains a memories dictionary where each key represents a lesson the agent has learned, and the value stores the corresponding rule or preference. The class exposes methods for analyzing user input, deciding whether a teaching moment has occurred, and retrieving relevant memories for the current context.

2. Teaching Triggers

Not every user utterance is a teaching moment. The teachability module uses pattern recognition and semantic analysis to detect when a user is explicitly providing feedback — phrases like "remember that," "from now on," "actually," "no, that's wrong," or "let me correct you" act as strong signals. You can customize these triggers to match your domain's vocabulary.

3. Memory Storage and Retrieval

When a teaching trigger fires, the agent extracts the lesson from the user's message (often using an LLM call to parse the intent) and stores it in the memory dictionary. During subsequent conversations, the agent performs semantic retrieval against stored memories to find relevant lessons. This retrieval uses embedding similarity or keyword matching to surface applicable rules without flooding the context window.

4. Context Injection

Retrieved memories are injected into the agent's system prompt or conversation context before the LLM generates a response. This ensures the agent "remembers" past teachings without the user needing to repeat them. The injection format is carefully designed to be concise and non-disruptive to the conversation flow.

Getting Started: Installation and Setup

Before diving into teachability, ensure you have AutoGen installed with the necessary dependencies. The teachability module is part of the core AutoGen library (version 0.2.0+).

pip install autogen-agentchat autogen-ext[openai] --upgrade

You'll also need an LLM provider configured. The examples below use OpenAI, but teachability works with any provider supported by AutoGen.

Basic Teachability Example

Let's start with a minimal working example. We'll create a simple assistant agent and equip it with teachability so it can learn and remember user preferences.

import asyncio
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teachability import Teachability
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_agentchat.messages import TextMessage

# Step 1: Configure the model client
model_client = OpenAIChatCompletionClient(
    model="gpt-4o",
    api_key="YOUR_API_KEY_HERE"  # Replace with your actual key
)

# Step 2: Create a teachability instance with persistent storage
teachability = Teachability(
    # Path to a JSON file where memories will be persisted
    memory_store_path="agent_memories.json"
)

# Step 3: Create the assistant agent and attach teachability
assistant = AssistantAgent(
    name="TeachableAssistant",
    system_message="You are a helpful assistant. Pay attention when users correct you or ask you to remember things.",
    model_client=model_client,
    reflect_on_tool_use=False,
    # Attach the teachability capability
    teachability=teachability
)

# Step 4: Run a conversation
async def main():
    # First conversation: teach the agent a preference
    print("=== Conversation 1: Teaching ===")
    response1 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Remember that I prefer metric units — use kilometers, not miles, and Celsius, not Fahrenheit."
        )]
    )
    print(response1.messages[-1].content if response1.messages else "No response")
    
    # Second conversation: the agent should recall the teaching
    print("\n=== Conversation 2: Recall ===")
    response2 = await assistant.run(
        messages=[TextMessage(
            source="user", 
            content="What's the distance from Paris to Berlin?"
        )]
    )
    print(response2.messages[-1].content if response2.messages else "No response")
    
    # Third conversation: agent should still remember
    print("\n=== Conversation 3: Persistence Check ===")
    response3 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="What's the boiling point of water?"
        )]
    )
    print(response3.messages[-1].content if response3.messages else "No response")

asyncio.run(main())

In this example, after the user teaches the agent about metric unit preferences in Conversation 1, the agent stores that lesson in agent_memories.json. In Conversations 2 and 3, the agent automatically retrieves and applies the stored preference — expressing distances in kilometers and temperatures in Celsius — without any prompting from the user.

Advanced Teachability with Custom Memory Processing

For production use cases, you'll often want more granular control over how memories are created, retrieved, and applied. The Teachability class supports custom callback functions for each stage of the learning pipeline.

import asyncio
import json
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teachability import Teachability, Memory
from autogen_agentchat.messages import TextMessage

model_client = OpenAIChatCompletionClient(
    model="gpt-4o",
    api_key="YOUR_API_KEY_HERE"
)

# Custom function to determine if a user message is a teaching moment
def custom_teaching_detector(message: str) -> bool:
    """Detect if the user is trying to teach something."""
    teaching_indicators = [
        "remember", "note that", "from now on", "actually",
        "let me correct", "that's wrong", "instead use",
        "prefer", "always use", "never use"
    ]
    message_lower = message.lower()
    return any(indicator in message_lower for indicator in teaching_indicators)

# Custom function to extract the lesson from a teaching message
async def custom_memory_extractor(
    user_message: str,
    assistant_response: str,
    model_client
) -> Memory | None:
    """Extract a structured memory from a teaching interaction."""
    
    # Use the LLM to parse the lesson
    extraction_prompt = f"""
    The user said: "{user_message}"
    The assistant responded: "{assistant_response}"
    
    If the user was teaching the assistant something, extract it as a JSON object:
    {{"rule": "the specific rule or preference learned", "category": "one-word category"}}
    
    If no teaching occurred, return: {{"rule": null, "category": null}}
    
    Only return valid JSON, no other text.
    """
    
    response = await model_client.create(
        messages=[{"role": "user", "content": extraction_prompt}],
        response_format={"type": "json_object"}
    )
    
    extracted = json.loads(response.content)
    
    if extracted.get("rule"):
        return Memory(
            content=extracted["rule"],
            metadata={"category": extracted.get("category", "general")},
            source_message=user_message
        )
    return None

# Create teachability with custom functions
teachability = Teachability(
    memory_store_path="advanced_memories.json",
    # Custom detector — override default teaching trigger detection
    teaching_message_detector=custom_teaching_detector,
    # Custom extractor — control how memories are parsed and stored
    memory_extractor=custom_memory_extractor,
    # Maximum number of memories to retrieve per conversation turn
    max_memories_per_turn=3,
    # Minimum similarity threshold for memory retrieval (0.0 to 1.0)
    retrieval_threshold=0.65
)

assistant = AssistantAgent(
    name="AdvancedTeachableAssistant",
    system_message="""You are a precise assistant. 
    When users correct you or give you rules to follow, 
    acknowledge the teaching and confirm you'll remember it.
    Always check your memories before responding.""",
    model_client=model_client,
    teachability=teachability
)

async def advanced_example():
    # Teaching interaction
    print("=== Teaching the agent ===")
    response1 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Note that all SQL queries I share should use PostgreSQL syntax, not MySQL."
        )]
    )
    print(f"Assistant: {response1.messages[-1].content}")
    
    # Another teaching
    response2 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Also remember: I prefer snake_case for all variable names, never camelCase."
        )]
    )
    print(f"Assistant: {response2.messages[-1].content}")
    
    # Test recall with a query-writing task
    print("\n=== Testing memory recall ===")
    response3 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Write a SQL query to find all users who registered in the last 30 days."
        )]
    )
    print(f"Assistant: {response3.messages[-1].content}")
    
    # Test recall with a coding task
    response4 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Write a Python function to calculate user_age from date_of_birth."
        )]
    )
    print(f"Assistant: {response4.messages[-1].content}")

asyncio.run(advanced_example())

This advanced example demonstrates three key customizations: a teaching detector that uses domain-specific keywords to identify teaching moments, a memory extractor that leverages the LLM itself to parse lessons into structured JSON, and retrieval parameters that control how many memories are injected and how similar they must be to the current context. These give you fine-grained control over the learning behavior.

Persistent Memory Across Sessions

One of teachability's most valuable features is persistence. Memories stored in the JSON file survive process restarts, meaning an agent can accumulate knowledge over days, weeks, or months of interaction. Here's how to work with persistent memory effectively:

import asyncio
import json
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teachability import Teachability
from autogen_agentchat.messages import TextMessage

model_client = OpenAIChatCompletionClient(
    model="gpt-4o",
    api_key="YOUR_API_KEY_HERE"
)

# Initialize teachability with a persistent store
teachability = Teachability(
    memory_store_path="long_term_memories.json"
)

# Optional: inspect existing memories before the conversation
try:
    with open("long_term_memories.json", "r") as f:
        existing_memories = json.load(f)
        print(f"Loaded {len(existing_memories)} existing memories:")
        for key, memory in existing_memories.items():
            print(f"  - {key}: {memory.get('content', 'N/A')[:80]}...")
except FileNotFoundError:
    print("No existing memories found — starting fresh.")

assistant = AssistantAgent(
    name="PersistentAssistant",
    system_message="You are an assistant with long-term memory. Apply all remembered preferences.",
    model_client=model_client,
    teachability=teachability
)

async def persistent_session():
    # The agent will use any previously stored memories automatically
    response = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Generate a weekly report template for our sales data."
        )]
    )
    print(f"Assistant: {response.messages[-1].content}")
    
    # Manually add a memory programmatically (without a teaching interaction)
    teachability.add_memory(
        content="The sales data always includes columns: date, revenue, units_sold, region, product_category",
        metadata={"category": "data_schema", "added_by": "system"}
    )
    
    # Now the agent knows about the sales schema for future requests
    response2 = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Write a query to analyze monthly revenue trends."
        )]
    )
    print(f"Assistant: {response2.messages[-1].content}")
    
    # You can also manually retrieve memories for inspection
    relevant_memories = teachability.retrieve_relevant_memories("monthly revenue analysis")
    print(f"\nRetrieved {len(relevant_memories)} relevant memories for the query.")
    
    # Clear specific memories or all memories
    # teachability.clear_all_memories()  # Use with caution!
    # teachability.remove_memory("specific_memory_key")

asyncio.run(persistent_session())

The JSON memory store is human-readable and can be inspected or edited manually. Each memory entry typically contains the learned content, metadata like categories or timestamps, and the original source message. This transparency makes debugging and auditing straightforward — you can always see exactly what the agent has learned.

Teachability in Multi-Agent Teams

Teachability becomes even more powerful in multi-agent scenarios where different agents can have distinct learned knowledge. Each agent maintains its own teachability instance and memory store, allowing specialized learning across a team.

import asyncio
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teachability import Teachability
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.messages import TextMessage

model_client = OpenAIChatCompletionClient(
    model="gpt-4o",
    api_key="YOUR_API_KEY_HERE"
)

# Each agent gets its own teachability and memory store
coder_teachability = Teachability(memory_store_path="coder_memories.json")
reviewer_teachability = Teachability(memory_store_path="reviewer_memories.json")

# Coding specialist agent
coder_agent = AssistantAgent(
    name="CodeWriter",
    system_message="""You are an expert Python developer. 
    Write clean, well-documented code. Learn from user feedback about 
    coding style, library preferences, and architectural patterns.""",
    model_client=model_client,
    teachability=coder_teachability
)

# Code reviewer agent
reviewer_agent = AssistantAgent(
    name="CodeReviewer",
    system_message="""You are a thorough code reviewer. 
    Check for bugs, security issues, and style violations. 
    Learn the user's review criteria and standards over time.""",
    model_client=model_client,
    teachability=reviewer_teachability
)

# Create a team with both agents
team = RoundRobinGroupChat(
    participants=[coder_agent, reviewer_agent],
    max_turns=4
)

async def multi_agent_teaching():
    # Teach the coder specific preferences
    print("=== Teaching the CodeWriter ===")
    await coder_agent.run(
        messages=[TextMessage(
            source="user",
            content="CodeWriter, remember: I prefer using httpx for HTTP requests, not requests library. Always use type hints."
        )]
    )
    
    # Teach the reviewer specific criteria
    print("\n=== Teaching the CodeReviewer ===")
    await reviewer_agent.run(
        messages=[TextMessage(
            source="user",
            content="CodeReviewer, remember: flag any function longer than 50 lines. Also check for missing docstrings."
        )]
    )
    
    # Now run a team task — both agents use their learned knowledge
    print("\n=== Team Task with Learned Knowledge ===")
    team_response = await team.run(
        messages=[TextMessage(
            source="user",
            content="Write a function that fetches weather data from an API and parses the JSON response."
        )]
    )
    
    for msg in team_response.messages:
        if hasattr(msg, 'source') and msg.source != 'user':
            print(f"\n[{msg.source}]: {msg.content[:300]}...")

asyncio.run(multi_agent_teaching())

In this multi-agent setup, the CodeWriter remembers to use httpx and type hints, while the CodeReviewer independently remembers to flag long functions and missing docstrings. Each agent's learnings are siloed to their role, preventing cross-contamination and enabling specialized growth.

Best Practices for Production Teachability

1. Design Clear Teaching Protocols

Establish explicit conventions for how users can teach the agent. Document these for your users so they know which phrases trigger learning. For example: "Say 'remember:' followed by your rule to teach me permanently." Ambiguous feedback like "that's not great" is hard to parse reliably — encourage structured teaching language.

2. Implement Memory Hygiene

Over time, memory stores can accumulate outdated, contradictory, or overly specific rules. Implement periodic memory review:

3. Balance Memory Injection with Context Limits

Every retrieved memory consumes tokens in the agent's context window. Set max_memories_per_turn conservatively (3-5 is usually safe) and use retrieval_threshold to filter borderline matches. Monitor your model's context utilization and adjust these parameters if responses become truncated or less coherent.

4. Validate Learned Memories

Not everything a user says should be blindly memorized. Consider adding a validation step in your custom memory extractor — perhaps checking that the extracted rule is factually consistent, doesn't contradict system-level safety guidelines, and is specific enough to be useful. A memory like "always do good work" is too vague to help retrieval.

5. Test Memory Contamination

In multi-tenant or multi-user scenarios, ensure memories from one user don't leak into another's sessions. Use separate memory stores per user ID or session namespace. The memory_store_path parameter can be dynamically set based on user context.

# Example: user-scoped memory stores
def create_teachability_for_user(user_id: str) -> Teachability:
    return Teachability(
        memory_store_path=f"memories_{user_id}.json",
        max_memories_per_turn=4,
        retrieval_threshold=0.7
    )

# Alice's agent learns different things than Bob's
alice_teachability = create_teachability_for_user("alice_123")
bob_teachability = create_teachability_for_user("bob_456")

6. Log and Audit Learning Events

Every time a memory is created, updated, or retrieved, log the event with sufficient context for debugging. This is invaluable when users report unexpected agent behavior — you can trace exactly which learned rule influenced a particular response.

7. Provide Memory Transparency to Users

Allow users to inspect what the agent has learned. A simple command like "show me what you've learned" or "what memories do you have?" should trigger the agent to list its stored knowledge. This builds trust and lets users correct erroneous learnings.

# Adding a memory inspection command to your agent
async def handle_memory_inspection(assistant, teachability):
    response = await assistant.run(
        messages=[TextMessage(
            source="user",
            content="Show me everything you've learned from our conversations."
        )]
    )
    # Alternatively, access memories programmatically
    all_memories = teachability.memories
    for key, memory in all_memories.items():
        print(f"[{key}] {memory.content}")

8. Handle Contradictory Teachings Gracefully

Users may inadvertently teach contradictory rules ("always use JSON" followed later by "switch to YAML for configs"). Your memory management should detect conflicts and either ask the user for clarification or apply the most recent teaching while flagging the contradiction in logs.

Conclusion

AutoGen's teachability feature transforms conversational agents from static tools into adaptive collaborators that grow more useful with every interaction. By combining persistent memory storage, intelligent teaching detection, and context-aware retrieval, teachability enables agents to internalize user preferences, correct past mistakes, and deliver increasingly personalized experiences — all without complex retraining pipelines or manual prompt maintenance.

The implementation is remarkably straightforward: instantiate a Teachability object, attach it to your agent, and the learning loop activates automatically. For advanced scenarios, the customizable detector and extractor functions give you complete control over what gets learned and how it's applied. Whether you're building a single intelligent assistant or orchestrating a team of specialized agents, teachability adds a layer of continuous improvement that directly translates to user satisfaction and operational efficiency.

Start with a simple memory store, establish clear teaching conventions for your users, and iterate on your retrieval parameters. With these foundations in place, your AutoGen agents will accumulate valuable knowledge organically — one conversation at a time.

— Ad —

Google AdSense will appear here after approval

← Back to all articles